* IN THE SOFTWARE.
*/
-#include <dlfcn.h>
#include <assert.h>
#include <stdbool.h>
#include <string.h>
#include <sys/mman.h>
-#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
+#include <xf86drm.h>
#include "anv_private.h"
#include "util/strtod.h"
#include "util/debug.h"
+#include "util/build_id.h"
+#include "util/vk_util.h"
#include "genxml/gen7_pack.h"
-struct anv_dispatch_table dtable;
-
static void
compiler_debug_log(void *data, const char *fmt, ...)
{ }
va_end(args);
}
-static bool
-anv_get_function_timestamp(void *ptr, uint32_t* timestamp)
-{
- Dl_info info;
- struct stat st;
- if (!dladdr(ptr, &info) || !info.dli_fname)
- return false;
-
- if (stat(info.dli_fname, &st))
- return false;
-
- *timestamp = st.st_mtim.tv_sec;
- return true;
-}
-
static bool
anv_device_get_cache_uuid(void *uuid)
{
- uint32_t timestamp;
+ const struct build_id_note *note = build_id_find_nhdr("libvulkan_intel.so");
+ if (!note)
+ return false;
- memset(uuid, 0, VK_UUID_SIZE);
- if (!anv_get_function_timestamp(anv_device_get_cache_uuid, ×tamp))
+ unsigned len = build_id_length(note);
+ if (len < VK_UUID_SIZE)
return false;
- snprintf(uuid, VK_UUID_SIZE, "anv-%d", timestamp);
+ memcpy(uuid, build_id_data(note), VK_UUID_SIZE);
return true;
}
isl_device_init(&device->isl_dev, &device->info, swizzled);
- close(fd);
+ device->local_fd = fd;
return VK_SUCCESS;
fail:
{
anv_finish_wsi(device);
ralloc_free(device->compiler);
+ close(device->local_fd);
}
static const VkExtensionProperties global_extensions[] = {
{
.extensionName = VK_KHR_SHADER_DRAW_PARAMETERS_EXTENSION_NAME,
.specVersion = 1,
+ },
+ {
+ .extensionName = VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME,
+ .specVersion = 1,
+ },
+ {
+ .extensionName = VK_KHR_DESCRIPTOR_UPDATE_TEMPLATE_EXTENSION_NAME,
+ .specVersion = 1,
}
};
{
ANV_FROM_HANDLE(anv_instance, instance, _instance);
+ if (!instance)
+ return;
+
if (instance->physicalDeviceCount > 0) {
/* We support at most one physical device. */
assert(instance->physicalDeviceCount == 1);
vk_free(&instance->alloc, instance);
}
+static VkResult
+anv_enumerate_devices(struct anv_instance *instance)
+{
+ /* TODO: Check for more devices ? */
+ drmDevicePtr devices[8];
+ VkResult result = VK_ERROR_INCOMPATIBLE_DRIVER;
+ int max_devices;
+
+ instance->physicalDeviceCount = 0;
+
+ max_devices = drmGetDevices2(0, devices, sizeof(devices));
+ if (max_devices < 1)
+ return VK_ERROR_INCOMPATIBLE_DRIVER;
+
+ for (unsigned i = 0; i < (unsigned)max_devices; i++) {
+ if (devices[i]->available_nodes & 1 << DRM_NODE_RENDER &&
+ devices[i]->bustype == DRM_BUS_PCI &&
+ devices[i]->deviceinfo.pci->vendor_id == 0x8086) {
+
+ result = anv_physical_device_init(&instance->physicalDevice,
+ instance,
+ devices[i]->nodes[DRM_NODE_RENDER]);
+ if (result != VK_ERROR_INCOMPATIBLE_DRIVER)
+ break;
+ }
+ }
+
+ if (result == VK_SUCCESS)
+ instance->physicalDeviceCount = 1;
+
+ return result;
+}
+
+
VkResult anv_EnumeratePhysicalDevices(
VkInstance _instance,
uint32_t* pPhysicalDeviceCount,
VkPhysicalDevice* pPhysicalDevices)
{
ANV_FROM_HANDLE(anv_instance, instance, _instance);
+ VK_OUTARRAY_MAKE(out, pPhysicalDevices, pPhysicalDeviceCount);
VkResult result;
if (instance->physicalDeviceCount < 0) {
- char path[20];
- for (unsigned i = 0; i < 8; i++) {
- snprintf(path, sizeof(path), "/dev/dri/renderD%d", 128 + i);
- result = anv_physical_device_init(&instance->physicalDevice,
- instance, path);
- if (result != VK_ERROR_INCOMPATIBLE_DRIVER)
- break;
- }
-
- if (result == VK_ERROR_INCOMPATIBLE_DRIVER) {
- instance->physicalDeviceCount = 0;
- } else if (result == VK_SUCCESS) {
- instance->physicalDeviceCount = 1;
- } else {
+ result = anv_enumerate_devices(instance);
+ if (result != VK_SUCCESS &&
+ result != VK_ERROR_INCOMPATIBLE_DRIVER)
return result;
- }
}
- /* pPhysicalDeviceCount is an out parameter if pPhysicalDevices is NULL;
- * otherwise it's an inout parameter.
- *
- * The Vulkan spec (git aaed022) says:
- *
- * pPhysicalDeviceCount is a pointer to an unsigned integer variable
- * that is initialized with the number of devices the application is
- * prepared to receive handles to. pname:pPhysicalDevices is pointer to
- * an array of at least this many VkPhysicalDevice handles [...].
- *
- * Upon success, if pPhysicalDevices is NULL, vkEnumeratePhysicalDevices
- * overwrites the contents of the variable pointed to by
- * pPhysicalDeviceCount with the number of physical devices in in the
- * instance; otherwise, vkEnumeratePhysicalDevices overwrites
- * pPhysicalDeviceCount with the number of physical handles written to
- * pPhysicalDevices.
- */
- if (!pPhysicalDevices) {
- *pPhysicalDeviceCount = instance->physicalDeviceCount;
- } else if (*pPhysicalDeviceCount >= 1) {
- pPhysicalDevices[0] = anv_physical_device_to_handle(&instance->physicalDevice);
- *pPhysicalDeviceCount = 1;
- } else if (*pPhysicalDeviceCount < instance->physicalDeviceCount) {
- return VK_INCOMPLETE;
- } else {
- *pPhysicalDeviceCount = 0;
+ if (instance->physicalDeviceCount > 0) {
+ assert(instance->physicalDeviceCount == 1);
+ vk_outarray_append(&out, i) {
+ *i = anv_physical_device_to_handle(&instance->physicalDevice);
+ }
}
- return VK_SUCCESS;
+ return vk_outarray_status(&out);
}
void anv_GetPhysicalDeviceFeatures(
.shaderStorageImageExtendedFormats = true,
.shaderStorageImageMultisample = false,
.shaderStorageImageReadWithoutFormat = false,
- .shaderStorageImageWriteWithoutFormat = false,
+ .shaderStorageImageWriteWithoutFormat = true,
.shaderUniformBufferArrayDynamicIndexing = true,
.shaderSampledImageArrayDynamicIndexing = true,
.shaderStorageBufferArrayDynamicIndexing = true,
.shaderClipDistance = true,
.shaderCullDistance = true,
.shaderFloat64 = pdevice->info.gen >= 8,
- .shaderInt64 = false,
+ .shaderInt64 = pdevice->info.gen >= 8,
.shaderInt16 = false,
.shaderResourceMinLod = false,
.variableMultisampleRate = false,
{
anv_GetPhysicalDeviceFeatures(physicalDevice, &pFeatures->features);
- for (struct anv_common *c = pFeatures->pNext; c != NULL; c = c->pNext) {
- switch (c->sType) {
+ vk_foreach_struct(ext, pFeatures->pNext) {
+ switch (ext->sType) {
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PUSH_DESCRIPTOR_PROPERTIES_KHR: {
+ VkPhysicalDevicePushDescriptorPropertiesKHR *properties =
+ (VkPhysicalDevicePushDescriptorPropertiesKHR *) ext;
+
+ properties->maxPushDescriptors = MAX_PUSH_DESCRIPTORS;
+ break;
+ }
+
default:
- anv_debug_ignored_stype(c->sType);
+ anv_debug_ignored_stype(ext->sType);
break;
}
}
.maxPerStageResources = 128,
.maxDescriptorSetSamplers = 256,
.maxDescriptorSetUniformBuffers = 256,
- .maxDescriptorSetUniformBuffersDynamic = 256,
+ .maxDescriptorSetUniformBuffersDynamic = MAX_DYNAMIC_BUFFERS / 2,
.maxDescriptorSetStorageBuffers = 256,
- .maxDescriptorSetStorageBuffersDynamic = 256,
+ .maxDescriptorSetStorageBuffersDynamic = MAX_DYNAMIC_BUFFERS / 2,
.maxDescriptorSetSampledImages = 256,
.maxDescriptorSetStorageImages = 256,
.maxDescriptorSetInputAttachments = 256,
};
*pProperties = (VkPhysicalDeviceProperties) {
- .apiVersion = VK_MAKE_VERSION(1, 0, 39),
+ .apiVersion = VK_MAKE_VERSION(1, 0, 42),
.driverVersion = 1,
.vendorID = 0x8086,
.deviceID = pdevice->chipset_id,
{
anv_GetPhysicalDeviceProperties(physicalDevice, &pProperties->properties);
- for (struct anv_common *c = pProperties->pNext; c != NULL; c = c->pNext) {
- switch (c->sType) {
+ vk_foreach_struct(ext, pProperties->pNext) {
+ switch (ext->sType) {
default:
- anv_debug_ignored_stype(c->sType);
+ anv_debug_ignored_stype(ext->sType);
break;
}
}
}
-static void
-anv_get_queue_family_properties(struct anv_physical_device *phys_dev,
- VkQueueFamilyProperties *props)
-{
- *props = (VkQueueFamilyProperties) {
- .queueFlags = VK_QUEUE_GRAPHICS_BIT |
- VK_QUEUE_COMPUTE_BIT |
- VK_QUEUE_TRANSFER_BIT,
- .queueCount = 1,
- .timestampValidBits = 36, /* XXX: Real value here */
- .minImageTransferGranularity = (VkExtent3D) { 1, 1, 1 },
- };
-}
+/* We support exactly one queue family. */
+static const VkQueueFamilyProperties
+anv_queue_family_properties = {
+ .queueFlags = VK_QUEUE_GRAPHICS_BIT |
+ VK_QUEUE_COMPUTE_BIT |
+ VK_QUEUE_TRANSFER_BIT,
+ .queueCount = 1,
+ .timestampValidBits = 36, /* XXX: Real value here */
+ .minImageTransferGranularity = { 1, 1, 1 },
+};
void anv_GetPhysicalDeviceQueueFamilyProperties(
VkPhysicalDevice physicalDevice,
uint32_t* pCount,
VkQueueFamilyProperties* pQueueFamilyProperties)
{
- ANV_FROM_HANDLE(anv_physical_device, phys_dev, physicalDevice);
+ VK_OUTARRAY_MAKE(out, pQueueFamilyProperties, pCount);
- if (pQueueFamilyProperties == NULL) {
- *pCount = 1;
- return;
+ vk_outarray_append(&out, p) {
+ *p = anv_queue_family_properties;
}
-
- /* The spec implicitly allows the incoming count to be 0. From the Vulkan
- * 1.0.38 spec, Section 4.1 Physical Devices:
- *
- * If the value referenced by pQueueFamilyPropertyCount is not 0 [then
- * do stuff].
- */
- if (*pCount == 0)
- return;
-
- *pCount = 1;
- anv_get_queue_family_properties(phys_dev, pQueueFamilyProperties);
}
void anv_GetPhysicalDeviceQueueFamilyProperties2KHR(
VkQueueFamilyProperties2KHR* pQueueFamilyProperties)
{
- ANV_FROM_HANDLE(anv_physical_device, phys_dev, physicalDevice);
-
- if (pQueueFamilyProperties == NULL) {
- *pQueueFamilyPropertyCount = 1;
- return;
- }
-
- /* The spec implicitly allows the incoming count to be 0. From the Vulkan
- * 1.0.38 spec, Section 4.1 Physical Devices:
- *
- * If the value referenced by pQueueFamilyPropertyCount is not 0 [then
- * do stuff].
- */
- if (*pQueueFamilyPropertyCount == 0)
- return;
+ VK_OUTARRAY_MAKE(out, pQueueFamilyProperties, pQueueFamilyPropertyCount);
- /* We support exactly one queue family. So need to traverse only the first
- * array element's pNext chain.
- */
- *pQueueFamilyPropertyCount = 1;
- anv_get_queue_family_properties(phys_dev,
- &pQueueFamilyProperties->queueFamilyProperties);
+ vk_outarray_append(&out, p) {
+ p->queueFamilyProperties = anv_queue_family_properties;
- for (struct anv_common *c = pQueueFamilyProperties->pNext;
- c != NULL; c = c->pNext) {
- switch (c->sType) {
- default:
- anv_debug_ignored_stype(c->sType);
- break;
+ vk_foreach_struct(s, p->pNext) {
+ anv_debug_ignored_stype(s->sType);
}
}
}
anv_GetPhysicalDeviceMemoryProperties(physicalDevice,
&pMemoryProperties->memoryProperties);
- for (struct anv_common *c = pMemoryProperties->pNext;
- c != NULL; c = c->pNext) {
- switch (c->sType) {
+ vk_foreach_struct(ext, pMemoryProperties->pNext) {
+ switch (ext->sType) {
default:
- anv_debug_ignored_stype(c->sType);
+ anv_debug_ignored_stype(ext->sType);
break;
}
}
state = anv_state_pool_alloc(pool, size, align);
memcpy(state.map, p, size);
- if (!pool->block_pool->device->info.has_llc)
- anv_state_clflush(state);
+ anv_state_flush(pool->block_pool->device, state);
return state;
}
memcpy(bo.map, batch->start, size);
if (!device->info.has_llc)
- anv_clflush_range(bo.map, size);
+ anv_flush_range(bo.map, size);
exec_bos[0] = &bo;
exec2_objects[0].handle = bo.gem_handle;
device->robust_buffer_access = pCreateInfo->pEnabledFeatures &&
pCreateInfo->pEnabledFeatures->robustBufferAccess;
- pthread_mutex_init(&device->mutex, NULL);
+ if (pthread_mutex_init(&device->mutex, NULL) != 0) {
+ result = vk_error(VK_ERROR_INITIALIZATION_FAILED);
+ goto fail_context_id;
+ }
pthread_condattr_t condattr;
- pthread_condattr_init(&condattr);
- pthread_condattr_setclock(&condattr, CLOCK_MONOTONIC);
- pthread_cond_init(&device->queue_submit, NULL);
+ if (pthread_condattr_init(&condattr) != 0) {
+ result = vk_error(VK_ERROR_INITIALIZATION_FAILED);
+ goto fail_mutex;
+ }
+ if (pthread_condattr_setclock(&condattr, CLOCK_MONOTONIC) != 0) {
+ pthread_condattr_destroy(&condattr);
+ result = vk_error(VK_ERROR_INITIALIZATION_FAILED);
+ goto fail_mutex;
+ }
+ if (pthread_cond_init(&device->queue_submit, NULL) != 0) {
+ pthread_condattr_destroy(&condattr);
+ result = vk_error(VK_ERROR_INITIALIZATION_FAILED);
+ goto fail_mutex;
+ }
pthread_condattr_destroy(&condattr);
anv_bo_pool_init(&device->batch_bo_pool, device);
- anv_block_pool_init(&device->dynamic_state_block_pool, device, 16384);
+ result = anv_block_pool_init(&device->dynamic_state_block_pool, device,
+ 16384);
+ if (result != VK_SUCCESS)
+ goto fail_batch_bo_pool;
anv_state_pool_init(&device->dynamic_state_pool,
&device->dynamic_state_block_pool);
- anv_block_pool_init(&device->instruction_block_pool, device, 1024 * 1024);
+ result = anv_block_pool_init(&device->instruction_block_pool, device,
+ 1024 * 1024);
+ if (result != VK_SUCCESS)
+ goto fail_dynamic_state_pool;
+
anv_state_pool_init(&device->instruction_state_pool,
&device->instruction_block_pool);
- anv_block_pool_init(&device->surface_state_block_pool, device, 4096);
+ result = anv_block_pool_init(&device->surface_state_block_pool, device,
+ 4096);
+ if (result != VK_SUCCESS)
+ goto fail_instruction_state_pool;
anv_state_pool_init(&device->surface_state_pool,
&device->surface_state_block_pool);
- anv_bo_init_new(&device->workaround_bo, device, 1024);
+ result = anv_bo_init_new(&device->workaround_bo, device, 1024);
+ if (result != VK_SUCCESS)
+ goto fail_surface_state_pool;
anv_scratch_pool_init(device, &device->scratch_pool);
unreachable("unhandled gen");
}
if (result != VK_SUCCESS)
- goto fail_fd;
+ goto fail_workaround_bo;
anv_device_init_blorp(device);
return VK_SUCCESS;
+ fail_workaround_bo:
+ anv_queue_finish(&device->queue);
+ anv_scratch_pool_finish(device, &device->scratch_pool);
+ anv_gem_munmap(device->workaround_bo.map, device->workaround_bo.size);
+ anv_gem_close(device, device->workaround_bo.gem_handle);
+ fail_surface_state_pool:
+ anv_state_pool_finish(&device->surface_state_pool);
+ anv_block_pool_finish(&device->surface_state_block_pool);
+ fail_instruction_state_pool:
+ anv_state_pool_finish(&device->instruction_state_pool);
+ anv_block_pool_finish(&device->instruction_block_pool);
+ fail_dynamic_state_pool:
+ anv_state_pool_finish(&device->dynamic_state_pool);
+ anv_block_pool_finish(&device->dynamic_state_block_pool);
+ fail_batch_bo_pool:
+ anv_bo_pool_finish(&device->batch_bo_pool);
+ pthread_cond_destroy(&device->queue_submit);
+ fail_mutex:
+ pthread_mutex_destroy(&device->mutex);
+ fail_context_id:
+ anv_gem_destroy_context(device, device->context_id);
fail_fd:
close(device->fd);
fail_device:
{
ANV_FROM_HANDLE(anv_device, device, _device);
+ if (!device)
+ return;
+
anv_device_finish_blorp(device);
anv_queue_finish(&device->queue);
ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer,
pSubmits[i].pCommandBuffers[j]);
assert(cmd_buffer->level == VK_COMMAND_BUFFER_LEVEL_PRIMARY);
+ assert(!anv_batch_has_error(&cmd_buffer->batch));
result = anv_cmd_buffer_execbuf(device, cmd_buffer);
if (result != VK_SUCCESS)
{
for (uint32_t i = 0; i < count; i++) {
ANV_FROM_HANDLE(anv_device_memory, mem, ranges[i].memory);
- void *p = mem->map + (ranges[i].offset & ~CACHELINE_MASK);
- void *end;
-
- if (ranges[i].offset + ranges[i].size > mem->map_size)
- end = mem->map + mem->map_size;
- else
- end = mem->map + ranges[i].offset + ranges[i].size;
+ if (ranges[i].offset >= mem->map_size)
+ continue;
- while (p < end) {
- __builtin_ia32_clflush(p);
- p += CACHELINE_SIZE;
- }
+ anv_clflush_range(mem->map + ranges[i].offset,
+ MIN2(ranges[i].size, mem->map_size - ranges[i].offset));
}
}
}
void anv_GetBufferMemoryRequirements(
- VkDevice device,
+ VkDevice _device,
VkBuffer _buffer,
VkMemoryRequirements* pMemoryRequirements)
{
ANV_FROM_HANDLE(anv_buffer, buffer, _buffer);
+ ANV_FROM_HANDLE(anv_device, device, _device);
/* The Vulkan spec (git aaed022) says:
*
* only if the memory type `i` in the VkPhysicalDeviceMemoryProperties
* structure for the physical device is supported.
*
- * We support exactly one memory type.
+ * We support exactly one memory type on LLC, two on non-LLC.
*/
- pMemoryRequirements->memoryTypeBits = 1;
+ pMemoryRequirements->memoryTypeBits = device->info.has_llc ? 1 : 3;
pMemoryRequirements->size = buffer->size;
pMemoryRequirements->alignment = 16;
}
void anv_GetImageMemoryRequirements(
- VkDevice device,
+ VkDevice _device,
VkImage _image,
VkMemoryRequirements* pMemoryRequirements)
{
ANV_FROM_HANDLE(anv_image, image, _image);
+ ANV_FROM_HANDLE(anv_device, device, _device);
/* The Vulkan spec (git aaed022) says:
*
* only if the memory type `i` in the VkPhysicalDeviceMemoryProperties
* structure for the physical device is supported.
*
- * We support exactly one memory type.
+ * We support exactly one memory type on LLC, two on non-LLC.
*/
- pMemoryRequirements->memoryTypeBits = 1;
+ pMemoryRequirements->memoryTypeBits = device->info.has_llc ? 1 : 3;
pMemoryRequirements->size = image->size;
pMemoryRequirements->alignment = image->alignment;
uint32_t* pSparseMemoryRequirementCount,
VkSparseImageMemoryRequirements* pSparseMemoryRequirements)
{
- stub();
+ *pSparseMemoryRequirementCount = 0;
}
void anv_GetDeviceMemoryCommitment(
const VkBindSparseInfo* pBindInfo,
VkFence fence)
{
- stub_return(VK_ERROR_INCOMPATIBLE_DRIVER);
+ return vk_error(VK_ERROR_FEATURE_NOT_PRESENT);
}
VkResult anv_CreateFence(
.format = format,
.stride = stride);
- if (!device->info.has_llc)
- anv_state_clflush(state);
+ anv_state_flush(device, state);
}
void anv_DestroySampler(