summaryrefslogtreecommitdiff
path: root/lib/mesa/src/vulkan/util
diff options
context:
space:
mode:
authorJonathan Gray <jsg@cvs.openbsd.org>2021-07-22 10:17:30 +0000
committerJonathan Gray <jsg@cvs.openbsd.org>2021-07-22 10:17:30 +0000
commitca11beabae33eb59fb981b8adf50b1d47a2a98f0 (patch)
tree3e4691a396e6e54cd54224a190663d5cf976625b /lib/mesa/src/vulkan/util
parent27c8a50e8bbde7d28b1fc46d715a4c469e24f2c4 (diff)
Import Mesa 21.1.5
Diffstat (limited to 'lib/mesa/src/vulkan/util')
-rw-r--r--lib/mesa/src/vulkan/util/meson.build104
-rw-r--r--lib/mesa/src/vulkan/util/vk_cmd_copy.c285
-rw-r--r--lib/mesa/src/vulkan/util/vk_debug_report.c138
-rw-r--r--lib/mesa/src/vulkan/util/vk_debug_report.h46
-rw-r--r--lib/mesa/src/vulkan/util/vk_deferred_operation.c85
-rw-r--r--lib/mesa/src/vulkan/util/vk_deferred_operation.h47
-rw-r--r--lib/mesa/src/vulkan/util/vk_descriptors.c56
-rw-r--r--lib/mesa/src/vulkan/util/vk_descriptors.h44
-rw-r--r--lib/mesa/src/vulkan/util/vk_device.c221
-rw-r--r--lib/mesa/src/vulkan/util/vk_device.h73
-rw-r--r--lib/mesa/src/vulkan/util/vk_dispatch_table_gen.py929
-rw-r--r--lib/mesa/src/vulkan/util/vk_entrypoints_gen.py258
-rw-r--r--lib/mesa/src/vulkan/util/vk_extensions.py214
-rw-r--r--lib/mesa/src/vulkan/util/vk_extensions_gen.py254
-rw-r--r--lib/mesa/src/vulkan/util/vk_format.c99
-rw-r--r--lib/mesa/src/vulkan/util/vk_format.h31
-rw-r--r--lib/mesa/src/vulkan/util/vk_icd_gen.py78
-rw-r--r--lib/mesa/src/vulkan/util/vk_instance.c230
-rw-r--r--lib/mesa/src/vulkan/util/vk_instance.h97
-rw-r--r--lib/mesa/src/vulkan/util/vk_object.c325
-rw-r--r--lib/mesa/src/vulkan/util/vk_object.h177
-rw-r--r--lib/mesa/src/vulkan/util/vk_physical_device.c193
-rw-r--r--lib/mesa/src/vulkan/util/vk_physical_device.h59
-rw-r--r--lib/mesa/src/vulkan/util/vk_render_pass.c291
-rw-r--r--lib/mesa/src/vulkan/util/vk_shader_module.c77
-rw-r--r--lib/mesa/src/vulkan/util/vk_shader_module.h63
26 files changed, 4373 insertions, 101 deletions
diff --git a/lib/mesa/src/vulkan/util/meson.build b/lib/mesa/src/vulkan/util/meson.build
index f4f7d1730..1a3723990 100644
--- a/lib/mesa/src/vulkan/util/meson.build
+++ b/lib/mesa/src/vulkan/util/meson.build
@@ -18,15 +18,74 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
+# Mesa-local imports in the Python files must be declared here for correct
+# dependency tracking.
+vk_extensions_depend_files = [
+]
+vk_extensions_gen_depend_files = [
+ files('vk_extensions.py'),
+ vk_extensions_depend_files,
+]
+vk_dispatch_table_gen_depend_files = [
+ files('vk_extensions.py'),
+ vk_extensions_depend_files,
+]
+vk_entrypoints_gen_depend_files = [
+ files('vk_dispatch_table_gen.py'),
+ vk_dispatch_table_gen_depend_files,
+]
+
+vk_entrypoints_gen = files('vk_entrypoints_gen.py')
+vk_extensions_gen = files('vk_extensions_gen.py')
+vk_icd_gen = files('vk_icd_gen.py')
+
files_vulkan_util = files(
'vk_alloc.h',
+ 'vk_cmd_copy.c',
'vk_debug_report.c',
'vk_debug_report.h',
+ 'vk_deferred_operation.c',
+ 'vk_deferred_operation.h',
+ 'vk_descriptors.c',
+ 'vk_descriptors.h',
+ 'vk_device.c',
+ 'vk_device.h',
'vk_format.c',
+ 'vk_instance.c',
+ 'vk_instance.h',
+ 'vk_object.c',
+ 'vk_object.h',
+ 'vk_physical_device.c',
+ 'vk_physical_device.h',
+ 'vk_render_pass.c',
+ 'vk_shader_module.c',
+ 'vk_shader_module.h',
'vk_util.c',
'vk_util.h',
)
+vk_common_entrypoints = custom_target(
+ 'vk_common_entrypoints',
+ input : [vk_entrypoints_gen, vk_api_xml],
+ output : ['vk_common_entrypoints.h', 'vk_common_entrypoints.c'],
+ command : [
+ prog_python, '@INPUT0@', '--xml', '@INPUT1@', '--proto', '--weak',
+ '--out-h', '@OUTPUT0@', '--out-c', '@OUTPUT1@', '--prefix', 'vk_common',
+ ],
+ depend_files : vk_entrypoints_gen_depend_files,
+)
+
+vk_dispatch_table = custom_target(
+ 'vk_dispatch_table',
+ input : ['vk_dispatch_table_gen.py', vk_api_xml],
+ output : ['vk_dispatch_table.c', 'vk_dispatch_table.h'],
+ command : [
+ prog_python, '@INPUT0@', '--xml', '@INPUT1@',
+ '--out-c', '@OUTPUT0@', '--out-h', '@OUTPUT1@'
+ ],
+ depend_files : vk_dispatch_table_gen_depend_files,
+)
+
vk_enum_to_str = custom_target(
'vk_enum_to_str',
input : ['gen_enum_to_str.py', vk_api_xml],
@@ -37,21 +96,48 @@ vk_enum_to_str = custom_target(
],
)
+vk_extensions = custom_target(
+ 'vk_extensions',
+ input : ['vk_extensions_gen.py', vk_api_xml],
+ output : ['vk_extensions.c', 'vk_extensions.h'],
+ command : [
+ prog_python, '@INPUT0@', '--xml', '@INPUT1@',
+ '--out-c', '@OUTPUT0@', '--out-h', '@OUTPUT1@'
+ ],
+ depend_files : vk_extensions_gen_depend_files,
+)
+
libvulkan_util = static_library(
'vulkan_util',
- [files_vulkan_util, vk_enum_to_str],
- include_directories : inc_common,
- dependencies : vulkan_wsi_deps,
- c_args : [c_vis_args, vulkan_wsi_args],
+ [files_vulkan_util, vk_common_entrypoints, vk_dispatch_table,
+ vk_enum_to_str, vk_extensions],
+ include_directories : [inc_include, inc_src, inc_gallium],
+ dependencies : [vulkan_wsi_deps, idep_mesautil],
+ # For glsl_type_singleton
+ link_with : libcompiler,
+ c_args : [vulkan_wsi_args],
+ gnu_symbol_visibility : 'hidden',
build_by_default : false,
)
idep_vulkan_util_headers = declare_dependency(
- sources : vk_enum_to_str[1],
+ sources : [vk_dispatch_table[1], vk_enum_to_str[1], vk_extensions[1]],
include_directories : include_directories('.')
)
-idep_vulkan_util = declare_dependency(
- link_with : libvulkan_util,
- dependencies : idep_vulkan_util_headers
-)
+# This is likely a bug in the Meson VS backend, as MSVC with ninja works fine.
+# See this discussion here:
+# https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/10506
+if get_option('backend').startswith('vs')
+ idep_vulkan_util = declare_dependency(
+ link_with : libvulkan_util,
+ dependencies : idep_vulkan_util_headers
+ )
+else
+ idep_vulkan_util = declare_dependency(
+ # Instruct users of this library to link with --whole-archive. Otherwise,
+ # our weak function overloads may not resolve properly.
+ link_whole : libvulkan_util,
+ dependencies : idep_vulkan_util_headers
+ )
+endif
diff --git a/lib/mesa/src/vulkan/util/vk_cmd_copy.c b/lib/mesa/src/vulkan/util/vk_cmd_copy.c
new file mode 100644
index 000000000..5c71dbb38
--- /dev/null
+++ b/lib/mesa/src/vulkan/util/vk_cmd_copy.c
@@ -0,0 +1,285 @@
+/*
+ * Copyright © 2021 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include "vk_common_entrypoints.h"
+#include "vk_device.h"
+
+#define STACK_ARRAY_SIZE 8
+
+#define STACK_ARRAY(type, name, size) \
+ type _stack_##name[STACK_ARRAY_SIZE], *const name = \
+ (size) <= STACK_ARRAY_SIZE ? _stack_##name : malloc((size) * sizeof(type))
+
+#define STACK_ARRAY_FINISH(name) \
+ if (name != _stack_##name) free(name)
+
+VKAPI_ATTR void VKAPI_CALL
+vk_common_CmdCopyBuffer(VkCommandBuffer commandBuffer,
+ VkBuffer srcBuffer,
+ VkBuffer dstBuffer,
+ uint32_t regionCount,
+ const VkBufferCopy *pRegions)
+{
+ /* We don't have a vk_command_buffer object but we can assume, since we're
+ * using common dispatch, that it's a vk_object of some sort.
+ */
+ struct vk_object_base *disp = (struct vk_object_base *)commandBuffer;
+
+ STACK_ARRAY(VkBufferCopy2KHR, region2s, regionCount);
+
+ for (uint32_t r = 0; r < regionCount; r++) {
+ region2s[r] = (VkBufferCopy2KHR) {
+ .sType = VK_STRUCTURE_TYPE_BUFFER_COPY_2_KHR,
+ .srcOffset = pRegions[r].srcOffset,
+ .dstOffset = pRegions[r].dstOffset,
+ .size = pRegions[r].size,
+ };
+ }
+
+ VkCopyBufferInfo2KHR info = {
+ .sType = VK_STRUCTURE_TYPE_COPY_BUFFER_INFO_2_KHR,
+ .srcBuffer = srcBuffer,
+ .dstBuffer = dstBuffer,
+ .regionCount = regionCount,
+ .pRegions = region2s,
+ };
+
+ disp->device->dispatch_table.CmdCopyBuffer2KHR(commandBuffer, &info);
+
+ STACK_ARRAY_FINISH(region2s);
+}
+
+VKAPI_ATTR void VKAPI_CALL
+vk_common_CmdCopyImage(VkCommandBuffer commandBuffer,
+ VkImage srcImage,
+ VkImageLayout srcImageLayout,
+ VkImage dstImage,
+ VkImageLayout dstImageLayout,
+ uint32_t regionCount,
+ const VkImageCopy *pRegions)
+{
+ /* We don't have a vk_command_buffer object but we can assume, since we're
+ * using common dispatch, that it's a vk_object of some sort.
+ */
+ struct vk_object_base *disp = (struct vk_object_base *)commandBuffer;
+
+ STACK_ARRAY(VkImageCopy2KHR, region2s, regionCount);
+
+ for (uint32_t r = 0; r < regionCount; r++) {
+ region2s[r] = (VkImageCopy2KHR) {
+ .sType = VK_STRUCTURE_TYPE_IMAGE_COPY_2_KHR,
+ .srcSubresource = pRegions[r].srcSubresource,
+ .srcOffset = pRegions[r].srcOffset,
+ .dstSubresource = pRegions[r].dstSubresource,
+ .dstOffset = pRegions[r].dstOffset,
+ .extent = pRegions[r].extent,
+ };
+ }
+
+ VkCopyImageInfo2KHR info = {
+ .sType = VK_STRUCTURE_TYPE_COPY_IMAGE_INFO_2_KHR,
+ .srcImage = srcImage,
+ .srcImageLayout = srcImageLayout,
+ .dstImage = dstImage,
+ .dstImageLayout = dstImageLayout,
+ .regionCount = regionCount,
+ .pRegions = region2s,
+ };
+
+ disp->device->dispatch_table.CmdCopyImage2KHR(commandBuffer, &info);
+
+ STACK_ARRAY_FINISH(region2s);
+}
+
+VKAPI_ATTR void VKAPI_CALL
+vk_common_CmdCopyBufferToImage(VkCommandBuffer commandBuffer,
+ VkBuffer srcBuffer,
+ VkImage dstImage,
+ VkImageLayout dstImageLayout,
+ uint32_t regionCount,
+ const VkBufferImageCopy *pRegions)
+{
+ /* We don't have a vk_command_buffer object but we can assume, since we're
+ * using common dispatch, that it's a vk_object of some sort.
+ */
+ struct vk_object_base *disp = (struct vk_object_base *)commandBuffer;
+
+ STACK_ARRAY(VkBufferImageCopy2KHR, region2s, regionCount);
+
+ for (uint32_t r = 0; r < regionCount; r++) {
+ region2s[r] = (VkBufferImageCopy2KHR) {
+ .sType = VK_STRUCTURE_TYPE_BUFFER_IMAGE_COPY_2_KHR,
+ .bufferOffset = pRegions[r].bufferOffset,
+ .bufferRowLength = pRegions[r].bufferRowLength,
+ .bufferImageHeight = pRegions[r].bufferImageHeight,
+ .imageSubresource = pRegions[r].imageSubresource,
+ .imageOffset = pRegions[r].imageOffset,
+ .imageExtent = pRegions[r].imageExtent,
+ };
+ }
+
+ VkCopyBufferToImageInfo2KHR info = {
+ .sType = VK_STRUCTURE_TYPE_COPY_BUFFER_TO_IMAGE_INFO_2_KHR,
+ .srcBuffer = srcBuffer,
+ .dstImage = dstImage,
+ .dstImageLayout = dstImageLayout,
+ .regionCount = regionCount,
+ .pRegions = region2s,
+ };
+
+ disp->device->dispatch_table.CmdCopyBufferToImage2KHR(commandBuffer, &info);
+
+ STACK_ARRAY_FINISH(region2s);
+}
+
+VKAPI_ATTR void VKAPI_CALL
+vk_common_CmdCopyImageToBuffer(VkCommandBuffer commandBuffer,
+ VkImage srcImage,
+ VkImageLayout srcImageLayout,
+ VkBuffer dstBuffer,
+ uint32_t regionCount,
+ const VkBufferImageCopy *pRegions)
+{
+ /* We don't have a vk_command_buffer object but we can assume, since we're
+ * using common dispatch, that it's a vk_object of some sort.
+ */
+ struct vk_object_base *disp = (struct vk_object_base *)commandBuffer;
+
+ STACK_ARRAY(VkBufferImageCopy2KHR, region2s, regionCount);
+
+ for (uint32_t r = 0; r < regionCount; r++) {
+ region2s[r] = (VkBufferImageCopy2KHR) {
+ .sType = VK_STRUCTURE_TYPE_BUFFER_IMAGE_COPY_2_KHR,
+ .bufferOffset = pRegions[r].bufferOffset,
+ .bufferRowLength = pRegions[r].bufferRowLength,
+ .bufferImageHeight = pRegions[r].bufferImageHeight,
+ .imageSubresource = pRegions[r].imageSubresource,
+ .imageOffset = pRegions[r].imageOffset,
+ .imageExtent = pRegions[r].imageExtent,
+ };
+ }
+
+ VkCopyImageToBufferInfo2KHR info = {
+ .sType = VK_STRUCTURE_TYPE_COPY_IMAGE_TO_BUFFER_INFO_2_KHR,
+ .srcImage = srcImage,
+ .srcImageLayout = srcImageLayout,
+ .dstBuffer = dstBuffer,
+ .regionCount = regionCount,
+ .pRegions = region2s,
+ };
+
+ disp->device->dispatch_table.CmdCopyImageToBuffer2KHR(commandBuffer, &info);
+
+ STACK_ARRAY_FINISH(region2s);
+}
+
+VKAPI_ATTR void VKAPI_CALL
+vk_common_CmdBlitImage(VkCommandBuffer commandBuffer,
+ VkImage srcImage,
+ VkImageLayout srcImageLayout,
+ VkImage dstImage,
+ VkImageLayout dstImageLayout,
+ uint32_t regionCount,
+ const VkImageBlit *pRegions,
+ VkFilter filter)
+{
+ /* We don't have a vk_command_buffer object but we can assume, since we're
+ * using common dispatch, that it's a vk_object of some sort.
+ */
+ struct vk_object_base *disp = (struct vk_object_base *)commandBuffer;
+
+ STACK_ARRAY(VkImageBlit2KHR, region2s, regionCount);
+
+ for (uint32_t r = 0; r < regionCount; r++) {
+ region2s[r] = (VkImageBlit2KHR) {
+ .sType = VK_STRUCTURE_TYPE_IMAGE_BLIT_2_KHR,
+ .srcSubresource = pRegions[r].srcSubresource,
+ .srcOffsets = {
+ pRegions[r].srcOffsets[0],
+ pRegions[r].srcOffsets[1],
+ },
+ .dstSubresource = pRegions[r].dstSubresource,
+ .dstOffsets = {
+ pRegions[r].dstOffsets[0],
+ pRegions[r].dstOffsets[1],
+ },
+ };
+ }
+
+ VkBlitImageInfo2KHR info = {
+ .sType = VK_STRUCTURE_TYPE_BLIT_IMAGE_INFO_2_KHR,
+ .srcImage = srcImage,
+ .srcImageLayout = srcImageLayout,
+ .dstImage = dstImage,
+ .dstImageLayout = dstImageLayout,
+ .regionCount = regionCount,
+ .pRegions = region2s,
+ .filter = filter,
+ };
+
+ disp->device->dispatch_table.CmdBlitImage2KHR(commandBuffer, &info);
+
+ STACK_ARRAY_FINISH(region2s);
+}
+
+VKAPI_ATTR void VKAPI_CALL
+vk_common_CmdResolveImage(VkCommandBuffer commandBuffer,
+ VkImage srcImage,
+ VkImageLayout srcImageLayout,
+ VkImage dstImage,
+ VkImageLayout dstImageLayout,
+ uint32_t regionCount,
+ const VkImageResolve *pRegions)
+{
+ /* We don't have a vk_command_buffer object but we can assume, since we're
+ * using common dispatch, that it's a vk_object of some sort.
+ */
+ struct vk_object_base *disp = (struct vk_object_base *)commandBuffer;
+
+ STACK_ARRAY(VkImageResolve2KHR, region2s, regionCount);
+
+ for (uint32_t r = 0; r < regionCount; r++) {
+ region2s[r] = (VkImageResolve2KHR) {
+ .sType = VK_STRUCTURE_TYPE_IMAGE_RESOLVE_2_KHR,
+ .srcSubresource = pRegions[r].srcSubresource,
+ .srcOffset = pRegions[r].srcOffset,
+ .dstSubresource = pRegions[r].dstSubresource,
+ .dstOffset = pRegions[r].dstOffset,
+ .extent = pRegions[r].extent,
+ };
+ }
+
+ VkResolveImageInfo2KHR info = {
+ .sType = VK_STRUCTURE_TYPE_RESOLVE_IMAGE_INFO_2_KHR,
+ .srcImage = srcImage,
+ .srcImageLayout = srcImageLayout,
+ .dstImage = dstImage,
+ .dstImageLayout = dstImageLayout,
+ .regionCount = regionCount,
+ .pRegions = region2s,
+ };
+
+ disp->device->dispatch_table.CmdResolveImage2KHR(commandBuffer, &info);
+
+ STACK_ARRAY_FINISH(region2s);
+}
diff --git a/lib/mesa/src/vulkan/util/vk_debug_report.c b/lib/mesa/src/vulkan/util/vk_debug_report.c
index 78dcfa6e2..db89e3d6f 100644
--- a/lib/mesa/src/vulkan/util/vk_debug_report.c
+++ b/lib/mesa/src/vulkan/util/vk_debug_report.c
@@ -24,88 +24,90 @@
#include "vk_debug_report.h"
#include "vk_alloc.h"
+#include "vk_common_entrypoints.h"
+#include "vk_instance.h"
#include "vk_util.h"
-VkResult vk_debug_report_instance_init(struct vk_debug_report_instance *instance)
-{
- if (pthread_mutex_init(&instance->callbacks_mutex, NULL) != 0) {
- return VK_ERROR_INITIALIZATION_FAILED;
- }
-
- list_inithead(&instance->callbacks);
-
- return VK_SUCCESS;
-}
-
-void vk_debug_report_instance_destroy(struct vk_debug_report_instance *instance)
-{
- pthread_mutex_destroy(&instance->callbacks_mutex);
-}
-
-VkResult
-vk_create_debug_report_callback(struct vk_debug_report_instance *instance,
- const VkDebugReportCallbackCreateInfoEXT* pCreateInfo,
- const VkAllocationCallbacks* pAllocator,
- const VkAllocationCallbacks* instance_allocator,
- VkDebugReportCallbackEXT* pCallback)
+struct vk_debug_report_callback {
+ struct vk_object_base base;
+
+ /* Link in the 'callbacks' list in anv_instance struct. */
+ struct list_head link;
+ VkDebugReportFlagsEXT flags;
+ PFN_vkDebugReportCallbackEXT callback;
+ void * data;
+};
+
+VK_DEFINE_NONDISP_HANDLE_CASTS(vk_debug_report_callback, base,
+ VkDebugReportCallbackEXT,
+ VK_OBJECT_TYPE_DEBUG_REPORT_CALLBACK_EXT)
+
+VKAPI_ATTR VkResult VKAPI_CALL
+vk_common_CreateDebugReportCallbackEXT(VkInstance _instance,
+ const VkDebugReportCallbackCreateInfoEXT *pCreateInfo,
+ const VkAllocationCallbacks *pAllocator,
+ VkDebugReportCallbackEXT *pCallback)
{
+ VK_FROM_HANDLE(vk_instance, instance, _instance);
struct vk_debug_report_callback *cb =
- vk_alloc2(instance_allocator, pAllocator,
+ vk_alloc2(&instance->alloc, pAllocator,
sizeof(struct vk_debug_report_callback), 8,
VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
if (!cb)
return VK_ERROR_OUT_OF_HOST_MEMORY;
+ vk_object_base_init(NULL, &cb->base,
+ VK_OBJECT_TYPE_DEBUG_REPORT_CALLBACK_EXT);
+
cb->flags = pCreateInfo->flags;
cb->callback = pCreateInfo->pfnCallback;
cb->data = pCreateInfo->pUserData;
- pthread_mutex_lock(&instance->callbacks_mutex);
- list_addtail(&cb->link, &instance->callbacks);
- pthread_mutex_unlock(&instance->callbacks_mutex);
+ mtx_lock(&instance->debug_report.callbacks_mutex);
+ list_addtail(&cb->link, &instance->debug_report.callbacks);
+ mtx_unlock(&instance->debug_report.callbacks_mutex);
- *pCallback = (VkDebugReportCallbackEXT)(uintptr_t)cb;
+ *pCallback = vk_debug_report_callback_to_handle(cb);
return VK_SUCCESS;
}
-void
-vk_destroy_debug_report_callback(struct vk_debug_report_instance *instance,
- VkDebugReportCallbackEXT _callback,
- const VkAllocationCallbacks* pAllocator,
- const VkAllocationCallbacks* instance_allocator)
+VKAPI_ATTR void VKAPI_CALL
+vk_common_DestroyDebugReportCallbackEXT(VkInstance _instance,
+ VkDebugReportCallbackEXT _callback,
+ const VkAllocationCallbacks *pAllocator)
{
- if (_callback == VK_NULL_HANDLE)
- return;
+ VK_FROM_HANDLE(vk_instance, instance, _instance);
+ VK_FROM_HANDLE(vk_debug_report_callback, callback, _callback);
- struct vk_debug_report_callback *callback =
- (struct vk_debug_report_callback *)(uintptr_t)_callback;
+ if (callback == NULL)
+ return;
/* Remove from list and destroy given callback. */
- pthread_mutex_lock(&instance->callbacks_mutex);
+ mtx_lock(&instance->debug_report.callbacks_mutex);
list_del(&callback->link);
- vk_free2(instance_allocator, pAllocator, callback);
- pthread_mutex_unlock(&instance->callbacks_mutex);
+ vk_object_base_finish(&callback->base);
+ vk_free2(&instance->alloc, pAllocator, callback);
+ mtx_unlock(&instance->debug_report.callbacks_mutex);
}
-
-void
-vk_debug_report(struct vk_debug_report_instance *instance,
- VkDebugReportFlagsEXT flags,
- VkDebugReportObjectTypeEXT object_type,
- uint64_t handle,
- size_t location,
- int32_t messageCode,
- const char* pLayerPrefix,
- const char *pMessage)
+static void
+debug_report(struct vk_instance *instance,
+ VkDebugReportFlagsEXT flags,
+ VkDebugReportObjectTypeEXT object_type,
+ uint64_t handle,
+ size_t location,
+ int32_t messageCode,
+ const char* pLayerPrefix,
+ const char *pMessage)
{
/* Allow NULL for convinience, return if no callbacks registered. */
- if (!instance || list_is_empty(&instance->callbacks))
+ if (!instance || list_is_empty(&instance->debug_report.callbacks))
return;
- pthread_mutex_lock(&instance->callbacks_mutex);
+ mtx_lock(&instance->debug_report.callbacks_mutex);
/* Section 33.2 of the Vulkan 1.0.59 spec says:
*
@@ -115,11 +117,41 @@ vk_debug_report(struct vk_debug_report_instance *instance,
* is active."
*/
list_for_each_entry(struct vk_debug_report_callback, cb,
- &instance->callbacks, link) {
+ &instance->debug_report.callbacks, link) {
if (cb->flags & flags)
cb->callback(flags, object_type, handle, location, messageCode,
pLayerPrefix, pMessage, cb->data);
}
- pthread_mutex_unlock(&instance->callbacks_mutex);
+ mtx_unlock(&instance->debug_report.callbacks_mutex);
+}
+
+VKAPI_ATTR void VKAPI_CALL
+vk_common_DebugReportMessageEXT(VkInstance _instance,
+ VkDebugReportFlagsEXT flags,
+ VkDebugReportObjectTypeEXT objectType,
+ uint64_t object,
+ size_t location,
+ int32_t messageCode,
+ const char* pLayerPrefix,
+ const char* pMessage)
+{
+ VK_FROM_HANDLE(vk_instance, instance, _instance);
+ debug_report(instance, flags, objectType,
+ object, location, messageCode, pLayerPrefix, pMessage);
+}
+
+void
+vk_debug_report(struct vk_instance *instance,
+ VkDebugReportFlagsEXT flags,
+ const struct vk_object_base *object,
+ size_t location,
+ int32_t messageCode,
+ const char* pLayerPrefix,
+ const char *pMessage)
+{
+ VkDebugReportObjectTypeEXT object_type =
+ object ? object->type : VK_OBJECT_TYPE_UNKNOWN;
+ debug_report(instance, flags, object_type, (uint64_t)(uintptr_t)object,
+ location, messageCode, pLayerPrefix, pMessage);
}
diff --git a/lib/mesa/src/vulkan/util/vk_debug_report.h b/lib/mesa/src/vulkan/util/vk_debug_report.h
index 625ecbb69..ca208bb5f 100644
--- a/lib/mesa/src/vulkan/util/vk_debug_report.h
+++ b/lib/mesa/src/vulkan/util/vk_debug_report.h
@@ -26,47 +26,23 @@
#ifndef VK_DEBUG_REPORT_H
#define VK_DEBUG_REPORT_H
-#include <pthread.h>
+#include "vk_instance.h"
-#include "util/list.h"
-#include <vulkan/vulkan.h>
-
-struct vk_debug_report_callback {
- /* Link in the 'callbacks' list in anv_instance struct. */
- struct list_head link;
- VkDebugReportFlagsEXT flags;
- PFN_vkDebugReportCallbackEXT callback;
- void * data;
-};
-
-struct vk_debug_report_instance {
- /* VK_EXT_debug_report debug callbacks */
- pthread_mutex_t callbacks_mutex;
- struct list_head callbacks;
-};
-
-VkResult vk_debug_report_instance_init(struct vk_debug_report_instance *instance);
-void vk_debug_report_instance_destroy(struct vk_debug_report_instance *instance);
-
-VkResult
-vk_create_debug_report_callback(struct vk_debug_report_instance *instance,
- const VkDebugReportCallbackCreateInfoEXT* pCreateInfo,
- const VkAllocationCallbacks* pAllocator,
- const VkAllocationCallbacks* instance_allocator,
- VkDebugReportCallbackEXT* pCallback);
-void
-vk_destroy_debug_report_callback(struct vk_debug_report_instance *instance,
- VkDebugReportCallbackEXT _callback,
- const VkAllocationCallbacks* pAllocator,
- const VkAllocationCallbacks* instance_allocator);
+#ifdef __cplusplus
+extern "C" {
+#endif
void
-vk_debug_report(struct vk_debug_report_instance *instance,
+vk_debug_report(struct vk_instance *instance,
VkDebugReportFlagsEXT flags,
- VkDebugReportObjectTypeEXT object_type,
- uint64_t handle,
+ const struct vk_object_base *object,
size_t location,
int32_t messageCode,
const char* pLayerPrefix,
const char *pMessage);
+
+#ifdef __cplusplus
+}
#endif
+
+#endif /* VK_DEBUG_REPORT_H */
diff --git a/lib/mesa/src/vulkan/util/vk_deferred_operation.c b/lib/mesa/src/vulkan/util/vk_deferred_operation.c
new file mode 100644
index 000000000..a9f6e0d26
--- /dev/null
+++ b/lib/mesa/src/vulkan/util/vk_deferred_operation.c
@@ -0,0 +1,85 @@
+/*
+ * Copyright © 2020 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include "vk_deferred_operation.h"
+
+#include "vk_alloc.h"
+#include "vk_common_entrypoints.h"
+#include "vk_device.h"
+
+VKAPI_ATTR VkResult VKAPI_CALL
+vk_common_CreateDeferredOperationKHR(VkDevice _device,
+ const VkAllocationCallbacks *pAllocator,
+ VkDeferredOperationKHR *pDeferredOperation)
+{
+ VK_FROM_HANDLE(vk_device, device, _device);
+
+ struct vk_deferred_operation *op =
+ vk_alloc2(&device->alloc, pAllocator, sizeof(*op), 8,
+ VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
+ if (op == NULL)
+ return VK_ERROR_OUT_OF_HOST_MEMORY;
+
+ vk_object_base_init(device, &op->base,
+ VK_OBJECT_TYPE_DEFERRED_OPERATION_KHR);
+
+ *pDeferredOperation = vk_deferred_operation_to_handle(op);
+
+ return VK_SUCCESS;
+}
+
+VKAPI_ATTR void VKAPI_CALL
+vk_common_DestroyDeferredOperationKHR(VkDevice _device,
+ VkDeferredOperationKHR operation,
+ const VkAllocationCallbacks *pAllocator)
+{
+ VK_FROM_HANDLE(vk_device, device, _device);
+ VK_FROM_HANDLE(vk_deferred_operation, op, operation);
+
+ if (op == NULL)
+ return;
+
+ vk_object_base_finish(&op->base);
+ vk_free2(&device->alloc, pAllocator, op);
+}
+
+VKAPI_ATTR uint32_t VKAPI_CALL
+vk_common_GetDeferredOperationMaxConcurrencyKHR(UNUSED VkDevice device,
+ UNUSED VkDeferredOperationKHR operation)
+{
+ return 1;
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL
+vk_common_GetDeferredOperationResultKHR(UNUSED VkDevice device,
+ UNUSED VkDeferredOperationKHR operation)
+{
+ return VK_SUCCESS;
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL
+vk_common_DeferredOperationJoinKHR(UNUSED VkDevice device,
+ UNUSED VkDeferredOperationKHR operation)
+{
+ return VK_SUCCESS;
+}
diff --git a/lib/mesa/src/vulkan/util/vk_deferred_operation.h b/lib/mesa/src/vulkan/util/vk_deferred_operation.h
new file mode 100644
index 000000000..588db8085
--- /dev/null
+++ b/lib/mesa/src/vulkan/util/vk_deferred_operation.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright © 2020 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+#ifndef VK_DEFERRED_OPERATION_H
+#define VK_DEFERRED_OPERATION_H
+
+#include "vk_object.h"
+
+#include "c11/threads.h"
+#include "util/list.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct vk_deferred_operation {
+ struct vk_object_base base;
+};
+
+VK_DEFINE_NONDISP_HANDLE_CASTS(vk_deferred_operation, base,
+ VkDeferredOperationKHR,
+ VK_OBJECT_TYPE_DEFERRED_OPERATION_KHR)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* VK_DEFERRED_OPERATION_H */
diff --git a/lib/mesa/src/vulkan/util/vk_descriptors.c b/lib/mesa/src/vulkan/util/vk_descriptors.c
new file mode 100644
index 000000000..7aee7e821
--- /dev/null
+++ b/lib/mesa/src/vulkan/util/vk_descriptors.c
@@ -0,0 +1,56 @@
+/*
+ * Copyright © 2016 Red Hat.
+ * Copyright © 2016 Bas Nieuwenhuizen
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include "vk_descriptors.h"
+#include "util/macros.h"
+
+static int
+binding_compare(const void* av, const void *bv)
+{
+ const VkDescriptorSetLayoutBinding *a = (const VkDescriptorSetLayoutBinding*)av;
+ const VkDescriptorSetLayoutBinding *b = (const VkDescriptorSetLayoutBinding*)bv;
+
+ return (a->binding < b->binding) ? -1 : (a->binding > b->binding) ? 1 : 0;
+}
+
+VkResult
+vk_create_sorted_bindings(const VkDescriptorSetLayoutBinding *bindings, unsigned count,
+ VkDescriptorSetLayoutBinding **sorted_bindings)
+{
+ if (!count) {
+ *sorted_bindings = NULL;
+ return VK_SUCCESS;
+ }
+
+ *sorted_bindings = malloc(count * sizeof(VkDescriptorSetLayoutBinding));
+ if (!*sorted_bindings)
+ return VK_ERROR_OUT_OF_HOST_MEMORY;
+
+ memcpy(*sorted_bindings, bindings, count * sizeof(VkDescriptorSetLayoutBinding));
+ qsort(*sorted_bindings, count, sizeof(VkDescriptorSetLayoutBinding), binding_compare);
+
+ return VK_SUCCESS;
+}
diff --git a/lib/mesa/src/vulkan/util/vk_descriptors.h b/lib/mesa/src/vulkan/util/vk_descriptors.h
new file mode 100644
index 000000000..a37eae8a7
--- /dev/null
+++ b/lib/mesa/src/vulkan/util/vk_descriptors.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright © 2016 Red Hat.
+ * Copyright © 2016 Bas Nieuwenhuizen
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#ifndef VK_DESCRIPTORS_H
+#define VK_DESCRIPTORS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <vulkan/vulkan.h>
+
+VkResult
+vk_create_sorted_bindings(const VkDescriptorSetLayoutBinding *bindings, unsigned count,
+ VkDescriptorSetLayoutBinding **sorted_bindings);
+
+#ifdef __cplusplus
+}
+#endif
+
+
+
+#endif
diff --git a/lib/mesa/src/vulkan/util/vk_device.c b/lib/mesa/src/vulkan/util/vk_device.c
new file mode 100644
index 000000000..cfaebc58d
--- /dev/null
+++ b/lib/mesa/src/vulkan/util/vk_device.c
@@ -0,0 +1,221 @@
+/*
+ * Copyright © 2020 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include "vk_device.h"
+
+#include "vk_common_entrypoints.h"
+#include "vk_instance.h"
+#include "vk_physical_device.h"
+#include "util/hash_table.h"
+#include "util/ralloc.h"
+
+VkResult
+vk_device_init(struct vk_device *device,
+ struct vk_physical_device *physical_device,
+ const struct vk_device_dispatch_table *dispatch_table,
+ const VkDeviceCreateInfo *pCreateInfo,
+ const VkAllocationCallbacks *alloc)
+{
+ memset(device, 0, sizeof(*device));
+ vk_object_base_init(device, &device->base, VK_OBJECT_TYPE_DEVICE);
+ if (alloc != NULL)
+ device->alloc = *alloc;
+ else
+ device->alloc = physical_device->instance->alloc;
+
+ device->physical = physical_device;
+
+ device->dispatch_table = *dispatch_table;
+
+ /* Add common entrypoints without overwriting driver-provided ones. */
+ vk_device_dispatch_table_from_entrypoints(
+ &device->dispatch_table, &vk_common_device_entrypoints, false);
+
+ for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
+ int idx;
+ for (idx = 0; idx < VK_DEVICE_EXTENSION_COUNT; idx++) {
+ if (strcmp(pCreateInfo->ppEnabledExtensionNames[i],
+ vk_device_extensions[idx].extensionName) == 0)
+ break;
+ }
+
+ if (idx >= VK_DEVICE_EXTENSION_COUNT)
+ return VK_ERROR_EXTENSION_NOT_PRESENT;
+
+ if (!physical_device->supported_extensions.extensions[idx])
+ return VK_ERROR_EXTENSION_NOT_PRESENT;
+
+#ifdef ANDROID
+ if (!vk_android_allowed_device_extensions.extensions[idx])
+ return VK_ERROR_EXTENSION_NOT_PRESENT;
+#endif
+
+ device->enabled_extensions.extensions[idx] = true;
+ }
+
+ p_atomic_set(&device->private_data_next_index, 0);
+
+#ifdef ANDROID
+ mtx_init(&device->swapchain_private_mtx, mtx_plain);
+ device->swapchain_private = NULL;
+#endif /* ANDROID */
+
+ return VK_SUCCESS;
+}
+
+void
+vk_device_finish(UNUSED struct vk_device *device)
+{
+#ifdef ANDROID
+ if (device->swapchain_private) {
+ hash_table_foreach(device->swapchain_private, entry)
+ util_sparse_array_finish(entry->data);
+ ralloc_free(device->swapchain_private);
+ }
+#endif /* ANDROID */
+
+ vk_object_base_finish(&device->base);
+}
+
+PFN_vkVoidFunction
+vk_device_get_proc_addr(const struct vk_device *device,
+ const char *name)
+{
+ if (device == NULL || name == NULL)
+ return NULL;
+
+ struct vk_instance *instance = device->physical->instance;
+ return vk_device_dispatch_table_get_if_supported(&device->dispatch_table,
+ name,
+ instance->app_info.api_version,
+ &instance->enabled_extensions,
+ &device->enabled_extensions);
+}
+
+VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL
+vk_common_GetDeviceProcAddr(VkDevice _device,
+ const char *pName)
+{
+ VK_FROM_HANDLE(vk_device, device, _device);
+ return vk_device_get_proc_addr(device, pName);
+}
+
+VKAPI_ATTR void VKAPI_CALL
+vk_common_GetDeviceQueue(VkDevice _device,
+ uint32_t queueFamilyIndex,
+ uint32_t queueIndex,
+ VkQueue *pQueue)
+{
+ VK_FROM_HANDLE(vk_device, device, _device);
+
+ const VkDeviceQueueInfo2 info = {
+ .sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_INFO_2,
+ .pNext = NULL,
+ /* flags = 0 because (Vulkan spec 1.2.170 - vkGetDeviceQueue):
+ *
+ * "vkGetDeviceQueue must only be used to get queues that were
+ * created with the flags parameter of VkDeviceQueueCreateInfo set
+ * to zero. To get queues that were created with a non-zero flags
+ * parameter use vkGetDeviceQueue2."
+ */
+ .flags = 0,
+ .queueFamilyIndex = queueFamilyIndex,
+ .queueIndex = queueIndex,
+ };
+
+ device->dispatch_table.GetDeviceQueue2(_device, &info, pQueue);
+}
+
+VKAPI_ATTR void VKAPI_CALL
+vk_common_GetBufferMemoryRequirements(VkDevice _device,
+ VkBuffer buffer,
+ VkMemoryRequirements *pMemoryRequirements)
+{
+ VK_FROM_HANDLE(vk_device, device, _device);
+
+ VkBufferMemoryRequirementsInfo2 info = {
+ .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2,
+ .buffer = buffer,
+ };
+ VkMemoryRequirements2 reqs = {
+ .sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2,
+ };
+ device->dispatch_table.GetBufferMemoryRequirements2(_device, &info, &reqs);
+
+ *pMemoryRequirements = reqs.memoryRequirements;
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL
+vk_common_BindBufferMemory(VkDevice _device,
+ VkBuffer buffer,
+ VkDeviceMemory memory,
+ VkDeviceSize memoryOffset)
+{
+ VK_FROM_HANDLE(vk_device, device, _device);
+
+ VkBindBufferMemoryInfo bind = {
+ .sType = VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_INFO,
+ .buffer = buffer,
+ .memory = memory,
+ .memoryOffset = memoryOffset,
+ };
+
+ return device->dispatch_table.BindBufferMemory2(_device, 1, &bind);
+}
+
+VKAPI_ATTR void VKAPI_CALL
+vk_common_GetImageMemoryRequirements(VkDevice _device,
+ VkImage image,
+ VkMemoryRequirements *pMemoryRequirements)
+{
+ VK_FROM_HANDLE(vk_device, device, _device);
+
+ VkImageMemoryRequirementsInfo2 info = {
+ .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2,
+ .image = image,
+ };
+ VkMemoryRequirements2 reqs = {
+ .sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2,
+ };
+ device->dispatch_table.GetImageMemoryRequirements2(_device, &info, &reqs);
+
+ *pMemoryRequirements = reqs.memoryRequirements;
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL
+vk_common_BindImageMemory(VkDevice _device,
+ VkImage image,
+ VkDeviceMemory memory,
+ VkDeviceSize memoryOffset)
+{
+ VK_FROM_HANDLE(vk_device, device, _device);
+
+ VkBindImageMemoryInfo bind = {
+ .sType = VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO,
+ .image = image,
+ .memory = memory,
+ .memoryOffset = memoryOffset,
+ };
+
+ return device->dispatch_table.BindImageMemory2(_device, 1, &bind);
+}
diff --git a/lib/mesa/src/vulkan/util/vk_device.h b/lib/mesa/src/vulkan/util/vk_device.h
new file mode 100644
index 000000000..e31688475
--- /dev/null
+++ b/lib/mesa/src/vulkan/util/vk_device.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright © 2020 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+#ifndef VK_DEVICE_H
+#define VK_DEVICE_H
+
+#include "vk_dispatch_table.h"
+#include "vk_extensions.h"
+#include "vk_object.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct vk_device {
+ struct vk_object_base base;
+ VkAllocationCallbacks alloc;
+ struct vk_physical_device *physical;
+
+ struct vk_device_extension_table enabled_extensions;
+
+ struct vk_device_dispatch_table dispatch_table;
+
+ /* For VK_EXT_private_data */
+ uint32_t private_data_next_index;
+
+#ifdef ANDROID
+ mtx_t swapchain_private_mtx;
+ struct hash_table *swapchain_private;
+#endif
+};
+
+VK_DEFINE_HANDLE_CASTS(vk_device, base, VkDevice,
+ VK_OBJECT_TYPE_DEVICE)
+
+VkResult MUST_CHECK
+vk_device_init(struct vk_device *device,
+ struct vk_physical_device *physical_device,
+ const struct vk_device_dispatch_table *dispatch_table,
+ const VkDeviceCreateInfo *pCreateInfo,
+ const VkAllocationCallbacks *alloc);
+
+void
+vk_device_finish(struct vk_device *device);
+
+PFN_vkVoidFunction
+vk_device_get_proc_addr(const struct vk_device *device,
+ const char *name);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* VK_DEVICE_H */
diff --git a/lib/mesa/src/vulkan/util/vk_dispatch_table_gen.py b/lib/mesa/src/vulkan/util/vk_dispatch_table_gen.py
new file mode 100644
index 000000000..7b566ba0f
--- /dev/null
+++ b/lib/mesa/src/vulkan/util/vk_dispatch_table_gen.py
@@ -0,0 +1,929 @@
+# coding=utf-8
+COPYRIGHT = """\
+/*
+ * Copyright 2020 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+"""
+
+import argparse
+import math
+import os
+import xml.etree.ElementTree as et
+
+from collections import OrderedDict, namedtuple
+from mako.template import Template
+
+# Mesa-local imports must be declared in meson variable
+# '{file_without_suffix}_depend_files'.
+from vk_extensions import *
+
+# We generate a static hash table for entry point lookup
+# (vkGetProcAddress). We use a linear congruential generator for our hash
+# function and a power-of-two size table. The prime numbers are determined
+# experimentally.
+
+TEMPLATE_H = Template(COPYRIGHT + """\
+/* This file generated from ${filename}, don't edit directly. */
+
+#ifndef VK_DISPATCH_TABLE_H
+#define VK_DISPATCH_TABLE_H
+
+#include "vulkan/vulkan.h"
+#include "vulkan/vk_android_native_buffer.h"
+
+#include "vk_extensions.h"
+
+/* Windows api conflict */
+#ifdef _WIN32
+#ifdef CreateSemaphore
+#undef CreateSemaphore
+#endif
+#ifdef CreateEvent
+#undef CreateEvent
+#endif
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+<%def name="dispatch_table(type, entrypoints)">
+struct vk_${type}_dispatch_table {
+% for e in entrypoints:
+ % if e.alias:
+ <% continue %>
+ % endif
+ % if e.guard is not None:
+#ifdef ${e.guard}
+ % endif
+ % if e.aliases:
+ union {
+ PFN_vk${e.name} ${e.name};
+ % for a in e.aliases:
+ PFN_vk${a.name} ${a.name};
+ % endfor
+ };
+ % else:
+ PFN_vk${e.name} ${e.name};
+ % endif
+ % if e.guard is not None:
+#else
+ % if e.aliases:
+ union {
+ PFN_vkVoidFunction ${e.name};
+ % for a in e.aliases:
+ PFN_vkVoidFunction ${a.name};
+ % endfor
+ };
+ % else:
+ PFN_vkVoidFunction ${e.name};
+ % endif
+#endif
+ % endif
+% endfor
+};
+
+struct vk_${type}_entrypoint_table {
+% for e in entrypoints:
+ % if e.guard is not None:
+#ifdef ${e.guard}
+ % endif
+ PFN_vk${e.name} ${e.name};
+ % if e.guard is not None:
+#else
+ PFN_vkVoidFunction ${e.name};
+# endif
+ % endif
+% endfor
+};
+</%def>
+
+${dispatch_table('instance', instance_entrypoints)}
+${dispatch_table('physical_device', physical_device_entrypoints)}
+${dispatch_table('device', device_entrypoints)}
+
+void
+vk_instance_dispatch_table_load(struct vk_instance_dispatch_table *table,
+ PFN_vkGetInstanceProcAddr gpa,
+ VkInstance instance);
+void
+vk_physical_device_dispatch_table_load(struct vk_physical_device_dispatch_table *table,
+ PFN_vkGetInstanceProcAddr gpa,
+ VkInstance instance);
+void
+vk_device_dispatch_table_load(struct vk_device_dispatch_table *table,
+ PFN_vkGetDeviceProcAddr gpa,
+ VkDevice device);
+
+void vk_instance_dispatch_table_from_entrypoints(
+ struct vk_instance_dispatch_table *dispatch_table,
+ const struct vk_instance_entrypoint_table *entrypoint_table,
+ bool overwrite);
+
+void vk_physical_device_dispatch_table_from_entrypoints(
+ struct vk_physical_device_dispatch_table *dispatch_table,
+ const struct vk_physical_device_entrypoint_table *entrypoint_table,
+ bool overwrite);
+
+void vk_device_dispatch_table_from_entrypoints(
+ struct vk_device_dispatch_table *dispatch_table,
+ const struct vk_device_entrypoint_table *entrypoint_table,
+ bool overwrite);
+
+PFN_vkVoidFunction
+vk_instance_dispatch_table_get(const struct vk_instance_dispatch_table *table,
+ const char *name);
+
+PFN_vkVoidFunction
+vk_physical_device_dispatch_table_get(const struct vk_physical_device_dispatch_table *table,
+ const char *name);
+
+PFN_vkVoidFunction
+vk_device_dispatch_table_get(const struct vk_device_dispatch_table *table,
+ const char *name);
+
+PFN_vkVoidFunction
+vk_instance_dispatch_table_get_if_supported(
+ const struct vk_instance_dispatch_table *table,
+ const char *name,
+ uint32_t core_version,
+ const struct vk_instance_extension_table *instance_exts);
+
+PFN_vkVoidFunction
+vk_physical_device_dispatch_table_get_if_supported(
+ const struct vk_physical_device_dispatch_table *table,
+ const char *name,
+ uint32_t core_version,
+ const struct vk_instance_extension_table *instance_exts);
+
+PFN_vkVoidFunction
+vk_device_dispatch_table_get_if_supported(
+ const struct vk_device_dispatch_table *table,
+ const char *name,
+ uint32_t core_version,
+ const struct vk_instance_extension_table *instance_exts,
+ const struct vk_device_extension_table *device_exts);
+
+extern struct vk_physical_device_dispatch_table vk_physical_device_trampolines;
+extern struct vk_device_dispatch_table vk_device_trampolines;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* VK_DISPATCH_TABLE_H */
+""", output_encoding='utf-8')
+
+TEMPLATE_C = Template(COPYRIGHT + """\
+/* This file generated from ${filename}, don't edit directly. */
+
+#include "vk_device.h"
+#include "vk_dispatch_table.h"
+#include "vk_instance.h"
+#include "vk_object.h"
+#include "vk_physical_device.h"
+
+#include "util/macros.h"
+#include "string.h"
+
+<%def name="load_dispatch_table(type, VkType, ProcAddr, entrypoints)">
+void
+vk_${type}_dispatch_table_load(struct vk_${type}_dispatch_table *table,
+ PFN_vk${ProcAddr} gpa,
+ ${VkType} obj)
+{
+% if type != 'physical_device':
+ table->${ProcAddr} = gpa;
+% endif
+% for e in entrypoints:
+ % if e.alias or e.name == '${ProcAddr}':
+ <% continue %>
+ % endif
+ % if e.guard is not None:
+#ifdef ${e.guard}
+ % endif
+ table->${e.name} = (PFN_vk${e.name}) gpa(obj, "vk${e.name}");
+ % for a in e.aliases:
+ if (table->${e.name} == NULL) {
+ table->${e.name} = (PFN_vk${e.name}) gpa(obj, "vk${a.name}");
+ }
+ % endfor
+ % if e.guard is not None:
+#endif
+ % endif
+% endfor
+}
+</%def>
+
+${load_dispatch_table('instance', 'VkInstance', 'GetInstanceProcAddr',
+ instance_entrypoints)}
+
+${load_dispatch_table('physical_device', 'VkInstance', 'GetInstanceProcAddr',
+ physical_device_entrypoints)}
+
+${load_dispatch_table('device', 'VkDevice', 'GetDeviceProcAddr',
+ device_entrypoints)}
+
+
+struct string_map_entry {
+ uint32_t name;
+ uint32_t hash;
+ uint32_t num;
+};
+
+/* We use a big string constant to avoid lots of reloctions from the entry
+ * point table to lots of little strings. The entries in the entry point table
+ * store the index into this big string.
+ */
+
+<%def name="strmap(strmap, prefix)">
+static const char ${prefix}_strings[] =
+% for s in strmap.sorted_strings:
+ "${s.string}\\0"
+% endfor
+;
+
+static const struct string_map_entry ${prefix}_string_map_entries[] = {
+% for s in strmap.sorted_strings:
+ { ${s.offset}, ${'{:0=#8x}'.format(s.hash)}, ${s.num} }, /* ${s.string} */
+% endfor
+};
+
+/* Hash table stats:
+ * size ${len(strmap.sorted_strings)} entries
+ * collisions entries:
+% for i in range(10):
+ * ${i}${'+' if i == 9 else ' '} ${strmap.collisions[i]}
+% endfor
+ */
+
+#define none 0xffff
+static const uint16_t ${prefix}_string_map[${strmap.hash_size}] = {
+% for e in strmap.mapping:
+ ${ '{:0=#6x}'.format(e) if e >= 0 else 'none' },
+% endfor
+};
+
+static int
+${prefix}_string_map_lookup(const char *str)
+{
+ static const uint32_t prime_factor = ${strmap.prime_factor};
+ static const uint32_t prime_step = ${strmap.prime_step};
+ const struct string_map_entry *e;
+ uint32_t hash, h;
+ uint16_t i;
+ const char *p;
+
+ hash = 0;
+ for (p = str; *p; p++)
+ hash = hash * prime_factor + *p;
+
+ h = hash;
+ while (1) {
+ i = ${prefix}_string_map[h & ${strmap.hash_mask}];
+ if (i == none)
+ return -1;
+ e = &${prefix}_string_map_entries[i];
+ if (e->hash == hash && strcmp(str, ${prefix}_strings + e->name) == 0)
+ return e->num;
+ h += prime_step;
+ }
+
+ return -1;
+}
+</%def>
+
+${strmap(instance_strmap, 'instance')}
+${strmap(physical_device_strmap, 'physical_device')}
+${strmap(device_strmap, 'device')}
+
+<% assert len(instance_entrypoints) < 2**8 %>
+static const uint8_t instance_compaction_table[] = {
+% for e in instance_entrypoints:
+ ${e.disp_table_index},
+% endfor
+};
+
+<% assert len(physical_device_entrypoints) < 2**8 %>
+static const uint8_t physical_device_compaction_table[] = {
+% for e in physical_device_entrypoints:
+ ${e.disp_table_index},
+% endfor
+};
+
+<% assert len(device_entrypoints) < 2**16 %>
+static const uint16_t device_compaction_table[] = {
+% for e in device_entrypoints:
+ ${e.disp_table_index},
+% endfor
+};
+
+static bool
+vk_instance_entrypoint_is_enabled(int index, uint32_t core_version,
+ const struct vk_instance_extension_table *instance)
+{
+ switch (index) {
+% for e in instance_entrypoints:
+ case ${e.entry_table_index}:
+ /* ${e.name} */
+ % if e.core_version:
+ return ${e.core_version.c_vk_version()} <= core_version;
+ % elif e.extensions:
+ % for ext in e.extensions:
+ % if ext.type == 'instance':
+ if (instance->${ext.name[3:]}) return true;
+ % else:
+ /* All device extensions are considered enabled at the instance level */
+ return true;
+ % endif
+ % endfor
+ return false;
+ % else:
+ return true;
+ % endif
+% endfor
+ default:
+ return false;
+ }
+}
+
+/** Return true if the core version or extension in which the given entrypoint
+ * is defined is enabled.
+ *
+ * If device is NULL, all device extensions are considered enabled.
+ */
+static bool
+vk_physical_device_entrypoint_is_enabled(int index, uint32_t core_version,
+ const struct vk_instance_extension_table *instance)
+{
+ switch (index) {
+% for e in physical_device_entrypoints:
+ case ${e.entry_table_index}:
+ /* ${e.name} */
+ % if e.core_version:
+ return ${e.core_version.c_vk_version()} <= core_version;
+ % elif e.extensions:
+ % for ext in e.extensions:
+ % if ext.type == 'instance':
+ if (instance->${ext.name[3:]}) return true;
+ % else:
+ /* All device extensions are considered enabled at the instance level */
+ return true;
+ % endif
+ % endfor
+ return false;
+ % else:
+ return true;
+ % endif
+% endfor
+ default:
+ return false;
+ }
+}
+
+/** Return true if the core version or extension in which the given entrypoint
+ * is defined is enabled.
+ *
+ * If device is NULL, all device extensions are considered enabled.
+ */
+static bool
+vk_device_entrypoint_is_enabled(int index, uint32_t core_version,
+ const struct vk_instance_extension_table *instance,
+ const struct vk_device_extension_table *device)
+{
+ switch (index) {
+% for e in device_entrypoints:
+ case ${e.entry_table_index}:
+ /* ${e.name} */
+ % if e.core_version:
+ return ${e.core_version.c_vk_version()} <= core_version;
+ % elif e.extensions:
+ % for ext in e.extensions:
+ % if ext.type == 'instance':
+ if (instance->${ext.name[3:]}) return true;
+ % else:
+ if (!device || device->${ext.name[3:]}) return true;
+ % endif
+ % endfor
+ return false;
+ % else:
+ return true;
+ % endif
+% endfor
+ default:
+ return false;
+ }
+}
+
+<%def name="dispatch_table_from_entrypoints(type)">
+void vk_${type}_dispatch_table_from_entrypoints(
+ struct vk_${type}_dispatch_table *dispatch_table,
+ const struct vk_${type}_entrypoint_table *entrypoint_table,
+ bool overwrite)
+{
+ PFN_vkVoidFunction *disp = (PFN_vkVoidFunction *)dispatch_table;
+ PFN_vkVoidFunction *entry = (PFN_vkVoidFunction *)entrypoint_table;
+
+ if (overwrite) {
+ memset(dispatch_table, 0, sizeof(*dispatch_table));
+ for (unsigned i = 0; i < ARRAY_SIZE(${type}_compaction_table); i++) {
+#ifdef _MSC_VER
+ const uintptr_t zero = 0;
+ if (entry[i] == NULL || memcmp(entry[i], &zero, sizeof(zero)) == 0)
+#else
+ if (entry[i] == NULL)
+#endif
+ continue;
+ unsigned disp_index = ${type}_compaction_table[i];
+ assert(disp[disp_index] == NULL);
+ disp[disp_index] = entry[i];
+ }
+ } else {
+ for (unsigned i = 0; i < ARRAY_SIZE(${type}_compaction_table); i++) {
+ unsigned disp_index = ${type}_compaction_table[i];
+ if (disp[disp_index] == NULL)
+ disp[disp_index] = entry[i];
+ }
+ }
+}
+</%def>
+
+${dispatch_table_from_entrypoints('instance')}
+${dispatch_table_from_entrypoints('physical_device')}
+${dispatch_table_from_entrypoints('device')}
+
+<%def name="lookup_funcs(type)">
+static PFN_vkVoidFunction
+vk_${type}_dispatch_table_get_for_entry_index(
+ const struct vk_${type}_dispatch_table *table, int entry_index)
+{
+ assert(entry_index < ARRAY_SIZE(${type}_compaction_table));
+ int disp_index = ${type}_compaction_table[entry_index];
+ return ((PFN_vkVoidFunction *)table)[disp_index];
+}
+
+PFN_vkVoidFunction
+vk_${type}_dispatch_table_get(
+ const struct vk_${type}_dispatch_table *table, const char *name)
+{
+ int entry_index = ${type}_string_map_lookup(name);
+ if (entry_index < 0)
+ return NULL;
+
+ return vk_${type}_dispatch_table_get_for_entry_index(table, entry_index);
+}
+</%def>
+
+${lookup_funcs('instance')}
+${lookup_funcs('physical_device')}
+${lookup_funcs('device')}
+
+PFN_vkVoidFunction
+vk_instance_dispatch_table_get_if_supported(
+ const struct vk_instance_dispatch_table *table,
+ const char *name,
+ uint32_t core_version,
+ const struct vk_instance_extension_table *instance_exts)
+{
+ int entry_index = instance_string_map_lookup(name);
+ if (entry_index < 0)
+ return NULL;
+
+ if (!vk_instance_entrypoint_is_enabled(entry_index, core_version,
+ instance_exts))
+ return NULL;
+
+ return vk_instance_dispatch_table_get_for_entry_index(table, entry_index);
+}
+
+PFN_vkVoidFunction
+vk_physical_device_dispatch_table_get_if_supported(
+ const struct vk_physical_device_dispatch_table *table,
+ const char *name,
+ uint32_t core_version,
+ const struct vk_instance_extension_table *instance_exts)
+{
+ int entry_index = physical_device_string_map_lookup(name);
+ if (entry_index < 0)
+ return NULL;
+
+ if (!vk_physical_device_entrypoint_is_enabled(entry_index, core_version,
+ instance_exts))
+ return NULL;
+
+ return vk_physical_device_dispatch_table_get_for_entry_index(table, entry_index);
+}
+
+PFN_vkVoidFunction
+vk_device_dispatch_table_get_if_supported(
+ const struct vk_device_dispatch_table *table,
+ const char *name,
+ uint32_t core_version,
+ const struct vk_instance_extension_table *instance_exts,
+ const struct vk_device_extension_table *device_exts)
+{
+ int entry_index = device_string_map_lookup(name);
+ if (entry_index < 0)
+ return NULL;
+
+ if (!vk_device_entrypoint_is_enabled(entry_index, core_version,
+ instance_exts, device_exts))
+ return NULL;
+
+ return vk_device_dispatch_table_get_for_entry_index(table, entry_index);
+}
+
+% for e in physical_device_entrypoints:
+ % if e.alias:
+ <% continue %>
+ % endif
+ % if e.guard is not None:
+#ifdef ${e.guard}
+ % endif
+static VKAPI_ATTR ${e.return_type} VKAPI_CALL
+${e.prefixed_name('vk_tramp')}(${e.decl_params()})
+{
+ <% assert e.params[0].type == 'VkPhysicalDevice' %>
+ VK_FROM_HANDLE(vk_physical_device, vk_physical_device, ${e.params[0].name});
+ % if e.return_type == 'void':
+ vk_physical_device->dispatch_table.${e.name}(${e.call_params()});
+ % else:
+ return vk_physical_device->dispatch_table.${e.name}(${e.call_params()});
+ % endif
+}
+ % if e.guard is not None:
+#endif
+ % endif
+% endfor
+
+struct vk_physical_device_dispatch_table vk_physical_device_trampolines = {
+% for e in physical_device_entrypoints:
+ % if e.alias:
+ <% continue %>
+ % endif
+ % if e.guard is not None:
+#ifdef ${e.guard}
+ % endif
+ .${e.name} = ${e.prefixed_name('vk_tramp')},
+ % if e.guard is not None:
+#endif
+ % endif
+% endfor
+};
+
+% for e in device_entrypoints:
+ % if e.alias:
+ <% continue %>
+ % endif
+ % if e.guard is not None:
+#ifdef ${e.guard}
+ % endif
+static VKAPI_ATTR ${e.return_type} VKAPI_CALL
+${e.prefixed_name('vk_tramp')}(${e.decl_params()})
+{
+ % if e.params[0].type == 'VkDevice':
+ VK_FROM_HANDLE(vk_device, vk_device, ${e.params[0].name});
+ % if e.return_type == 'void':
+ vk_device->dispatch_table.${e.name}(${e.call_params()});
+ % else:
+ return vk_device->dispatch_table.${e.name}(${e.call_params()});
+ % endif
+ % elif e.params[0].type in ('VkCommandBuffer', 'VkQueue'):
+ struct vk_object_base *vk_object = (struct vk_object_base *)${e.params[0].name};
+ % if e.return_type == 'void':
+ vk_object->device->dispatch_table.${e.name}(${e.call_params()});
+ % else:
+ return vk_object->device->dispatch_table.${e.name}(${e.call_params()});
+ % endif
+ % else:
+ assert(!"Unhandled device child trampoline case: ${e.params[0].type}");
+ % endif
+}
+ % if e.guard is not None:
+#endif
+ % endif
+% endfor
+
+struct vk_device_dispatch_table vk_device_trampolines = {
+% for e in device_entrypoints:
+ % if e.alias:
+ <% continue %>
+ % endif
+ % if e.guard is not None:
+#ifdef ${e.guard}
+ % endif
+ .${e.name} = ${e.prefixed_name('vk_tramp')},
+ % if e.guard is not None:
+#endif
+ % endif
+% endfor
+};
+""", output_encoding='utf-8')
+
+U32_MASK = 2**32 - 1
+
+PRIME_FACTOR = 5024183
+PRIME_STEP = 19
+
+class StringIntMapEntry(object):
+ def __init__(self, string, num):
+ self.string = string
+ self.num = num
+
+ # Calculate the same hash value that we will calculate in C.
+ h = 0
+ for c in string:
+ h = ((h * PRIME_FACTOR) + ord(c)) & U32_MASK
+ self.hash = h
+
+ self.offset = None
+
+def round_to_pow2(x):
+ return 2**int(math.ceil(math.log(x, 2)))
+
+class StringIntMap(object):
+ def __init__(self):
+ self.baked = False
+ self.strings = dict()
+
+ def add_string(self, string, num):
+ assert not self.baked
+ assert string not in self.strings
+ assert 0 <= num < 2**31
+ self.strings[string] = StringIntMapEntry(string, num)
+
+ def bake(self):
+ self.sorted_strings = \
+ sorted(self.strings.values(), key=lambda x: x.string)
+ offset = 0
+ for entry in self.sorted_strings:
+ entry.offset = offset
+ offset += len(entry.string) + 1
+
+ # Save off some values that we'll need in C
+ self.hash_size = round_to_pow2(len(self.strings) * 1.25)
+ self.hash_mask = self.hash_size - 1
+ self.prime_factor = PRIME_FACTOR
+ self.prime_step = PRIME_STEP
+
+ self.mapping = [-1] * self.hash_size
+ self.collisions = [0] * 10
+ for idx, s in enumerate(self.sorted_strings):
+ level = 0
+ h = s.hash
+ while self.mapping[h & self.hash_mask] >= 0:
+ h = h + PRIME_STEP
+ level = level + 1
+ self.collisions[min(level, 9)] += 1
+ self.mapping[h & self.hash_mask] = idx
+
+EntrypointParam = namedtuple('EntrypointParam', 'type name decl')
+
+class EntrypointBase(object):
+ def __init__(self, name):
+ assert name.startswith('vk')
+ self.name = name[2:]
+ self.alias = None
+ self.guard = None
+ self.entry_table_index = None
+ # Extensions which require this entrypoint
+ self.core_version = None
+ self.extensions = []
+
+ def prefixed_name(self, prefix):
+ return prefix + '_' + self.name
+
+class Entrypoint(EntrypointBase):
+ def __init__(self, name, return_type, params, guard=None):
+ super(Entrypoint, self).__init__(name)
+ self.return_type = return_type
+ self.params = params
+ self.guard = guard
+ self.aliases = []
+ self.disp_table_index = None
+
+ def is_physical_device_entrypoint(self):
+ return self.params[0].type in ('VkPhysicalDevice', )
+
+ def is_device_entrypoint(self):
+ return self.params[0].type in ('VkDevice', 'VkCommandBuffer', 'VkQueue')
+
+ def decl_params(self):
+ return ', '.join(p.decl for p in self.params)
+
+ def call_params(self):
+ return ', '.join(p.name for p in self.params)
+
+class EntrypointAlias(EntrypointBase):
+ def __init__(self, name, entrypoint):
+ super(EntrypointAlias, self).__init__(name)
+ self.alias = entrypoint
+ entrypoint.aliases.append(self)
+
+ def is_physical_device_entrypoint(self):
+ return self.alias.is_physical_device_entrypoint()
+
+ def is_device_entrypoint(self):
+ return self.alias.is_device_entrypoint()
+
+ def prefixed_name(self, prefix):
+ return self.alias.prefixed_name(prefix)
+
+ @property
+ def params(self):
+ return self.alias.params
+
+ @property
+ def return_type(self):
+ return self.alias.return_type
+
+ @property
+ def disp_table_index(self):
+ return self.alias.disp_table_index
+
+ def decl_params(self):
+ return self.alias.decl_params()
+
+ def call_params(self):
+ return self.alias.call_params()
+
+def get_entrypoints(doc, entrypoints_to_defines):
+ """Extract the entry points from the registry."""
+ entrypoints = OrderedDict()
+
+ for command in doc.findall('./commands/command'):
+ if 'alias' in command.attrib:
+ alias = command.attrib['name']
+ target = command.attrib['alias']
+ entrypoints[alias] = EntrypointAlias(alias, entrypoints[target])
+ else:
+ name = command.find('./proto/name').text
+ ret_type = command.find('./proto/type').text
+ params = [EntrypointParam(
+ type=p.find('./type').text,
+ name=p.find('./name').text,
+ decl=''.join(p.itertext())
+ ) for p in command.findall('./param')]
+ guard = entrypoints_to_defines.get(name)
+ # They really need to be unique
+ assert name not in entrypoints
+ entrypoints[name] = Entrypoint(name, ret_type, params, guard)
+
+ for feature in doc.findall('./feature'):
+ assert feature.attrib['api'] == 'vulkan'
+ version = VkVersion(feature.attrib['number'])
+ for command in feature.findall('./require/command'):
+ e = entrypoints[command.attrib['name']]
+ assert e.core_version is None
+ e.core_version = version
+
+ for extension in doc.findall('.extensions/extension'):
+ if extension.attrib['supported'] != 'vulkan':
+ continue
+
+ ext_name = extension.attrib['name']
+
+ ext = Extension(ext_name, 1, True)
+ ext.type = extension.attrib['type']
+
+ for command in extension.findall('./require/command'):
+ e = entrypoints[command.attrib['name']]
+ assert e.core_version is None
+ e.extensions.append(ext)
+
+ return entrypoints.values()
+
+
+def get_entrypoints_defines(doc):
+ """Maps entry points to extension defines."""
+ entrypoints_to_defines = {}
+
+ platform_define = {}
+ for platform in doc.findall('./platforms/platform'):
+ name = platform.attrib['name']
+ define = platform.attrib['protect']
+ platform_define[name] = define
+
+ for extension in doc.findall('./extensions/extension[@platform]'):
+ platform = extension.attrib['platform']
+ define = platform_define[platform]
+
+ for entrypoint in extension.findall('./require/command'):
+ fullname = entrypoint.attrib['name']
+ entrypoints_to_defines[fullname] = define
+
+ return entrypoints_to_defines
+
+def get_entrypoints_from_xml(xml_files):
+ entrypoints = []
+
+ for filename in xml_files:
+ doc = et.parse(filename)
+ entrypoints += get_entrypoints(doc, get_entrypoints_defines(doc))
+
+ return entrypoints
+
+def main():
+ parser = argparse.ArgumentParser()
+ parser.add_argument('--out-c', help='Output C file.')
+ parser.add_argument('--out-h', help='Output H file.')
+ parser.add_argument('--xml',
+ help='Vulkan API XML file.',
+ required=True,
+ action='append',
+ dest='xml_files')
+ args = parser.parse_args()
+
+ entrypoints = get_entrypoints_from_xml(args.xml_files)
+
+ device_entrypoints = []
+ physical_device_entrypoints = []
+ instance_entrypoints = []
+ for e in entrypoints:
+ if e.is_device_entrypoint():
+ device_entrypoints.append(e)
+ elif e.is_physical_device_entrypoint():
+ physical_device_entrypoints.append(e)
+ else:
+ instance_entrypoints.append(e)
+
+ for i, e in enumerate(e for e in device_entrypoints if not e.alias):
+ e.disp_table_index = i
+
+ device_strmap = StringIntMap()
+ for i, e in enumerate(device_entrypoints):
+ e.entry_table_index = i
+ device_strmap.add_string("vk" + e.name, e.entry_table_index)
+ device_strmap.bake()
+
+ for i, e in enumerate(e for e in physical_device_entrypoints if not e.alias):
+ e.disp_table_index = i
+
+ physical_device_strmap = StringIntMap()
+ for i, e in enumerate(physical_device_entrypoints):
+ e.entry_table_index = i
+ physical_device_strmap.add_string("vk" + e.name, e.entry_table_index)
+ physical_device_strmap.bake()
+
+ for i, e in enumerate(e for e in instance_entrypoints if not e.alias):
+ e.disp_table_index = i
+
+ instance_strmap = StringIntMap()
+ for i, e in enumerate(instance_entrypoints):
+ e.entry_table_index = i
+ instance_strmap.add_string("vk" + e.name, e.entry_table_index)
+ instance_strmap.bake()
+
+ # For outputting entrypoints.h we generate a anv_EntryPoint() prototype
+ # per entry point.
+ try:
+ if args.out_h:
+ with open(args.out_h, 'wb') as f:
+ f.write(TEMPLATE_H.render(instance_entrypoints=instance_entrypoints,
+ physical_device_entrypoints=physical_device_entrypoints,
+ device_entrypoints=device_entrypoints,
+ filename=os.path.basename(__file__)))
+ if args.out_c:
+ with open(args.out_c, 'wb') as f:
+ f.write(TEMPLATE_C.render(instance_entrypoints=instance_entrypoints,
+ physical_device_entrypoints=physical_device_entrypoints,
+ device_entrypoints=device_entrypoints,
+ instance_strmap=instance_strmap,
+ physical_device_strmap=physical_device_strmap,
+ device_strmap=device_strmap,
+ filename=os.path.basename(__file__)))
+ except Exception:
+ # In the event there's an error, this imports some helpers from mako
+ # to print a useful stack trace and prints it, then exits with
+ # status 1, if python is run with debug; otherwise it just raises
+ # the exception
+ if __debug__:
+ import sys
+ from mako import exceptions
+ sys.stderr.write(exceptions.text_error_template().render() + '\n')
+ sys.exit(1)
+ raise
+
+
+if __name__ == '__main__':
+ main()
diff --git a/lib/mesa/src/vulkan/util/vk_entrypoints_gen.py b/lib/mesa/src/vulkan/util/vk_entrypoints_gen.py
new file mode 100644
index 000000000..a663d10e1
--- /dev/null
+++ b/lib/mesa/src/vulkan/util/vk_entrypoints_gen.py
@@ -0,0 +1,258 @@
+# coding=utf-8
+COPYRIGHT=u"""
+/* Copyright © 2015-2021 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+"""
+
+import argparse
+import os
+
+from mako.template import Template
+
+# Mesa-local imports must be declared in meson variable
+# '{file_without_suffix}_depend_files'.
+from vk_dispatch_table_gen import get_entrypoints_from_xml
+
+TEMPLATE_H = Template(COPYRIGHT + """\
+/* This file generated from ${filename}, don't edit directly. */
+
+#include "vk_dispatch_table.h"
+
+#ifndef ${guard}
+#define ${guard}
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+% for p in instance_prefixes:
+extern const struct vk_instance_entrypoint_table ${p}_instance_entrypoints;
+% endfor
+
+% for p in physical_device_prefixes:
+extern const struct vk_physical_device_entrypoint_table ${p}_physical_device_entrypoints;
+% endfor
+
+% for p in device_prefixes:
+extern const struct vk_device_entrypoint_table ${p}_device_entrypoints;
+% endfor
+
+% if gen_proto:
+% for e in instance_entrypoints:
+ % if e.guard is not None:
+#ifdef ${e.guard}
+ % endif
+ % for p in physical_device_prefixes:
+ VKAPI_ATTR ${e.return_type} VKAPI_CALL ${p}_${e.name}(${e.decl_params()});
+ % endfor
+ % if e.guard is not None:
+#endif // ${e.guard}
+ % endif
+% endfor
+
+% for e in physical_device_entrypoints:
+ % if e.guard is not None:
+#ifdef ${e.guard}
+ % endif
+ % for p in physical_device_prefixes:
+ VKAPI_ATTR ${e.return_type} VKAPI_CALL ${p}_${e.name}(${e.decl_params()});
+ % endfor
+ % if e.guard is not None:
+#endif // ${e.guard}
+ % endif
+% endfor
+
+% for e in device_entrypoints:
+ % if e.guard is not None:
+#ifdef ${e.guard}
+ % endif
+ % for p in device_prefixes:
+ VKAPI_ATTR ${e.return_type} VKAPI_CALL ${p}_${e.name}(${e.decl_params()});
+ % endfor
+ % if e.guard is not None:
+#endif // ${e.guard}
+ % endif
+% endfor
+% endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ${guard} */
+""", output_encoding='utf-8')
+
+TEMPLATE_C = Template(COPYRIGHT + """
+/* This file generated from ${filename}, don't edit directly. */
+
+#include "${header}"
+
+/* Weak aliases for all potential implementations. These will resolve to
+ * NULL if they're not defined, which lets the resolve_entrypoint() function
+ * either pick the correct entry point.
+ *
+ * MSVC uses different decorated names for 32-bit versus 64-bit. Declare
+ * all argument sizes for 32-bit because computing the actual size would be
+ * difficult.
+ */
+
+<%def name="entrypoint_table(type, entrypoints, prefixes)">
+% if gen_weak:
+ % for e in entrypoints:
+ % if e.guard is not None:
+#ifdef ${e.guard}
+ % endif
+ % for p in prefixes:
+#ifdef _MSC_VER
+ ${e.return_type} (*${p}_${e.name}_Null)(${e.decl_params()}) = 0;
+#ifdef _M_IX86
+ % for args_size in [4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 60, 104]:
+ #pragma comment(linker, "/alternatename:_${p}_${e.name}@${args_size}=_${p}_${e.name}_Null")
+ % endfor
+#else
+ #pragma comment(linker, "/alternatename:${p}_${e.name}=${p}_${e.name}_Null")
+#endif
+#else
+ VKAPI_ATTR ${e.return_type} VKAPI_CALL ${p}_${e.name}(${e.decl_params()}) __attribute__ ((weak));
+#endif
+ % endfor
+ % if e.guard is not None:
+#endif // ${e.guard}
+ % endif
+ % endfor
+% endif
+
+% for p in prefixes:
+const struct vk_${type}_entrypoint_table ${p}_${type}_entrypoints = {
+ % for e in entrypoints:
+ % if e.guard is not None:
+#ifdef ${e.guard}
+ % endif
+ .${e.name} = ${p}_${e.name},
+ % if e.guard is not None:
+#endif // ${e.guard}
+ % endif
+ % endfor
+};
+% endfor
+</%def>
+
+${entrypoint_table('instance', instance_entrypoints, instance_prefixes)}
+${entrypoint_table('physical_device', physical_device_entrypoints, physical_device_prefixes)}
+${entrypoint_table('device', device_entrypoints, device_prefixes)}
+""", output_encoding='utf-8')
+
+def get_entrypoints_defines(doc):
+ """Maps entry points to extension defines."""
+ entrypoints_to_defines = {}
+
+ platform_define = {}
+ for platform in doc.findall('./platforms/platform'):
+ name = platform.attrib['name']
+ define = platform.attrib['protect']
+ platform_define[name] = define
+
+ for extension in doc.findall('./extensions/extension[@platform]'):
+ platform = extension.attrib['platform']
+ define = platform_define[platform]
+
+ for entrypoint in extension.findall('./require/command'):
+ fullname = entrypoint.attrib['name']
+ entrypoints_to_defines[fullname] = define
+
+ return entrypoints_to_defines
+
+
+def main():
+ parser = argparse.ArgumentParser()
+ parser.add_argument('--out-c', required=True, help='Output C file.')
+ parser.add_argument('--out-h', required=True, help='Output H file.')
+ parser.add_argument('--xml',
+ help='Vulkan API XML file.',
+ required=True, action='append', dest='xml_files')
+ parser.add_argument('--proto', help='Generate entrypoint prototypes',
+ action='store_true', dest='gen_proto')
+ parser.add_argument('--weak', help='Generate weak entrypoint declarations',
+ action='store_true', dest='gen_weak')
+ parser.add_argument('--prefix',
+ help='Prefix to use for all dispatch tables.',
+ action='append', default=[], dest='prefixes')
+ parser.add_argument('--device-prefix',
+ help='Prefix to use for device dispatch tables.',
+ action='append', default=[], dest='device_prefixes')
+ args = parser.parse_args()
+
+ instance_prefixes = args.prefixes
+ physical_device_prefixes = args.prefixes
+ device_prefixes = args.prefixes + args.device_prefixes
+
+ entrypoints = get_entrypoints_from_xml(args.xml_files)
+
+ device_entrypoints = []
+ physical_device_entrypoints = []
+ instance_entrypoints = []
+ for e in entrypoints:
+ if e.is_device_entrypoint():
+ device_entrypoints.append(e)
+ elif e.is_physical_device_entrypoint():
+ physical_device_entrypoints.append(e)
+ else:
+ instance_entrypoints.append(e)
+
+ assert os.path.dirname(args.out_c) == os.path.dirname(args.out_h)
+
+ environment = {
+ 'gen_proto': args.gen_proto,
+ 'gen_weak': args.gen_weak,
+ 'header': os.path.basename(args.out_h),
+ 'instance_entrypoints': instance_entrypoints,
+ 'instance_prefixes': instance_prefixes,
+ 'physical_device_entrypoints': physical_device_entrypoints,
+ 'physical_device_prefixes': physical_device_prefixes,
+ 'device_entrypoints': device_entrypoints,
+ 'device_prefixes': device_prefixes,
+ 'filename': os.path.basename(__file__),
+ }
+
+ # For outputting entrypoints.h we generate a anv_EntryPoint() prototype
+ # per entry point.
+ try:
+ with open(args.out_h, 'wb') as f:
+ guard = os.path.basename(args.out_h).replace('.', '_').upper()
+ f.write(TEMPLATE_H.render(guard=guard, **environment))
+ with open(args.out_c, 'wb') as f:
+ f.write(TEMPLATE_C.render(**environment))
+
+ except Exception:
+ # In the event there's an error, this imports some helpers from mako
+ # to print a useful stack trace and prints it, then exits with
+ # status 1, if python is run with debug; otherwise it just raises
+ # the exception
+ if __debug__:
+ import sys
+ from mako import exceptions
+ sys.stderr.write(exceptions.text_error_template().render() + '\n')
+ sys.exit(1)
+ raise
+
+if __name__ == '__main__':
+ main()
diff --git a/lib/mesa/src/vulkan/util/vk_extensions.py b/lib/mesa/src/vulkan/util/vk_extensions.py
new file mode 100644
index 000000000..852951f05
--- /dev/null
+++ b/lib/mesa/src/vulkan/util/vk_extensions.py
@@ -0,0 +1,214 @@
+import argparse
+import copy
+import re
+import xml.etree.ElementTree as et
+
+def _bool_to_c_expr(b):
+ if b is True:
+ return 'true'
+ if b is False:
+ return 'false'
+ return b
+
+class Extension:
+ def __init__(self, name, ext_version, enable):
+ self.name = name
+ self.ext_version = int(ext_version)
+ self.enable = _bool_to_c_expr(enable)
+
+ def c_android_condition(self):
+ # if it's an EXT or vendor extension, it's allowed
+ if not self.name.startswith(ANDROID_EXTENSION_WHITELIST_PREFIXES):
+ return 'true'
+
+ allowed_version = ALLOWED_ANDROID_VERSION.get(self.name, None)
+ if allowed_version is None:
+ return 'false'
+
+ return 'ANDROID_API_LEVEL >= %d' % (allowed_version)
+
+class ApiVersion:
+ def __init__(self, version, enable):
+ self.version = version
+ self.enable = _bool_to_c_expr(enable)
+
+class VkVersion:
+ def __init__(self, string):
+ split = string.split('.')
+ self.major = int(split[0])
+ self.minor = int(split[1])
+ if len(split) > 2:
+ assert len(split) == 3
+ self.patch = int(split[2])
+ else:
+ self.patch = None
+
+ # Sanity check. The range bits are required by the definition of the
+ # VK_MAKE_VERSION macro
+ assert self.major < 1024 and self.minor < 1024
+ assert self.patch is None or self.patch < 4096
+ assert(str(self) == string)
+
+ def __str__(self):
+ ver_list = [str(self.major), str(self.minor)]
+ if self.patch is not None:
+ ver_list.append(str(self.patch))
+ return '.'.join(ver_list)
+
+ def c_vk_version(self):
+ patch = self.patch if self.patch is not None else 0
+ ver_list = [str(self.major), str(self.minor), str(patch)]
+ return 'VK_MAKE_VERSION(' + ', '.join(ver_list) + ')'
+
+ def __int_ver(self):
+ # This is just an expansion of VK_VERSION
+ patch = self.patch if self.patch is not None else 0
+ return (self.major << 22) | (self.minor << 12) | patch
+
+ def __gt__(self, other):
+ # If only one of them has a patch version, "ignore" it by making
+ # other's patch version match self.
+ if (self.patch is None) != (other.patch is None):
+ other = copy.copy(other)
+ other.patch = self.patch
+
+ return self.__int_ver() > other.__int_ver()
+
+# Sort the extension list the way we expect: KHR, then EXT, then vendors
+# alphabetically. For digits, read them as a whole number sort that.
+# eg.: VK_KHR_8bit_storage < VK_KHR_16bit_storage < VK_EXT_acquire_xlib_display
+def extension_order(ext):
+ order = []
+ for substring in re.split('(KHR|EXT|[0-9]+)', ext.name):
+ if substring == 'KHR':
+ order.append(1)
+ if substring == 'EXT':
+ order.append(2)
+ elif substring.isdigit():
+ order.append(int(substring))
+ else:
+ order.append(substring)
+ return order
+
+def get_all_exts_from_xml(xml):
+ """ Get a list of all Vulkan extensions. """
+
+ xml = et.parse(xml)
+
+ extensions = []
+ for ext_elem in xml.findall('.extensions/extension'):
+ supported = ext_elem.attrib['supported'] == 'vulkan'
+ name = ext_elem.attrib['name']
+ if not supported and name != 'VK_ANDROID_native_buffer':
+ continue
+ version = None
+ for enum_elem in ext_elem.findall('.require/enum'):
+ if enum_elem.attrib['name'].endswith('_SPEC_VERSION'):
+ assert version is None
+ version = int(enum_elem.attrib['value'])
+ ext = Extension(name, version, True)
+ extensions.append(Extension(name, version, True))
+
+ return sorted(extensions, key=extension_order)
+
+def init_exts_from_xml(xml, extensions, platform_defines):
+ """ Walk the Vulkan XML and fill out extra extension information. """
+
+ xml = et.parse(xml)
+
+ ext_name_map = {}
+ for ext in extensions:
+ ext_name_map[ext.name] = ext
+
+ # KHR_display is missing from the list.
+ platform_defines.append('VK_USE_PLATFORM_DISPLAY_KHR')
+ for platform in xml.findall('./platforms/platform'):
+ platform_defines.append(platform.attrib['protect'])
+
+ for ext_elem in xml.findall('.extensions/extension'):
+ ext_name = ext_elem.attrib['name']
+ if ext_name not in ext_name_map:
+ continue
+
+ ext = ext_name_map[ext_name]
+ ext.type = ext_elem.attrib['type']
+
+# Mapping between extension name and the android version in which the extension
+# was whitelisted in Android CTS.
+ALLOWED_ANDROID_VERSION = {
+ # Allowed Instance KHR Extensions
+ "VK_KHR_surface": 26,
+ "VK_KHR_display": 26,
+ "VK_KHR_android_surface": 26,
+ "VK_KHR_mir_surface": 26,
+ "VK_KHR_wayland_surface": 26,
+ "VK_KHR_win32_surface": 26,
+ "VK_KHR_xcb_surface": 26,
+ "VK_KHR_xlib_surface": 26,
+ "VK_KHR_get_physical_device_properties2": 26,
+ "VK_KHR_get_surface_capabilities2": 26,
+ "VK_KHR_external_memory_capabilities": 28,
+ "VK_KHR_external_semaphore_capabilities": 28,
+ "VK_KHR_external_fence_capabilities": 28,
+ "VK_KHR_device_group_creation": 28,
+ "VK_KHR_get_display_properties2": 29,
+ "VK_KHR_surface_protected_capabilities": 29,
+
+ # Allowed Device KHR Extensions
+ "VK_KHR_swapchain": 26,
+ "VK_KHR_display_swapchain": 26,
+ "VK_KHR_sampler_mirror_clamp_to_edge": 26,
+ "VK_KHR_shader_draw_parameters": 26,
+ "VK_KHR_shader_float_controls": 29,
+ "VK_KHR_shader_float16_int8": 29,
+ "VK_KHR_maintenance1": 26,
+ "VK_KHR_push_descriptor": 26,
+ "VK_KHR_descriptor_update_template": 26,
+ "VK_KHR_incremental_present": 26,
+ "VK_KHR_shared_presentable_image": 26,
+ "VK_KHR_storage_buffer_storage_class": 28,
+ "VK_KHR_8bit_storage": 29,
+ "VK_KHR_16bit_storage": 28,
+ "VK_KHR_get_memory_requirements2": 28,
+ "VK_KHR_external_memory": 28,
+ "VK_KHR_external_memory_fd": 28,
+ "VK_KHR_external_memory_win32": 28,
+ "VK_KHR_external_semaphore": 28,
+ "VK_KHR_external_semaphore_fd": 28,
+ "VK_KHR_external_semaphore_win32": 28,
+ "VK_KHR_external_fence": 28,
+ "VK_KHR_external_fence_fd": 28,
+ "VK_KHR_external_fence_win32": 28,
+ "VK_KHR_win32_keyed_mutex": 28,
+ "VK_KHR_dedicated_allocation": 28,
+ "VK_KHR_variable_pointers": 28,
+ "VK_KHR_relaxed_block_layout": 28,
+ "VK_KHR_bind_memory2": 28,
+ "VK_KHR_maintenance2": 28,
+ "VK_KHR_image_format_list": 28,
+ "VK_KHR_sampler_ycbcr_conversion": 28,
+ "VK_KHR_device_group": 28,
+ "VK_KHR_multiview": 28,
+ "VK_KHR_maintenance3": 28,
+ "VK_KHR_draw_indirect_count": 28,
+ "VK_KHR_create_renderpass2": 28,
+ "VK_KHR_depth_stencil_resolve": 29,
+ "VK_KHR_driver_properties": 28,
+ "VK_KHR_swapchain_mutable_format": 29,
+ "VK_KHR_shader_atomic_int64": 29,
+ "VK_KHR_vulkan_memory_model": 29,
+ "VK_KHR_performance_query": 30,
+
+ "VK_GOOGLE_display_timing": 26,
+ "VK_ANDROID_native_buffer": 26,
+ "VK_ANDROID_external_memory_android_hardware_buffer": 28,
+}
+
+# Extensions with these prefixes are checked in Android CTS, and thus must be
+# whitelisted per the preceding dict.
+ANDROID_EXTENSION_WHITELIST_PREFIXES = (
+ "VK_KHX",
+ "VK_KHR",
+ "VK_GOOGLE",
+ "VK_ANDROID"
+)
diff --git a/lib/mesa/src/vulkan/util/vk_extensions_gen.py b/lib/mesa/src/vulkan/util/vk_extensions_gen.py
new file mode 100644
index 000000000..4f8f66c40
--- /dev/null
+++ b/lib/mesa/src/vulkan/util/vk_extensions_gen.py
@@ -0,0 +1,254 @@
+COPYRIGHT = """\
+/*
+ * Copyright 2017 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+"""
+
+import xml.etree.ElementTree as et
+
+from mako.template import Template
+
+# Mesa-local imports must be declared in meson variable
+# '{file_without_suffix}_depend_files'.
+from vk_extensions import *
+
+_TEMPLATE_H = Template(COPYRIGHT + """
+
+#ifndef ${driver.upper()}_EXTENSIONS_H
+#define ${driver.upper()}_EXTENSIONS_H
+
+#include <stdbool.h>
+
+%for include in includes:
+#include "${include}"
+%endfor
+
+%if driver == 'vk':
+#define VK_INSTANCE_EXTENSION_COUNT ${len(instance_extensions)}
+
+extern const VkExtensionProperties vk_instance_extensions[];
+
+struct vk_instance_extension_table {
+ union {
+ bool extensions[VK_INSTANCE_EXTENSION_COUNT];
+ struct {
+%for ext in instance_extensions:
+ bool ${ext.name[3:]};
+%endfor
+ };
+ };
+};
+
+
+#define VK_DEVICE_EXTENSION_COUNT ${len(device_extensions)}
+
+extern const VkExtensionProperties vk_device_extensions[];
+
+struct vk_device_extension_table {
+ union {
+ bool extensions[VK_DEVICE_EXTENSION_COUNT];
+ struct {
+%for ext in device_extensions:
+ bool ${ext.name[3:]};
+%endfor
+ };
+ };
+};
+%else:
+#include "vk_extensions.h"
+%endif
+
+struct ${driver}_physical_device;
+
+%if driver == 'vk':
+#ifdef ANDROID
+extern const struct vk_instance_extension_table vk_android_allowed_instance_extensions;
+extern const struct vk_device_extension_table vk_android_allowed_device_extensions;
+#endif
+%else:
+extern const struct vk_instance_extension_table ${driver}_instance_extensions_supported;
+
+void
+${driver}_physical_device_get_supported_extensions(const struct ${driver}_physical_device *device,
+ struct vk_device_extension_table *extensions);
+%endif
+
+#endif /* ${driver.upper()}_EXTENSIONS_H */
+""")
+
+_TEMPLATE_C = Template(COPYRIGHT + """
+%if driver == 'vk':
+#include "vk_object.h"
+%else:
+#include "${driver}_private.h"
+%endif
+
+#include "${driver}_extensions.h"
+
+%if driver == 'vk':
+const VkExtensionProperties ${driver}_instance_extensions[${driver.upper()}_INSTANCE_EXTENSION_COUNT] = {
+%for ext in instance_extensions:
+ {"${ext.name}", ${ext.ext_version}},
+%endfor
+};
+
+const VkExtensionProperties ${driver}_device_extensions[${driver.upper()}_DEVICE_EXTENSION_COUNT] = {
+%for ext in device_extensions:
+ {"${ext.name}", ${ext.ext_version}},
+%endfor
+};
+
+#ifdef ANDROID
+const struct vk_instance_extension_table vk_android_allowed_instance_extensions = {
+%for ext in instance_extensions:
+ .${ext.name[3:]} = ${ext.c_android_condition()},
+%endfor
+};
+
+extern const struct vk_device_extension_table vk_android_allowed_device_extensions = {
+%for ext in device_extensions:
+ .${ext.name[3:]} = ${ext.c_android_condition()},
+%endfor
+};
+#endif
+%endif
+
+%if driver != 'vk':
+#include "vk_util.h"
+
+/* Convert the VK_USE_PLATFORM_* defines to booleans */
+%for platform_define in platform_defines:
+#ifdef ${platform_define}
+# undef ${platform_define}
+# define ${platform_define} true
+#else
+# define ${platform_define} false
+#endif
+%endfor
+
+/* And ANDROID too */
+#ifdef ANDROID
+# undef ANDROID
+# define ANDROID true
+#else
+# define ANDROID false
+# define ANDROID_API_LEVEL 0
+#endif
+
+#define ${driver.upper()}_HAS_SURFACE (VK_USE_PLATFORM_WIN32_KHR || \\
+ VK_USE_PLATFORM_WAYLAND_KHR || \\
+ VK_USE_PLATFORM_XCB_KHR || \\
+ VK_USE_PLATFORM_XLIB_KHR || \\
+ VK_USE_PLATFORM_DISPLAY_KHR)
+
+static const uint32_t MAX_API_VERSION = ${MAX_API_VERSION.c_vk_version()};
+
+VKAPI_ATTR VkResult VKAPI_CALL ${driver}_EnumerateInstanceVersion(
+ uint32_t* pApiVersion)
+{
+ *pApiVersion = MAX_API_VERSION;
+ return VK_SUCCESS;
+}
+
+const struct vk_instance_extension_table ${driver}_instance_extensions_supported = {
+%for ext in instance_extensions:
+ .${ext.name[3:]} = ${ext.enable},
+%endfor
+};
+
+uint32_t
+${driver}_physical_device_api_version(struct ${driver}_physical_device *device)
+{
+ uint32_t version = 0;
+
+ uint32_t override = vk_get_version_override();
+ if (override)
+ return MIN2(override, MAX_API_VERSION);
+
+%for version in API_VERSIONS:
+ if (!(${version.enable}))
+ return version;
+ version = ${version.version.c_vk_version()};
+
+%endfor
+ return version;
+}
+
+void
+${driver}_physical_device_get_supported_extensions(const struct ${driver}_physical_device *device,
+ struct vk_device_extension_table *extensions)
+{
+ *extensions = (struct vk_device_extension_table) {
+%for ext in device_extensions:
+ .${ext.name[3:]} = ${ext.enable},
+%endfor
+ };
+}
+%endif
+""")
+
+def gen_extensions(driver, xml_files, api_versions, max_api_version,
+ extensions, out_c, out_h, includes = []):
+ platform_defines = []
+ for filename in xml_files:
+ init_exts_from_xml(filename, extensions, platform_defines)
+
+ for ext in extensions:
+ assert ext.type == 'instance' or ext.type == 'device'
+
+ template_env = {
+ 'driver': driver,
+ 'API_VERSIONS': api_versions,
+ 'MAX_API_VERSION': max_api_version,
+ 'instance_extensions': [e for e in extensions if e.type == 'instance'],
+ 'device_extensions': [e for e in extensions if e.type == 'device'],
+ 'platform_defines': platform_defines,
+ 'includes': includes,
+ }
+
+ if out_h:
+ with open(out_h, 'w') as f:
+ f.write(_TEMPLATE_H.render(**template_env))
+
+ if out_c:
+ with open(out_c, 'w') as f:
+ f.write(_TEMPLATE_C.render(**template_env))
+
+
+if __name__ == '__main__':
+ parser = argparse.ArgumentParser()
+ parser.add_argument('--out-c', help='Output C file.')
+ parser.add_argument('--out-h', help='Output H file.')
+ parser.add_argument('--xml',
+ help='Vulkan API XML file.',
+ required=True,
+ action='append',
+ dest='xml_files')
+ args = parser.parse_args()
+
+ extensions = []
+ for filename in args.xml_files:
+ extensions += get_all_exts_from_xml(filename)
+
+ gen_extensions('vk', args.xml_files, None, None,
+ extensions, args.out_c, args.out_h, [])
diff --git a/lib/mesa/src/vulkan/util/vk_format.c b/lib/mesa/src/vulkan/util/vk_format.c
index 4fdfb6d5a..f6e6bcec7 100644
--- a/lib/mesa/src/vulkan/util/vk_format.c
+++ b/lib/mesa/src/vulkan/util/vk_format.c
@@ -1,4 +1,5 @@
/*
+ * Copyright © 2016 Intel Corporation
* Copyright © 2019 Google LLC
*
* Permission is hereby granted, free of charge, to any person obtaining a
@@ -158,7 +159,9 @@ static const enum pipe_format vk_format_map[] = {
[VK_FORMAT_R32G32B32A32_SINT] = PIPE_FORMAT_R32G32B32A32_SINT,
[VK_FORMAT_R32G32B32A32_SFLOAT] = PIPE_FORMAT_R32G32B32A32_FLOAT,
- /* Missing 64-bit uint/sint formats */
+ [VK_FORMAT_R64_UINT] = PIPE_FORMAT_R64_UINT,
+ [VK_FORMAT_R64_SINT] = PIPE_FORMAT_R64_SINT,
+ /* Missing rest of 64-bit uint/sint formats */
[VK_FORMAT_R64_SFLOAT] = PIPE_FORMAT_R64_FLOAT,
[VK_FORMAT_R64G64_SFLOAT] = PIPE_FORMAT_R64G64_FLOAT,
[VK_FORMAT_R64G64B64_SFLOAT] = PIPE_FORMAT_R64G64B64_FLOAT,
@@ -171,7 +174,7 @@ static const enum pipe_format vk_format_map[] = {
[VK_FORMAT_X8_D24_UNORM_PACK32] = PIPE_FORMAT_Z24X8_UNORM,
[VK_FORMAT_D32_SFLOAT] = PIPE_FORMAT_Z32_FLOAT,
[VK_FORMAT_S8_UINT] = PIPE_FORMAT_S8_UINT,
- /* Missing D16_UNORM_S8_UINT */
+ [VK_FORMAT_D16_UNORM_S8_UINT] = PIPE_FORMAT_Z16_UNORM_S8_UINT,
[VK_FORMAT_D24_UNORM_S8_UINT] = PIPE_FORMAT_Z24_UNORM_S8_UINT,
[VK_FORMAT_D32_SFLOAT_S8_UINT] = PIPE_FORMAT_Z32_FLOAT_S8X24_UINT,
@@ -183,6 +186,10 @@ static const enum pipe_format vk_format_map[] = {
[VK_FORMAT_BC2_SRGB_BLOCK] = PIPE_FORMAT_DXT3_SRGBA,
[VK_FORMAT_BC3_UNORM_BLOCK] = PIPE_FORMAT_DXT5_RGBA,
[VK_FORMAT_BC3_SRGB_BLOCK] = PIPE_FORMAT_DXT5_SRGBA,
+ [VK_FORMAT_BC4_UNORM_BLOCK] = PIPE_FORMAT_RGTC1_UNORM,
+ [VK_FORMAT_BC4_SNORM_BLOCK] = PIPE_FORMAT_RGTC1_SNORM,
+ [VK_FORMAT_BC5_UNORM_BLOCK] = PIPE_FORMAT_RGTC2_UNORM,
+ [VK_FORMAT_BC5_SNORM_BLOCK] = PIPE_FORMAT_RGTC2_SNORM,
[VK_FORMAT_BC6H_UFLOAT_BLOCK] = PIPE_FORMAT_BPTC_RGB_UFLOAT,
[VK_FORMAT_BC6H_SFLOAT_BLOCK] = PIPE_FORMAT_BPTC_RGB_FLOAT,
[VK_FORMAT_BC7_UNORM_BLOCK] = PIPE_FORMAT_BPTC_RGBA_UNORM,
@@ -240,11 +247,95 @@ static const enum pipe_format vk_format_map[] = {
enum pipe_format
vk_format_to_pipe_format(enum VkFormat vkformat)
{
- if (vkformat >= ARRAY_SIZE(vk_format_map))
- return PIPE_FORMAT_NONE;
+ if (vkformat >= ARRAY_SIZE(vk_format_map)) {
+ switch (vkformat) {
+ case VK_FORMAT_G8B8G8R8_422_UNORM:
+ return PIPE_FORMAT_YUYV;
+ case VK_FORMAT_B8G8R8G8_422_UNORM:
+ return PIPE_FORMAT_UYVY;
+ case VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM:
+ return PIPE_FORMAT_IYUV;
+ case VK_FORMAT_G8_B8R8_2PLANE_420_UNORM:
+ return PIPE_FORMAT_NV12;
+ case VK_FORMAT_G8_B8_R8_3PLANE_422_UNORM:
+ return PIPE_FORMAT_Y8_U8_V8_422_UNORM;
+ case VK_FORMAT_G8_B8R8_2PLANE_422_UNORM:
+ return PIPE_FORMAT_Y8_U8V8_422_UNORM;
+ case VK_FORMAT_G8_B8_R8_3PLANE_444_UNORM:
+ return PIPE_FORMAT_Y8_U8_V8_444_UNORM;
+ case VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM:
+ return PIPE_FORMAT_Y16_U16_V16_420_UNORM;
+ case VK_FORMAT_G16_B16R16_2PLANE_420_UNORM:
+ return PIPE_FORMAT_P016;
+ case VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM:
+ return PIPE_FORMAT_Y16_U16_V16_422_UNORM;
+ case VK_FORMAT_G16_B16R16_2PLANE_422_UNORM:
+ return PIPE_FORMAT_Y16_U16V16_422_UNORM;
+ case VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM:
+ return PIPE_FORMAT_Y16_U16_V16_444_UNORM;
+ case VK_FORMAT_A4R4G4B4_UNORM_PACK16_EXT:
+ return PIPE_FORMAT_B4G4R4A4_UNORM;
+ case VK_FORMAT_A4B4G4R4_UNORM_PACK16_EXT:
+ return PIPE_FORMAT_R4G4B4A4_UNORM;
+ default:
+ return PIPE_FORMAT_NONE;
+ }
+ }
/* Unpopulated entries in the table must be PIPE_FORMAT_NONE */
STATIC_ASSERT(PIPE_FORMAT_NONE == 0);
return vk_format_map[vkformat];
}
+
+VkImageAspectFlags
+vk_format_aspects(VkFormat format)
+{
+ switch (format) {
+ case VK_FORMAT_UNDEFINED:
+ return 0;
+
+ case VK_FORMAT_S8_UINT:
+ return VK_IMAGE_ASPECT_STENCIL_BIT;
+
+ case VK_FORMAT_D16_UNORM_S8_UINT:
+ case VK_FORMAT_D24_UNORM_S8_UINT:
+ case VK_FORMAT_D32_SFLOAT_S8_UINT:
+ return VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
+
+ case VK_FORMAT_D16_UNORM:
+ case VK_FORMAT_X8_D24_UNORM_PACK32:
+ case VK_FORMAT_D32_SFLOAT:
+ return VK_IMAGE_ASPECT_DEPTH_BIT;
+
+ case VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM:
+ case VK_FORMAT_G8_B8_R8_3PLANE_422_UNORM:
+ case VK_FORMAT_G8_B8_R8_3PLANE_444_UNORM:
+ case VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16:
+ case VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_422_UNORM_3PACK16:
+ case VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_444_UNORM_3PACK16:
+ case VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16:
+ case VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_422_UNORM_3PACK16:
+ case VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_444_UNORM_3PACK16:
+ case VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM:
+ case VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM:
+ case VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM:
+ return (VK_IMAGE_ASPECT_PLANE_0_BIT |
+ VK_IMAGE_ASPECT_PLANE_1_BIT |
+ VK_IMAGE_ASPECT_PLANE_2_BIT);
+
+ case VK_FORMAT_G8_B8R8_2PLANE_420_UNORM:
+ case VK_FORMAT_G8_B8R8_2PLANE_422_UNORM:
+ case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16:
+ case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16:
+ case VK_FORMAT_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16:
+ case VK_FORMAT_G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16:
+ case VK_FORMAT_G16_B16R16_2PLANE_420_UNORM:
+ case VK_FORMAT_G16_B16R16_2PLANE_422_UNORM:
+ return (VK_IMAGE_ASPECT_PLANE_0_BIT |
+ VK_IMAGE_ASPECT_PLANE_1_BIT);
+
+ default:
+ return VK_IMAGE_ASPECT_COLOR_BIT;
+ }
+}
diff --git a/lib/mesa/src/vulkan/util/vk_format.h b/lib/mesa/src/vulkan/util/vk_format.h
index ecc79f7f7..813ec4c36 100644
--- a/lib/mesa/src/vulkan/util/vk_format.h
+++ b/lib/mesa/src/vulkan/util/vk_format.h
@@ -1,4 +1,5 @@
/*
+ * Copyright © 2016 Intel Corporation
* Copyright © 2019 Google LLC
*
* Permission is hereby granted, free of charge, to any person obtaining a
@@ -30,4 +31,34 @@
enum pipe_format
vk_format_to_pipe_format(enum VkFormat vkformat);
+VkImageAspectFlags
+vk_format_aspects(VkFormat format);
+
+static inline bool
+vk_format_is_color(VkFormat format)
+{
+ return vk_format_aspects(format) == VK_IMAGE_ASPECT_COLOR_BIT;
+}
+
+static inline bool
+vk_format_is_depth_or_stencil(VkFormat format)
+{
+ const VkImageAspectFlags aspects = vk_format_aspects(format);
+ return aspects & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT);
+}
+
+static inline bool
+vk_format_has_depth(VkFormat format)
+{
+ const VkImageAspectFlags aspects = vk_format_aspects(format);
+ return aspects & VK_IMAGE_ASPECT_DEPTH_BIT;
+}
+
+static inline bool
+vk_format_has_stencil(VkFormat format)
+{
+ const VkImageAspectFlags aspects = vk_format_aspects(format);
+ return aspects & VK_IMAGE_ASPECT_STENCIL_BIT;
+}
+
#endif
diff --git a/lib/mesa/src/vulkan/util/vk_icd_gen.py b/lib/mesa/src/vulkan/util/vk_icd_gen.py
new file mode 100644
index 000000000..d5401e801
--- /dev/null
+++ b/lib/mesa/src/vulkan/util/vk_icd_gen.py
@@ -0,0 +1,78 @@
+# Copyright 2017 Intel Corporation
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sub license, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice (including the
+# next paragraph) shall be included in all copies or substantial portions
+# of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+# IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+# ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+import argparse
+import json
+import os.path
+import re
+import xml.etree.ElementTree as et
+
+def get_xml_patch_version(xml_file):
+ xml = et.parse(xml_file)
+ for d in xml.findall('.types/type'):
+ if d.get('category', None) != 'define':
+ continue
+
+ name = d.find('.name')
+ if name.text != 'VK_HEADER_VERSION':
+ continue;
+
+ return name.tail.strip()
+
+if __name__ == '__main__':
+ parser = argparse.ArgumentParser()
+ parser.add_argument('--api-version', required=True,
+ help='Vulkan API version.')
+ parser.add_argument('--xml', required=False,
+ help='Vulkan registry XML for patch version')
+ parser.add_argument('--lib-path', required=True,
+ help='Path to installed library')
+ parser.add_argument('--out', required=False,
+ help='Output json file.')
+ args = parser.parse_args()
+
+ version = args.api_version
+ if args.xml:
+ re.match(r'\d+\.\d+', version)
+ version = version + '.' + get_xml_patch_version(args.xml)
+ else:
+ re.match(r'\d+\.\d+\.\d+', version)
+
+ json_data = {
+ 'file_format_version': '1.0.0',
+ 'ICD': {
+ 'library_path': args.lib_path,
+ 'api_version': version,
+ },
+ }
+
+ json_params = {
+ 'indent': 4,
+ 'sort_keys': True,
+ 'separators': (',', ': '),
+ }
+
+ if args.out:
+ with open(args.out, 'w') as f:
+ json.dump(json_data, f, **json_params)
+ else:
+ print(json.dumps(json_data, **json_params))
diff --git a/lib/mesa/src/vulkan/util/vk_instance.c b/lib/mesa/src/vulkan/util/vk_instance.c
new file mode 100644
index 000000000..5787be170
--- /dev/null
+++ b/lib/mesa/src/vulkan/util/vk_instance.c
@@ -0,0 +1,230 @@
+/*
+ * Copyright © 2021 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include "vk_instance.h"
+
+#include "vk_alloc.h"
+#include "vk_common_entrypoints.h"
+#include "vk_util.h"
+
+#include "compiler/glsl_types.h"
+
+VkResult
+vk_instance_init(struct vk_instance *instance,
+ const struct vk_instance_extension_table *supported_extensions,
+ const struct vk_instance_dispatch_table *dispatch_table,
+ const VkInstanceCreateInfo *pCreateInfo,
+ const VkAllocationCallbacks *alloc)
+{
+ memset(instance, 0, sizeof(*instance));
+ vk_object_base_init(NULL, &instance->base, VK_OBJECT_TYPE_INSTANCE);
+ instance->alloc = *alloc;
+
+ instance->app_info = (struct vk_app_info) { .api_version = 0 };
+ if (pCreateInfo->pApplicationInfo) {
+ const VkApplicationInfo *app = pCreateInfo->pApplicationInfo;
+
+ instance->app_info.app_name =
+ vk_strdup(&instance->alloc, app->pApplicationName,
+ VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
+ instance->app_info.app_version = app->applicationVersion;
+
+ instance->app_info.engine_name =
+ vk_strdup(&instance->alloc, app->pEngineName,
+ VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
+ instance->app_info.engine_version = app->engineVersion;
+
+ instance->app_info.api_version = app->apiVersion;
+ }
+
+ if (instance->app_info.api_version == 0)
+ instance->app_info.api_version = VK_API_VERSION_1_0;
+
+ for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
+ int idx;
+ for (idx = 0; idx < VK_INSTANCE_EXTENSION_COUNT; idx++) {
+ if (strcmp(pCreateInfo->ppEnabledExtensionNames[i],
+ vk_instance_extensions[idx].extensionName) == 0)
+ break;
+ }
+
+ if (idx >= VK_INSTANCE_EXTENSION_COUNT)
+ return VK_ERROR_EXTENSION_NOT_PRESENT;
+
+ if (!supported_extensions->extensions[idx])
+ return VK_ERROR_EXTENSION_NOT_PRESENT;
+
+#ifdef ANDROID
+ if (!vk_android_allowed_instance_extensions.extensions[idx])
+ return VK_ERROR_EXTENSION_NOT_PRESENT;
+#endif
+
+ instance->enabled_extensions.extensions[idx] = true;
+ }
+
+ instance->dispatch_table = *dispatch_table;
+
+ /* Add common entrypoints without overwriting driver-provided ones. */
+ vk_instance_dispatch_table_from_entrypoints(
+ &instance->dispatch_table, &vk_common_instance_entrypoints, false);
+
+ if (mtx_init(&instance->debug_report.callbacks_mutex, mtx_plain) != 0)
+ return VK_ERROR_INITIALIZATION_FAILED;
+
+ list_inithead(&instance->debug_report.callbacks);
+
+ glsl_type_singleton_init_or_ref();
+
+ return VK_SUCCESS;
+}
+
+void
+vk_instance_finish(struct vk_instance *instance)
+{
+ glsl_type_singleton_decref();
+ mtx_destroy(&instance->debug_report.callbacks_mutex);
+ vk_free(&instance->alloc, (char *)instance->app_info.app_name);
+ vk_free(&instance->alloc, (char *)instance->app_info.engine_name);
+ vk_object_base_finish(&instance->base);
+}
+
+VkResult
+vk_enumerate_instance_extension_properties(
+ const struct vk_instance_extension_table *supported_extensions,
+ uint32_t *pPropertyCount,
+ VkExtensionProperties *pProperties)
+{
+ VK_OUTARRAY_MAKE_TYPED(VkExtensionProperties, out, pProperties, pPropertyCount);
+
+ for (int i = 0; i < VK_INSTANCE_EXTENSION_COUNT; i++) {
+ if (!supported_extensions->extensions[i])
+ continue;
+
+#ifdef ANDROID
+ if (!vk_android_allowed_instance_extensions.extensions[i])
+ continue;
+#endif
+
+ vk_outarray_append_typed(VkExtensionProperties, &out, prop) {
+ *prop = vk_instance_extensions[i];
+ }
+ }
+
+ return vk_outarray_status(&out);
+}
+
+PFN_vkVoidFunction
+vk_instance_get_proc_addr(const struct vk_instance *instance,
+ const struct vk_instance_entrypoint_table *entrypoints,
+ const char *name)
+{
+ PFN_vkVoidFunction func;
+
+ /* The Vulkan 1.0 spec for vkGetInstanceProcAddr has a table of exactly
+ * when we have to return valid function pointers, NULL, or it's left
+ * undefined. See the table for exact details.
+ */
+ if (name == NULL)
+ return NULL;
+
+#define LOOKUP_VK_ENTRYPOINT(entrypoint) \
+ if (strcmp(name, "vk" #entrypoint) == 0) \
+ return (PFN_vkVoidFunction)entrypoints->entrypoint
+
+ LOOKUP_VK_ENTRYPOINT(EnumerateInstanceExtensionProperties);
+ LOOKUP_VK_ENTRYPOINT(EnumerateInstanceLayerProperties);
+ LOOKUP_VK_ENTRYPOINT(EnumerateInstanceVersion);
+ LOOKUP_VK_ENTRYPOINT(CreateInstance);
+
+ /* GetInstanceProcAddr() can also be called with a NULL instance.
+ * See https://gitlab.khronos.org/vulkan/vulkan/issues/2057
+ */
+ LOOKUP_VK_ENTRYPOINT(GetInstanceProcAddr);
+
+#undef LOOKUP_VK_ENTRYPOINT
+
+ if (instance == NULL)
+ return NULL;
+
+ func = vk_instance_dispatch_table_get_if_supported(&instance->dispatch_table,
+ name,
+ instance->app_info.api_version,
+ &instance->enabled_extensions);
+ if (func != NULL)
+ return func;
+
+ func = vk_physical_device_dispatch_table_get_if_supported(&vk_physical_device_trampolines,
+ name,
+ instance->app_info.api_version,
+ &instance->enabled_extensions);
+ if (func != NULL)
+ return func;
+
+ func = vk_device_dispatch_table_get_if_supported(&vk_device_trampolines,
+ name,
+ instance->app_info.api_version,
+ &instance->enabled_extensions,
+ NULL);
+ if (func != NULL)
+ return func;
+
+ return NULL;
+}
+
+PFN_vkVoidFunction
+vk_instance_get_proc_addr_unchecked(const struct vk_instance *instance,
+ const char *name)
+{
+ PFN_vkVoidFunction func;
+
+ if (instance == NULL || name == NULL)
+ return NULL;
+
+ func = vk_instance_dispatch_table_get(&instance->dispatch_table, name);
+ if (func != NULL)
+ return func;
+
+ func = vk_physical_device_dispatch_table_get(
+ &vk_physical_device_trampolines, name);
+ if (func != NULL)
+ return func;
+
+ func = vk_device_dispatch_table_get(&vk_device_trampolines, name);
+ if (func != NULL)
+ return func;
+
+ return NULL;
+}
+
+PFN_vkVoidFunction
+vk_instance_get_physical_device_proc_addr(const struct vk_instance *instance,
+ const char *name)
+{
+ if (instance == NULL || name == NULL)
+ return NULL;
+
+ return vk_physical_device_dispatch_table_get_if_supported(&vk_physical_device_trampolines,
+ name,
+ instance->app_info.api_version,
+ &instance->enabled_extensions);
+}
diff --git a/lib/mesa/src/vulkan/util/vk_instance.h b/lib/mesa/src/vulkan/util/vk_instance.h
new file mode 100644
index 000000000..5f195ca0d
--- /dev/null
+++ b/lib/mesa/src/vulkan/util/vk_instance.h
@@ -0,0 +1,97 @@
+/*
+ * Copyright © 2021 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+#ifndef VK_INSTANCE_H
+#define VK_INSTANCE_H
+
+#include "vk_dispatch_table.h"
+#include "vk_extensions.h"
+#include "vk_object.h"
+
+#include "c11/threads.h"
+#include "util/list.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct vk_app_info {
+ const char* app_name;
+ uint32_t app_version;
+ const char* engine_name;
+ uint32_t engine_version;
+ uint32_t api_version;
+};
+
+struct vk_instance {
+ struct vk_object_base base;
+ VkAllocationCallbacks alloc;
+
+ struct vk_app_info app_info;
+ struct vk_instance_extension_table enabled_extensions;
+
+ struct vk_instance_dispatch_table dispatch_table;
+
+ /* VK_EXT_debug_report debug callbacks */
+ struct {
+ mtx_t callbacks_mutex;
+ struct list_head callbacks;
+ } debug_report;
+};
+
+VK_DEFINE_HANDLE_CASTS(vk_instance, base, VkInstance,
+ VK_OBJECT_TYPE_INSTANCE)
+
+VkResult MUST_CHECK
+vk_instance_init(struct vk_instance *instance,
+ const struct vk_instance_extension_table *supported_extensions,
+ const struct vk_instance_dispatch_table *dispatch_table,
+ const VkInstanceCreateInfo *pCreateInfo,
+ const VkAllocationCallbacks *alloc);
+
+void
+vk_instance_finish(struct vk_instance *instance);
+
+VkResult
+vk_enumerate_instance_extension_properties(
+ const struct vk_instance_extension_table *supported_extensions,
+ uint32_t *pPropertyCount,
+ VkExtensionProperties *pProperties);
+
+PFN_vkVoidFunction
+vk_instance_get_proc_addr(const struct vk_instance *instance,
+ const struct vk_instance_entrypoint_table *entrypoints,
+ const char *name);
+
+PFN_vkVoidFunction
+vk_instance_get_proc_addr_unchecked(const struct vk_instance *instance,
+ const char *name);
+
+PFN_vkVoidFunction
+vk_instance_get_physical_device_proc_addr(const struct vk_instance *instance,
+ const char *name);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* VK_INSTANCE_H */
diff --git a/lib/mesa/src/vulkan/util/vk_object.c b/lib/mesa/src/vulkan/util/vk_object.c
new file mode 100644
index 000000000..af2c72ba9
--- /dev/null
+++ b/lib/mesa/src/vulkan/util/vk_object.c
@@ -0,0 +1,325 @@
+/*
+ * Copyright © 2020 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include "vk_object.h"
+
+#include "vk_alloc.h"
+#include "vk_common_entrypoints.h"
+#include "vk_device.h"
+#include "util/hash_table.h"
+#include "util/ralloc.h"
+
+static void
+vk_object_base_reinit(struct vk_object_base *base)
+{
+ base->_loader_data.loaderMagic = ICD_LOADER_MAGIC;
+ util_sparse_array_init(&base->private_data, sizeof(uint64_t), 8);
+}
+
+void
+vk_object_base_init(struct vk_device *device,
+ struct vk_object_base *base,
+ UNUSED VkObjectType obj_type)
+{
+ vk_object_base_reinit(base);
+ base->type = obj_type;
+ base->device = device;
+}
+
+void
+vk_object_base_finish(struct vk_object_base *base)
+{
+ util_sparse_array_finish(&base->private_data);
+}
+
+void
+vk_object_base_reset(struct vk_object_base *base)
+{
+ vk_object_base_finish(base);
+ vk_object_base_reinit(base);
+}
+
+void *
+vk_object_alloc(struct vk_device *device,
+ const VkAllocationCallbacks *alloc,
+ size_t size,
+ VkObjectType obj_type)
+{
+ void *ptr = vk_alloc2(&device->alloc, alloc, size, 8,
+ VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
+ if (ptr == NULL)
+ return NULL;
+
+ vk_object_base_init(device, (struct vk_object_base *)ptr, obj_type);
+
+ return ptr;
+}
+
+void *
+vk_object_zalloc(struct vk_device *device,
+ const VkAllocationCallbacks *alloc,
+ size_t size,
+ VkObjectType obj_type)
+{
+ void *ptr = vk_zalloc2(&device->alloc, alloc, size, 8,
+ VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
+ if (ptr == NULL)
+ return NULL;
+
+ vk_object_base_init(device, (struct vk_object_base *)ptr, obj_type);
+
+ return ptr;
+}
+
+void *
+vk_object_multialloc(struct vk_device *device,
+ struct vk_multialloc *ma,
+ const VkAllocationCallbacks *alloc,
+ VkObjectType obj_type)
+{
+ void *ptr = vk_multialloc_alloc2(ma, &device->alloc, alloc,
+ VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
+ if (ptr == NULL)
+ return NULL;
+
+ vk_object_base_init(device, (struct vk_object_base *)ptr, obj_type);
+
+ return ptr;
+}
+
+void *
+vk_object_multizalloc(struct vk_device *device,
+ struct vk_multialloc *ma,
+ const VkAllocationCallbacks *alloc,
+ VkObjectType obj_type)
+{
+ void *ptr = vk_multialloc_alloc2(ma, &device->alloc, alloc,
+ VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
+ if (ptr == NULL)
+ return NULL;
+
+ memset(ptr, 0, ma->size);
+ vk_object_base_init(device, (struct vk_object_base *)ptr, obj_type);
+
+ return ptr;
+}
+
+void
+vk_object_free(struct vk_device *device,
+ const VkAllocationCallbacks *alloc,
+ void *data)
+{
+ vk_object_base_finish((struct vk_object_base *)data);
+ vk_free2(&device->alloc, alloc, data);
+}
+
+VkResult
+vk_private_data_slot_create(struct vk_device *device,
+ const VkPrivateDataSlotCreateInfoEXT* pCreateInfo,
+ const VkAllocationCallbacks* pAllocator,
+ VkPrivateDataSlotEXT* pPrivateDataSlot)
+{
+ struct vk_private_data_slot *slot =
+ vk_alloc2(&device->alloc, pAllocator, sizeof(*slot), 8,
+ VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
+ if (slot == NULL)
+ return VK_ERROR_OUT_OF_HOST_MEMORY;
+
+ vk_object_base_init(device, &slot->base,
+ VK_OBJECT_TYPE_PRIVATE_DATA_SLOT_EXT);
+ slot->index = p_atomic_inc_return(&device->private_data_next_index);
+
+ *pPrivateDataSlot = vk_private_data_slot_to_handle(slot);
+
+ return VK_SUCCESS;
+}
+
+void
+vk_private_data_slot_destroy(struct vk_device *device,
+ VkPrivateDataSlotEXT privateDataSlot,
+ const VkAllocationCallbacks *pAllocator)
+{
+ VK_FROM_HANDLE(vk_private_data_slot, slot, privateDataSlot);
+ if (slot == NULL)
+ return;
+
+ vk_object_base_finish(&slot->base);
+ vk_free2(&device->alloc, pAllocator, slot);
+}
+
+#ifdef ANDROID
+static VkResult
+get_swapchain_private_data_locked(struct vk_device *device,
+ uint64_t objectHandle,
+ struct vk_private_data_slot *slot,
+ uint64_t **private_data)
+{
+ if (unlikely(device->swapchain_private == NULL)) {
+ /* Even though VkSwapchain is a non-dispatchable object, we know a
+ * priori that Android swapchains are actually pointers so we can use
+ * the pointer hash table for them.
+ */
+ device->swapchain_private = _mesa_pointer_hash_table_create(NULL);
+ if (device->swapchain_private == NULL)
+ return VK_ERROR_OUT_OF_HOST_MEMORY;
+ }
+
+ struct hash_entry *entry =
+ _mesa_hash_table_search(device->swapchain_private,
+ (void *)(uintptr_t)objectHandle);
+ if (unlikely(entry == NULL)) {
+ struct util_sparse_array *swapchain_private =
+ ralloc(device->swapchain_private, struct util_sparse_array);
+ util_sparse_array_init(swapchain_private, sizeof(uint64_t), 8);
+
+ entry = _mesa_hash_table_insert(device->swapchain_private,
+ (void *)(uintptr_t)objectHandle,
+ swapchain_private);
+ if (entry == NULL)
+ return VK_ERROR_OUT_OF_HOST_MEMORY;
+ }
+
+ struct util_sparse_array *swapchain_private = entry->data;
+ *private_data = util_sparse_array_get(swapchain_private, slot->index);
+
+ return VK_SUCCESS;
+}
+#endif /* ANDROID */
+
+static VkResult
+vk_object_base_private_data(struct vk_device *device,
+ VkObjectType objectType,
+ uint64_t objectHandle,
+ VkPrivateDataSlotEXT privateDataSlot,
+ uint64_t **private_data)
+{
+ VK_FROM_HANDLE(vk_private_data_slot, slot, privateDataSlot);
+
+#ifdef ANDROID
+ /* There is an annoying spec corner here on Android. Because WSI is
+ * implemented in the Vulkan loader which doesn't know about the
+ * VK_EXT_private_data extension, we have to handle VkSwapchainKHR in the
+ * driver as a special case. On future versions of Android where the
+ * loader does understand VK_EXT_private_data, we'll never see a
+ * vkGet/SetPrivateDataEXT call on a swapchain because the loader will
+ * handle it.
+ */
+ if (objectType == VK_OBJECT_TYPE_SWAPCHAIN_KHR) {
+ mtx_lock(&device->swapchain_private_mtx);
+ VkResult result = get_swapchain_private_data_locked(device, objectHandle,
+ slot, private_data);
+ mtx_unlock(&device->swapchain_private_mtx);
+ return result;
+ }
+#endif /* ANDROID */
+
+ struct vk_object_base *obj =
+ vk_object_base_from_u64_handle(objectHandle, objectType);
+ *private_data = util_sparse_array_get(&obj->private_data, slot->index);
+
+ return VK_SUCCESS;
+}
+
+VkResult
+vk_object_base_set_private_data(struct vk_device *device,
+ VkObjectType objectType,
+ uint64_t objectHandle,
+ VkPrivateDataSlotEXT privateDataSlot,
+ uint64_t data)
+{
+ uint64_t *private_data;
+ VkResult result = vk_object_base_private_data(device,
+ objectType, objectHandle,
+ privateDataSlot,
+ &private_data);
+ if (unlikely(result != VK_SUCCESS))
+ return result;
+
+ *private_data = data;
+ return VK_SUCCESS;
+}
+
+void
+vk_object_base_get_private_data(struct vk_device *device,
+ VkObjectType objectType,
+ uint64_t objectHandle,
+ VkPrivateDataSlotEXT privateDataSlot,
+ uint64_t *pData)
+{
+ uint64_t *private_data;
+ VkResult result = vk_object_base_private_data(device,
+ objectType, objectHandle,
+ privateDataSlot,
+ &private_data);
+ if (likely(result == VK_SUCCESS)) {
+ *pData = *private_data;
+ } else {
+ *pData = 0;
+ }
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL
+vk_common_CreatePrivateDataSlotEXT(VkDevice _device,
+ const VkPrivateDataSlotCreateInfoEXT *pCreateInfo,
+ const VkAllocationCallbacks *pAllocator,
+ VkPrivateDataSlotEXT *pPrivateDataSlot)
+{
+ VK_FROM_HANDLE(vk_device, device, _device);
+ return vk_private_data_slot_create(device, pCreateInfo, pAllocator,
+ pPrivateDataSlot);
+}
+
+VKAPI_ATTR void VKAPI_CALL
+vk_common_DestroyPrivateDataSlotEXT(VkDevice _device,
+ VkPrivateDataSlotEXT privateDataSlot,
+ const VkAllocationCallbacks *pAllocator)
+{
+ VK_FROM_HANDLE(vk_device, device, _device);
+ vk_private_data_slot_destroy(device, privateDataSlot, pAllocator);
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL
+vk_common_SetPrivateDataEXT(VkDevice _device,
+ VkObjectType objectType,
+ uint64_t objectHandle,
+ VkPrivateDataSlotEXT privateDataSlot,
+ uint64_t data)
+{
+ VK_FROM_HANDLE(vk_device, device, _device);
+ return vk_object_base_set_private_data(device,
+ objectType, objectHandle,
+ privateDataSlot, data);
+}
+
+VKAPI_ATTR void VKAPI_CALL
+vk_common_GetPrivateDataEXT(VkDevice _device,
+ VkObjectType objectType,
+ uint64_t objectHandle,
+ VkPrivateDataSlotEXT privateDataSlot,
+ uint64_t *pData)
+{
+ VK_FROM_HANDLE(vk_device, device, _device);
+ vk_object_base_get_private_data(device,
+ objectType, objectHandle,
+ privateDataSlot, pData);
+}
diff --git a/lib/mesa/src/vulkan/util/vk_object.h b/lib/mesa/src/vulkan/util/vk_object.h
new file mode 100644
index 000000000..c9c751ae2
--- /dev/null
+++ b/lib/mesa/src/vulkan/util/vk_object.h
@@ -0,0 +1,177 @@
+/*
+ * Copyright © 2020 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+#ifndef VK_OBJECT_H
+#define VK_OBJECT_H
+
+#include <vulkan/vulkan.h>
+#include <vulkan/vk_icd.h>
+
+#include "c11/threads.h"
+#include "util/macros.h"
+#include "util/sparse_array.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct hash_table;
+
+struct vk_device;
+
+struct vk_object_base {
+ VK_LOADER_DATA _loader_data;
+ VkObjectType type;
+
+ struct vk_device *device;
+
+ /* For VK_EXT_private_data */
+ struct util_sparse_array private_data;
+};
+
+void vk_object_base_init(UNUSED struct vk_device *device,
+ struct vk_object_base *base,
+ UNUSED VkObjectType obj_type);
+void vk_object_base_finish(UNUSED struct vk_object_base *base);
+void vk_object_base_reset(struct vk_object_base *base);
+
+static inline void
+vk_object_base_assert_valid(ASSERTED struct vk_object_base *base,
+ ASSERTED VkObjectType obj_type)
+{
+ assert(base == NULL || base->type == obj_type);
+}
+
+static inline struct vk_object_base *
+vk_object_base_from_u64_handle(uint64_t handle, VkObjectType obj_type)
+{
+ struct vk_object_base *base = (struct vk_object_base *)(uintptr_t)handle;
+ vk_object_base_assert_valid(base, obj_type);
+ return base;
+}
+
+#define VK_DEFINE_HANDLE_CASTS(__driver_type, __base, __VkType, __VK_TYPE) \
+ static inline struct __driver_type * \
+ __driver_type ## _from_handle(__VkType _handle) \
+ { \
+ struct vk_object_base *base = (struct vk_object_base *)_handle; \
+ vk_object_base_assert_valid(base, __VK_TYPE); \
+ STATIC_ASSERT(offsetof(struct __driver_type, __base) == 0); \
+ return (struct __driver_type *) base; \
+ } \
+ \
+ static inline __VkType \
+ __driver_type ## _to_handle(struct __driver_type *_obj) \
+ { \
+ vk_object_base_assert_valid(&_obj->__base, __VK_TYPE); \
+ return (__VkType) _obj; \
+ }
+
+#define VK_DEFINE_NONDISP_HANDLE_CASTS(__driver_type, __base, __VkType, __VK_TYPE) \
+ static inline struct __driver_type * \
+ __driver_type ## _from_handle(__VkType _handle) \
+ { \
+ struct vk_object_base *base = \
+ (struct vk_object_base *)(uintptr_t)_handle; \
+ vk_object_base_assert_valid(base, __VK_TYPE); \
+ STATIC_ASSERT(offsetof(struct __driver_type, __base) == 0); \
+ return (struct __driver_type *)base; \
+ } \
+ \
+ static inline __VkType \
+ __driver_type ## _to_handle(struct __driver_type *_obj) \
+ { \
+ vk_object_base_assert_valid(&_obj->__base, __VK_TYPE); \
+ return (__VkType)(uintptr_t) _obj; \
+ }
+
+#define VK_FROM_HANDLE(__driver_type, __name, __handle) \
+ struct __driver_type *__name = __driver_type ## _from_handle(__handle)
+
+/* Helpers for vk object (de)allocation and (de)initialization */
+void *
+vk_object_alloc(struct vk_device *device,
+ const VkAllocationCallbacks *alloc,
+ size_t size,
+ VkObjectType vk_obj_type);
+
+void *
+vk_object_zalloc(struct vk_device *device,
+ const VkAllocationCallbacks *alloc,
+ size_t size,
+ VkObjectType vk_obj_type);
+
+struct vk_multialloc;
+
+void *
+vk_object_multialloc(struct vk_device *device,
+ struct vk_multialloc *ma,
+ const VkAllocationCallbacks *alloc,
+ VkObjectType vk_obj_type);
+
+void *
+vk_object_multizalloc(struct vk_device *device,
+ struct vk_multialloc *ma,
+ const VkAllocationCallbacks *alloc,
+ VkObjectType vk_obj_type);
+
+void
+vk_object_free(struct vk_device *device,
+ const VkAllocationCallbacks *alloc,
+ void *data);
+
+
+struct vk_private_data_slot {
+ struct vk_object_base base;
+ uint32_t index;
+};
+VK_DEFINE_NONDISP_HANDLE_CASTS(vk_private_data_slot, base,
+ VkPrivateDataSlotEXT,
+ VK_OBJECT_TYPE_PRIVATE_DATA_SLOT_EXT);
+
+VkResult
+vk_private_data_slot_create(struct vk_device *device,
+ const VkPrivateDataSlotCreateInfoEXT* pCreateInfo,
+ const VkAllocationCallbacks* pAllocator,
+ VkPrivateDataSlotEXT* pPrivateDataSlot);
+void
+vk_private_data_slot_destroy(struct vk_device *device,
+ VkPrivateDataSlotEXT privateDataSlot,
+ const VkAllocationCallbacks *pAllocator);
+VkResult
+vk_object_base_set_private_data(struct vk_device *device,
+ VkObjectType objectType,
+ uint64_t objectHandle,
+ VkPrivateDataSlotEXT privateDataSlot,
+ uint64_t data);
+void
+vk_object_base_get_private_data(struct vk_device *device,
+ VkObjectType objectType,
+ uint64_t objectHandle,
+ VkPrivateDataSlotEXT privateDataSlot,
+ uint64_t *pData);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* VK_OBJECT_H */
diff --git a/lib/mesa/src/vulkan/util/vk_physical_device.c b/lib/mesa/src/vulkan/util/vk_physical_device.c
new file mode 100644
index 000000000..18cab2e87
--- /dev/null
+++ b/lib/mesa/src/vulkan/util/vk_physical_device.c
@@ -0,0 +1,193 @@
+/*
+ * Copyright © 2021 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include "vk_physical_device.h"
+
+#include "vk_common_entrypoints.h"
+#include "vk_util.h"
+
+VkResult
+vk_physical_device_init(struct vk_physical_device *pdevice,
+ struct vk_instance *instance,
+ const struct vk_device_extension_table *supported_extensions,
+ const struct vk_physical_device_dispatch_table *dispatch_table)
+{
+ memset(pdevice, 0, sizeof(*pdevice));
+ vk_object_base_init(NULL, &pdevice->base, VK_OBJECT_TYPE_PHYSICAL_DEVICE);
+ pdevice->instance = instance;
+
+ if (supported_extensions != NULL)
+ pdevice->supported_extensions = *supported_extensions;
+
+ pdevice->dispatch_table = *dispatch_table;
+
+ /* Add common entrypoints without overwriting driver-provided ones. */
+ vk_physical_device_dispatch_table_from_entrypoints(
+ &pdevice->dispatch_table, &vk_common_physical_device_entrypoints, false);
+
+ return VK_SUCCESS;
+}
+
+void
+vk_physical_device_finish(struct vk_physical_device *physical_device)
+{
+ vk_object_base_finish(&physical_device->base);
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL
+vk_common_EnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice,
+ uint32_t *pPropertyCount,
+ VkLayerProperties *pProperties)
+{
+ if (pProperties == NULL) {
+ *pPropertyCount = 0;
+ return VK_SUCCESS;
+ }
+
+ /* None supported at this time */
+ return VK_ERROR_LAYER_NOT_PRESENT;
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL
+vk_common_EnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice,
+ const char *pLayerName,
+ uint32_t *pPropertyCount,
+ VkExtensionProperties *pProperties)
+{
+ VK_FROM_HANDLE(vk_physical_device, pdevice, physicalDevice);
+ VK_OUTARRAY_MAKE_TYPED(VkExtensionProperties, out, pProperties, pPropertyCount);
+
+ for (int i = 0; i < VK_DEVICE_EXTENSION_COUNT; i++) {
+ if (!pdevice->supported_extensions.extensions[i])
+ continue;
+
+#ifdef ANDROID
+ if (!vk_android_allowed_device_extensions.extensions[i])
+ continue;
+#endif
+
+ vk_outarray_append_typed(VkExtensionProperties, &out, prop) {
+ *prop = vk_device_extensions[i];
+ }
+ }
+
+ return vk_outarray_status(&out);
+}
+
+VKAPI_ATTR void VKAPI_CALL
+vk_common_GetPhysicalDeviceFeatures(VkPhysicalDevice physicalDevice,
+ VkPhysicalDeviceFeatures *pFeatures)
+{
+ VK_FROM_HANDLE(vk_physical_device, pdevice, physicalDevice);
+
+ /* Don't zero-init this struct since the driver fills it out entirely */
+ VkPhysicalDeviceFeatures2 features2;
+ features2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
+ features2.pNext = NULL;
+
+ pdevice->dispatch_table.GetPhysicalDeviceFeatures2(physicalDevice,
+ &features2);
+ *pFeatures = features2.features;
+}
+
+VKAPI_ATTR void VKAPI_CALL
+vk_common_GetPhysicalDeviceProperties(VkPhysicalDevice physicalDevice,
+ VkPhysicalDeviceProperties *pProperties)
+{
+ VK_FROM_HANDLE(vk_physical_device, pdevice, physicalDevice);
+
+ /* Don't zero-init this struct since the driver fills it out entirely */
+ VkPhysicalDeviceProperties2 props2;
+ props2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
+ props2.pNext = NULL;
+
+ pdevice->dispatch_table.GetPhysicalDeviceProperties2(physicalDevice,
+ &props2);
+ *pProperties = props2.properties;
+}
+
+VKAPI_ATTR void VKAPI_CALL
+vk_common_GetPhysicalDeviceMemoryProperties(VkPhysicalDevice physicalDevice,
+ VkPhysicalDeviceMemoryProperties *pMemoryProperties)
+{
+ VK_FROM_HANDLE(vk_physical_device, pdevice, physicalDevice);
+
+ /* Don't zero-init this struct since the driver fills it out entirely */
+ VkPhysicalDeviceMemoryProperties2 props2;
+ props2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2;
+ props2.pNext = NULL;
+
+ pdevice->dispatch_table.GetPhysicalDeviceMemoryProperties2(physicalDevice,
+ &props2);
+ *pMemoryProperties = props2.memoryProperties;
+}
+
+VKAPI_ATTR void VKAPI_CALL
+vk_common_GetPhysicalDeviceFormatProperties(VkPhysicalDevice physicalDevice,
+ VkFormat format,
+ VkFormatProperties *pFormatProperties)
+{
+ VK_FROM_HANDLE(vk_physical_device, pdevice, physicalDevice);
+
+ /* Don't zero-init this struct since the driver fills it out entirely */
+ VkFormatProperties2 props2;
+ props2.sType = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2;
+ props2.pNext = NULL;
+
+ pdevice->dispatch_table.GetPhysicalDeviceFormatProperties2(physicalDevice,
+ format, &props2);
+ *pFormatProperties = props2.formatProperties;
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL
+vk_common_GetPhysicalDeviceImageFormatProperties(VkPhysicalDevice physicalDevice,
+ VkFormat format,
+ VkImageType type,
+ VkImageTiling tiling,
+ VkImageUsageFlags usage,
+ VkImageCreateFlags flags,
+ VkImageFormatProperties *pImageFormatProperties)
+{
+ VK_FROM_HANDLE(vk_physical_device, pdevice, physicalDevice);
+
+ VkPhysicalDeviceImageFormatInfo2 info = {
+ .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,
+ .format = format,
+ .type = type,
+ .tiling = tiling,
+ .usage = usage,
+ .flags = flags
+ };
+
+ /* Don't zero-init this struct since the driver fills it out entirely */
+ VkImageFormatProperties2 props2;
+ props2.sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2;
+ props2.pNext = NULL;
+
+ VkResult result =
+ pdevice->dispatch_table.GetPhysicalDeviceImageFormatProperties2(physicalDevice,
+ &info, &props2);
+ *pImageFormatProperties = props2.imageFormatProperties;
+
+ return result;
+}
diff --git a/lib/mesa/src/vulkan/util/vk_physical_device.h b/lib/mesa/src/vulkan/util/vk_physical_device.h
new file mode 100644
index 000000000..fea39ae9d
--- /dev/null
+++ b/lib/mesa/src/vulkan/util/vk_physical_device.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright © 2021 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+#ifndef VK_PHYSICAL_DEVICE_H
+#define VK_PHYSICAL_DEVICE_H
+
+#include "vk_dispatch_table.h"
+#include "vk_extensions.h"
+#include "vk_object.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct vk_physical_device {
+ struct vk_object_base base;
+ struct vk_instance *instance;
+
+ struct vk_device_extension_table supported_extensions;
+
+ struct vk_physical_device_dispatch_table dispatch_table;
+};
+
+VK_DEFINE_HANDLE_CASTS(vk_physical_device, base, VkPhysicalDevice,
+ VK_OBJECT_TYPE_PHYSICAL_DEVICE)
+
+VkResult MUST_CHECK
+vk_physical_device_init(struct vk_physical_device *physical_device,
+ struct vk_instance *instance,
+ const struct vk_device_extension_table *supported_extensions,
+ const struct vk_physical_device_dispatch_table *dispatch_table);
+
+void
+vk_physical_device_finish(struct vk_physical_device *physical_device);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* VK_PHYSICAL_DEVICE_H */
diff --git a/lib/mesa/src/vulkan/util/vk_render_pass.c b/lib/mesa/src/vulkan/util/vk_render_pass.c
new file mode 100644
index 000000000..fa736ec9c
--- /dev/null
+++ b/lib/mesa/src/vulkan/util/vk_render_pass.c
@@ -0,0 +1,291 @@
+/*
+ * Copyright © 2020 Valve Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include "vk_alloc.h"
+#include "vk_common_entrypoints.h"
+#include "vk_device.h"
+#include "vk_format.h"
+#include "vk_util.h"
+
+#include "util/log.h"
+
+static void
+translate_references(VkAttachmentReference2 **reference_ptr,
+ uint32_t reference_count,
+ const VkAttachmentReference *reference,
+ const VkRenderPassCreateInfo *pass_info,
+ bool is_input_attachment)
+{
+ VkAttachmentReference2 *reference2 = *reference_ptr;
+ *reference_ptr += reference_count;
+ for (uint32_t i = 0; i < reference_count; i++) {
+ reference2[i] = (VkAttachmentReference2) {
+ .sType = VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2,
+ .pNext = NULL,
+ .attachment = reference[i].attachment,
+ .layout = reference[i].layout,
+ };
+
+ if (is_input_attachment &&
+ reference2[i].attachment != VK_ATTACHMENT_UNUSED) {
+ assert(reference2[i].attachment < pass_info->attachmentCount);
+ const VkAttachmentDescription *att =
+ &pass_info->pAttachments[reference2[i].attachment];
+ reference2[i].aspectMask = vk_format_aspects(att->format);
+ }
+ }
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL
+vk_common_CreateRenderPass(VkDevice _device,
+ const VkRenderPassCreateInfo *pCreateInfo,
+ const VkAllocationCallbacks *pAllocator,
+ VkRenderPass *pRenderPass)
+{
+ VK_FROM_HANDLE(vk_device, device, _device);
+
+ uint32_t reference_count = 0;
+ for (uint32_t i = 0; i < pCreateInfo->subpassCount; i++) {
+ reference_count += pCreateInfo->pSubpasses[i].inputAttachmentCount;
+ reference_count += pCreateInfo->pSubpasses[i].colorAttachmentCount;
+ if (pCreateInfo->pSubpasses[i].pResolveAttachments)
+ reference_count += pCreateInfo->pSubpasses[i].colorAttachmentCount;
+ if (pCreateInfo->pSubpasses[i].pDepthStencilAttachment)
+ reference_count += 1;
+ }
+
+ VK_MULTIALLOC(ma);
+ VK_MULTIALLOC_DECL(&ma, VkRenderPassCreateInfo2, create_info, 1);
+ VK_MULTIALLOC_DECL(&ma, VkSubpassDescription2, subpasses,
+ pCreateInfo->subpassCount);
+ VK_MULTIALLOC_DECL(&ma, VkAttachmentDescription2, attachments,
+ pCreateInfo->attachmentCount);
+ VK_MULTIALLOC_DECL(&ma, VkSubpassDependency2, dependencies,
+ pCreateInfo->dependencyCount);
+ VK_MULTIALLOC_DECL(&ma, VkAttachmentReference2, references,
+ reference_count);
+ if (!vk_multialloc_alloc2(&ma, &device->alloc, pAllocator,
+ VK_SYSTEM_ALLOCATION_SCOPE_COMMAND))
+ return VK_ERROR_OUT_OF_HOST_MEMORY;
+
+ VkAttachmentReference2 *reference_ptr = references;
+
+ const VkRenderPassMultiviewCreateInfo *multiview_info = NULL;
+ const VkRenderPassInputAttachmentAspectCreateInfo *aspect_info = NULL;
+ vk_foreach_struct(ext, pCreateInfo->pNext) {
+ switch (ext->sType) {
+ case VK_STRUCTURE_TYPE_RENDER_PASS_INPUT_ATTACHMENT_ASPECT_CREATE_INFO:
+ aspect_info = (const VkRenderPassInputAttachmentAspectCreateInfo *)ext;
+ /* We don't care about this information */
+ break;
+
+ case VK_STRUCTURE_TYPE_RENDER_PASS_MULTIVIEW_CREATE_INFO:
+ multiview_info = (const VkRenderPassMultiviewCreateInfo*) ext;
+ break;
+
+ default:
+ mesa_logd("%s: ignored VkStructureType %u\n", __func__, ext->sType);
+ break;
+ }
+ }
+
+ for (uint32_t i = 0; i < pCreateInfo->attachmentCount; i++) {
+ attachments[i] = (VkAttachmentDescription2) {
+ .sType = VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2,
+ .pNext = NULL,
+ .flags = pCreateInfo->pAttachments[i].flags,
+ .format = pCreateInfo->pAttachments[i].format,
+ .samples = pCreateInfo->pAttachments[i].samples,
+ .loadOp = pCreateInfo->pAttachments[i].loadOp,
+ .storeOp = pCreateInfo->pAttachments[i].storeOp,
+ .stencilLoadOp = pCreateInfo->pAttachments[i].stencilLoadOp,
+ .stencilStoreOp = pCreateInfo->pAttachments[i].stencilStoreOp,
+ .initialLayout = pCreateInfo->pAttachments[i].initialLayout,
+ .finalLayout = pCreateInfo->pAttachments[i].finalLayout,
+ };
+ }
+
+ for (uint32_t i = 0; i < pCreateInfo->subpassCount; i++) {
+ subpasses[i] = (VkSubpassDescription2) {
+ .sType = VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2,
+ .pNext = NULL,
+ .flags = pCreateInfo->pSubpasses[i].flags,
+ .pipelineBindPoint = pCreateInfo->pSubpasses[i].pipelineBindPoint,
+ .viewMask = 0,
+ .inputAttachmentCount = pCreateInfo->pSubpasses[i].inputAttachmentCount,
+ .colorAttachmentCount = pCreateInfo->pSubpasses[i].colorAttachmentCount,
+ .preserveAttachmentCount = pCreateInfo->pSubpasses[i].preserveAttachmentCount,
+ .pPreserveAttachments = pCreateInfo->pSubpasses[i].pPreserveAttachments,
+ };
+
+ if (multiview_info && multiview_info->subpassCount) {
+ assert(multiview_info->subpassCount == pCreateInfo->subpassCount);
+ subpasses[i].viewMask = multiview_info->pViewMasks[i];
+ }
+
+ subpasses[i].pInputAttachments = reference_ptr;
+ translate_references(&reference_ptr,
+ subpasses[i].inputAttachmentCount,
+ pCreateInfo->pSubpasses[i].pInputAttachments,
+ pCreateInfo, true);
+ subpasses[i].pColorAttachments = reference_ptr;
+ translate_references(&reference_ptr,
+ subpasses[i].colorAttachmentCount,
+ pCreateInfo->pSubpasses[i].pColorAttachments,
+ pCreateInfo, false);
+ subpasses[i].pResolveAttachments = NULL;
+ if (pCreateInfo->pSubpasses[i].pResolveAttachments) {
+ subpasses[i].pResolveAttachments = reference_ptr;
+ translate_references(&reference_ptr,
+ subpasses[i].colorAttachmentCount,
+ pCreateInfo->pSubpasses[i].pResolveAttachments,
+ pCreateInfo, false);
+ }
+ subpasses[i].pDepthStencilAttachment = NULL;
+ if (pCreateInfo->pSubpasses[i].pDepthStencilAttachment) {
+ subpasses[i].pDepthStencilAttachment = reference_ptr;
+ translate_references(&reference_ptr, 1,
+ pCreateInfo->pSubpasses[i].pDepthStencilAttachment,
+ pCreateInfo, false);
+ }
+ }
+
+ assert(reference_ptr == references + reference_count);
+
+ if (aspect_info != NULL) {
+ for (uint32_t i = 0; i < aspect_info->aspectReferenceCount; i++) {
+ const VkInputAttachmentAspectReference *ref =
+ &aspect_info->pAspectReferences[i];
+
+ assert(ref->subpass < pCreateInfo->subpassCount);
+ VkSubpassDescription2 *subpass = &subpasses[ref->subpass];
+
+ assert(ref->inputAttachmentIndex < subpass->inputAttachmentCount);
+ VkAttachmentReference2 *att = (VkAttachmentReference2 *)
+ &subpass->pInputAttachments[ref->inputAttachmentIndex];
+
+ att->aspectMask = ref->aspectMask;
+ }
+ }
+
+ for (uint32_t i = 0; i < pCreateInfo->dependencyCount; i++) {
+ dependencies[i] = (VkSubpassDependency2) {
+ .sType = VK_STRUCTURE_TYPE_SUBPASS_DEPENDENCY_2,
+ .pNext = NULL,
+ .srcSubpass = pCreateInfo->pDependencies[i].srcSubpass,
+ .dstSubpass = pCreateInfo->pDependencies[i].dstSubpass,
+ .srcStageMask = pCreateInfo->pDependencies[i].srcStageMask,
+ .dstStageMask = pCreateInfo->pDependencies[i].dstStageMask,
+ .srcAccessMask = pCreateInfo->pDependencies[i].srcAccessMask,
+ .dstAccessMask = pCreateInfo->pDependencies[i].dstAccessMask,
+ .dependencyFlags = pCreateInfo->pDependencies[i].dependencyFlags,
+ .viewOffset = 0,
+ };
+
+ if (multiview_info && multiview_info->dependencyCount) {
+ assert(multiview_info->dependencyCount == pCreateInfo->dependencyCount);
+ dependencies[i].viewOffset = multiview_info->pViewOffsets[i];
+ }
+ }
+
+ *create_info = (VkRenderPassCreateInfo2) {
+ .sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO_2,
+ .pNext = pCreateInfo->pNext,
+ .flags = pCreateInfo->flags,
+ .attachmentCount = pCreateInfo->attachmentCount,
+ .pAttachments = attachments,
+ .subpassCount = pCreateInfo->subpassCount,
+ .pSubpasses = subpasses,
+ .dependencyCount = pCreateInfo->dependencyCount,
+ .pDependencies = dependencies,
+ };
+
+ if (multiview_info && multiview_info->correlationMaskCount > 0) {
+ create_info->correlatedViewMaskCount = multiview_info->correlationMaskCount;
+ create_info->pCorrelatedViewMasks = multiview_info->pCorrelationMasks;
+ }
+
+ VkResult result =
+ device->dispatch_table.CreateRenderPass2(_device, create_info,
+ pAllocator, pRenderPass);
+
+ vk_free2(&device->alloc, pAllocator, create_info);
+
+ return result;
+}
+
+VKAPI_ATTR void VKAPI_CALL
+vk_common_CmdBeginRenderPass(VkCommandBuffer commandBuffer,
+ const VkRenderPassBeginInfo* pRenderPassBegin,
+ VkSubpassContents contents)
+{
+ /* We don't have a vk_command_buffer object but we can assume, since we're
+ * using common dispatch, that it's a vk_object of some sort.
+ */
+ struct vk_object_base *disp = (struct vk_object_base *)commandBuffer;
+
+ VkSubpassBeginInfo info = {
+ .sType = VK_STRUCTURE_TYPE_SUBPASS_BEGIN_INFO,
+ .contents = contents,
+ };
+
+ disp->device->dispatch_table.CmdBeginRenderPass2(commandBuffer,
+ pRenderPassBegin, &info);
+}
+
+VKAPI_ATTR void VKAPI_CALL
+vk_common_CmdEndRenderPass(VkCommandBuffer commandBuffer)
+{
+ /* We don't have a vk_command_buffer object but we can assume, since we're
+ * using common dispatch, that it's a vk_object of some sort.
+ */
+ struct vk_object_base *disp = (struct vk_object_base *)commandBuffer;
+
+ VkSubpassEndInfo info = {
+ .sType = VK_STRUCTURE_TYPE_SUBPASS_END_INFO,
+ };
+
+ disp->device->dispatch_table.CmdEndRenderPass2(commandBuffer, &info);
+}
+
+VKAPI_ATTR void VKAPI_CALL
+vk_common_CmdNextSubpass(VkCommandBuffer commandBuffer,
+ VkSubpassContents contents)
+{
+ /* We don't have a vk_command_buffer object but we can assume, since we're
+ * using common dispatch, that it's a vk_object of some sort.
+ */
+ struct vk_object_base *disp = (struct vk_object_base *)commandBuffer;
+
+ VkSubpassBeginInfo begin_info = {
+ .sType = VK_STRUCTURE_TYPE_SUBPASS_BEGIN_INFO,
+ .contents = contents,
+ };
+
+ VkSubpassEndInfo end_info = {
+ .sType = VK_STRUCTURE_TYPE_SUBPASS_END_INFO,
+ };
+
+ disp->device->dispatch_table.CmdNextSubpass2(commandBuffer, &begin_info,
+ &end_info);
+}
diff --git a/lib/mesa/src/vulkan/util/vk_shader_module.c b/lib/mesa/src/vulkan/util/vk_shader_module.c
new file mode 100644
index 000000000..fd3671744
--- /dev/null
+++ b/lib/mesa/src/vulkan/util/vk_shader_module.c
@@ -0,0 +1,77 @@
+/*
+ * Copyright © 2017 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include "vk_shader_module.h"
+#include "util/mesa-sha1.h"
+#include "vk_common_entrypoints.h"
+#include "vk_device.h"
+
+VKAPI_ATTR VkResult VKAPI_CALL
+vk_common_CreateShaderModule(VkDevice _device,
+ const VkShaderModuleCreateInfo *pCreateInfo,
+ const VkAllocationCallbacks *pAllocator,
+ VkShaderModule *pShaderModule)
+{
+ VK_FROM_HANDLE(vk_device, device, _device);
+ struct vk_shader_module *module;
+
+ assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO);
+ assert(pCreateInfo->flags == 0);
+
+ module = vk_object_alloc(device, pAllocator,
+ sizeof(*module) + pCreateInfo->codeSize,
+ VK_OBJECT_TYPE_SHADER_MODULE);
+ if (module == NULL)
+ return VK_ERROR_OUT_OF_HOST_MEMORY;
+
+ module->size = pCreateInfo->codeSize;
+ module->nir = NULL;
+ memcpy(module->data, pCreateInfo->pCode, module->size);
+
+ _mesa_sha1_compute(module->data, module->size, module->sha1);
+
+ *pShaderModule = vk_shader_module_to_handle(module);
+
+ return VK_SUCCESS;
+}
+
+VKAPI_ATTR void VKAPI_CALL
+vk_common_DestroyShaderModule(VkDevice _device,
+ VkShaderModule _module,
+ const VkAllocationCallbacks *pAllocator)
+{
+ VK_FROM_HANDLE(vk_device, device, _device);
+ VK_FROM_HANDLE(vk_shader_module, module, _module);
+
+ if (!module)
+ return;
+
+ /* NIR modules (which are only created internally by the driver) are not
+ * dynamically allocated so we should never call this for them.
+ * Instead the driver is responsible for freeing the NIR code when it is
+ * no longer needed.
+ */
+ assert(module->nir == NULL);
+
+ vk_object_free(device, pAllocator, module);
+}
diff --git a/lib/mesa/src/vulkan/util/vk_shader_module.h b/lib/mesa/src/vulkan/util/vk_shader_module.h
new file mode 100644
index 000000000..d4e64dfc3
--- /dev/null
+++ b/lib/mesa/src/vulkan/util/vk_shader_module.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright © 2017 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#ifndef VK_SHADER_MODULE_H
+#define VK_SHADER_MODULE_H
+
+#include <vulkan/vulkan.h>
+#include "vk_object.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct nir_shader;
+
+struct vk_shader_module {
+ struct vk_object_base base;
+ struct nir_shader *nir;
+ unsigned char sha1[20];
+ uint32_t size;
+ char data[0];
+};
+
+VK_DEFINE_NONDISP_HANDLE_CASTS(vk_shader_module, base, VkShaderModule,
+ VK_OBJECT_TYPE_SHADER_MODULE)
+
+/* this should only be used for stack-allocated, temporary objects */
+#define vk_shader_module_handle_from_nir(_nir) \
+ vk_shader_module_to_handle(&(struct vk_shader_module) { \
+ .base.type = VK_OBJECT_TYPE_SHADER_MODULE, \
+ .nir = _nir, \
+ })
+#define vk_shader_module_from_nir(_nir) \
+ (struct vk_shader_module) { \
+ .base.type = VK_OBJECT_TYPE_SHADER_MODULE, \
+ .nir = _nir, \
+ }
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* VK_SHADER_MODULE_H */