summaryrefslogtreecommitdiff
path: root/lib/mesa/src/vulkan
diff options
context:
space:
mode:
Diffstat (limited to 'lib/mesa/src/vulkan')
-rw-r--r--lib/mesa/src/vulkan/Android.mk50
-rw-r--r--lib/mesa/src/vulkan/meson.build13
-rw-r--r--lib/mesa/src/vulkan/overlay-layer/meson.build13
-rw-r--r--lib/mesa/src/vulkan/overlay-layer/overlay.cpp154
-rw-r--r--lib/mesa/src/vulkan/overlay-layer/overlay_params.c2
-rw-r--r--lib/mesa/src/vulkan/overlay-layer/overlay_params.h2
-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
-rw-r--r--lib/mesa/src/vulkan/vulkan-icd-symbols.txt5
-rw-r--r--lib/mesa/src/vulkan/wsi/meson.build15
-rw-r--r--lib/mesa/src/vulkan/wsi/wsi_common.c643
-rw-r--r--lib/mesa/src/vulkan/wsi/wsi_common_display.c69
-rw-r--r--lib/mesa/src/vulkan/wsi/wsi_common_display.h11
-rw-r--r--lib/mesa/src/vulkan/wsi/wsi_common_drm.c621
-rw-r--r--lib/mesa/src/vulkan/wsi/wsi_common_private.h28
-rw-r--r--lib/mesa/src/vulkan/wsi/wsi_common_win32.c675
-rw-r--r--lib/mesa/src/vulkan/wsi/wsi_common_win32.h37
41 files changed, 6011 insertions, 801 deletions
diff --git a/lib/mesa/src/vulkan/Android.mk b/lib/mesa/src/vulkan/Android.mk
index 4b1695abc..295c57d3c 100644
--- a/lib/mesa/src/vulkan/Android.mk
+++ b/lib/mesa/src/vulkan/Android.mk
@@ -38,7 +38,8 @@ intermediates := $(call local-generated-sources-dir)
LOCAL_C_INCLUDES := \
$(MESA_TOP)/include/vulkan \
$(MESA_TOP)/src/vulkan/util \
- $(MESA_TOP)/src/gallium/include
+ $(MESA_TOP)/src/gallium/include \
+ $(intermediates)/util \
ifeq ($(shell test $(PLATFORM_SDK_VERSION) -ge 27; echo $$?), 0)
LOCAL_C_INCLUDES += \
@@ -55,7 +56,7 @@ LOCAL_SRC_FILES := $(VULKAN_UTIL_FILES) $(VULKAN_WSI_FILES)
vulkan_api_xml = $(MESA_TOP)/src/vulkan/registry/vk.xml
-$(firstword $(LOCAL_GENERATED_SOURCES)): $(MESA_TOP)/src/vulkan/util/gen_enum_to_str.py \
+$(intermediates)/util/vk_enum_to_str.c: $(MESA_TOP)/src/vulkan/util/gen_enum_to_str.py \
$(vulkan_api_xml)
@echo "target Generated: $(PRIVATE_MODULE) <= $(notdir $(@))"
@mkdir -p $(dir $@)
@@ -63,7 +64,50 @@ $(firstword $(LOCAL_GENERATED_SOURCES)): $(MESA_TOP)/src/vulkan/util/gen_enum_to
--xml $(vulkan_api_xml) \
--outdir $(dir $@)
-$(lastword $(LOCAL_GENERATED_SOURCES)): $(firstword $(LOCAL_GENERATED_SOURCES))
+$(intermediates)/util/vk_enum_to_str.h: $(intermediates)/util/vk_enum_to_str.c
+
+$(intermediates)/util/vk_common_entrypoints.c: $(MESA_TOP)/src/vulkan/util/vk_entrypoints_gen.py \
+ $(vulkan_api_xml)
+ @echo "target Generated: $(PRIVATE_MODULE) <= $(notdir $(@))"
+ @mkdir -p $(dir $@)
+ $(hide) $(MESA_PYTHON2) $< \
+ --xml $(vulkan_api_xml) \
+ --proto --weak --prefix vk_common \
+ --out-c $@ --out-h $(dir $@)/vk_common_entrypoints.h
+
+$(intermediates)/util/vk_common_entrypoints.h: $(intermediates)/util/vk_common_entrypoints.c
+
+$(intermediates)/util/vk_dispatch_table.c: $(MESA_TOP)/src/vulkan/util/vk_dispatch_table_gen.py \
+ $(vulkan_api_xml)
+ @echo "target Generated: $(PRIVATE_MODULE) <= $(notdir $(@))"
+ @mkdir -p $(dir $@)
+ $(hide) $(MESA_PYTHON2) $< \
+ --xml $(vulkan_api_xml) \
+ --out-c $@
+
+$(intermediates)/util/vk_dispatch_table.h: $(MESA_TOP)/src/vulkan/util/vk_dispatch_table_gen.py \
+ $(vulkan_api_xml)
+ @echo "target Generated: $(PRIVATE_MODULE) <= $(notdir $(@))"
+ @mkdir -p $(dir $@)
+ $(hide) $(MESA_PYTHON2) $< \
+ --xml $(vulkan_api_xml) \
+ --out-h $@
+
+$(intermediates)/util/vk_extensions.c: $(MESA_TOP)/src/vulkan/util/vk_extensions_gen.py \
+ $(vulkan_api_xml)
+ @echo "target Generated: $(PRIVATE_MODULE) <= $(notdir $(@))"
+ @mkdir -p $(dir $@)
+ $(hide) $(MESA_PYTHON2) $< \
+ --xml $(vulkan_api_xml) \
+ --out-c $@
+
+$(intermediates)/util/vk_extensions.h: $(MESA_TOP)/src/vulkan/util/vk_extensions_gen.py \
+ $(vulkan_api_xml)
+ @echo "target Generated: $(PRIVATE_MODULE) <= $(notdir $(@))"
+ @mkdir -p $(dir $@)
+ $(hide) $(MESA_PYTHON2) $< \
+ --xml $(vulkan_api_xml) \
+ --out-h $@
LOCAL_EXPORT_C_INCLUDE_DIRS := $(intermediates)/util
diff --git a/lib/mesa/src/vulkan/meson.build b/lib/mesa/src/vulkan/meson.build
index e1e8f753b..3f95551f2 100644
--- a/lib/mesa/src/vulkan/meson.build
+++ b/lib/mesa/src/vulkan/meson.build
@@ -22,6 +22,7 @@ vk_api_xml = files('registry/vk.xml')
vulkan_icd_symbols = files('vulkan-icd-symbols.txt')
inc_vulkan_wsi = include_directories('wsi')
+inc_vulkan_util = include_directories('util')
vulkan_wsi_args = []
vulkan_wsi_deps = []
@@ -32,10 +33,10 @@ if with_platform_x11
vulkan_wsi_deps += [
dep_xcb,
dep_x11_xcb,
- dep_xcb_dri2,
dep_xcb_dri3,
dep_xcb_present,
dep_xcb_sync,
+ dep_xcb_xrandr,
dep_xshmfence,
]
vulkan_wsi_list += ['xcb', 'x11']
@@ -45,14 +46,17 @@ if with_platform_wayland
vulkan_wsi_deps += dep_wayland_client
vulkan_wsi_list += ['wayland']
endif
-if with_platform_drm
+if with_platform_windows
+ vulkan_wsi_args += ['-DVK_USE_PLATFORM_WIN32_KHR']
+endif
+if system_has_kms_drm and not with_platform_android
vulkan_wsi_args += '-DVK_USE_PLATFORM_DISPLAY_KHR'
vulkan_wsi_deps += [dep_libdrm]
vulkan_wsi_list += ['drm']
endif
if with_xlib_lease
vulkan_wsi_args += '-DVK_USE_PLATFORM_XLIB_XRANDR_EXT'
- vulkan_wsi_deps += [dep_xcb_xrandr, dep_xlib_xrandr]
+ vulkan_wsi_deps += [dep_xlib_xrandr]
vulkan_wsi_list += ['xlib_xrandr']
endif
@@ -62,3 +66,6 @@ subdir('wsi')
if with_vulkan_overlay_layer
subdir('overlay-layer')
endif
+if with_vulkan_device_select_layer
+ subdir('device-select-layer')
+endif
diff --git a/lib/mesa/src/vulkan/overlay-layer/meson.build b/lib/mesa/src/vulkan/overlay-layer/meson.build
index 5f9224048..3225b3f51 100644
--- a/lib/mesa/src/vulkan/overlay-layer/meson.build
+++ b/lib/mesa/src/vulkan/overlay-layer/meson.build
@@ -18,8 +18,6 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
-glslang = find_program('glslangValidator')
-
overlay_shaders = [
'overlay.frag',
'overlay.vert',
@@ -28,7 +26,7 @@ overlay_spv = []
foreach s : ['overlay.frag', 'overlay.vert']
overlay_spv += custom_target(
s + '.spv.h', input : s, output : s + '.spv.h',
- command : [glslang, '-V', '-x', '-o', '@OUTPUT@', '@INPUT@'])
+ command : [prog_glslang, '-V', '-x', '-o', '@OUTPUT@', '@INPUT@'])
endforeach
vklayer_files = files(
@@ -38,11 +36,12 @@ vklayer_files = files(
vklayer_mesa_overlay = shared_library(
'VkLayer_MESA_overlay',
- vklayer_files, overlay_spv,
- c_args : [c_vis_args, no_override_init_args, vulkan_wsi_args],
- cpp_args : [cpp_vis_args, vulkan_wsi_args],
+ vklayer_files, overlay_spv, sha1_h,
+ c_args : [no_override_init_args, vulkan_wsi_args],
+ cpp_args : [vulkan_wsi_args],
+ gnu_symbol_visibility : 'hidden',
dependencies : [idep_vulkan_util, idep_mesautil, vulkan_wsi_deps, libimgui_core_dep, dep_dl],
- include_directories : inc_common,
+ include_directories : [inc_include, inc_src],
link_args : cc.get_supported_link_arguments(['-Wl,-Bsymbolic-functions', '-Wl,-z,relro']),
install : true
)
diff --git a/lib/mesa/src/vulkan/overlay-layer/overlay.cpp b/lib/mesa/src/vulkan/overlay-layer/overlay.cpp
index 565f5884b..6500c477b 100644
--- a/lib/mesa/src/vulkan/overlay-layer/overlay.cpp
+++ b/lib/mesa/src/vulkan/overlay-layer/overlay.cpp
@@ -43,11 +43,13 @@
#include "util/simple_mtx.h"
#include "vk_enum_to_str.h"
+#include "vk_dispatch_table.h"
#include "vk_util.h"
/* Mapped from VkInstace/VkPhysicalDevice */
struct instance_data {
struct vk_instance_dispatch_table vtable;
+ struct vk_physical_device_dispatch_table pd_vtable;
VkInstance instance;
struct overlay_params params;
@@ -125,6 +127,8 @@ struct overlay_draw {
VkCommandBuffer command_buffer;
+ VkSemaphore cross_engine_semaphore;
+
VkSemaphore semaphore;
VkFence fence;
@@ -417,14 +421,14 @@ static void device_map_queues(struct device_data *data,
struct instance_data *instance_data = data->instance;
uint32_t n_family_props;
- instance_data->vtable.GetPhysicalDeviceQueueFamilyProperties(data->physical_device,
- &n_family_props,
- NULL);
+ instance_data->pd_vtable.GetPhysicalDeviceQueueFamilyProperties(data->physical_device,
+ &n_family_props,
+ NULL);
VkQueueFamilyProperties *family_props =
(VkQueueFamilyProperties *)malloc(sizeof(VkQueueFamilyProperties) * n_family_props);
- instance_data->vtable.GetPhysicalDeviceQueueFamilyProperties(data->physical_device,
- &n_family_props,
- family_props);
+ instance_data->pd_vtable.GetPhysicalDeviceQueueFamilyProperties(data->physical_device,
+ &n_family_props,
+ family_props);
uint32_t queue_index = 0;
for (uint32_t i = 0; i < pCreateInfo->queueCreateInfoCount; i++) {
@@ -544,6 +548,8 @@ struct overlay_draw *get_overlay_draw(struct swapchain_data *data)
VK_CHECK(device_data->vtable.CreateSemaphore(device_data->device, &sem_info,
NULL, &draw->semaphore));
+ VK_CHECK(device_data->vtable.CreateSemaphore(device_data->device, &sem_info,
+ NULL, &draw->cross_engine_semaphore));
list_addtail(&draw->link, &data->draws);
@@ -924,12 +930,16 @@ static void compute_swapchain_display(struct swapchain_data *data)
ImGui::NewFrame();
position_layer(data);
ImGui::Begin("Mesa overlay");
- ImGui::Text("Device: %s", device_data->properties.deviceName);
+ if (instance_data->params.enabled[OVERLAY_PARAM_ENABLED_device])
+ ImGui::Text("Device: %s", device_data->properties.deviceName);
- const char *format_name = vk_Format_to_str(data->format);
- format_name = format_name ? (format_name + strlen("VK_FORMAT_")) : "unknown";
- ImGui::Text("Swapchain format: %s", format_name);
- ImGui::Text("Frames: %" PRIu64, data->n_frames);
+ if (instance_data->params.enabled[OVERLAY_PARAM_ENABLED_format]) {
+ const char *format_name = vk_Format_to_str(data->format);
+ format_name = format_name ? (format_name + strlen("VK_FORMAT_")) : "unknown";
+ ImGui::Text("Swapchain format: %s", format_name);
+ }
+ if (instance_data->params.enabled[OVERLAY_PARAM_ENABLED_frame])
+ ImGui::Text("Frames: %" PRIu64, data->n_frames);
if (instance_data->params.enabled[OVERLAY_PARAM_ENABLED_fps])
ImGui::Text("FPS: %.2f" , data->fps);
@@ -999,7 +1009,7 @@ static uint32_t vk_memory_type(struct device_data *data,
uint32_t type_bits)
{
VkPhysicalDeviceMemoryProperties prop;
- data->instance->vtable.GetPhysicalDeviceMemoryProperties(data->physical_device, &prop);
+ data->instance->pd_vtable.GetPhysicalDeviceMemoryProperties(data->physical_device, &prop);
for (uint32_t i = 0; i < prop.memoryTypeCount; i++)
if ((prop.memoryTypes[i].propertyFlags & properties) == properties && type_bits & (1<<i))
return i;
@@ -1322,7 +1332,7 @@ static struct overlay_draw *render_swapchain_display(struct swapchain_data *data
if (device_data->graphic_queue->family_index != present_queue->family_index)
{
/* Transfer the image back to the present queue family
- * image layout was already changed to present by the render pass
+ * image layout was already changed to present by the render pass
*/
imb.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
imb.pNext = nullptr;
@@ -1349,26 +1359,55 @@ static struct overlay_draw *render_swapchain_display(struct swapchain_data *data
device_data->vtable.EndCommandBuffer(draw->command_buffer);
- VkPipelineStageFlags *stages_wait = (VkPipelineStageFlags*) malloc(sizeof(VkPipelineStageFlags) * n_wait_semaphores);
- for (unsigned i = 0; i < n_wait_semaphores; i++)
- {
- // wait in the fragment stage until the swapchain image is ready
- stages_wait[i] = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
+ /* When presenting on a different queue than where we're drawing the
+ * overlay *AND* when the application does not provide a semaphore to
+ * vkQueuePresent, insert our own cross engine synchronization
+ * semaphore.
+ */
+ if (n_wait_semaphores == 0 && device_data->graphic_queue->queue != present_queue->queue) {
+ VkPipelineStageFlags stages_wait = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
+ VkSubmitInfo submit_info = {};
+ submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
+ submit_info.commandBufferCount = 0;
+ submit_info.pWaitDstStageMask = &stages_wait;
+ submit_info.waitSemaphoreCount = 0;
+ submit_info.signalSemaphoreCount = 1;
+ submit_info.pSignalSemaphores = &draw->cross_engine_semaphore;
+
+ device_data->vtable.QueueSubmit(present_queue->queue, 1, &submit_info, VK_NULL_HANDLE);
+
+ submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
+ submit_info.commandBufferCount = 1;
+ submit_info.pWaitDstStageMask = &stages_wait;
+ submit_info.pCommandBuffers = &draw->command_buffer;
+ submit_info.waitSemaphoreCount = 1;
+ submit_info.pWaitSemaphores = &draw->cross_engine_semaphore;
+ submit_info.signalSemaphoreCount = 1;
+ submit_info.pSignalSemaphores = &draw->semaphore;
+
+ device_data->vtable.QueueSubmit(device_data->graphic_queue->queue, 1, &submit_info, draw->fence);
+ } else {
+ VkPipelineStageFlags *stages_wait = (VkPipelineStageFlags*) malloc(sizeof(VkPipelineStageFlags) * n_wait_semaphores);
+ for (unsigned i = 0; i < n_wait_semaphores; i++)
+ {
+ // wait in the fragment stage until the swapchain image is ready
+ stages_wait[i] = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
+ }
+
+ VkSubmitInfo submit_info = {};
+ submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
+ submit_info.commandBufferCount = 1;
+ submit_info.pCommandBuffers = &draw->command_buffer;
+ submit_info.pWaitDstStageMask = stages_wait;
+ submit_info.waitSemaphoreCount = n_wait_semaphores;
+ submit_info.pWaitSemaphores = wait_semaphores;
+ submit_info.signalSemaphoreCount = 1;
+ submit_info.pSignalSemaphores = &draw->semaphore;
+
+ device_data->vtable.QueueSubmit(device_data->graphic_queue->queue, 1, &submit_info, draw->fence);
+
+ free(stages_wait);
}
-
- VkSubmitInfo submit_info = {};
- submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
- submit_info.commandBufferCount = 1;
- submit_info.pCommandBuffers = &draw->command_buffer;
- submit_info.pWaitDstStageMask = stages_wait;
- submit_info.waitSemaphoreCount = n_wait_semaphores;
- submit_info.pWaitSemaphores = wait_semaphores;
- submit_info.signalSemaphoreCount = 1;
- submit_info.pSignalSemaphores = &draw->semaphore;
-
- device_data->vtable.QueueSubmit(device_data->graphic_queue->queue, 1, &submit_info, draw->fence);
-
- free(stages_wait);
return draw;
}
@@ -1750,6 +1789,7 @@ static void shutdown_swapchain_data(struct swapchain_data *data)
struct device_data *device_data = data->device;
list_for_each_entry_safe(struct overlay_draw, draw, &data->draws, link) {
+ device_data->vtable.DestroySemaphore(device_data->device, draw->cross_engine_semaphore, NULL);
device_data->vtable.DestroySemaphore(device_data->device, draw->semaphore, NULL);
device_data->vtable.DestroyFence(device_data->device, draw->fence, NULL);
device_data->vtable.DestroyBuffer(device_data->device, draw->vertex_buffer, NULL);
@@ -1827,6 +1867,12 @@ static void overlay_DestroySwapchainKHR(
VkSwapchainKHR swapchain,
const VkAllocationCallbacks* pAllocator)
{
+ if (swapchain == VK_NULL_HANDLE) {
+ struct device_data *device_data = FIND(struct device_data, device);
+ device_data->vtable.DestroySwapchainKHR(device, swapchain, pAllocator);
+ return;
+ }
+
struct swapchain_data *swapchain_data =
FIND(struct swapchain_data, swapchain);
@@ -2426,26 +2472,40 @@ static VkResult overlay_CreateDevice(
chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
VkPhysicalDeviceFeatures device_features = {};
- VkDeviceCreateInfo device_info = *pCreateInfo;
+ VkPhysicalDeviceFeatures *device_features_ptr = NULL;
+
+ VkDeviceCreateInfo *device_info = (VkDeviceCreateInfo *)
+ clone_chain((const struct VkBaseInStructure *)pCreateInfo);
+
+ VkPhysicalDeviceFeatures2 *device_features2 = (VkPhysicalDeviceFeatures2 *)
+ vk_find_struct(device_info, PHYSICAL_DEVICE_FEATURES_2);
+ if (device_features2) {
+ /* Can't use device_info->pEnabledFeatures when VkPhysicalDeviceFeatures2 is present */
+ device_features_ptr = &device_features2->features;
+ } else {
+ if (device_info->pEnabledFeatures)
+ device_features = *(device_info->pEnabledFeatures);
+ device_features_ptr = &device_features;
+ device_info->pEnabledFeatures = &device_features;
+ }
- if (pCreateInfo->pEnabledFeatures)
- device_features = *(pCreateInfo->pEnabledFeatures);
if (instance_data->pipeline_statistics_enabled) {
- device_features.inheritedQueries = true;
- device_features.pipelineStatisticsQuery = true;
+ device_features_ptr->inheritedQueries = true;
+ device_features_ptr->pipelineStatisticsQuery = true;
}
- device_info.pEnabledFeatures = &device_features;
- VkResult result = fpCreateDevice(physicalDevice, &device_info, pAllocator, pDevice);
+ VkResult result = fpCreateDevice(physicalDevice, device_info, pAllocator, pDevice);
+ free_chain((struct VkBaseOutStructure *)device_info);
if (result != VK_SUCCESS) return result;
struct device_data *device_data = new_device_data(*pDevice, instance_data);
device_data->physical_device = physicalDevice;
- vk_load_device_commands(*pDevice, fpGetDeviceProcAddr, &device_data->vtable);
+ vk_device_dispatch_table_load(&device_data->vtable,
+ fpGetDeviceProcAddr, *pDevice);
- instance_data->vtable.GetPhysicalDeviceProperties(device_data->physical_device,
- &device_data->properties);
+ instance_data->pd_vtable.GetPhysicalDeviceProperties(device_data->physical_device,
+ &device_data->properties);
VkLayerDeviceCreateInfo *load_data_info =
get_device_chain_info(pCreateInfo, VK_LOADER_DATA_CALLBACK);
@@ -2490,9 +2550,12 @@ static VkResult overlay_CreateInstance(
if (result != VK_SUCCESS) return result;
struct instance_data *instance_data = new_instance_data(*pInstance);
- vk_load_instance_commands(instance_data->instance,
- fpGetInstanceProcAddr,
- &instance_data->vtable);
+ vk_instance_dispatch_table_load(&instance_data->vtable,
+ fpGetInstanceProcAddr,
+ instance_data->instance);
+ vk_physical_device_dispatch_table_load(&instance_data->pd_vtable,
+ fpGetInstanceProcAddr,
+ instance_data->instance);
instance_data_map_physical_devices(instance_data, true);
parse_overlay_env(&instance_data->params, getenv("VK_LAYER_MESA_OVERLAY_CONFIG"));
@@ -2529,6 +2592,7 @@ static const struct {
const char *name;
void *ptr;
} name_to_funcptr_map[] = {
+ { "vkGetInstanceProcAddr", (void *) vkGetInstanceProcAddr },
{ "vkGetDeviceProcAddr", (void *) vkGetDeviceProcAddr },
#define ADD_HOOK(fn) { "vk" # fn, (void *) overlay_ ## fn }
#define ADD_ALIAS_HOOK(alias, fn) { "vk" # alias, (void *) overlay_ ## fn }
diff --git a/lib/mesa/src/vulkan/overlay-layer/overlay_params.c b/lib/mesa/src/vulkan/overlay-layer/overlay_params.c
index afc17ec07..48a9f7e3b 100644
--- a/lib/mesa/src/vulkan/overlay-layer/overlay_params.c
+++ b/lib/mesa/src/vulkan/overlay-layer/overlay_params.c
@@ -165,6 +165,8 @@ parse_overlay_env(struct overlay_params *params,
/* Visible by default */
params->enabled[OVERLAY_PARAM_ENABLED_fps] = true;
params->enabled[OVERLAY_PARAM_ENABLED_frame_timing] = true;
+ params->enabled[OVERLAY_PARAM_ENABLED_device] = true;
+ params->enabled[OVERLAY_PARAM_ENABLED_format] = true;
params->fps_sampling_period = 500000; /* 500ms */
params->width = params->height = 300;
params->control = -1;
diff --git a/lib/mesa/src/vulkan/overlay-layer/overlay_params.h b/lib/mesa/src/vulkan/overlay-layer/overlay_params.h
index 7ff092dae..e919f74ff 100644
--- a/lib/mesa/src/vulkan/overlay-layer/overlay_params.h
+++ b/lib/mesa/src/vulkan/overlay-layer/overlay_params.h
@@ -33,6 +33,8 @@ extern "C" {
#include <stdbool.h>
#define OVERLAY_PARAMS \
+ OVERLAY_PARAM_BOOL(device) \
+ OVERLAY_PARAM_BOOL(format) \
OVERLAY_PARAM_BOOL(fps) \
OVERLAY_PARAM_BOOL(frame) \
OVERLAY_PARAM_BOOL(frame_timing) \
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 */
diff --git a/lib/mesa/src/vulkan/vulkan-icd-symbols.txt b/lib/mesa/src/vulkan/vulkan-icd-symbols.txt
index feca419c0..b463ca83a 100644
--- a/lib/mesa/src/vulkan/vulkan-icd-symbols.txt
+++ b/lib/mesa/src/vulkan/vulkan-icd-symbols.txt
@@ -12,3 +12,8 @@ vk_icdNegotiateLoaderICDInterfaceVersion
# Version 4 - Add unknown physical device extension querying via
# vk_icdGetPhysicalDeviceProcAddr.
(optional) vk_icdGetPhysicalDeviceProcAddr
+
+# Andoid looks for this global in HAL modules. In the source it occurs
+# as HAL_MODULE_INFO_SYM (which is just a #define for HMI) and it's an
+# instance of struct hwvulkan_module_t.
+(optional) HMI
diff --git a/lib/mesa/src/vulkan/wsi/meson.build b/lib/mesa/src/vulkan/wsi/meson.build
index 6cf9a04f3..1deafa0c5 100644
--- a/lib/mesa/src/vulkan/wsi/meson.build
+++ b/lib/mesa/src/vulkan/wsi/meson.build
@@ -20,6 +20,10 @@
files_vulkan_wsi = files('wsi_common.c')
+if dep_libdrm.found()
+ files_vulkan_wsi += files('wsi_common_drm.c')
+endif
+
if with_platform_x11
files_vulkan_wsi += files('wsi_common_x11.c')
endif
@@ -34,15 +38,20 @@ if with_platform_wayland
]
endif
-if with_platform_drm
+if with_platform_windows
+ files_vulkan_wsi += files('wsi_common_win32.c')
+endif
+
+if system_has_kms_drm and not with_platform_android
files_vulkan_wsi += files('wsi_common_display.c')
endif
libvulkan_wsi = static_library(
'vulkan_wsi',
files_vulkan_wsi,
- include_directories : [inc_common, inc_include],
+ include_directories : [inc_include, inc_src],
dependencies : [vulkan_wsi_deps, dep_libdrm, idep_vulkan_util, idep_xmlconfig],
- c_args : [c_vis_args, vulkan_wsi_args],
+ c_args : [vulkan_wsi_args],
+ gnu_symbol_visibility : 'hidden',
build_by_default : false,
)
diff --git a/lib/mesa/src/vulkan/wsi/wsi_common.c b/lib/mesa/src/vulkan/wsi/wsi_common.c
index d629ea339..b1360edb9 100644
--- a/lib/mesa/src/vulkan/wsi/wsi_common.c
+++ b/lib/mesa/src/vulkan/wsi/wsi_common.c
@@ -22,14 +22,13 @@
*/
#include "wsi_common_private.h"
-#include "drm-uapi/drm_fourcc.h"
#include "util/macros.h"
+#include "util/os_file.h"
+#include "util/os_time.h"
#include "util/xmlconfig.h"
#include "vk_util.h"
#include <time.h>
-#include <unistd.h>
-#include <xf86drm.h>
#include <stdlib.h>
#include <stdio.h>
@@ -39,7 +38,8 @@ wsi_device_init(struct wsi_device *wsi,
WSI_FN_GetPhysicalDeviceProcAddr proc_addr,
const VkAllocationCallbacks *alloc,
int display_fd,
- const struct driOptionCache *dri_options)
+ const struct driOptionCache *dri_options,
+ bool sw_device)
{
const char *present_mode;
UNUSED VkResult result;
@@ -48,7 +48,7 @@ wsi_device_init(struct wsi_device *wsi,
wsi->instance_alloc = *alloc;
wsi->pdevice = pdevice;
-
+ wsi->sw = sw_device;
#define WSI_GET_CB(func) \
PFN_vk##func func = (PFN_vk##func)proc_addr(pdevice, "vk" #func)
WSI_GET_CB(GetPhysicalDeviceProperties2);
@@ -93,13 +93,16 @@ wsi_device_init(struct wsi_device *wsi,
WSI_GET_CB(GetImageDrmFormatModifierPropertiesEXT);
WSI_GET_CB(GetImageMemoryRequirements);
WSI_GET_CB(GetImageSubresourceLayout);
- WSI_GET_CB(GetMemoryFdKHR);
+ if (!wsi->sw)
+ WSI_GET_CB(GetMemoryFdKHR);
WSI_GET_CB(GetPhysicalDeviceFormatProperties);
WSI_GET_CB(GetPhysicalDeviceFormatProperties2KHR);
WSI_GET_CB(GetPhysicalDeviceImageFormatProperties2);
WSI_GET_CB(ResetFences);
WSI_GET_CB(QueueSubmit);
WSI_GET_CB(WaitForFences);
+ WSI_GET_CB(MapMemory);
+ WSI_GET_CB(UnmapMemory);
#undef WSI_GET_CB
#ifdef VK_USE_PLATFORM_XCB_KHR
@@ -114,6 +117,12 @@ wsi_device_init(struct wsi_device *wsi,
goto fail;
#endif
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ result = wsi_win32_init_wsi(wsi, alloc, pdevice);
+ if (result != VK_SUCCESS)
+ goto fail;
+#endif
+
#ifdef VK_USE_PLATFORM_DISPLAY_KHR
result = wsi_display_init_wsi(wsi, alloc, display_fd);
if (result != VK_SUCCESS)
@@ -124,6 +133,8 @@ wsi_device_init(struct wsi_device *wsi,
if (present_mode) {
if (!strcmp(present_mode, "fifo")) {
wsi->override_present_mode = VK_PRESENT_MODE_FIFO_KHR;
+ } else if (!strcmp(present_mode, "relaxed")) {
+ wsi->override_present_mode = VK_PRESENT_MODE_FIFO_RELAXED_KHR;
} else if (!strcmp(present_mode, "mailbox")) {
wsi->override_present_mode = VK_PRESENT_MODE_MAILBOX_KHR;
} else if (!strcmp(present_mode, "immediate")) {
@@ -147,6 +158,7 @@ wsi_device_init(struct wsi_device *wsi,
return VK_SUCCESS;
#if defined(VK_USE_PLATFORM_XCB_KHR) || \
defined(VK_USE_PLATFORM_WAYLAND_KHR) || \
+ defined(VK_USE_PLATFORM_WIN32_KHR) || \
defined(VK_USE_PLATFORM_DISPLAY_KHR)
fail:
wsi_device_finish(wsi, alloc);
@@ -164,37 +176,14 @@ wsi_device_finish(struct wsi_device *wsi,
#ifdef VK_USE_PLATFORM_WAYLAND_KHR
wsi_wl_finish_wsi(wsi, alloc);
#endif
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ wsi_win32_finish_wsi(wsi, alloc);
+#endif
#ifdef VK_USE_PLATFORM_XCB_KHR
wsi_x11_finish_wsi(wsi, alloc);
#endif
}
-bool
-wsi_device_matches_drm_fd(const struct wsi_device *wsi, int drm_fd)
-{
- drmDevicePtr fd_device;
- int ret = drmGetDevice2(drm_fd, 0, &fd_device);
- if (ret)
- return false;
-
- bool match = false;
- switch (fd_device->bustype) {
- case DRM_BUS_PCI:
- match = wsi->pci_bus_info.pciDomain == fd_device->businfo.pci->domain &&
- wsi->pci_bus_info.pciBus == fd_device->businfo.pci->bus &&
- wsi->pci_bus_info.pciDevice == fd_device->businfo.pci->dev &&
- wsi->pci_bus_info.pciFunction == fd_device->businfo.pci->func;
- break;
-
- default:
- break;
- }
-
- drmFreeDevice(&fd_device);
-
- return match;
-}
-
VkResult
wsi_swapchain_init(const struct wsi_device *wsi,
struct wsi_swapchain *chain,
@@ -206,6 +195,8 @@ wsi_swapchain_init(const struct wsi_device *wsi,
memset(chain, 0, sizeof(*chain));
+ vk_object_base_init(NULL, &chain->base, VK_OBJECT_TYPE_SWAPCHAIN_KHR);
+
chain->wsi = wsi;
chain->device = device;
chain->alloc = *pAllocator;
@@ -305,562 +296,8 @@ wsi_swapchain_finish(struct wsi_swapchain *chain)
&chain->alloc);
}
vk_free(&chain->alloc, chain->cmd_pools);
-}
-
-static uint32_t
-select_memory_type(const struct wsi_device *wsi,
- VkMemoryPropertyFlags props,
- uint32_t type_bits)
-{
- for (uint32_t i = 0; i < wsi->memory_props.memoryTypeCount; i++) {
- const VkMemoryType type = wsi->memory_props.memoryTypes[i];
- if ((type_bits & (1 << i)) && (type.propertyFlags & props) == props)
- return i;
- }
-
- unreachable("No memory type found");
-}
-
-static uint32_t
-vk_format_size(VkFormat format)
-{
- switch (format) {
- case VK_FORMAT_B8G8R8A8_UNORM:
- case VK_FORMAT_B8G8R8A8_SRGB:
- return 4;
- default:
- unreachable("Unknown WSI Format");
- }
-}
-
-static inline uint32_t
-align_u32(uint32_t v, uint32_t a)
-{
- assert(a != 0 && a == (a & -a));
- return (v + a - 1) & ~(a - 1);
-}
-
-VkResult
-wsi_create_native_image(const struct wsi_swapchain *chain,
- const VkSwapchainCreateInfoKHR *pCreateInfo,
- uint32_t num_modifier_lists,
- const uint32_t *num_modifiers,
- const uint64_t *const *modifiers,
- struct wsi_image *image)
-{
- const struct wsi_device *wsi = chain->wsi;
- VkResult result;
-
- memset(image, 0, sizeof(*image));
- for (int i = 0; i < ARRAY_SIZE(image->fds); i++)
- image->fds[i] = -1;
-
- VkImageCreateInfo image_info = {
- .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
- .flags = 0,
- .imageType = VK_IMAGE_TYPE_2D,
- .format = pCreateInfo->imageFormat,
- .extent = {
- .width = pCreateInfo->imageExtent.width,
- .height = pCreateInfo->imageExtent.height,
- .depth = 1,
- },
- .mipLevels = 1,
- .arrayLayers = 1,
- .samples = VK_SAMPLE_COUNT_1_BIT,
- .tiling = VK_IMAGE_TILING_OPTIMAL,
- .usage = pCreateInfo->imageUsage,
- .sharingMode = pCreateInfo->imageSharingMode,
- .queueFamilyIndexCount = pCreateInfo->queueFamilyIndexCount,
- .pQueueFamilyIndices = pCreateInfo->pQueueFamilyIndices,
- .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED,
- };
-
- VkImageFormatListCreateInfoKHR image_format_list;
- if (pCreateInfo->flags & VK_SWAPCHAIN_CREATE_MUTABLE_FORMAT_BIT_KHR) {
- image_info.flags |= VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT |
- VK_IMAGE_CREATE_EXTENDED_USAGE_BIT_KHR;
-
- const VkImageFormatListCreateInfoKHR *format_list =
- vk_find_struct_const(pCreateInfo->pNext,
- IMAGE_FORMAT_LIST_CREATE_INFO_KHR);
-
-#ifndef NDEBUG
- assume(format_list && format_list->viewFormatCount > 0);
- bool format_found = false;
- for (int i = 0; i < format_list->viewFormatCount; i++)
- if (pCreateInfo->imageFormat == format_list->pViewFormats[i])
- format_found = true;
- assert(format_found);
-#endif
-
- image_format_list = *format_list;
- image_format_list.pNext = NULL;
- __vk_append_struct(&image_info, &image_format_list);
- }
-
- struct wsi_image_create_info image_wsi_info;
- VkImageDrmFormatModifierListCreateInfoEXT image_modifier_list;
-
- uint32_t image_modifier_count = 0, modifier_prop_count = 0;
- struct VkDrmFormatModifierPropertiesEXT *modifier_props = NULL;
- uint64_t *image_modifiers = NULL;
- if (num_modifier_lists == 0) {
- /* If we don't have modifiers, fall back to the legacy "scanout" flag */
- image_wsi_info = (struct wsi_image_create_info) {
- .sType = VK_STRUCTURE_TYPE_WSI_IMAGE_CREATE_INFO_MESA,
- .scanout = true,
- };
- __vk_append_struct(&image_info, &image_wsi_info);
- } else {
- /* The winsys can't request modifiers if we don't support them. */
- assert(wsi->supports_modifiers);
- struct VkDrmFormatModifierPropertiesListEXT modifier_props_list = {
- .sType = VK_STRUCTURE_TYPE_DRM_FORMAT_MODIFIER_PROPERTIES_LIST_EXT,
- };
- VkFormatProperties2 format_props = {
- .sType = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2,
- .pNext = &modifier_props_list,
- };
- wsi->GetPhysicalDeviceFormatProperties2KHR(wsi->pdevice,
- pCreateInfo->imageFormat,
- &format_props);
- assert(modifier_props_list.drmFormatModifierCount > 0);
- modifier_props = vk_alloc(&chain->alloc,
- sizeof(*modifier_props) *
- modifier_props_list.drmFormatModifierCount,
- 8,
- VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
- if (!modifier_props) {
- result = VK_ERROR_OUT_OF_HOST_MEMORY;
- goto fail;
- }
-
- modifier_props_list.pDrmFormatModifierProperties = modifier_props;
- wsi->GetPhysicalDeviceFormatProperties2KHR(wsi->pdevice,
- pCreateInfo->imageFormat,
- &format_props);
-
- /* Call GetImageFormatProperties with every modifier and filter the list
- * down to those that we know work.
- */
- modifier_prop_count = 0;
- for (uint32_t i = 0; i < modifier_props_list.drmFormatModifierCount; i++) {
- VkPhysicalDeviceImageDrmFormatModifierInfoEXT mod_info = {
- .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_DRM_FORMAT_MODIFIER_INFO_EXT,
- .drmFormatModifier = modifier_props[i].drmFormatModifier,
- .sharingMode = pCreateInfo->imageSharingMode,
- .queueFamilyIndexCount = pCreateInfo->queueFamilyIndexCount,
- .pQueueFamilyIndices = pCreateInfo->pQueueFamilyIndices,
- };
- VkPhysicalDeviceImageFormatInfo2 format_info = {
- .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,
- .format = pCreateInfo->imageFormat,
- .type = VK_IMAGE_TYPE_2D,
- .tiling = VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT,
- .usage = pCreateInfo->imageUsage,
- .flags = image_info.flags,
- };
-
- VkImageFormatListCreateInfoKHR format_list;
- if (image_info.flags & VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT) {
- format_list = image_format_list;
- format_list.pNext = NULL;
- __vk_append_struct(&format_info, &format_list);
- }
-
- VkImageFormatProperties2 format_props = {
- .sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2,
- .pNext = NULL,
- };
- __vk_append_struct(&format_info, &mod_info);
- result = wsi->GetPhysicalDeviceImageFormatProperties2(wsi->pdevice,
- &format_info,
- &format_props);
- if (result == VK_SUCCESS)
- modifier_props[modifier_prop_count++] = modifier_props[i];
- }
-
- uint32_t max_modifier_count = 0;
- for (uint32_t l = 0; l < num_modifier_lists; l++)
- max_modifier_count = MAX2(max_modifier_count, num_modifiers[l]);
-
- image_modifiers = vk_alloc(&chain->alloc,
- sizeof(*image_modifiers) *
- max_modifier_count,
- 8,
- VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
- if (!image_modifiers) {
- result = VK_ERROR_OUT_OF_HOST_MEMORY;
- goto fail;
- }
-
- image_modifier_count = 0;
- for (uint32_t l = 0; l < num_modifier_lists; l++) {
- /* Walk the modifier lists and construct a list of supported
- * modifiers.
- */
- for (uint32_t i = 0; i < num_modifiers[l]; i++) {
- for (uint32_t j = 0; j < modifier_prop_count; j++) {
- if (modifier_props[j].drmFormatModifier == modifiers[l][i])
- image_modifiers[image_modifier_count++] = modifiers[l][i];
- }
- }
-
- /* We only want to take the modifiers from the first list */
- if (image_modifier_count > 0)
- break;
- }
-
- if (image_modifier_count > 0) {
- image_modifier_list = (VkImageDrmFormatModifierListCreateInfoEXT) {
- .sType = VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_LIST_CREATE_INFO_EXT,
- .drmFormatModifierCount = image_modifier_count,
- .pDrmFormatModifiers = image_modifiers,
- };
- image_info.tiling = VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT;
- __vk_append_struct(&image_info, &image_modifier_list);
- } else {
- /* TODO: Add a proper error here */
- assert(!"Failed to find a supported modifier! This should never "
- "happen because LINEAR should always be available");
- result = VK_ERROR_OUT_OF_HOST_MEMORY;
- goto fail;
- }
- }
-
- result = wsi->CreateImage(chain->device, &image_info,
- &chain->alloc, &image->image);
- if (result != VK_SUCCESS)
- goto fail;
-
- VkMemoryRequirements reqs;
- wsi->GetImageMemoryRequirements(chain->device, image->image, &reqs);
-
- const struct wsi_memory_allocate_info memory_wsi_info = {
- .sType = VK_STRUCTURE_TYPE_WSI_MEMORY_ALLOCATE_INFO_MESA,
- .pNext = NULL,
- .implicit_sync = true,
- };
- const VkExportMemoryAllocateInfo memory_export_info = {
- .sType = VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO,
- .pNext = &memory_wsi_info,
- .handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT,
- };
- const VkMemoryDedicatedAllocateInfo memory_dedicated_info = {
- .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO,
- .pNext = &memory_export_info,
- .image = image->image,
- .buffer = VK_NULL_HANDLE,
- };
- const VkMemoryAllocateInfo memory_info = {
- .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
- .pNext = &memory_dedicated_info,
- .allocationSize = reqs.size,
- .memoryTypeIndex = select_memory_type(wsi, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
- reqs.memoryTypeBits),
- };
- result = wsi->AllocateMemory(chain->device, &memory_info,
- &chain->alloc, &image->memory);
- if (result != VK_SUCCESS)
- goto fail;
-
- result = wsi->BindImageMemory(chain->device, image->image,
- image->memory, 0);
- if (result != VK_SUCCESS)
- goto fail;
-
- const VkMemoryGetFdInfoKHR memory_get_fd_info = {
- .sType = VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR,
- .pNext = NULL,
- .memory = image->memory,
- .handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT,
- };
- int fd;
- result = wsi->GetMemoryFdKHR(chain->device, &memory_get_fd_info, &fd);
- if (result != VK_SUCCESS)
- goto fail;
-
- if (num_modifier_lists > 0) {
- VkImageDrmFormatModifierPropertiesEXT image_mod_props = {
- .sType = VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_PROPERTIES_EXT,
- };
- result = wsi->GetImageDrmFormatModifierPropertiesEXT(chain->device,
- image->image,
- &image_mod_props);
- if (result != VK_SUCCESS) {
- close(fd);
- goto fail;
- }
- image->drm_modifier = image_mod_props.drmFormatModifier;
- assert(image->drm_modifier != DRM_FORMAT_MOD_INVALID);
- for (uint32_t j = 0; j < modifier_prop_count; j++) {
- if (modifier_props[j].drmFormatModifier == image->drm_modifier) {
- image->num_planes = modifier_props[j].drmFormatModifierPlaneCount;
- break;
- }
- }
-
- for (uint32_t p = 0; p < image->num_planes; p++) {
- const VkImageSubresource image_subresource = {
- .aspectMask = VK_IMAGE_ASPECT_PLANE_0_BIT << p,
- .mipLevel = 0,
- .arrayLayer = 0,
- };
- VkSubresourceLayout image_layout;
- wsi->GetImageSubresourceLayout(chain->device, image->image,
- &image_subresource, &image_layout);
- image->sizes[p] = image_layout.size;
- image->row_pitches[p] = image_layout.rowPitch;
- image->offsets[p] = image_layout.offset;
- if (p == 0) {
- image->fds[p] = fd;
- } else {
- image->fds[p] = dup(fd);
- if (image->fds[p] == -1) {
- for (uint32_t i = 0; i < p; i++)
- close(image->fds[i]);
-
- result = VK_ERROR_OUT_OF_HOST_MEMORY;
- goto fail;
- }
- }
- }
- } else {
- const VkImageSubresource image_subresource = {
- .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
- .mipLevel = 0,
- .arrayLayer = 0,
- };
- VkSubresourceLayout image_layout;
- wsi->GetImageSubresourceLayout(chain->device, image->image,
- &image_subresource, &image_layout);
-
- image->drm_modifier = DRM_FORMAT_MOD_INVALID;
- image->num_planes = 1;
- image->sizes[0] = reqs.size;
- image->row_pitches[0] = image_layout.rowPitch;
- image->offsets[0] = 0;
- image->fds[0] = fd;
- }
-
- vk_free(&chain->alloc, modifier_props);
- vk_free(&chain->alloc, image_modifiers);
-
- return VK_SUCCESS;
-
-fail:
- vk_free(&chain->alloc, modifier_props);
- vk_free(&chain->alloc, image_modifiers);
- wsi_destroy_image(chain, image);
-
- return result;
-}
-
-#define WSI_PRIME_LINEAR_STRIDE_ALIGN 256
-
-VkResult
-wsi_create_prime_image(const struct wsi_swapchain *chain,
- const VkSwapchainCreateInfoKHR *pCreateInfo,
- bool use_modifier,
- struct wsi_image *image)
-{
- const struct wsi_device *wsi = chain->wsi;
- VkResult result;
-
- memset(image, 0, sizeof(*image));
-
- const uint32_t cpp = vk_format_size(pCreateInfo->imageFormat);
- const uint32_t linear_stride = align_u32(pCreateInfo->imageExtent.width * cpp,
- WSI_PRIME_LINEAR_STRIDE_ALIGN);
-
- uint32_t linear_size = linear_stride * pCreateInfo->imageExtent.height;
- linear_size = align_u32(linear_size, 4096);
-
- const VkExternalMemoryBufferCreateInfo prime_buffer_external_info = {
- .sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO,
- .pNext = NULL,
- .handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT,
- };
- const VkBufferCreateInfo prime_buffer_info = {
- .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
- .pNext = &prime_buffer_external_info,
- .size = linear_size,
- .usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT,
- .sharingMode = VK_SHARING_MODE_EXCLUSIVE,
- };
- result = wsi->CreateBuffer(chain->device, &prime_buffer_info,
- &chain->alloc, &image->prime.buffer);
- if (result != VK_SUCCESS)
- goto fail;
-
- VkMemoryRequirements reqs;
- wsi->GetBufferMemoryRequirements(chain->device, image->prime.buffer, &reqs);
- assert(reqs.size <= linear_size);
-
- const struct wsi_memory_allocate_info memory_wsi_info = {
- .sType = VK_STRUCTURE_TYPE_WSI_MEMORY_ALLOCATE_INFO_MESA,
- .pNext = NULL,
- .implicit_sync = true,
- };
- const VkExportMemoryAllocateInfo prime_memory_export_info = {
- .sType = VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO,
- .pNext = &memory_wsi_info,
- .handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT,
- };
- const VkMemoryDedicatedAllocateInfo prime_memory_dedicated_info = {
- .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO,
- .pNext = &prime_memory_export_info,
- .image = VK_NULL_HANDLE,
- .buffer = image->prime.buffer,
- };
- const VkMemoryAllocateInfo prime_memory_info = {
- .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
- .pNext = &prime_memory_dedicated_info,
- .allocationSize = linear_size,
- .memoryTypeIndex = select_memory_type(wsi, 0, reqs.memoryTypeBits),
- };
- result = wsi->AllocateMemory(chain->device, &prime_memory_info,
- &chain->alloc, &image->prime.memory);
- if (result != VK_SUCCESS)
- goto fail;
-
- result = wsi->BindBufferMemory(chain->device, image->prime.buffer,
- image->prime.memory, 0);
- if (result != VK_SUCCESS)
- goto fail;
-
- const VkImageCreateInfo image_info = {
- .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
- .pNext = NULL,
- .flags = 0,
- .imageType = VK_IMAGE_TYPE_2D,
- .format = pCreateInfo->imageFormat,
- .extent = {
- .width = pCreateInfo->imageExtent.width,
- .height = pCreateInfo->imageExtent.height,
- .depth = 1,
- },
- .mipLevels = 1,
- .arrayLayers = 1,
- .samples = VK_SAMPLE_COUNT_1_BIT,
- .tiling = VK_IMAGE_TILING_OPTIMAL,
- .usage = pCreateInfo->imageUsage | VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
- .sharingMode = pCreateInfo->imageSharingMode,
- .queueFamilyIndexCount = pCreateInfo->queueFamilyIndexCount,
- .pQueueFamilyIndices = pCreateInfo->pQueueFamilyIndices,
- .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED,
- };
- result = wsi->CreateImage(chain->device, &image_info,
- &chain->alloc, &image->image);
- if (result != VK_SUCCESS)
- goto fail;
-
- wsi->GetImageMemoryRequirements(chain->device, image->image, &reqs);
-
- const VkMemoryDedicatedAllocateInfo memory_dedicated_info = {
- .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO,
- .pNext = NULL,
- .image = image->image,
- .buffer = VK_NULL_HANDLE,
- };
- const VkMemoryAllocateInfo memory_info = {
- .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
- .pNext = &memory_dedicated_info,
- .allocationSize = reqs.size,
- .memoryTypeIndex = select_memory_type(wsi, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
- reqs.memoryTypeBits),
- };
- result = wsi->AllocateMemory(chain->device, &memory_info,
- &chain->alloc, &image->memory);
- if (result != VK_SUCCESS)
- goto fail;
-
- result = wsi->BindImageMemory(chain->device, image->image,
- image->memory, 0);
- if (result != VK_SUCCESS)
- goto fail;
-
- image->prime.blit_cmd_buffers =
- vk_zalloc(&chain->alloc,
- sizeof(VkCommandBuffer) * wsi->queue_family_count, 8,
- VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
- if (!image->prime.blit_cmd_buffers) {
- result = VK_ERROR_OUT_OF_HOST_MEMORY;
- goto fail;
- }
-
- for (uint32_t i = 0; i < wsi->queue_family_count; i++) {
- const VkCommandBufferAllocateInfo cmd_buffer_info = {
- .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
- .pNext = NULL,
- .commandPool = chain->cmd_pools[i],
- .level = VK_COMMAND_BUFFER_LEVEL_PRIMARY,
- .commandBufferCount = 1,
- };
- result = wsi->AllocateCommandBuffers(chain->device, &cmd_buffer_info,
- &image->prime.blit_cmd_buffers[i]);
- if (result != VK_SUCCESS)
- goto fail;
-
- const VkCommandBufferBeginInfo begin_info = {
- .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
- };
- wsi->BeginCommandBuffer(image->prime.blit_cmd_buffers[i], &begin_info);
-
- struct VkBufferImageCopy buffer_image_copy = {
- .bufferOffset = 0,
- .bufferRowLength = linear_stride / cpp,
- .bufferImageHeight = 0,
- .imageSubresource = {
- .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
- .mipLevel = 0,
- .baseArrayLayer = 0,
- .layerCount = 1,
- },
- .imageOffset = { .x = 0, .y = 0, .z = 0 },
- .imageExtent = {
- .width = pCreateInfo->imageExtent.width,
- .height = pCreateInfo->imageExtent.height,
- .depth = 1,
- },
- };
- wsi->CmdCopyImageToBuffer(image->prime.blit_cmd_buffers[i],
- image->image,
- VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
- image->prime.buffer,
- 1, &buffer_image_copy);
-
- result = wsi->EndCommandBuffer(image->prime.blit_cmd_buffers[i]);
- if (result != VK_SUCCESS)
- goto fail;
- }
-
- const VkMemoryGetFdInfoKHR linear_memory_get_fd_info = {
- .sType = VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR,
- .pNext = NULL,
- .memory = image->prime.memory,
- .handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT,
- };
- int fd;
- result = wsi->GetMemoryFdKHR(chain->device, &linear_memory_get_fd_info, &fd);
- if (result != VK_SUCCESS)
- goto fail;
-
- image->drm_modifier = use_modifier ? DRM_FORMAT_MOD_LINEAR : DRM_FORMAT_MOD_INVALID;
- image->num_planes = 1;
- image->sizes[0] = linear_size;
- image->row_pitches[0] = linear_stride;
- image->offsets[0] = 0;
- image->fds[0] = fd;
-
- return VK_SUCCESS;
-
-fail:
- wsi_destroy_image(chain, image);
-
- return result;
+ vk_object_base_finish(&chain->base);
}
void
@@ -1061,7 +498,7 @@ wsi_common_destroy_swapchain(VkDevice device,
VkSwapchainKHR _swapchain,
const VkAllocationCallbacks *pAllocator)
{
- WSI_FROM_HANDLE(wsi_swapchain, swapchain, _swapchain);
+ VK_FROM_HANDLE(wsi_swapchain, swapchain, _swapchain);
if (!swapchain)
return;
@@ -1073,11 +510,11 @@ wsi_common_get_images(VkSwapchainKHR _swapchain,
uint32_t *pSwapchainImageCount,
VkImage *pSwapchainImages)
{
- WSI_FROM_HANDLE(wsi_swapchain, swapchain, _swapchain);
- VK_OUTARRAY_MAKE(images, pSwapchainImages, pSwapchainImageCount);
+ VK_FROM_HANDLE(wsi_swapchain, swapchain, _swapchain);
+ VK_OUTARRAY_MAKE_TYPED(VkImage, images, pSwapchainImages, pSwapchainImageCount);
for (uint32_t i = 0; i < swapchain->image_count; i++) {
- vk_outarray_append(&images, image) {
+ vk_outarray_append_typed(VkImage, &images, image) {
*image = swapchain->get_wsi_image(swapchain, i)->image;
}
}
@@ -1091,13 +528,18 @@ wsi_common_acquire_next_image2(const struct wsi_device *wsi,
const VkAcquireNextImageInfoKHR *pAcquireInfo,
uint32_t *pImageIndex)
{
- WSI_FROM_HANDLE(wsi_swapchain, swapchain, pAcquireInfo->swapchain);
+ VK_FROM_HANDLE(wsi_swapchain, swapchain, pAcquireInfo->swapchain);
VkResult result = swapchain->acquire_next_image(swapchain, pAcquireInfo,
pImageIndex);
- if (result != VK_SUCCESS)
+ if (result != VK_SUCCESS && result != VK_SUBOPTIMAL_KHR)
return result;
+ if (wsi->set_memory_ownership) {
+ VkDeviceMemory mem = swapchain->get_wsi_image(swapchain, *pImageIndex)->memory;
+ wsi->set_memory_ownership(swapchain->device, mem, true);
+ }
+
if (pAcquireInfo->semaphore != VK_NULL_HANDLE &&
wsi->signal_semaphore_for_memory != NULL) {
struct wsi_image *image =
@@ -1114,7 +556,7 @@ wsi_common_acquire_next_image2(const struct wsi_device *wsi,
image->memory);
}
- return VK_SUCCESS;
+ return result;
}
VkResult
@@ -1130,7 +572,7 @@ wsi_common_queue_present(const struct wsi_device *wsi,
vk_find_struct_const(pPresentInfo->pNext, PRESENT_REGIONS_KHR);
for (uint32_t i = 0; i < pPresentInfo->swapchainCount; i++) {
- WSI_FROM_HANDLE(wsi_swapchain, swapchain, pPresentInfo->pSwapchains[i]);
+ VK_FROM_HANDLE(wsi_swapchain, swapchain, pPresentInfo->pSwapchains[i]);
uint32_t image_index = pPresentInfo->pImageIndices[i];
VkResult result;
@@ -1216,9 +658,14 @@ wsi_common_queue_present(const struct wsi_device *wsi,
region = &regions->pRegions[i];
result = swapchain->queue_present(swapchain, image_index, region);
- if (result != VK_SUCCESS)
+ if (result != VK_SUCCESS && result != VK_SUBOPTIMAL_KHR)
goto fail_present;
+ if (wsi->set_memory_ownership) {
+ VkDeviceMemory mem = swapchain->get_wsi_image(swapchain, image_index)->memory;
+ wsi->set_memory_ownership(swapchain->device, mem, false);
+ }
+
fail_present:
if (pPresentInfo->pResults != NULL)
pPresentInfo->pResults[i] = result;
@@ -1234,7 +681,5 @@ wsi_common_queue_present(const struct wsi_device *wsi,
uint64_t
wsi_common_get_current_time(void)
{
- struct timespec current;
- clock_gettime(CLOCK_MONOTONIC, &current);
- return current.tv_nsec + current.tv_sec * 1000000000ull;
+ return os_time_get_nano();
}
diff --git a/lib/mesa/src/vulkan/wsi/wsi_common_display.c b/lib/mesa/src/vulkan/wsi/wsi_common_display.c
index 0f9a1ffe8..e25dc1a3f 100644
--- a/lib/mesa/src/vulkan/wsi/wsi_common_display.c
+++ b/lib/mesa/src/vulkan/wsi/wsi_common_display.c
@@ -137,6 +137,7 @@ struct wsi_display_fence {
struct wsi_fence base;
bool event_received;
bool destroyed;
+ uint32_t syncobj; /* syncobj to signal on event */
uint64_t sequence;
};
@@ -814,7 +815,10 @@ wsi_display_surface_get_support(VkIcdSurfaceBase *surface,
uint32_t queueFamilyIndex,
VkBool32* pSupported)
{
- *pSupported = VK_TRUE;
+ struct wsi_display *wsi =
+ (struct wsi_display *) wsi_device->wsi[VK_ICD_WSI_PLATFORM_DISPLAY];
+
+ *pSupported = wsi->fd != -1;
return VK_SUCCESS;
}
@@ -1209,8 +1213,8 @@ wsi_display_wait_thread(void *data)
if (ret > 0) {
pthread_mutex_lock(&wsi->wait_mutex);
(void) drmHandleEvent(wsi->fd, &event_context);
- pthread_mutex_unlock(&wsi->wait_mutex);
pthread_cond_broadcast(&wsi->wait_cond);
+ pthread_mutex_unlock(&wsi->wait_mutex);
}
}
return NULL;
@@ -1228,6 +1232,18 @@ wsi_display_start_wait_thread(struct wsi_display *wsi)
return 0;
}
+static void
+wsi_display_stop_wait_thread(struct wsi_display *wsi)
+{
+ pthread_mutex_lock(&wsi->wait_mutex);
+ if (wsi->wait_thread) {
+ pthread_cancel(wsi->wait_thread);
+ pthread_join(wsi->wait_thread, NULL);
+ wsi->wait_thread = 0;
+ }
+ pthread_mutex_unlock(&wsi->wait_mutex);
+}
+
/*
* Wait for at least one event from the kernel to be processed.
* Call with wait_mutex held
@@ -1515,6 +1531,14 @@ wsi_display_fence_check_free(struct wsi_display_fence *fence)
static void wsi_display_fence_event_handler(struct wsi_display_fence *fence)
{
+ struct wsi_display *wsi =
+ (struct wsi_display *) fence->base.wsi_device->wsi[VK_ICD_WSI_PLATFORM_DISPLAY];
+
+ if (fence->syncobj) {
+ (void) drmSyncobjSignal(wsi->fd, &fence->syncobj, 1);
+ (void) drmSyncobjDestroy(wsi->fd, fence->syncobj);
+ }
+
fence->event_received = true;
wsi_display_fence_check_free(fence);
}
@@ -1533,7 +1557,8 @@ static struct wsi_display_fence *
wsi_display_fence_alloc(VkDevice device,
const struct wsi_device *wsi_device,
VkDisplayKHR display,
- const VkAllocationCallbacks *allocator)
+ const VkAllocationCallbacks *allocator,
+ int sync_fd)
{
struct wsi_display *wsi =
(struct wsi_display *) wsi_device->wsi[VK_ICD_WSI_PLATFORM_DISPLAY];
@@ -1544,6 +1569,14 @@ wsi_display_fence_alloc(VkDevice device,
if (!fence)
return NULL;
+ if (sync_fd >= 0) {
+ int ret = drmSyncobjFDToHandle(wsi->fd, sync_fd, &fence->syncobj);
+ if (ret) {
+ vk_free2(wsi->alloc, allocator, fence);
+ return NULL;
+ }
+ }
+
fence->base.device = device;
fence->base.display = display;
fence->base.wsi_device = wsi_device;
@@ -1936,12 +1969,7 @@ wsi_display_finish_wsi(struct wsi_device *wsi_device,
vk_free(wsi->alloc, connector);
}
- pthread_mutex_lock(&wsi->wait_mutex);
- if (wsi->wait_thread) {
- pthread_cancel(wsi->wait_thread);
- pthread_join(wsi->wait_thread, NULL);
- }
- pthread_mutex_unlock(&wsi->wait_mutex);
+ wsi_display_stop_wait_thread(wsi);
pthread_mutex_destroy(&wsi->wait_mutex);
pthread_cond_destroy(&wsi->wait_cond);
@@ -1961,9 +1989,12 @@ wsi_release_display(VkPhysicalDevice physical_device,
(struct wsi_display *) wsi_device->wsi[VK_ICD_WSI_PLATFORM_DISPLAY];
if (wsi->fd >= 0) {
+ wsi_display_stop_wait_thread(wsi);
+
close(wsi->fd);
wsi->fd = -1;
}
+
#ifdef VK_USE_PLATFORM_XLIB_XRANDR_EXT
wsi_display_connector_from_handle(display)->output = None;
#endif
@@ -2489,7 +2520,8 @@ wsi_register_device_event(VkDevice device,
struct wsi_device *wsi_device,
const VkDeviceEventInfoEXT *device_event_info,
const VkAllocationCallbacks *allocator,
- struct wsi_fence **fence_p)
+ struct wsi_fence **fence_p,
+ int sync_fd)
{
return VK_ERROR_FEATURE_NOT_PRESENT;
}
@@ -2500,7 +2532,8 @@ wsi_register_display_event(VkDevice device,
VkDisplayKHR display,
const VkDisplayEventInfoEXT *display_event_info,
const VkAllocationCallbacks *allocator,
- struct wsi_fence **fence_p)
+ struct wsi_fence **fence_p,
+ int sync_fd)
{
struct wsi_display *wsi =
(struct wsi_display *) wsi_device->wsi[VK_ICD_WSI_PLATFORM_DISPLAY];
@@ -2510,7 +2543,7 @@ wsi_register_display_event(VkDevice device,
switch (display_event_info->displayEvent) {
case VK_DISPLAY_EVENT_TYPE_FIRST_PIXEL_OUT_EXT:
- fence = wsi_display_fence_alloc(device, wsi_device, display, allocator);
+ fence = wsi_display_fence_alloc(device, wsi_device, display, allocator, sync_fd);
if (!fence)
return VK_ERROR_OUT_OF_HOST_MEMORY;
@@ -2518,10 +2551,16 @@ wsi_register_display_event(VkDevice device,
ret = wsi_register_vblank_event(fence, wsi_device, display,
DRM_CRTC_SEQUENCE_RELATIVE, 1, NULL);
- if (ret == VK_SUCCESS)
- *fence_p = &fence->base;
- else if (fence != NULL)
+ if (ret == VK_SUCCESS) {
+ if (fence_p)
+ *fence_p = &fence->base;
+ else
+ fence->base.destroy(&fence->base);
+ } else if (fence != NULL) {
+ if (fence->syncobj)
+ drmSyncobjDestroy(wsi->fd, fence->syncobj);
vk_free2(wsi->alloc, allocator, fence);
+ }
break;
default:
diff --git a/lib/mesa/src/vulkan/wsi/wsi_common_display.h b/lib/mesa/src/vulkan/wsi/wsi_common_display.h
index be0bd4e06..d65517ab9 100644
--- a/lib/mesa/src/vulkan/wsi/wsi_common_display.h
+++ b/lib/mesa/src/vulkan/wsi/wsi_common_display.h
@@ -27,11 +27,6 @@
#include <xf86drm.h>
#include <xf86drmMode.h>
-#define typed_memcpy(dest, src, count) ({ \
- STATIC_ASSERT(sizeof(*src) == sizeof(*dest)); \
- memcpy((dest), (src), (count) * sizeof(*(src))); \
-})
-
VkResult
wsi_display_get_physical_device_display_properties(
VkPhysicalDevice physical_device,
@@ -143,7 +138,8 @@ wsi_register_device_event(VkDevice device,
struct wsi_device *wsi_device,
const VkDeviceEventInfoEXT *device_event_info,
const VkAllocationCallbacks *allocator,
- struct wsi_fence **fence);
+ struct wsi_fence **fence,
+ int sync_fd);
VkResult
wsi_register_display_event(VkDevice device,
@@ -151,7 +147,8 @@ wsi_register_display_event(VkDevice device,
VkDisplayKHR display,
const VkDisplayEventInfoEXT *display_event_info,
const VkAllocationCallbacks *allocator,
- struct wsi_fence **fence);
+ struct wsi_fence **fence,
+ int sync_fd);
VkResult
wsi_get_swapchain_counter(VkDevice device,
diff --git a/lib/mesa/src/vulkan/wsi/wsi_common_drm.c b/lib/mesa/src/vulkan/wsi/wsi_common_drm.c
new file mode 100644
index 000000000..1f81a92ff
--- /dev/null
+++ b/lib/mesa/src/vulkan/wsi/wsi_common_drm.c
@@ -0,0 +1,621 @@
+/*
+ * 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 "wsi_common_private.h"
+#include "util/macros.h"
+#include "util/os_file.h"
+#include "util/xmlconfig.h"
+#include "vk_util.h"
+#include "drm-uapi/drm_fourcc.h"
+
+#include <time.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <xf86drm.h>
+
+bool
+wsi_device_matches_drm_fd(const struct wsi_device *wsi, int drm_fd)
+{
+ drmDevicePtr fd_device;
+ int ret = drmGetDevice2(drm_fd, 0, &fd_device);
+ if (ret)
+ return false;
+
+ bool match = false;
+ switch (fd_device->bustype) {
+ case DRM_BUS_PCI:
+ match = wsi->pci_bus_info.pciDomain == fd_device->businfo.pci->domain &&
+ wsi->pci_bus_info.pciBus == fd_device->businfo.pci->bus &&
+ wsi->pci_bus_info.pciDevice == fd_device->businfo.pci->dev &&
+ wsi->pci_bus_info.pciFunction == fd_device->businfo.pci->func;
+ break;
+
+ default:
+ break;
+ }
+
+ drmFreeDevice(&fd_device);
+
+ return match;
+}
+
+static uint32_t
+select_memory_type(const struct wsi_device *wsi,
+ VkMemoryPropertyFlags props,
+ uint32_t type_bits)
+{
+ for (uint32_t i = 0; i < wsi->memory_props.memoryTypeCount; i++) {
+ const VkMemoryType type = wsi->memory_props.memoryTypes[i];
+ if ((type_bits & (1 << i)) && (type.propertyFlags & props) == props)
+ return i;
+ }
+
+ unreachable("No memory type found");
+}
+
+static uint32_t
+vk_format_size(VkFormat format)
+{
+ switch (format) {
+ case VK_FORMAT_B8G8R8A8_UNORM:
+ case VK_FORMAT_B8G8R8A8_SRGB:
+ return 4;
+ default:
+ unreachable("Unknown WSI Format");
+ }
+}
+
+VkResult
+wsi_create_native_image(const struct wsi_swapchain *chain,
+ const VkSwapchainCreateInfoKHR *pCreateInfo,
+ uint32_t num_modifier_lists,
+ const uint32_t *num_modifiers,
+ const uint64_t *const *modifiers,
+ struct wsi_image *image)
+{
+ const struct wsi_device *wsi = chain->wsi;
+ VkResult result;
+
+ memset(image, 0, sizeof(*image));
+ for (int i = 0; i < ARRAY_SIZE(image->fds); i++)
+ image->fds[i] = -1;
+
+ VkImageCreateInfo image_info = {
+ .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
+ .flags = 0,
+ .imageType = VK_IMAGE_TYPE_2D,
+ .format = pCreateInfo->imageFormat,
+ .extent = {
+ .width = pCreateInfo->imageExtent.width,
+ .height = pCreateInfo->imageExtent.height,
+ .depth = 1,
+ },
+ .mipLevels = 1,
+ .arrayLayers = 1,
+ .samples = VK_SAMPLE_COUNT_1_BIT,
+ .tiling = VK_IMAGE_TILING_OPTIMAL,
+ .usage = pCreateInfo->imageUsage,
+ .sharingMode = pCreateInfo->imageSharingMode,
+ .queueFamilyIndexCount = pCreateInfo->queueFamilyIndexCount,
+ .pQueueFamilyIndices = pCreateInfo->pQueueFamilyIndices,
+ .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED,
+ };
+
+ VkImageFormatListCreateInfoKHR image_format_list;
+ if (pCreateInfo->flags & VK_SWAPCHAIN_CREATE_MUTABLE_FORMAT_BIT_KHR) {
+ image_info.flags |= VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT |
+ VK_IMAGE_CREATE_EXTENDED_USAGE_BIT_KHR;
+
+ const VkImageFormatListCreateInfoKHR *format_list =
+ vk_find_struct_const(pCreateInfo->pNext,
+ IMAGE_FORMAT_LIST_CREATE_INFO_KHR);
+
+#ifndef NDEBUG
+ assume(format_list && format_list->viewFormatCount > 0);
+ bool format_found = false;
+ for (int i = 0; i < format_list->viewFormatCount; i++)
+ if (pCreateInfo->imageFormat == format_list->pViewFormats[i])
+ format_found = true;
+ assert(format_found);
+#endif
+
+ image_format_list = *format_list;
+ image_format_list.pNext = NULL;
+ __vk_append_struct(&image_info, &image_format_list);
+ }
+
+ struct wsi_image_create_info image_wsi_info;
+ VkImageDrmFormatModifierListCreateInfoEXT image_modifier_list;
+
+ uint32_t image_modifier_count = 0, modifier_prop_count = 0;
+ struct VkDrmFormatModifierPropertiesEXT *modifier_props = NULL;
+ uint64_t *image_modifiers = NULL;
+ if (num_modifier_lists == 0) {
+ /* If we don't have modifiers, fall back to the legacy "scanout" flag */
+ image_wsi_info = (struct wsi_image_create_info) {
+ .sType = VK_STRUCTURE_TYPE_WSI_IMAGE_CREATE_INFO_MESA,
+ .scanout = true,
+ };
+ __vk_append_struct(&image_info, &image_wsi_info);
+ } else {
+ /* The winsys can't request modifiers if we don't support them. */
+ assert(wsi->supports_modifiers);
+ struct VkDrmFormatModifierPropertiesListEXT modifier_props_list = {
+ .sType = VK_STRUCTURE_TYPE_DRM_FORMAT_MODIFIER_PROPERTIES_LIST_EXT,
+ };
+ VkFormatProperties2 format_props = {
+ .sType = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2,
+ .pNext = &modifier_props_list,
+ };
+ wsi->GetPhysicalDeviceFormatProperties2KHR(wsi->pdevice,
+ pCreateInfo->imageFormat,
+ &format_props);
+ assert(modifier_props_list.drmFormatModifierCount > 0);
+ modifier_props = vk_alloc(&chain->alloc,
+ sizeof(*modifier_props) *
+ modifier_props_list.drmFormatModifierCount,
+ 8,
+ VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
+ if (!modifier_props) {
+ result = VK_ERROR_OUT_OF_HOST_MEMORY;
+ goto fail;
+ }
+
+ modifier_props_list.pDrmFormatModifierProperties = modifier_props;
+ wsi->GetPhysicalDeviceFormatProperties2KHR(wsi->pdevice,
+ pCreateInfo->imageFormat,
+ &format_props);
+
+ /* Call GetImageFormatProperties with every modifier and filter the list
+ * down to those that we know work.
+ */
+ modifier_prop_count = 0;
+ for (uint32_t i = 0; i < modifier_props_list.drmFormatModifierCount; i++) {
+ VkPhysicalDeviceImageDrmFormatModifierInfoEXT mod_info = {
+ .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_DRM_FORMAT_MODIFIER_INFO_EXT,
+ .drmFormatModifier = modifier_props[i].drmFormatModifier,
+ .sharingMode = pCreateInfo->imageSharingMode,
+ .queueFamilyIndexCount = pCreateInfo->queueFamilyIndexCount,
+ .pQueueFamilyIndices = pCreateInfo->pQueueFamilyIndices,
+ };
+ VkPhysicalDeviceImageFormatInfo2 format_info = {
+ .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,
+ .format = pCreateInfo->imageFormat,
+ .type = VK_IMAGE_TYPE_2D,
+ .tiling = VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT,
+ .usage = pCreateInfo->imageUsage,
+ .flags = image_info.flags,
+ };
+
+ VkImageFormatListCreateInfoKHR format_list;
+ if (image_info.flags & VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT) {
+ format_list = image_format_list;
+ format_list.pNext = NULL;
+ __vk_append_struct(&format_info, &format_list);
+ }
+
+ VkImageFormatProperties2 format_props = {
+ .sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2,
+ .pNext = NULL,
+ };
+ __vk_append_struct(&format_info, &mod_info);
+ result = wsi->GetPhysicalDeviceImageFormatProperties2(wsi->pdevice,
+ &format_info,
+ &format_props);
+ if (result == VK_SUCCESS)
+ modifier_props[modifier_prop_count++] = modifier_props[i];
+ }
+
+ uint32_t max_modifier_count = 0;
+ for (uint32_t l = 0; l < num_modifier_lists; l++)
+ max_modifier_count = MAX2(max_modifier_count, num_modifiers[l]);
+
+ image_modifiers = vk_alloc(&chain->alloc,
+ sizeof(*image_modifiers) *
+ max_modifier_count,
+ 8,
+ VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
+ if (!image_modifiers) {
+ result = VK_ERROR_OUT_OF_HOST_MEMORY;
+ goto fail;
+ }
+
+ image_modifier_count = 0;
+ for (uint32_t l = 0; l < num_modifier_lists; l++) {
+ /* Walk the modifier lists and construct a list of supported
+ * modifiers.
+ */
+ for (uint32_t i = 0; i < num_modifiers[l]; i++) {
+ for (uint32_t j = 0; j < modifier_prop_count; j++) {
+ if (modifier_props[j].drmFormatModifier == modifiers[l][i])
+ image_modifiers[image_modifier_count++] = modifiers[l][i];
+ }
+ }
+
+ /* We only want to take the modifiers from the first list */
+ if (image_modifier_count > 0)
+ break;
+ }
+
+ if (image_modifier_count > 0) {
+ image_modifier_list = (VkImageDrmFormatModifierListCreateInfoEXT) {
+ .sType = VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_LIST_CREATE_INFO_EXT,
+ .drmFormatModifierCount = image_modifier_count,
+ .pDrmFormatModifiers = image_modifiers,
+ };
+ image_info.tiling = VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT;
+ __vk_append_struct(&image_info, &image_modifier_list);
+ } else {
+ /* TODO: Add a proper error here */
+ assert(!"Failed to find a supported modifier! This should never "
+ "happen because LINEAR should always be available");
+ result = VK_ERROR_OUT_OF_HOST_MEMORY;
+ goto fail;
+ }
+ }
+
+ result = wsi->CreateImage(chain->device, &image_info,
+ &chain->alloc, &image->image);
+ if (result != VK_SUCCESS)
+ goto fail;
+
+ VkMemoryRequirements reqs;
+ wsi->GetImageMemoryRequirements(chain->device, image->image, &reqs);
+
+ const struct wsi_memory_allocate_info memory_wsi_info = {
+ .sType = VK_STRUCTURE_TYPE_WSI_MEMORY_ALLOCATE_INFO_MESA,
+ .pNext = NULL,
+ .implicit_sync = true,
+ };
+ const VkExportMemoryAllocateInfo memory_export_info = {
+ .sType = VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO,
+ .pNext = &memory_wsi_info,
+ .handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT,
+ };
+ const VkMemoryDedicatedAllocateInfo memory_dedicated_info = {
+ .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO,
+ .pNext = &memory_export_info,
+ .image = image->image,
+ .buffer = VK_NULL_HANDLE,
+ };
+ const VkMemoryAllocateInfo memory_info = {
+ .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
+ .pNext = &memory_dedicated_info,
+ .allocationSize = reqs.size,
+ .memoryTypeIndex = select_memory_type(wsi, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
+ reqs.memoryTypeBits),
+ };
+ result = wsi->AllocateMemory(chain->device, &memory_info,
+ &chain->alloc, &image->memory);
+ if (result != VK_SUCCESS)
+ goto fail;
+
+ result = wsi->BindImageMemory(chain->device, image->image,
+ image->memory, 0);
+ if (result != VK_SUCCESS)
+ goto fail;
+
+ int fd = -1;
+ if (!wsi->sw) {
+ const VkMemoryGetFdInfoKHR memory_get_fd_info = {
+ .sType = VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR,
+ .pNext = NULL,
+ .memory = image->memory,
+ .handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT,
+ };
+
+ result = wsi->GetMemoryFdKHR(chain->device, &memory_get_fd_info, &fd);
+ if (result != VK_SUCCESS)
+ goto fail;
+ }
+
+ if (!wsi->sw && num_modifier_lists > 0) {
+ VkImageDrmFormatModifierPropertiesEXT image_mod_props = {
+ .sType = VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_PROPERTIES_EXT,
+ };
+ result = wsi->GetImageDrmFormatModifierPropertiesEXT(chain->device,
+ image->image,
+ &image_mod_props);
+ if (result != VK_SUCCESS) {
+ close(fd);
+ goto fail;
+ }
+ image->drm_modifier = image_mod_props.drmFormatModifier;
+ assert(image->drm_modifier != DRM_FORMAT_MOD_INVALID);
+
+ for (uint32_t j = 0; j < modifier_prop_count; j++) {
+ if (modifier_props[j].drmFormatModifier == image->drm_modifier) {
+ image->num_planes = modifier_props[j].drmFormatModifierPlaneCount;
+ break;
+ }
+ }
+
+ for (uint32_t p = 0; p < image->num_planes; p++) {
+ const VkImageSubresource image_subresource = {
+ .aspectMask = VK_IMAGE_ASPECT_PLANE_0_BIT << p,
+ .mipLevel = 0,
+ .arrayLayer = 0,
+ };
+ VkSubresourceLayout image_layout;
+ wsi->GetImageSubresourceLayout(chain->device, image->image,
+ &image_subresource, &image_layout);
+ image->sizes[p] = image_layout.size;
+ image->row_pitches[p] = image_layout.rowPitch;
+ image->offsets[p] = image_layout.offset;
+ if (p == 0) {
+ image->fds[p] = fd;
+ } else {
+ image->fds[p] = os_dupfd_cloexec(fd);
+ if (image->fds[p] == -1) {
+ for (uint32_t i = 0; i < p; i++)
+ close(image->fds[i]);
+
+ result = VK_ERROR_OUT_OF_HOST_MEMORY;
+ goto fail;
+ }
+ }
+ }
+ } else {
+ const VkImageSubresource image_subresource = {
+ .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
+ .mipLevel = 0,
+ .arrayLayer = 0,
+ };
+ VkSubresourceLayout image_layout;
+ wsi->GetImageSubresourceLayout(chain->device, image->image,
+ &image_subresource, &image_layout);
+
+ image->drm_modifier = DRM_FORMAT_MOD_INVALID;
+ image->num_planes = 1;
+ image->sizes[0] = reqs.size;
+ image->row_pitches[0] = image_layout.rowPitch;
+ image->offsets[0] = 0;
+ image->fds[0] = fd;
+ }
+
+ vk_free(&chain->alloc, modifier_props);
+ vk_free(&chain->alloc, image_modifiers);
+
+ return VK_SUCCESS;
+
+fail:
+ vk_free(&chain->alloc, modifier_props);
+ vk_free(&chain->alloc, image_modifiers);
+ wsi_destroy_image(chain, image);
+
+ return result;
+}
+
+static inline uint32_t
+align_u32(uint32_t v, uint32_t a)
+{
+ assert(a != 0 && a == (a & -a));
+ return (v + a - 1) & ~(a - 1);
+}
+
+#define WSI_PRIME_LINEAR_STRIDE_ALIGN 256
+
+VkResult
+wsi_create_prime_image(const struct wsi_swapchain *chain,
+ const VkSwapchainCreateInfoKHR *pCreateInfo,
+ bool use_modifier,
+ struct wsi_image *image)
+{
+ const struct wsi_device *wsi = chain->wsi;
+ VkResult result;
+
+ memset(image, 0, sizeof(*image));
+
+ const uint32_t cpp = vk_format_size(pCreateInfo->imageFormat);
+ const uint32_t linear_stride = align_u32(pCreateInfo->imageExtent.width * cpp,
+ WSI_PRIME_LINEAR_STRIDE_ALIGN);
+
+ uint32_t linear_size = linear_stride * pCreateInfo->imageExtent.height;
+ linear_size = align_u32(linear_size, 4096);
+
+ const VkExternalMemoryBufferCreateInfo prime_buffer_external_info = {
+ .sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO,
+ .pNext = NULL,
+ .handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT,
+ };
+ const VkBufferCreateInfo prime_buffer_info = {
+ .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
+ .pNext = &prime_buffer_external_info,
+ .size = linear_size,
+ .usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT,
+ .sharingMode = VK_SHARING_MODE_EXCLUSIVE,
+ };
+ result = wsi->CreateBuffer(chain->device, &prime_buffer_info,
+ &chain->alloc, &image->prime.buffer);
+ if (result != VK_SUCCESS)
+ goto fail;
+
+ VkMemoryRequirements reqs;
+ wsi->GetBufferMemoryRequirements(chain->device, image->prime.buffer, &reqs);
+ assert(reqs.size <= linear_size);
+
+ const struct wsi_memory_allocate_info memory_wsi_info = {
+ .sType = VK_STRUCTURE_TYPE_WSI_MEMORY_ALLOCATE_INFO_MESA,
+ .pNext = NULL,
+ .implicit_sync = true,
+ };
+ const VkExportMemoryAllocateInfo prime_memory_export_info = {
+ .sType = VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO,
+ .pNext = &memory_wsi_info,
+ .handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT,
+ };
+ const VkMemoryDedicatedAllocateInfo prime_memory_dedicated_info = {
+ .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO,
+ .pNext = &prime_memory_export_info,
+ .image = VK_NULL_HANDLE,
+ .buffer = image->prime.buffer,
+ };
+ const VkMemoryAllocateInfo prime_memory_info = {
+ .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
+ .pNext = &prime_memory_dedicated_info,
+ .allocationSize = linear_size,
+ .memoryTypeIndex = select_memory_type(wsi, 0, reqs.memoryTypeBits),
+ };
+ result = wsi->AllocateMemory(chain->device, &prime_memory_info,
+ &chain->alloc, &image->prime.memory);
+ if (result != VK_SUCCESS)
+ goto fail;
+
+ result = wsi->BindBufferMemory(chain->device, image->prime.buffer,
+ image->prime.memory, 0);
+ if (result != VK_SUCCESS)
+ goto fail;
+
+ const VkImageCreateInfo image_info = {
+ .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
+ .pNext = NULL,
+ .flags = 0,
+ .imageType = VK_IMAGE_TYPE_2D,
+ .format = pCreateInfo->imageFormat,
+ .extent = {
+ .width = pCreateInfo->imageExtent.width,
+ .height = pCreateInfo->imageExtent.height,
+ .depth = 1,
+ },
+ .mipLevels = 1,
+ .arrayLayers = 1,
+ .samples = VK_SAMPLE_COUNT_1_BIT,
+ .tiling = VK_IMAGE_TILING_OPTIMAL,
+ .usage = pCreateInfo->imageUsage | VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
+ .sharingMode = pCreateInfo->imageSharingMode,
+ .queueFamilyIndexCount = pCreateInfo->queueFamilyIndexCount,
+ .pQueueFamilyIndices = pCreateInfo->pQueueFamilyIndices,
+ .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED,
+ };
+ result = wsi->CreateImage(chain->device, &image_info,
+ &chain->alloc, &image->image);
+ if (result != VK_SUCCESS)
+ goto fail;
+
+ wsi->GetImageMemoryRequirements(chain->device, image->image, &reqs);
+
+ const VkMemoryDedicatedAllocateInfo memory_dedicated_info = {
+ .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO,
+ .pNext = NULL,
+ .image = image->image,
+ .buffer = VK_NULL_HANDLE,
+ };
+ const VkMemoryAllocateInfo memory_info = {
+ .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
+ .pNext = &memory_dedicated_info,
+ .allocationSize = reqs.size,
+ .memoryTypeIndex = select_memory_type(wsi, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
+ reqs.memoryTypeBits),
+ };
+ result = wsi->AllocateMemory(chain->device, &memory_info,
+ &chain->alloc, &image->memory);
+ if (result != VK_SUCCESS)
+ goto fail;
+
+ result = wsi->BindImageMemory(chain->device, image->image,
+ image->memory, 0);
+ if (result != VK_SUCCESS)
+ goto fail;
+
+ image->prime.blit_cmd_buffers =
+ vk_zalloc(&chain->alloc,
+ sizeof(VkCommandBuffer) * wsi->queue_family_count, 8,
+ VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
+ if (!image->prime.blit_cmd_buffers) {
+ result = VK_ERROR_OUT_OF_HOST_MEMORY;
+ goto fail;
+ }
+
+ for (uint32_t i = 0; i < wsi->queue_family_count; i++) {
+ const VkCommandBufferAllocateInfo cmd_buffer_info = {
+ .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
+ .pNext = NULL,
+ .commandPool = chain->cmd_pools[i],
+ .level = VK_COMMAND_BUFFER_LEVEL_PRIMARY,
+ .commandBufferCount = 1,
+ };
+ result = wsi->AllocateCommandBuffers(chain->device, &cmd_buffer_info,
+ &image->prime.blit_cmd_buffers[i]);
+ if (result != VK_SUCCESS)
+ goto fail;
+
+ const VkCommandBufferBeginInfo begin_info = {
+ .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
+ };
+ wsi->BeginCommandBuffer(image->prime.blit_cmd_buffers[i], &begin_info);
+
+ struct VkBufferImageCopy buffer_image_copy = {
+ .bufferOffset = 0,
+ .bufferRowLength = linear_stride / cpp,
+ .bufferImageHeight = 0,
+ .imageSubresource = {
+ .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
+ .mipLevel = 0,
+ .baseArrayLayer = 0,
+ .layerCount = 1,
+ },
+ .imageOffset = { .x = 0, .y = 0, .z = 0 },
+ .imageExtent = {
+ .width = pCreateInfo->imageExtent.width,
+ .height = pCreateInfo->imageExtent.height,
+ .depth = 1,
+ },
+ };
+ wsi->CmdCopyImageToBuffer(image->prime.blit_cmd_buffers[i],
+ image->image,
+ VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
+ image->prime.buffer,
+ 1, &buffer_image_copy);
+
+ result = wsi->EndCommandBuffer(image->prime.blit_cmd_buffers[i]);
+ if (result != VK_SUCCESS)
+ goto fail;
+ }
+
+ const VkMemoryGetFdInfoKHR linear_memory_get_fd_info = {
+ .sType = VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR,
+ .pNext = NULL,
+ .memory = image->prime.memory,
+ .handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT,
+ };
+ int fd;
+ result = wsi->GetMemoryFdKHR(chain->device, &linear_memory_get_fd_info, &fd);
+ if (result != VK_SUCCESS)
+ goto fail;
+
+ image->drm_modifier = use_modifier ? DRM_FORMAT_MOD_LINEAR : DRM_FORMAT_MOD_INVALID;
+ image->num_planes = 1;
+ image->sizes[0] = linear_size;
+ image->row_pitches[0] = linear_stride;
+ image->offsets[0] = 0;
+ image->fds[0] = fd;
+
+ return VK_SUCCESS;
+
+fail:
+ wsi_destroy_image(chain, image);
+
+ return result;
+}
+
diff --git a/lib/mesa/src/vulkan/wsi/wsi_common_private.h b/lib/mesa/src/vulkan/wsi/wsi_common_private.h
index 88c360a24..1fe8211f9 100644
--- a/lib/mesa/src/vulkan/wsi/wsi_common_private.h
+++ b/lib/mesa/src/vulkan/wsi/wsi_common_private.h
@@ -24,6 +24,7 @@
#define WSI_COMMON_PRIVATE_H
#include "wsi_common.h"
+#include "vulkan/util/vk_object.h"
struct wsi_image {
VkImage image;
@@ -44,6 +45,8 @@ struct wsi_image {
};
struct wsi_swapchain {
+ struct vk_object_base base;
+
const struct wsi_device *wsi;
VkDevice device;
@@ -147,6 +150,11 @@ VkResult wsi_wl_init_wsi(struct wsi_device *wsi_device,
VkPhysicalDevice physical_device);
void wsi_wl_finish_wsi(struct wsi_device *wsi_device,
const VkAllocationCallbacks *alloc);
+VkResult wsi_win32_init_wsi(struct wsi_device *wsi_device,
+ const VkAllocationCallbacks *alloc,
+ VkPhysicalDevice physical_device);
+void wsi_win32_finish_wsi(struct wsi_device *wsi_device,
+ const VkAllocationCallbacks *alloc);
VkResult
@@ -158,23 +166,7 @@ void
wsi_display_finish_wsi(struct wsi_device *wsi_device,
const VkAllocationCallbacks *alloc);
-#define WSI_DEFINE_NONDISP_HANDLE_CASTS(__wsi_type, __VkType) \
- \
- static inline struct __wsi_type * \
- __wsi_type ## _from_handle(__VkType _handle) \
- { \
- return (struct __wsi_type *)(uintptr_t) _handle; \
- } \
- \
- static inline __VkType \
- __wsi_type ## _to_handle(struct __wsi_type *_obj) \
- { \
- return (__VkType)(uintptr_t) _obj; \
- }
-
-#define WSI_FROM_HANDLE(__wsi_type, __name, __handle) \
- struct __wsi_type *__name = __wsi_type ## _from_handle(__handle)
-
-WSI_DEFINE_NONDISP_HANDLE_CASTS(wsi_swapchain, VkSwapchainKHR)
+VK_DEFINE_NONDISP_HANDLE_CASTS(wsi_swapchain, base, VkSwapchainKHR,
+ VK_OBJECT_TYPE_SWAPCHAIN_KHR)
#endif /* WSI_COMMON_PRIVATE_H */
diff --git a/lib/mesa/src/vulkan/wsi/wsi_common_win32.c b/lib/mesa/src/vulkan/wsi/wsi_common_win32.c
new file mode 100644
index 000000000..fa6f898e5
--- /dev/null
+++ b/lib/mesa/src/vulkan/wsi/wsi_common_win32.c
@@ -0,0 +1,675 @@
+/*
+ * Copyright © 2015 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 <assert.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "vk_util.h"
+#include "wsi_common_private.h"
+#include "wsi_common_win32.h"
+
+#if defined(__GNUC__)
+#pragma GCC diagnostic ignored "-Wint-to-pointer-cast" // warning: cast to pointer from integer of different size
+#endif
+
+struct wsi_win32;
+
+struct wsi_win32 {
+ struct wsi_interface base;
+
+ struct wsi_device *wsi;
+
+ const VkAllocationCallbacks *alloc;
+ VkPhysicalDevice physical_device;
+};
+
+struct wsi_win32_image {
+ struct wsi_image base;
+ struct wsi_win32_swapchain *chain;
+ HDC dc;
+ HBITMAP bmp;
+ int bmp_row_pitch;
+ void *ppvBits;
+};
+
+
+struct wsi_win32_swapchain {
+ struct wsi_swapchain base;
+ struct wsi_win32 *wsi;
+ VkIcdSurfaceWin32 *surface;
+ uint64_t flip_sequence;
+ VkResult status;
+ VkExtent2D extent;
+ HWND wnd;
+ HDC chain_dc;
+ struct wsi_win32_image images[0];
+};
+
+VkBool32
+wsi_win32_get_presentation_support(struct wsi_device *wsi_device)
+{
+ return TRUE;
+}
+
+VkResult
+wsi_create_win32_surface(VkInstance instance,
+ const VkAllocationCallbacks *allocator,
+ const VkWin32SurfaceCreateInfoKHR *create_info,
+ VkSurfaceKHR *surface_khr)
+{
+ VkIcdSurfaceWin32 *surface = vk_zalloc(allocator, sizeof *surface, 8,
+ VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
+
+ if (surface == NULL)
+ return VK_ERROR_OUT_OF_HOST_MEMORY;
+
+ surface->base.platform = VK_ICD_WSI_PLATFORM_WIN32;
+
+ surface->hinstance = create_info->hinstance;
+ surface->hwnd = create_info->hwnd;
+
+ *surface_khr = VkIcdSurfaceBase_to_handle(&surface->base);
+ return VK_SUCCESS;
+}
+
+static VkResult
+wsi_win32_surface_get_support(VkIcdSurfaceBase *surface,
+ struct wsi_device *wsi_device,
+ uint32_t queueFamilyIndex,
+ VkBool32* pSupported)
+{
+ *pSupported = true;
+
+ return VK_SUCCESS;
+}
+
+static VkResult
+wsi_win32_surface_get_capabilities(VkIcdSurfaceBase *surface,
+ struct wsi_device *wsi_device,
+ VkSurfaceCapabilitiesKHR* caps)
+{
+ caps->minImageCount = 1;
+ /* There is no real maximum */
+ caps->maxImageCount = 0;
+
+ caps->currentExtent = (VkExtent2D) { UINT32_MAX, UINT32_MAX };
+ caps->minImageExtent = (VkExtent2D) { 1, 1 };
+ caps->maxImageExtent = (VkExtent2D) {
+ wsi_device->maxImageDimension2D,
+ wsi_device->maxImageDimension2D,
+ };
+
+ caps->supportedTransforms = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
+ caps->currentTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
+ caps->maxImageArrayLayers = 1;
+
+ caps->supportedCompositeAlpha =
+ VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR |
+ VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR;
+
+ caps->supportedUsageFlags =
+ VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
+ VK_IMAGE_USAGE_SAMPLED_BIT |
+ VK_IMAGE_USAGE_TRANSFER_DST_BIT |
+ VK_IMAGE_USAGE_STORAGE_BIT |
+ VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
+
+ return VK_SUCCESS;
+}
+
+static VkResult
+wsi_win32_surface_get_capabilities2(VkIcdSurfaceBase *surface,
+ struct wsi_device *wsi_device,
+ const void *info_next,
+ VkSurfaceCapabilities2KHR* caps)
+{
+ assert(caps->sType == VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_KHR);
+
+ VkResult result =
+ wsi_win32_surface_get_capabilities(surface, wsi_device,
+ &caps->surfaceCapabilities);
+
+ vk_foreach_struct(ext, caps->pNext) {
+ switch (ext->sType) {
+ case VK_STRUCTURE_TYPE_SURFACE_PROTECTED_CAPABILITIES_KHR: {
+ VkSurfaceProtectedCapabilitiesKHR *protected = (void *)ext;
+ protected->supportsProtected = VK_FALSE;
+ break;
+ }
+
+ default:
+ /* Ignored */
+ break;
+ }
+ }
+
+ return result;
+}
+
+
+static const struct {
+ VkFormat format;
+} available_surface_formats[] = {
+ { .format = VK_FORMAT_B8G8R8A8_SRGB },
+ { .format = VK_FORMAT_B8G8R8A8_UNORM },
+};
+
+
+static void
+get_sorted_vk_formats(struct wsi_device *wsi_device, VkFormat *sorted_formats)
+{
+ for (unsigned i = 0; i < ARRAY_SIZE(available_surface_formats); i++)
+ sorted_formats[i] = available_surface_formats[i].format;
+
+ if (wsi_device->force_bgra8_unorm_first) {
+ for (unsigned i = 0; i < ARRAY_SIZE(available_surface_formats); i++) {
+ if (sorted_formats[i] == VK_FORMAT_B8G8R8A8_UNORM) {
+ sorted_formats[i] = sorted_formats[0];
+ sorted_formats[0] = VK_FORMAT_B8G8R8A8_UNORM;
+ break;
+ }
+ }
+ }
+}
+
+static VkResult
+wsi_win32_surface_get_formats(VkIcdSurfaceBase *icd_surface,
+ struct wsi_device *wsi_device,
+ uint32_t* pSurfaceFormatCount,
+ VkSurfaceFormatKHR* pSurfaceFormats)
+{
+ VK_OUTARRAY_MAKE_TYPED(VkSurfaceFormatKHR, out, pSurfaceFormats, pSurfaceFormatCount);
+
+ VkFormat sorted_formats[ARRAY_SIZE(available_surface_formats)];
+ get_sorted_vk_formats(wsi_device, sorted_formats);
+
+ for (unsigned i = 0; i < ARRAY_SIZE(sorted_formats); i++) {
+ vk_outarray_append_typed(VkSurfaceFormatKHR, &out, f) {
+ f->format = sorted_formats[i];
+ f->colorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR;
+ }
+ }
+
+ return vk_outarray_status(&out);
+}
+
+static VkResult
+wsi_win32_surface_get_formats2(VkIcdSurfaceBase *icd_surface,
+ struct wsi_device *wsi_device,
+ const void *info_next,
+ uint32_t* pSurfaceFormatCount,
+ VkSurfaceFormat2KHR* pSurfaceFormats)
+{
+ VK_OUTARRAY_MAKE_TYPED(VkSurfaceFormat2KHR, out, pSurfaceFormats, pSurfaceFormatCount);
+
+ VkFormat sorted_formats[ARRAY_SIZE(available_surface_formats)];
+ get_sorted_vk_formats(wsi_device, sorted_formats);
+
+ for (unsigned i = 0; i < ARRAY_SIZE(sorted_formats); i++) {
+ vk_outarray_append_typed(VkSurfaceFormat2KHR, &out, f) {
+ assert(f->sType == VK_STRUCTURE_TYPE_SURFACE_FORMAT_2_KHR);
+ f->surfaceFormat.format = sorted_formats[i];
+ f->surfaceFormat.colorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR;
+ }
+ }
+
+ return vk_outarray_status(&out);
+}
+
+static const VkPresentModeKHR present_modes[] = {
+ //VK_PRESENT_MODE_MAILBOX_KHR,
+ VK_PRESENT_MODE_FIFO_KHR,
+};
+
+static VkResult
+wsi_win32_surface_get_present_modes(VkIcdSurfaceBase *surface,
+ uint32_t* pPresentModeCount,
+ VkPresentModeKHR* pPresentModes)
+{
+ if (pPresentModes == NULL) {
+ *pPresentModeCount = ARRAY_SIZE(present_modes);
+ return VK_SUCCESS;
+ }
+
+ *pPresentModeCount = MIN2(*pPresentModeCount, ARRAY_SIZE(present_modes));
+ typed_memcpy(pPresentModes, present_modes, *pPresentModeCount);
+
+ if (*pPresentModeCount < ARRAY_SIZE(present_modes))
+ return VK_INCOMPLETE;
+ else
+ return VK_SUCCESS;
+}
+
+static VkResult
+wsi_win32_surface_get_present_rectangles(VkIcdSurfaceBase *surface,
+ struct wsi_device *wsi_device,
+ uint32_t* pRectCount,
+ VkRect2D* pRects)
+{
+ VK_OUTARRAY_MAKE_TYPED(VkRect2D, out, pRects, pRectCount);
+
+ vk_outarray_append_typed(VkRect2D, &out, rect) {
+ /* We don't know a size so just return the usual "I don't know." */
+ *rect = (VkRect2D) {
+ .offset = { 0, 0 },
+ .extent = { UINT32_MAX, UINT32_MAX },
+ };
+ }
+
+ return vk_outarray_status(&out);
+}
+
+static uint32_t
+select_memory_type(const struct wsi_device *wsi,
+ VkMemoryPropertyFlags props,
+ uint32_t type_bits)
+{
+ for (uint32_t i = 0; i < wsi->memory_props.memoryTypeCount; i++) {
+ const VkMemoryType type = wsi->memory_props.memoryTypes[i];
+ if ((type_bits & (1 << i)) && (type.propertyFlags & props) == props)
+ return i;
+ }
+
+ unreachable("No memory type found");
+}
+
+VkResult
+wsi_create_native_image(const struct wsi_swapchain *chain,
+ const VkSwapchainCreateInfoKHR *pCreateInfo,
+ uint32_t num_modifier_lists,
+ const uint32_t *num_modifiers,
+ const uint64_t *const *modifiers,
+ struct wsi_image *image)
+{
+ const struct wsi_device *wsi = chain->wsi;
+ VkResult result;
+
+ memset(image, 0, sizeof(*image));
+ for (int i = 0; i < ARRAY_SIZE(image->fds); i++)
+ image->fds[i] = -1;
+
+ VkImageCreateInfo image_info = {
+ .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
+ .flags = 0,
+ .imageType = VK_IMAGE_TYPE_2D,
+ .format = pCreateInfo->imageFormat,
+ .extent = {
+ .width = pCreateInfo->imageExtent.width,
+ .height = pCreateInfo->imageExtent.height,
+ .depth = 1,
+ },
+ .mipLevels = 1,
+ .arrayLayers = 1,
+ .samples = VK_SAMPLE_COUNT_1_BIT,
+ .tiling = VK_IMAGE_TILING_OPTIMAL,
+ .usage = pCreateInfo->imageUsage,
+ .sharingMode = pCreateInfo->imageSharingMode,
+ .queueFamilyIndexCount = pCreateInfo->queueFamilyIndexCount,
+ .pQueueFamilyIndices = pCreateInfo->pQueueFamilyIndices,
+ .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED,
+ };
+
+ VkImageFormatListCreateInfoKHR image_format_list;
+ if (pCreateInfo->flags & VK_SWAPCHAIN_CREATE_MUTABLE_FORMAT_BIT_KHR) {
+ image_info.flags |= VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT |
+ VK_IMAGE_CREATE_EXTENDED_USAGE_BIT_KHR;
+
+ const VkImageFormatListCreateInfoKHR *format_list =
+ vk_find_struct_const(pCreateInfo->pNext,
+ IMAGE_FORMAT_LIST_CREATE_INFO_KHR);
+
+#ifndef NDEBUG
+ assume(format_list && format_list->viewFormatCount > 0);
+ bool format_found = false;
+ for (int i = 0; i < format_list->viewFormatCount; i++)
+ if (pCreateInfo->imageFormat == format_list->pViewFormats[i])
+ format_found = true;
+ assert(format_found);
+#endif
+
+ image_format_list = *format_list;
+ image_format_list.pNext = NULL;
+ __vk_append_struct(&image_info, &image_format_list);
+ }
+
+
+ result = wsi->CreateImage(chain->device, &image_info,
+ &chain->alloc, &image->image);
+ if (result != VK_SUCCESS)
+ goto fail;
+
+ VkMemoryRequirements reqs;
+ wsi->GetImageMemoryRequirements(chain->device, image->image, &reqs);
+
+ const struct wsi_memory_allocate_info memory_wsi_info = {
+ .sType = VK_STRUCTURE_TYPE_WSI_MEMORY_ALLOCATE_INFO_MESA,
+ .pNext = NULL,
+ .implicit_sync = true,
+ };
+ const VkExportMemoryAllocateInfo memory_export_info = {
+ .sType = VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO,
+ .pNext = &memory_wsi_info,
+ .handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT,
+ };
+ const VkMemoryDedicatedAllocateInfo memory_dedicated_info = {
+ .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO,
+ .pNext = &memory_export_info,
+ .image = image->image,
+ .buffer = VK_NULL_HANDLE,
+ };
+ const VkMemoryAllocateInfo memory_info = {
+ .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
+ .pNext = &memory_dedicated_info,
+ .allocationSize = reqs.size,
+ .memoryTypeIndex = select_memory_type(wsi, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
+ reqs.memoryTypeBits),
+ };
+ result = wsi->AllocateMemory(chain->device, &memory_info,
+ &chain->alloc, &image->memory);
+ if (result != VK_SUCCESS)
+ goto fail;
+
+ result = wsi->BindImageMemory(chain->device, image->image,
+ image->memory, 0);
+ if (result != VK_SUCCESS)
+ goto fail;
+
+ const VkImageSubresource image_subresource = {
+ .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
+ .mipLevel = 0,
+ .arrayLayer = 0,
+ };
+ VkSubresourceLayout image_layout;
+ wsi->GetImageSubresourceLayout(chain->device, image->image,
+ &image_subresource, &image_layout);
+
+ image->num_planes = 1;
+ image->sizes[0] = reqs.size;
+ image->row_pitches[0] = image_layout.rowPitch;
+ image->offsets[0] = 0;
+
+ return VK_SUCCESS;
+
+fail:
+ wsi_destroy_image(chain, image);
+
+ return result;
+}
+
+static VkResult
+wsi_win32_image_init(VkDevice device_h,
+ struct wsi_swapchain *drv_chain,
+ const VkSwapchainCreateInfoKHR *create_info,
+ const VkAllocationCallbacks *allocator,
+ struct wsi_win32_image *image)
+{
+ struct wsi_win32_swapchain *chain = (struct wsi_win32_swapchain *) drv_chain;
+
+ VkResult result = wsi_create_native_image(&chain->base, create_info,
+ 0, NULL, NULL,
+ &image->base);
+ if (result != VK_SUCCESS)
+ return result;
+
+ VkIcdSurfaceWin32 *win32_surface = (VkIcdSurfaceWin32 *)create_info->surface;
+ chain->wnd = win32_surface->hwnd;
+ chain->chain_dc = GetDC(chain->wnd);
+
+ image->dc = CreateCompatibleDC(chain->chain_dc);
+ HBITMAP bmp = NULL;
+
+ BITMAPINFO info = { 0 };
+ info.bmiHeader.biSize = sizeof(BITMAPINFO);
+ info.bmiHeader.biWidth = create_info->imageExtent.width;
+ info.bmiHeader.biHeight = -create_info->imageExtent.height;
+ info.bmiHeader.biPlanes = 1;
+ info.bmiHeader.biBitCount = 32;
+ info.bmiHeader.biCompression = BI_RGB;
+
+ bmp = CreateDIBSection(image->dc, &info, DIB_RGB_COLORS, &image->ppvBits, NULL, 0);
+ assert(bmp && image->ppvBits);
+
+ SelectObject(image->dc, bmp);
+
+ BITMAP header;
+ int status = GetObject(bmp, sizeof(BITMAP), &header);
+ (void)status;
+ image->bmp_row_pitch = header.bmWidthBytes;
+ image->bmp = bmp;
+ image->chain = chain;
+
+ return VK_SUCCESS;
+}
+
+static void
+wsi_win32_image_finish(struct wsi_swapchain *drv_chain,
+ const VkAllocationCallbacks *allocator,
+ struct wsi_win32_image *image)
+{
+ struct wsi_win32_swapchain *chain =
+ (struct wsi_win32_swapchain *) drv_chain;
+
+ DeleteDC(image->dc);
+ if(image->bmp)
+ DeleteObject(image->bmp);
+ wsi_destroy_image(&chain->base, &image->base);
+}
+
+static VkResult
+wsi_win32_swapchain_destroy(struct wsi_swapchain *drv_chain,
+ const VkAllocationCallbacks *allocator)
+{
+ struct wsi_win32_swapchain *chain =
+ (struct wsi_win32_swapchain *) drv_chain;
+
+ for (uint32_t i = 0; i < chain->base.image_count; i++)
+ wsi_win32_image_finish(drv_chain, allocator, &chain->images[i]);
+
+ DeleteDC(chain->chain_dc);
+
+ wsi_swapchain_finish(&chain->base);
+ vk_free(allocator, chain);
+ return VK_SUCCESS;
+}
+
+static struct wsi_image *
+wsi_win32_get_wsi_image(struct wsi_swapchain *drv_chain,
+ uint32_t image_index)
+{
+ struct wsi_win32_swapchain *chain =
+ (struct wsi_win32_swapchain *) drv_chain;
+
+ return &chain->images[image_index].base;
+}
+
+static VkResult
+wsi_win32_acquire_next_image(struct wsi_swapchain *drv_chain,
+ const VkAcquireNextImageInfoKHR *info,
+ uint32_t *image_index)
+{
+ struct wsi_win32_swapchain *chain =
+ (struct wsi_win32_swapchain *)drv_chain;
+
+ /* Bail early if the swapchain is broken */
+ if (chain->status != VK_SUCCESS)
+ return chain->status;
+
+ *image_index = 0;
+ return VK_SUCCESS;
+}
+
+static VkResult
+wsi_win32_queue_present(struct wsi_swapchain *drv_chain,
+ uint32_t image_index,
+ const VkPresentRegionKHR *damage)
+{
+ struct wsi_win32_swapchain *chain = (struct wsi_win32_swapchain *) drv_chain;
+ assert(image_index < chain->base.image_count);
+ struct wsi_win32_image *image = &chain->images[image_index];
+ VkResult result;
+
+ char *ptr;
+ char *dptr = image->ppvBits;
+ result = chain->base.wsi->MapMemory(chain->base.device,
+ image->base.memory,
+ 0, 0, 0, (void**)&ptr);
+
+ for (unsigned h = 0; h < chain->extent.height; h++) {
+ memcpy(dptr, ptr, chain->extent.width * 4);
+ dptr += image->bmp_row_pitch;
+ ptr += image->base.row_pitches[0];
+ }
+ if(StretchBlt(chain->chain_dc, 0, 0, chain->extent.width, chain->extent.height, image->dc, 0, 0, chain->extent.width, chain->extent.height, SRCCOPY))
+ result = VK_SUCCESS;
+ else
+ result = VK_ERROR_MEMORY_MAP_FAILED;
+
+ chain->base.wsi->UnmapMemory(chain->base.device, image->base.memory);
+ if (result != VK_SUCCESS)
+ chain->status = result;
+
+ if (result != VK_SUCCESS)
+ return result;
+
+ return chain->status;
+}
+
+static VkResult
+wsi_win32_surface_create_swapchain(
+ VkIcdSurfaceBase *icd_surface,
+ VkDevice device,
+ struct wsi_device *wsi_device,
+ const VkSwapchainCreateInfoKHR *create_info,
+ const VkAllocationCallbacks *allocator,
+ struct wsi_swapchain **swapchain_out)
+{
+ VkIcdSurfaceWin32 *surface = (VkIcdSurfaceWin32 *)icd_surface;
+ struct wsi_win32 *wsi =
+ (struct wsi_win32 *) wsi_device->wsi[VK_ICD_WSI_PLATFORM_WIN32];
+
+ assert(create_info->sType == VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR);
+
+ const unsigned num_images = create_info->minImageCount;
+ struct wsi_win32_swapchain *chain;
+ size_t size = sizeof(*chain) + num_images * sizeof(chain->images[0]);
+
+ chain = vk_zalloc(allocator, size,
+ 8, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
+
+ if (chain == NULL)
+ return VK_ERROR_OUT_OF_HOST_MEMORY;
+
+ VkResult result = wsi_swapchain_init(wsi_device, &chain->base, device,
+ create_info, allocator);
+ if (result != VK_SUCCESS) {
+ vk_free(allocator, chain);
+ return result;
+ }
+
+ chain->base.destroy = wsi_win32_swapchain_destroy;
+ chain->base.get_wsi_image = wsi_win32_get_wsi_image;
+ chain->base.acquire_next_image = wsi_win32_acquire_next_image;
+ chain->base.queue_present = wsi_win32_queue_present;
+ chain->base.present_mode = wsi_swapchain_get_present_mode(wsi_device, create_info);
+ chain->base.image_count = num_images;
+ chain->extent = create_info->imageExtent;
+
+ chain->wsi = wsi;
+ chain->status = VK_SUCCESS;
+
+ chain->surface = surface;
+
+ for (uint32_t image = 0; image < chain->base.image_count; image++) {
+ result = wsi_win32_image_init(device, &chain->base,
+ create_info, allocator,
+ &chain->images[image]);
+ if (result != VK_SUCCESS) {
+ while (image > 0) {
+ --image;
+ wsi_win32_image_finish(&chain->base, allocator,
+ &chain->images[image]);
+ }
+ vk_free(allocator, chain);
+ goto fail_init_images;
+ }
+ }
+
+ *swapchain_out = &chain->base;
+
+ return VK_SUCCESS;
+
+fail_init_images:
+ return result;
+}
+
+
+VkResult
+wsi_win32_init_wsi(struct wsi_device *wsi_device,
+ const VkAllocationCallbacks *alloc,
+ VkPhysicalDevice physical_device)
+{
+ struct wsi_win32 *wsi;
+ VkResult result;
+
+ wsi = vk_alloc(alloc, sizeof(*wsi), 8,
+ VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
+ if (!wsi) {
+ result = VK_ERROR_OUT_OF_HOST_MEMORY;
+ goto fail;
+ }
+
+ wsi->physical_device = physical_device;
+ wsi->alloc = alloc;
+ wsi->wsi = wsi_device;
+
+ wsi->base.get_support = wsi_win32_surface_get_support;
+ wsi->base.get_capabilities2 = wsi_win32_surface_get_capabilities2;
+ wsi->base.get_formats = wsi_win32_surface_get_formats;
+ wsi->base.get_formats2 = wsi_win32_surface_get_formats2;
+ wsi->base.get_present_modes = wsi_win32_surface_get_present_modes;
+ wsi->base.get_present_rectangles = wsi_win32_surface_get_present_rectangles;
+ wsi->base.create_swapchain = wsi_win32_surface_create_swapchain;
+
+ wsi_device->wsi[VK_ICD_WSI_PLATFORM_WIN32] = &wsi->base;
+
+ return VK_SUCCESS;
+
+fail:
+ wsi_device->wsi[VK_ICD_WSI_PLATFORM_WIN32] = NULL;
+
+ return result;
+}
+
+void
+wsi_win32_finish_wsi(struct wsi_device *wsi_device,
+ const VkAllocationCallbacks *alloc)
+{
+ struct wsi_win32 *wsi =
+ (struct wsi_win32 *)wsi_device->wsi[VK_ICD_WSI_PLATFORM_WIN32];
+ if (!wsi)
+ return;
+
+ vk_free(alloc, wsi);
+}
diff --git a/lib/mesa/src/vulkan/wsi/wsi_common_win32.h b/lib/mesa/src/vulkan/wsi/wsi_common_win32.h
new file mode 100644
index 000000000..661ba9dea
--- /dev/null
+++ b/lib/mesa/src/vulkan/wsi/wsi_common_win32.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright © 2015 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 WSI_COMMON_WIN32_H
+#define WSI_COMMON_WIN32_H
+
+#include "wsi_common.h"
+#include <vulkan/vulkan_win32.h>
+
+VkBool32
+wsi_win32_get_presentation_support(struct wsi_device *wsi_device);
+
+VkResult
+wsi_create_win32_surface(VkInstance instance,
+ const VkAllocationCallbacks *pAllocator,
+ const VkWin32SurfaceCreateInfoKHR *pCreateInfo,
+ VkSurfaceKHR *pSurface);
+#endif