* 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 "anv_private.h"
-#include "anv_timestamp.h"
#include "util/strtod.h"
#include "util/debug.h"
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;
+
+ memset(uuid, 0, VK_UUID_SIZE);
+ if (!anv_get_function_timestamp(anv_device_get_cache_uuid, ×tamp))
+ return false;
+
+ snprintf(uuid, VK_UUID_SIZE, "anv-%d", timestamp);
+ return true;
+}
+
static VkResult
anv_physical_device_init(struct anv_physical_device *device,
struct anv_instance *instance,
goto fail;
}
+ if (!anv_device_get_cache_uuid(device->uuid)) {
+ result = vk_errorf(VK_ERROR_INITIALIZATION_FAILED,
+ "cannot generate UUID");
+ goto fail;
+ }
bool swizzled = anv_gem_get_bit6_swizzle(fd, I915_TILING_X);
/* GENs prior to 8 do not support EU/Subslice info */
device->info.max_cs_threads = max_cs_threads;
}
- close(fd);
-
brw_process_intel_debug_variable();
device->compiler = brw_compiler_create(NULL, &device->info);
device->compiler->shader_perf_log = compiler_perf_log;
result = anv_init_wsi(device);
- if (result != VK_SUCCESS)
- goto fail;
+ if (result != VK_SUCCESS) {
+ ralloc_free(device->compiler);
+ goto fail;
+ }
- /* XXX: Actually detect bit6 swizzling */
isl_device_init(&device->isl_dev, &device->info, swizzled);
+ close(fd);
return VK_SUCCESS;
fail:
.extensionName = VK_KHR_SWAPCHAIN_EXTENSION_NAME,
.specVersion = 68,
},
+ {
+ .extensionName = VK_KHR_SAMPLER_MIRROR_CLAMP_TO_EDGE_EXTENSION_NAME,
+ .specVersion = 1,
+ },
+ {
+ .extensionName = VK_KHR_MAINTENANCE1_EXTENSION_NAME,
+ .specVersion = 1,
+ },
};
static void *
*pFeatures = (VkPhysicalDeviceFeatures) {
.robustBufferAccess = true,
.fullDrawIndexUint32 = true,
- .imageCubeArray = false,
+ .imageCubeArray = true,
.independentBlend = true,
.geometryShader = true,
- .tessellationShader = false,
+ .tessellationShader = true,
.sampleRateShading = true,
.dualSrcBlend = true,
.logicOp = true,
.multiDrawIndirect = false,
- .drawIndirectFirstInstance = false,
+ .drawIndirectFirstInstance = true,
.depthClamp = true,
- .depthBiasClamp = false,
+ .depthBiasClamp = true,
.fillModeNonSolid = true,
.depthBounds = false,
.wideLines = true,
.pipelineStatisticsQuery = false,
.fragmentStoresAndAtomics = true,
.shaderTessellationAndGeometryPointSize = true,
- .shaderImageGatherExtended = false,
- .shaderStorageImageExtendedFormats = false,
+ .shaderImageGatherExtended = true,
+ .shaderStorageImageExtendedFormats = true,
.shaderStorageImageMultisample = false,
+ .shaderStorageImageReadWithoutFormat = false,
+ .shaderStorageImageWriteWithoutFormat = false,
.shaderUniformBufferArrayDynamicIndexing = true,
.shaderSampledImageArrayDynamicIndexing = true,
.shaderStorageBufferArrayDynamicIndexing = true,
.shaderStorageImageArrayDynamicIndexing = true,
- .shaderStorageImageReadWithoutFormat = false,
- .shaderStorageImageWriteWithoutFormat = true,
- .shaderClipDistance = false,
- .shaderCullDistance = false,
- .shaderFloat64 = false,
+ .shaderClipDistance = true,
+ .shaderCullDistance = true,
+ .shaderFloat64 = pdevice->info.gen >= 8,
.shaderInt64 = false,
.shaderInt16 = false,
- .alphaToOne = true,
+ .shaderResourceMinLod = false,
.variableMultisampleRate = false,
.inheritedQueries = false,
};
pdevice->compiler->scalar_stage[MESA_SHADER_GEOMETRY];
}
-void
-anv_device_get_cache_uuid(void *uuid)
-{
- memset(uuid, 0, VK_UUID_SIZE);
- snprintf(uuid, VK_UUID_SIZE, "anv-%s", ANV_TIMESTAMP);
-}
-
void anv_GetPhysicalDeviceProperties(
VkPhysicalDevice physicalDevice,
VkPhysicalDeviceProperties* pProperties)
.maxVertexInputAttributeOffset = 2047,
.maxVertexInputBindingStride = 2048,
.maxVertexOutputComponents = 128,
- .maxTessellationGenerationLevel = 0,
- .maxTessellationPatchSize = 0,
- .maxTessellationControlPerVertexInputComponents = 0,
- .maxTessellationControlPerVertexOutputComponents = 0,
- .maxTessellationControlPerPatchOutputComponents = 0,
- .maxTessellationControlTotalOutputComponents = 0,
- .maxTessellationEvaluationInputComponents = 0,
- .maxTessellationEvaluationOutputComponents = 0,
+ .maxTessellationGenerationLevel = 64,
+ .maxTessellationPatchSize = 32,
+ .maxTessellationControlPerVertexInputComponents = 128,
+ .maxTessellationControlPerVertexOutputComponents = 128,
+ .maxTessellationControlPerPatchOutputComponents = 128,
+ .maxTessellationControlTotalOutputComponents = 2048,
+ .maxTessellationEvaluationInputComponents = 128,
+ .maxTessellationEvaluationOutputComponents = 128,
.maxGeometryShaderInvocations = 32,
.maxGeometryInputComponents = 64,
.maxGeometryOutputComponents = 128,
.maxGeometryTotalOutputComponents = 1024,
.maxFragmentInputComponents = 128,
.maxFragmentOutputAttachments = 8,
- .maxFragmentDualSrcAttachments = 2,
+ .maxFragmentDualSrcAttachments = 1,
.maxFragmentCombinedOutputResources = 8,
.maxComputeSharedMemorySize = 32768,
.maxComputeWorkGroupCount = { 65535, 65535, 65535 },
.viewportSubPixelBits = 13, /* We take a float? */
.minMemoryMapAlignment = 4096, /* A page */
.minTexelBufferOffsetAlignment = 1,
- .minUniformBufferOffsetAlignment = 1,
- .minStorageBufferOffsetAlignment = 1,
+ .minUniformBufferOffsetAlignment = 16,
+ .minStorageBufferOffsetAlignment = 4,
.minTexelOffset = -8,
.maxTexelOffset = 7,
- .minTexelGatherOffset = -8,
- .maxTexelGatherOffset = 7,
+ .minTexelGatherOffset = -32,
+ .maxTexelGatherOffset = 31,
.minInterpolationOffset = -0.5,
.maxInterpolationOffset = 0.4375,
.subPixelInterpolationOffsetBits = 4,
.maxFramebufferWidth = (1 << 14),
.maxFramebufferHeight = (1 << 14),
- .maxFramebufferLayers = (1 << 10),
+ .maxFramebufferLayers = (1 << 11),
.framebufferColorSampleCounts = sample_counts,
.framebufferDepthSampleCounts = sample_counts,
.framebufferStencilSampleCounts = sample_counts,
.maxSampleMaskWords = 1,
.timestampComputeAndGraphics = false,
.timestampPeriod = time_stamp_base,
- .maxClipDistances = 0 /* FIXME */,
- .maxCullDistances = 0 /* FIXME */,
- .maxCombinedClipAndCullDistances = 0 /* FIXME */,
+ .maxClipDistances = 8,
+ .maxCullDistances = 8,
+ .maxCombinedClipAndCullDistances = 8,
.discreteQueuePriorities = 1,
.pointSizeRange = { 0.125, 255.875 },
.lineWidthRange = { 0.0, 7.9921875 },
};
strcpy(pProperties->deviceName, pdevice->name);
- anv_device_get_cache_uuid(pProperties->pipelineCacheUUID);
+ memcpy(pProperties->pipelineCacheUUID, pdevice->uuid, VK_UUID_SIZE);
+}
+
+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 },
+ };
}
void anv_GetPhysicalDeviceQueueFamilyProperties(
uint32_t* pCount,
VkQueueFamilyProperties* pQueueFamilyProperties)
{
+ ANV_FROM_HANDLE(anv_physical_device, phys_dev, physicalDevice);
+
if (pQueueFamilyProperties == NULL) {
*pCount = 1;
return;
}
- assert(*pCount >= 1);
+ /* 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;
- *pQueueFamilyProperties = (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 },
- };
+ *pCount = 1;
+ anv_get_queue_family_properties(phys_dev, pQueueFamilyProperties);
}
void anv_GetPhysicalDeviceMemoryProperties(
return anv_lookup_entrypoint(&device->info, pName);
}
-static VkResult
+static void
anv_queue_init(struct anv_device *device, struct anv_queue *queue)
{
queue->_loader_data.loaderMagic = ICD_LOADER_MAGIC;
queue->device = device;
queue->pool = &device->surface_state_pool;
-
- return VK_SUCCESS;
}
static void
anv_state_pool_init(&device->dynamic_state_pool,
&device->dynamic_state_block_pool);
- anv_block_pool_init(&device->instruction_block_pool, device, 128 * 1024);
+ anv_block_pool_init(&device->instruction_block_pool, device, 1024 * 1024);
anv_state_pool_init(&device->instruction_state_pool,
&device->instruction_block_pool);
{
ANV_FROM_HANDLE(anv_device, device, _device);
- anv_queue_finish(&device->queue);
-
anv_device_finish_blorp(device);
+ anv_queue_finish(&device->queue);
+
#ifdef HAVE_VALGRIND
/* We only need to free these to prevent valgrind errors. The backing
* BO will go away in a couple of lines so we don't actually leak.
anv_state_pool_free(&device->dynamic_state_pool, device->border_colors);
#endif
+ 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);
- anv_bo_pool_finish(&device->batch_bo_pool);
- anv_state_pool_finish(&device->dynamic_state_pool);
- anv_block_pool_finish(&device->dynamic_state_block_pool);
- anv_state_pool_finish(&device->instruction_state_pool);
- anv_block_pool_finish(&device->instruction_block_pool);
anv_state_pool_finish(&device->surface_state_pool);
anv_block_pool_finish(&device->surface_state_block_pool);
- anv_scratch_pool_finish(device, &device->scratch_pool);
+ anv_state_pool_finish(&device->instruction_state_pool);
+ anv_block_pool_finish(&device->instruction_block_pool);
+ anv_state_pool_finish(&device->dynamic_state_pool);
+ anv_block_pool_finish(&device->dynamic_state_block_pool);
- close(device->fd);
+ anv_bo_pool_finish(&device->batch_bo_pool);
+ pthread_cond_destroy(&device->queue_submit);
pthread_mutex_destroy(&device->mutex);
+ anv_gem_destroy_context(device, device->context_id);
+
+ close(device->fd);
+
vk_free(&device->alloc, device);
}
return VK_SUCCESS;
}
- assert(*pPropertyCount >= ARRAY_SIZE(global_extensions));
+ *pPropertyCount = MIN2(*pPropertyCount, ARRAY_SIZE(global_extensions));
+ typed_memcpy(pProperties, global_extensions, *pPropertyCount);
- *pPropertyCount = ARRAY_SIZE(global_extensions);
- memcpy(pProperties, global_extensions, sizeof(global_extensions));
+ if (*pPropertyCount < ARRAY_SIZE(global_extensions))
+ return VK_INCOMPLETE;
return VK_SUCCESS;
}
return VK_SUCCESS;
}
- assert(*pPropertyCount >= ARRAY_SIZE(device_extensions));
+ *pPropertyCount = MIN2(*pPropertyCount, ARRAY_SIZE(device_extensions));
+ typed_memcpy(pProperties, device_extensions, *pPropertyCount);
- *pPropertyCount = ARRAY_SIZE(device_extensions);
- memcpy(pProperties, device_extensions, sizeof(device_extensions));
+ if (*pPropertyCount < ARRAY_SIZE(device_extensions))
+ return VK_INCOMPLETE;
return VK_SUCCESS;
}
assert(pAllocateInfo->sType == VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO);
- if (pAllocateInfo->allocationSize == 0) {
- /* Apparently, this is allowed */
- *pMem = VK_NULL_HANDLE;
- return VK_SUCCESS;
- }
+ /* The Vulkan 1.0.33 spec says "allocationSize must be greater than 0". */
+ assert(pAllocateInfo->allocationSize > 0);
/* We support exactly one memory heap. */
assert(pAllocateInfo->memoryTypeIndex == 0 ||
fence->execbuf.rsvd1 = device->context_id;
fence->execbuf.rsvd2 = 0;
- fence->state = ANV_FENCE_STATE_RESET;
+ if (pCreateInfo->flags & VK_FENCE_CREATE_SIGNALED_BIT) {
+ fence->state = ANV_FENCE_STATE_SIGNALED;
+ } else {
+ fence->state = ANV_FENCE_STATE_RESET;
+ }
*pFence = anv_fence_to_handle(fence);
ANV_FROM_HANDLE(anv_device, device, _device);
ANV_FROM_HANDLE(anv_fence, fence, _fence);
+ if (!fence)
+ return;
+
assert(fence->bo.map == fence);
anv_bo_pool_free(&device->batch_bo_pool, &fence->bo);
}
ANV_FROM_HANDLE(anv_device, device, _device);
ANV_FROM_HANDLE(anv_event, event, _event);
+ if (!event)
+ return;
+
anv_state_pool_free(&device->dynamic_state_pool, event->state);
}
ANV_FROM_HANDLE(anv_device, device, _device);
ANV_FROM_HANDLE(anv_buffer, buffer, _buffer);
+ if (!buffer)
+ return;
+
vk_free2(&device->alloc, pAllocator, buffer);
}
ANV_FROM_HANDLE(anv_device, device, _device);
ANV_FROM_HANDLE(anv_sampler, sampler, _sampler);
+ if (!sampler)
+ return;
+
vk_free2(&device->alloc, pAllocator, sampler);
}
ANV_FROM_HANDLE(anv_device, device, _device);
ANV_FROM_HANDLE(anv_framebuffer, fb, _fb);
+ if (!fb)
+ return;
+
vk_free2(&device->alloc, pAllocator, fb);
}
+
+/* vk_icd.h does not declare this function, so we declare it here to
+ * suppress Wmissing-prototypes.
+ */
+PUBLIC VKAPI_ATTR VkResult VKAPI_CALL
+vk_icdNegotiateLoaderICDInterfaceVersion(uint32_t* pSupportedVersion);
+
+PUBLIC VKAPI_ATTR VkResult VKAPI_CALL
+vk_icdNegotiateLoaderICDInterfaceVersion(uint32_t* pSupportedVersion)
+{
+ /* For the full details on loader interface versioning, see
+ * <https://github.com/KhronosGroup/Vulkan-LoaderAndValidationLayers/blob/master/loader/LoaderAndLayerInterface.md>.
+ * What follows is a condensed summary, to help you navigate the large and
+ * confusing official doc.
+ *
+ * - Loader interface v0 is incompatible with later versions. We don't
+ * support it.
+ *
+ * - In loader interface v1:
+ * - The first ICD entrypoint called by the loader is
+ * vk_icdGetInstanceProcAddr(). The ICD must statically expose this
+ * entrypoint.
+ * - The ICD must statically expose no other Vulkan symbol unless it is
+ * linked with -Bsymbolic.
+ * - Each dispatchable Vulkan handle created by the ICD must be
+ * a pointer to a struct whose first member is VK_LOADER_DATA. The
+ * ICD must initialize VK_LOADER_DATA.loadMagic to ICD_LOADER_MAGIC.
+ * - The loader implements vkCreate{PLATFORM}SurfaceKHR() and
+ * vkDestroySurfaceKHR(). The ICD must be capable of working with
+ * such loader-managed surfaces.
+ *
+ * - Loader interface v2 differs from v1 in:
+ * - The first ICD entrypoint called by the loader is
+ * vk_icdNegotiateLoaderICDInterfaceVersion(). The ICD must
+ * statically expose this entrypoint.
+ *
+ * - Loader interface v3 differs from v2 in:
+ * - The ICD must implement vkCreate{PLATFORM}SurfaceKHR(),
+ * vkDestroySurfaceKHR(), and other API which uses VKSurfaceKHR,
+ * because the loader no longer does so.
+ */
+ *pSupportedVersion = MIN2(*pSupportedVersion, 3u);
+ return VK_SUCCESS;
+}