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/meson.build9
-rw-r--r--lib/mesa/src/vulkan/overlay-layer/overlay.cpp8
-rw-r--r--lib/mesa/src/vulkan/util/meson.build53
-rw-r--r--lib/mesa/src/vulkan/util/vk_alloc.c55
-rw-r--r--lib/mesa/src/vulkan/util/vk_cmd_copy.c10
-rw-r--r--lib/mesa/src/vulkan/util/vk_cmd_queue_gen.py446
-rw-r--r--lib/mesa/src/vulkan/util/vk_command_buffer.c52
-rw-r--r--lib/mesa/src/vulkan/util/vk_command_buffer.h95
-rw-r--r--lib/mesa/src/vulkan/util/vk_commands_gen.py143
-rw-r--r--lib/mesa/src/vulkan/util/vk_debug_utils.c285
-rw-r--r--lib/mesa/src/vulkan/util/vk_debug_utils.h67
-rw-r--r--lib/mesa/src/vulkan/util/vk_device.c462
-rw-r--r--lib/mesa/src/vulkan/util/vk_device.h14
-rw-r--r--lib/mesa/src/vulkan/util/vk_dispatch_table_gen.py74
-rw-r--r--lib/mesa/src/vulkan/util/vk_entrypoints_gen.py15
-rw-r--r--lib/mesa/src/vulkan/util/vk_extensions.py6
-rw-r--r--lib/mesa/src/vulkan/util/vk_format.h31
-rw-r--r--lib/mesa/src/vulkan/util/vk_image.c617
-rw-r--r--lib/mesa/src/vulkan/util/vk_image.h231
-rw-r--r--lib/mesa/src/vulkan/util/vk_instance.c73
-rw-r--r--lib/mesa/src/vulkan/util/vk_instance.h11
-rw-r--r--lib/mesa/src/vulkan/util/vk_log.c339
-rw-r--r--lib/mesa/src/vulkan/util/vk_log.h89
-rw-r--r--lib/mesa/src/vulkan/util/vk_object.c41
-rw-r--r--lib/mesa/src/vulkan/util/vk_object.h14
-rw-r--r--lib/mesa/src/vulkan/util/vk_physical_device.c63
-rw-r--r--lib/mesa/src/vulkan/util/vk_physical_device.h8
-rw-r--r--lib/mesa/src/vulkan/util/vk_physical_device_features.py250
-rw-r--r--lib/mesa/src/vulkan/util/vk_queue.c56
-rw-r--r--lib/mesa/src/vulkan/util/vk_queue.h112
-rw-r--r--lib/mesa/src/vulkan/util/vk_shader_module.h2
-rw-r--r--lib/mesa/src/vulkan/util/vk_synchronization2.c405
-rw-r--r--lib/mesa/src/vulkan/wsi/meson.build40
-rw-r--r--lib/mesa/src/vulkan/wsi/wsi_common.c239
-rw-r--r--lib/mesa/src/vulkan/wsi/wsi_common_display.c408
-rw-r--r--lib/mesa/src/vulkan/wsi/wsi_common_display.h112
-rw-r--r--lib/mesa/src/vulkan/wsi/wsi_common_drm.c81
-rw-r--r--lib/mesa/src/vulkan/wsi/wsi_common_private.h1
-rw-r--r--lib/mesa/src/vulkan/wsi/wsi_common_queue.h8
-rw-r--r--lib/mesa/src/vulkan/wsi/wsi_common_win32.c38
40 files changed, 4639 insertions, 424 deletions
diff --git a/lib/mesa/src/vulkan/meson.build b/lib/mesa/src/vulkan/meson.build
index 3f95551f2..652805022 100644
--- a/lib/mesa/src/vulkan/meson.build
+++ b/lib/mesa/src/vulkan/meson.build
@@ -21,7 +21,6 @@
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 = []
@@ -29,7 +28,6 @@ vulkan_wsi_deps = []
vulkan_wsi_list = []
if with_platform_x11
- vulkan_wsi_args += ['-DVK_USE_PLATFORM_XCB_KHR', '-DVK_USE_PLATFORM_XLIB_KHR']
vulkan_wsi_deps += [
dep_xcb,
dep_x11_xcb,
@@ -37,25 +35,20 @@ if with_platform_x11
dep_xcb_present,
dep_xcb_sync,
dep_xcb_xrandr,
+ dep_xcb_shm,
dep_xshmfence,
]
vulkan_wsi_list += ['xcb', 'x11']
endif
if with_platform_wayland
- vulkan_wsi_args += ['-DVK_USE_PLATFORM_WAYLAND_KHR']
vulkan_wsi_deps += dep_wayland_client
vulkan_wsi_list += ['wayland']
endif
-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_xlib_xrandr]
vulkan_wsi_list += ['xlib_xrandr']
endif
diff --git a/lib/mesa/src/vulkan/overlay-layer/overlay.cpp b/lib/mesa/src/vulkan/overlay-layer/overlay.cpp
index 6500c477b..270dd9b39 100644
--- a/lib/mesa/src/vulkan/overlay-layer/overlay.cpp
+++ b/lib/mesa/src/vulkan/overlay-layer/overlay.cpp
@@ -41,6 +41,7 @@
#include "util/os_time.h"
#include "util/os_socket.h"
#include "util/simple_mtx.h"
+#include "util/u_math.h"
#include "vk_enum_to_str.h"
#include "vk_dispatch_table.h"
@@ -962,6 +963,8 @@ static void compute_swapchain_display(struct swapchain_data *data)
for (uint32_t s = 0; s < OVERLAY_PARAM_ENABLED_MAX; s++) {
if (!instance_data->params.enabled[s] ||
+ s == OVERLAY_PARAM_ENABLED_device ||
+ s == OVERLAY_PARAM_ENABLED_format ||
s == OVERLAY_PARAM_ENABLED_fps ||
s == OVERLAY_PARAM_ENABLED_frame)
continue;
@@ -1215,8 +1218,8 @@ static struct overlay_draw *render_swapchain_display(struct swapchain_data *data
VK_SUBPASS_CONTENTS_INLINE);
/* Create/Resize vertex & index buffers */
- size_t vertex_size = draw_data->TotalVtxCount * sizeof(ImDrawVert);
- size_t index_size = draw_data->TotalIdxCount * sizeof(ImDrawIdx);
+ size_t vertex_size = ALIGN(draw_data->TotalVtxCount * sizeof(ImDrawVert), device_data->properties.limits.nonCoherentAtomSize);
+ size_t index_size = ALIGN(draw_data->TotalIdxCount * sizeof(ImDrawIdx), device_data->properties.limits.nonCoherentAtomSize);
if (draw->vertex_buffer_size < vertex_size) {
CreateOrResizeBuffer(device_data,
&draw->vertex_buffer,
@@ -2630,6 +2633,7 @@ static const struct {
ADD_HOOK(CreateInstance),
ADD_HOOK(DestroyInstance),
#undef ADD_HOOK
+#undef ADD_ALIAS_HOOK
};
static void *find_ptr(const char *name)
diff --git a/lib/mesa/src/vulkan/util/meson.build b/lib/mesa/src/vulkan/util/meson.build
index 1a3723990..234e7f1be 100644
--- a/lib/mesa/src/vulkan/util/meson.build
+++ b/lib/mesa/src/vulkan/util/meson.build
@@ -34,16 +34,32 @@ vk_entrypoints_gen_depend_files = [
files('vk_dispatch_table_gen.py'),
vk_dispatch_table_gen_depend_files,
]
+vk_cmd_queue_gen_depend_files = [
+ files('vk_dispatch_table_gen.py'),
+ vk_dispatch_table_gen_depend_files,
+]
+vk_commands_gen_depend_files = [
+ files('vk_dispatch_table_gen.py'),
+ vk_dispatch_table_gen_depend_files,
+]
+vk_physical_device_features_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')
+vk_commands_gen = files('vk_commands_gen.py')
files_vulkan_util = files(
+ 'vk_alloc.c',
'vk_alloc.h',
'vk_cmd_copy.c',
+ 'vk_command_buffer.c',
+ 'vk_command_buffer.h',
'vk_debug_report.c',
'vk_debug_report.h',
+ 'vk_debug_utils.c',
+ 'vk_debug_utils.h',
'vk_deferred_operation.c',
'vk_deferred_operation.h',
'vk_descriptors.c',
@@ -51,15 +67,22 @@ files_vulkan_util = files(
'vk_device.c',
'vk_device.h',
'vk_format.c',
+ 'vk_image.c',
+ 'vk_image.h',
'vk_instance.c',
'vk_instance.h',
+ 'vk_log.c',
+ 'vk_log.h',
'vk_object.c',
'vk_object.h',
'vk_physical_device.c',
'vk_physical_device.h',
+ 'vk_queue.c',
+ 'vk_queue.h',
'vk_render_pass.c',
'vk_shader_module.c',
'vk_shader_module.h',
+ 'vk_synchronization2.c',
'vk_util.c',
'vk_util.h',
)
@@ -89,7 +112,7 @@ vk_dispatch_table = custom_target(
vk_enum_to_str = custom_target(
'vk_enum_to_str',
input : ['gen_enum_to_str.py', vk_api_xml],
- output : ['vk_enum_to_str.c', 'vk_enum_to_str.h'],
+ output : ['vk_enum_to_str.c', 'vk_enum_to_str.h', 'vk_enum_defines.h'],
command : [
prog_python, '@INPUT0@', '--xml', '@INPUT1@',
'--outdir', meson.current_build_dir()
@@ -107,12 +130,34 @@ vk_extensions = custom_target(
depend_files : vk_extensions_gen_depend_files,
)
+vk_cmd_queue = custom_target(
+ 'vk_cmd_queue',
+ input : ['vk_cmd_queue_gen.py', vk_api_xml],
+ output : ['vk_cmd_queue.c', 'vk_cmd_queue.h'],
+ command : [
+ prog_python, '@INPUT0@', '--xml', '@INPUT1@',
+ '--out-c', '@OUTPUT0@', '--out-h', '@OUTPUT1@'
+ ],
+ depend_files : vk_cmd_queue_gen_depend_files,
+)
+
+vk_physical_device_features = custom_target(
+ 'vk_physical_device_features',
+ input : ['vk_physical_device_features.py', vk_api_xml],
+ output : ['vk_physical_device_features.c'],
+ command : [
+ prog_python, '@INPUT0@', '--xml', '@INPUT1@',
+ '--out-c', '@OUTPUT0@'
+ ],
+ depend_files : vk_physical_device_features_gen_depend_files,
+)
+
libvulkan_util = static_library(
'vulkan_util',
[files_vulkan_util, vk_common_entrypoints, vk_dispatch_table,
- vk_enum_to_str, vk_extensions],
+ vk_enum_to_str, vk_extensions, vk_cmd_queue, vk_physical_device_features],
include_directories : [inc_include, inc_src, inc_gallium],
- dependencies : [vulkan_wsi_deps, idep_mesautil],
+ dependencies : [vulkan_wsi_deps, idep_mesautil, idep_nir_headers],
# For glsl_type_singleton
link_with : libcompiler,
c_args : [vulkan_wsi_args],
@@ -127,7 +172,7 @@ idep_vulkan_util_headers = declare_dependency(
# 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
+# https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/10506
if get_option('backend').startswith('vs')
idep_vulkan_util = declare_dependency(
link_with : libvulkan_util,
diff --git a/lib/mesa/src/vulkan/util/vk_alloc.c b/lib/mesa/src/vulkan/util/vk_alloc.c
new file mode 100644
index 000000000..c687f92ae
--- /dev/null
+++ b/lib/mesa/src/vulkan/util/vk_alloc.c
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2021 Google LLC
+ * SPDX-License-Identifier: MIT
+ */
+
+#include "vk_alloc.h"
+
+#include <stdlib.h>
+
+#if __STDC_VERSION__ >= 201112L && !defined(_MSC_VER)
+#include <stddef.h>
+#define MAX_ALIGN alignof(max_align_t)
+#else
+/* long double might be 128-bit, but our callers do not need that anyway(?) */
+#include <stdint.h>
+#define MAX_ALIGN alignof(uint64_t)
+#endif
+
+static VKAPI_ATTR void * VKAPI_CALL
+vk_default_alloc(void *pUserData,
+ size_t size,
+ size_t alignment,
+ VkSystemAllocationScope allocationScope)
+{
+ assert(MAX_ALIGN % alignment == 0);
+ return malloc(size);
+}
+
+static VKAPI_ATTR void * VKAPI_CALL
+vk_default_realloc(void *pUserData,
+ void *pOriginal,
+ size_t size,
+ size_t alignment,
+ VkSystemAllocationScope allocationScope)
+{
+ assert(MAX_ALIGN % alignment == 0);
+ return realloc(pOriginal, size);
+}
+
+static VKAPI_ATTR void VKAPI_CALL
+vk_default_free(void *pUserData, void *pMemory)
+{
+ free(pMemory);
+}
+
+const VkAllocationCallbacks *
+vk_default_allocator(void)
+{
+ static const VkAllocationCallbacks allocator = {
+ .pfnAllocation = vk_default_alloc,
+ .pfnReallocation = vk_default_realloc,
+ .pfnFree = vk_default_free,
+ };
+ return &allocator;
+}
diff --git a/lib/mesa/src/vulkan/util/vk_cmd_copy.c b/lib/mesa/src/vulkan/util/vk_cmd_copy.c
index 5c71dbb38..9fcb0c23d 100644
--- a/lib/mesa/src/vulkan/util/vk_cmd_copy.c
+++ b/lib/mesa/src/vulkan/util/vk_cmd_copy.c
@@ -23,15 +23,7 @@
#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)
+#include "vk_util.h"
VKAPI_ATTR void VKAPI_CALL
vk_common_CmdCopyBuffer(VkCommandBuffer commandBuffer,
diff --git a/lib/mesa/src/vulkan/util/vk_cmd_queue_gen.py b/lib/mesa/src/vulkan/util/vk_cmd_queue_gen.py
new file mode 100644
index 000000000..539392a31
--- /dev/null
+++ b/lib/mesa/src/vulkan/util/vk_cmd_queue_gen.py
@@ -0,0 +1,446 @@
+# coding=utf-8
+COPYRIGHT=u"""
+/* Copyright © 2015-2021 Intel Corporation
+ * Copyright © 2021 Collabora, Ltd.
+ *
+ * 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
+import re
+from collections import namedtuple
+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_dispatch_table_gen import get_entrypoints_from_xml, EntrypointParam
+
+MANUAL_COMMANDS = ['CmdPushDescriptorSetKHR', # This script doesn't know how to copy arrays in structs in arrays
+ 'CmdPushDescriptorSetWithTemplateKHR', # pData's size cannot be calculated from the xml
+ 'CmdDrawMultiEXT', # The size of the elements is specified in a stride param
+ 'CmdDrawMultiIndexedEXT', # The size of the elements is specified in a stride param
+ 'CmdBindDescriptorSets', # The VkPipelineLayout object could be released before the command is executed
+ ]
+
+TEMPLATE_H = Template(COPYRIGHT + """\
+/* This file generated from ${filename}, don't edit directly. */
+
+#pragma once
+
+#include "util/list.h"
+
+#define VK_PROTOTYPES
+#include <vulkan/vulkan.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct vk_cmd_queue {
+ VkAllocationCallbacks *alloc;
+ struct list_head cmds;
+};
+
+enum vk_cmd_type {
+% for c in commands:
+% if c.guard is not None:
+#ifdef ${c.guard}
+% endif
+ ${to_enum_name(c.name)},
+% if c.guard is not None:
+#endif // ${c.guard}
+% endif
+% endfor
+};
+
+extern const char *vk_cmd_queue_type_names[];
+
+% for c in commands:
+% if len(c.params) <= 1: # Avoid "error C2016: C requires that a struct or union have at least one member"
+<% continue %>
+% endif
+% if c.guard is not None:
+#ifdef ${c.guard}
+% endif
+struct ${to_struct_name(c.name)} {
+% for p in c.params[1:]:
+ ${to_field_decl(p.decl)};
+% endfor
+};
+% if c.guard is not None:
+#endif // ${c.guard}
+% endif
+% endfor
+
+struct vk_cmd_queue_entry {
+ struct list_head cmd_link;
+ enum vk_cmd_type type;
+ union {
+% for c in commands:
+% if len(c.params) <= 1:
+<% continue %>
+% endif
+% if c.guard is not None:
+#ifdef ${c.guard}
+% endif
+ struct ${to_struct_name(c.name)} ${to_struct_field_name(c.name)};
+% if c.guard is not None:
+#endif // ${c.guard}
+% endif
+% endfor
+ } u;
+ void *driver_data;
+};
+
+% for c in commands:
+% if c.name in manual_commands:
+<% continue %>
+% endif
+% if c.guard is not None:
+#ifdef ${c.guard}
+% endif
+ void vk_enqueue_${to_underscore(c.name)}(struct vk_cmd_queue *queue
+% for p in c.params[1:]:
+ , ${p.decl}
+% endfor
+ );
+% if c.guard is not None:
+#endif // ${c.guard}
+% endif
+
+% endfor
+
+void vk_free_queue(struct vk_cmd_queue *queue);
+
+#ifdef __cplusplus
+}
+#endif
+""", output_encoding='utf-8')
+
+TEMPLATE_C = Template(COPYRIGHT + """
+/* This file generated from ${filename}, don't edit directly. */
+
+#include "${header}"
+
+#define VK_PROTOTYPES
+#include <vulkan/vulkan.h>
+
+#include "vk_alloc.h"
+
+const char *vk_cmd_queue_type_names[] = {
+% for c in commands:
+% if c.guard is not None:
+#ifdef ${c.guard}
+% endif
+ "${to_enum_name(c.name)}",
+% if c.guard is not None:
+#endif // ${c.guard}
+% endif
+% endfor
+};
+
+% for c in commands:
+% if c.name in manual_commands:
+<% continue %>
+% endif
+% if c.guard is not None:
+#ifdef ${c.guard}
+% endif
+void vk_enqueue_${to_underscore(c.name)}(struct vk_cmd_queue *queue
+% for p in c.params[1:]:
+, ${p.decl}
+% endfor
+)
+{
+ struct vk_cmd_queue_entry *cmd = vk_zalloc(queue->alloc,
+ sizeof(*cmd), 8,
+ VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
+ if (!cmd)
+ return;
+
+ cmd->type = ${to_enum_name(c.name)};
+ list_addtail(&cmd->cmd_link, &queue->cmds);
+
+% for p in c.params[1:]:
+% if p.len:
+ if (${p.name}) {
+ ${get_array_copy(c, p)}
+ }
+% elif '[' in p.decl:
+ memcpy(cmd->u.${to_struct_field_name(c.name)}.${to_field_name(p.name)}, ${p.name},
+ sizeof(*${p.name}) * ${get_array_len(p)});
+% elif p.type == "void":
+ cmd->u.${to_struct_field_name(c.name)}.${to_field_name(p.name)} = (${remove_suffix(p.decl.replace("const", ""), p.name)}) ${p.name};
+% elif '*' in p.decl:
+ ${get_struct_copy("cmd->u.%s.%s" % (to_struct_field_name(c.name), to_field_name(p.name)), p.name, p.type, 'sizeof(%s)' % p.type, types)}
+% else:
+ cmd->u.${to_struct_field_name(c.name)}.${to_field_name(p.name)} = ${p.name};
+% endif
+% endfor
+}
+% if c.guard is not None:
+#endif // ${c.guard}
+% endif
+
+% endfor
+
+void
+vk_free_queue(struct vk_cmd_queue *queue)
+{
+ struct vk_cmd_queue_entry *tmp, *cmd;
+ LIST_FOR_EACH_ENTRY_SAFE(cmd, tmp, &queue->cmds, cmd_link) {
+ switch(cmd->type) {
+% for c in commands:
+% if c.guard is not None:
+#ifdef ${c.guard}
+% endif
+ case ${to_enum_name(c.name)}:
+% for p in c.params[1:]:
+% if p.len:
+ vk_free(queue->alloc, (${remove_suffix(p.decl.replace("const", ""), p.name)})cmd->u.${to_struct_field_name(c.name)}.${to_field_name(p.name)});
+% elif '*' in p.decl:
+ ${get_struct_free(c, p, types)}
+% endif
+% endfor
+ break;
+% if c.guard is not None:
+#endif // ${c.guard}
+% endif
+% endfor
+ }
+ vk_free(queue->alloc, cmd);
+ }
+}
+
+""", output_encoding='utf-8')
+
+def remove_prefix(text, prefix):
+ if text.startswith(prefix):
+ return text[len(prefix):]
+ return text
+
+def remove_suffix(text, suffix):
+ if text.endswith(suffix):
+ return text[:-len(suffix)]
+ return text
+
+def to_underscore(name):
+ return remove_prefix(re.sub('([A-Z]+)', r'_\1', name).lower(), '_')
+
+def to_struct_field_name(name):
+ return to_underscore(name).replace('cmd_', '')
+
+def to_field_name(name):
+ return remove_prefix(to_underscore(name).replace('cmd_', ''), 'p_')
+
+def to_field_decl(decl):
+ decl = decl.replace('const ', '')
+ [decl, name] = decl.rsplit(' ', 1)
+ return decl + ' ' + to_field_name(name)
+
+def to_enum_name(name):
+ return "VK_%s" % to_underscore(name).upper()
+
+def to_struct_name(name):
+ return "vk_%s" % to_underscore(name)
+
+def get_array_len(param):
+ return param.decl[param.decl.find("[") + 1:param.decl.find("]")]
+
+def get_array_copy(command, param):
+ field_name = "cmd->u.%s.%s" % (to_struct_field_name(command.name), to_field_name(param.name))
+ if param.type == "void":
+ field_size = "1"
+ else:
+ field_size = "sizeof(*%s)" % field_name
+ allocation = "%s = vk_zalloc(queue->alloc, %s * %s, 8, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);" % (field_name, field_size, param.len)
+ const_cast = remove_suffix(param.decl.replace("const", ""), param.name)
+ copy = "memcpy((%s)%s, %s, %s * %s);" % (const_cast, field_name, param.name, field_size, param.len)
+ return "%s\n %s" % (allocation, copy)
+
+def get_array_member_copy(struct, src_name, member):
+ field_name = "%s->%s" % (struct, member.name)
+ len_field_name = "%s->%s" % (struct, member.len)
+ allocation = "%s = vk_zalloc(queue->alloc, sizeof(*%s) * %s, 8, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);" % (field_name, field_name, len_field_name)
+ const_cast = remove_suffix(member.decl.replace("const", ""), member.name)
+ copy = "memcpy((%s)%s, %s->%s, sizeof(*%s) * %s);" % (const_cast, field_name, src_name, member.name, field_name, len_field_name)
+ return "%s\n %s\n" % (allocation, copy)
+
+def get_pnext_member_copy(struct, src_type, member, types, level):
+ if not types[src_type].extended_by:
+ return ""
+ field_name = "%s->%s" % (struct, member.name)
+ pnext_decl = "const VkBaseInStructure *pnext = %s;" % field_name
+ case_stmts = ""
+ for type in types[src_type].extended_by:
+ case_stmts += """
+ case %s:
+ %s
+ break;
+ """ % (type.enum, get_struct_copy(field_name, "pnext", type.name, "sizeof(%s)" % type.name, types, level))
+ return """
+ %s
+ if (pnext) {
+ switch ((int32_t)pnext->sType) {
+ %s
+ }
+ }
+ """ % (pnext_decl, case_stmts)
+
+def get_struct_copy(dst, src_name, src_type, size, types, level=0):
+ global tmp_dst_idx
+ global tmp_src_idx
+
+ allocation = "%s = vk_zalloc(queue->alloc, %s, 8, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);" % (dst, size)
+ copy = "memcpy((void*)%s, %s, %s);" % (dst, src_name, size)
+
+ level += 1
+ tmp_dst = "%s *tmp_dst%d = (void *) %s; (void) tmp_dst%d;" % (src_type, level, dst, level)
+ tmp_src = "%s *tmp_src%d = (void *) %s; (void) tmp_src%d;" % (src_type, level, src_name, level)
+
+ member_copies = ""
+ if src_type in types:
+ for member in types[src_type].members:
+ if member.len and member.len != 'null-terminated':
+ member_copies += get_array_member_copy("tmp_dst%d" % level, "tmp_src%d" % level, member)
+ elif member.name == 'pNext':
+ member_copies += get_pnext_member_copy("tmp_dst%d" % level, src_type, member, types, level)
+
+ null_assignment = "%s = NULL;" % dst
+ if_stmt = "if (%s) {" % src_name
+ return "%s\n %s\n %s\n %s\n %s \n %s } else {\n %s\n }" % (if_stmt, allocation, copy, tmp_dst, tmp_src, member_copies, null_assignment)
+
+def get_struct_free(command, param, types):
+ field_name = "cmd->u.%s.%s" % (to_struct_field_name(command.name), to_field_name(param.name))
+ const_cast = remove_suffix(param.decl.replace("const", ""), param.name)
+ driver_data_free = "vk_free(queue->alloc, cmd->driver_data);\n"
+ struct_free = "vk_free(queue->alloc, (%s)%s);" % (const_cast, field_name)
+ member_frees = ""
+ if (param.type in types):
+ for member in types[param.type].members:
+ if member.len and member.len != 'null-terminated':
+ member_name = "cmd->u.%s.%s->%s" % (to_struct_field_name(command.name), to_field_name(param.name), member.name)
+ const_cast = remove_suffix(member.decl.replace("const", ""), member.name)
+ member_frees += "vk_free(queue->alloc, (%s)%s);\n" % (const_cast, member_name)
+ return "%s %s %s\n" % (member_frees, driver_data_free, struct_free)
+
+EntrypointType = namedtuple('EntrypointType', 'name enum members extended_by')
+
+def get_types(doc):
+ """Extract the types from the registry."""
+ types = {}
+
+ for _type in doc.findall('./types/type'):
+ if _type.attrib.get('category') != 'struct':
+ continue
+ members = []
+ type_enum = None
+ for p in _type.findall('./member'):
+ member = EntrypointParam(type=p.find('./type').text,
+ name=p.find('./name').text,
+ decl=''.join(p.itertext()),
+ len=p.attrib.get('len', None))
+ members.append(member)
+
+ if p.find('./name').text == 'sType':
+ type_enum = p.attrib.get('values')
+ types[_type.attrib['name']] = EntrypointType(name=_type.attrib['name'], enum=type_enum, members=members, extended_by=[])
+
+ for _type in doc.findall('./types/type'):
+ if _type.attrib.get('category') != 'struct':
+ continue
+ if _type.attrib.get('structextends') is None:
+ continue
+ for extended in _type.attrib.get('structextends').split(','):
+ types[extended].extended_by.append(types[_type.attrib['name']])
+
+ return types
+
+def get_types_from_xml(xml_files):
+ types = {}
+
+ for filename in xml_files:
+ doc = et.parse(filename)
+ types.update(get_types(doc))
+
+ return types
+
+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')
+ args = parser.parse_args()
+
+ commands = []
+ for e in get_entrypoints_from_xml(args.xml_files):
+ if e.name.startswith('Cmd') and \
+ not e.alias:
+ commands.append(e)
+
+ types = get_types_from_xml(args.xml_files)
+
+ assert os.path.dirname(args.out_c) == os.path.dirname(args.out_h)
+
+ environment = {
+ 'header': os.path.basename(args.out_h),
+ 'commands': commands,
+ 'filename': os.path.basename(__file__),
+ 'to_underscore': to_underscore,
+ 'get_array_len': get_array_len,
+ 'to_struct_field_name': to_struct_field_name,
+ 'to_field_name': to_field_name,
+ 'to_field_decl': to_field_decl,
+ 'to_enum_name': to_enum_name,
+ 'to_struct_name': to_struct_name,
+ 'get_array_copy': get_array_copy,
+ 'get_struct_copy': get_struct_copy,
+ 'get_struct_free': get_struct_free,
+ 'types': types,
+ 'manual_commands': MANUAL_COMMANDS,
+ 'remove_suffix': remove_suffix,
+ }
+
+ 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_command_buffer.c b/lib/mesa/src/vulkan/util/vk_command_buffer.c
new file mode 100644
index 000000000..35b346d1e
--- /dev/null
+++ b/lib/mesa/src/vulkan/util/vk_command_buffer.c
@@ -0,0 +1,52 @@
+/*
+ * 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_command_buffer.h"
+
+VkResult
+vk_command_buffer_init(struct vk_command_buffer *command_buffer,
+ struct vk_device *device)
+{
+ memset(command_buffer, 0, sizeof(*command_buffer));
+ vk_object_base_init(device, &command_buffer->base,
+ VK_OBJECT_TYPE_COMMAND_BUFFER);
+
+ util_dynarray_init(&command_buffer->labels, NULL);
+ command_buffer->region_begin = true;
+
+ return VK_SUCCESS;
+}
+
+void
+vk_command_buffer_reset(struct vk_command_buffer *command_buffer)
+{
+ util_dynarray_clear(&command_buffer->labels);
+ command_buffer->region_begin = true;
+}
+
+void
+vk_command_buffer_finish(struct vk_command_buffer *command_buffer)
+{
+ util_dynarray_fini(&command_buffer->labels);
+ vk_object_base_finish(&command_buffer->base);
+}
diff --git a/lib/mesa/src/vulkan/util/vk_command_buffer.h b/lib/mesa/src/vulkan/util/vk_command_buffer.h
new file mode 100644
index 000000000..36622cfd9
--- /dev/null
+++ b/lib/mesa/src/vulkan/util/vk_command_buffer.h
@@ -0,0 +1,95 @@
+/*
+ * 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_COMMAND_BUFFER_H
+#define VK_COMMAND_BUFFER_H
+
+#include "vk_object.h"
+#include "util/u_dynarray.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct vk_command_buffer {
+ struct vk_object_base base;
+
+ /**
+ * VK_EXT_debug_utils
+ *
+ * The next two fields represent debug labels storage.
+ *
+ * VK_EXT_debug_utils spec requires that upon triggering a debug message
+ * with a command buffer attached to it, all "active" labels will also be
+ * provided to the callback. The spec describes two distinct ways of
+ * attaching a debug label to the command buffer: opening a label region
+ * and inserting a single label.
+ *
+ * Label region is active between the corresponding `*BeginDebugUtilsLabel`
+ * and `*EndDebugUtilsLabel` calls. The spec doesn't mention any limits on
+ * nestedness of label regions. This implementation assumes that there
+ * aren't any.
+ *
+ * The spec, however, doesn't explain the lifetime of a label submitted by
+ * an `*InsertDebugUtilsLabel` call. The LunarG whitepaper [1] (pp 12-15)
+ * provides a more detailed explanation along with some examples. According
+ * to those, such label remains active until the next `*DebugUtilsLabel`
+ * call. This means that there can be no more than one such label at a
+ * time.
+ *
+ * \c labels contains all active labels at this point in order of submission
+ * \c region_begin denotes whether the most recent label opens a new region
+ * If \t labels is empty \t region_begin must be true.
+ *
+ * Anytime we modify labels, we first check for \c region_begin. If it's
+ * false, it means that the most recent label was submitted by
+ * `*InsertDebugUtilsLabel` and we need to remove it before doing anything
+ * else.
+ *
+ * See the discussion here:
+ * https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/10318#note_1061317
+ *
+ * [1] https://www.lunarg.com/wp-content/uploads/2018/05/Vulkan-Debug-Utils_05_18_v1.pdf
+ */
+ struct util_dynarray labels;
+ bool region_begin;
+};
+
+VK_DEFINE_HANDLE_CASTS(vk_command_buffer, base, VkCommandBuffer,
+ VK_OBJECT_TYPE_COMMAND_BUFFER)
+
+VkResult MUST_CHECK
+vk_command_buffer_init(struct vk_command_buffer *command_buffer,
+ struct vk_device *device);
+
+void
+vk_command_buffer_reset(struct vk_command_buffer *command_buffer);
+
+void
+vk_command_buffer_finish(struct vk_command_buffer *command_buffer);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* VK_COMMAND_BUFFER_H */
diff --git a/lib/mesa/src/vulkan/util/vk_commands_gen.py b/lib/mesa/src/vulkan/util/vk_commands_gen.py
new file mode 100644
index 000000000..610c835ff
--- /dev/null
+++ b/lib/mesa/src/vulkan/util/vk_commands_gen.py
@@ -0,0 +1,143 @@
+# coding=utf-8
+COPYRIGHT=u"""
+/* Copyright © 2015-2021 Intel Corporation
+ * Copyright © 2021 Collabora, Ltd.
+ *
+ * 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
+import re
+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_dispatch_table_gen import get_entrypoints_from_xml, EntrypointParam
+
+MANUAL_COMMANDS = ['CmdPushDescriptorSetKHR', # This script doesn't know how to copy arrays in structs in arrays
+ 'CmdPushDescriptorSetWithTemplateKHR', # pData's size cannot be calculated from the xml
+ 'CmdDrawMultiEXT', # The size of the elements is specified in a stride param
+ 'CmdDrawMultiIndexedEXT', # The size of the elements is specified in a stride param
+ 'CmdBindDescriptorSets', # The VkPipelineLayout object could be released before the command is executed
+ 'CmdCopyImageToBuffer', # There are wrappers that implement these in terms of the newer variants
+ 'CmdCopyImage',
+ 'CmdCopyBuffer',
+ 'CmdCopyImage',
+ 'CmdCopyBufferToImage',
+ 'CmdCopyImageToBuffer',
+ 'CmdBlitImage',
+ 'CmdResolveImage',
+ ]
+
+TEMPLATE_C = Template(COPYRIGHT + """
+/* This file generated from ${filename}, don't edit directly. */
+
+#define VK_PROTOTYPES
+#include <vulkan/vulkan.h>
+
+#include "lvp_private.h"
+#include "pipe/p_context.h"
+#include "vk_util.h"
+
+% for c in commands:
+% if c.name in manual_commands:
+<% continue %>
+% endif
+% if c.guard is not None:
+#ifdef ${c.guard}
+% endif
+VKAPI_ATTR ${c.return_type} VKAPI_CALL lvp_${c.name} (VkCommandBuffer commandBuffer
+% for p in c.params[1:]:
+, ${p.decl}
+% endfor
+)
+{
+ LVP_FROM_HANDLE(lvp_cmd_buffer, cmd_buffer, commandBuffer);
+
+ vk_enqueue_${to_underscore(c.name)}(&cmd_buffer->queue
+% for p in c.params[1:]:
+, ${p.name}
+% endfor
+ );
+
+% if c.return_type == 'VkResult':
+ return VK_SUCCESS;
+% endif
+}
+% if c.guard is not None:
+#endif // ${c.guard}
+% endif
+% endfor
+
+""", output_encoding='utf-8')
+
+def remove_prefix(text, prefix):
+ if text.startswith(prefix):
+ return text[len(prefix):]
+ return text
+
+def to_underscore(name):
+ return remove_prefix(re.sub('([A-Z]+)', r'_\1', name).lower(), '_')
+
+def main():
+ parser = argparse.ArgumentParser()
+ parser.add_argument('--out-c', required=True, help='Output C file.')
+ parser.add_argument('--xml',
+ help='Vulkan API XML file.',
+ required=True, action='append', dest='xml_files')
+ parser.add_argument('--prefix',
+ help='Prefix to use for all dispatch tables.',
+ action='append', default=[], dest='prefixes')
+ args = parser.parse_args()
+
+ commands = []
+ for e in get_entrypoints_from_xml(args.xml_files):
+ if e.name.startswith('Cmd') and \
+ not e.alias:
+ commands.append(e)
+
+ environment = {
+ 'commands': commands,
+ 'filename': os.path.basename(__file__),
+ 'to_underscore': to_underscore,
+ 'manual_commands': MANUAL_COMMANDS,
+ }
+
+ try:
+ 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_debug_utils.c b/lib/mesa/src/vulkan/util/vk_debug_utils.c
new file mode 100644
index 000000000..cd798af11
--- /dev/null
+++ b/lib/mesa/src/vulkan/util/vk_debug_utils.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_debug_utils.h"
+
+#include "vk_common_entrypoints.h"
+#include "vk_command_buffer.h"
+#include "vk_device.h"
+#include "vk_queue.h"
+#include "vk_object.h"
+#include "vk_alloc.h"
+#include "vk_util.h"
+#include "stdarg.h"
+#include "u_dynarray.h"
+
+void
+vk_debug_message(struct vk_instance *instance,
+ VkDebugUtilsMessageSeverityFlagBitsEXT severity,
+ VkDebugUtilsMessageTypeFlagsEXT types,
+ const VkDebugUtilsMessengerCallbackDataEXT *pCallbackData)
+{
+ mtx_lock(&instance->debug_utils.callbacks_mutex);
+
+ list_for_each_entry(struct vk_debug_utils_messenger, messenger,
+ &instance->debug_utils.callbacks, link) {
+ if ((messenger->severity & severity) &&
+ (messenger->type & types))
+ messenger->callback(severity, types, pCallbackData, messenger->data);
+ }
+
+ mtx_unlock(&instance->debug_utils.callbacks_mutex);
+}
+
+/* This function intended to be used by the drivers to report a
+ * message to the special messenger, provided in the pNext chain while
+ * creating an instance. It's only meant to be used during
+ * vkCreateInstance or vkDestroyInstance calls.
+ */
+void
+vk_debug_message_instance(struct vk_instance *instance,
+ VkDebugUtilsMessageSeverityFlagBitsEXT severity,
+ VkDebugUtilsMessageTypeFlagsEXT types,
+ const char *pMessageIdName,
+ int32_t messageIdNumber,
+ const char *pMessage)
+{
+ if (list_is_empty(&instance->debug_utils.instance_callbacks))
+ return;
+
+ const VkDebugUtilsMessengerCallbackDataEXT cbData = {
+ .sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CALLBACK_DATA_EXT,
+ .pMessageIdName = pMessageIdName,
+ .messageIdNumber = messageIdNumber,
+ .pMessage = pMessage,
+ };
+
+ list_for_each_entry(struct vk_debug_utils_messenger, messenger,
+ &instance->debug_utils.instance_callbacks, link) {
+ if ((messenger->severity & severity) &&
+ (messenger->type & types))
+ messenger->callback(severity, types, &cbData, messenger->data);
+ }
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL
+vk_common_CreateDebugUtilsMessengerEXT(
+ VkInstance _instance,
+ const VkDebugUtilsMessengerCreateInfoEXT *pCreateInfo,
+ const VkAllocationCallbacks *pAllocator,
+ VkDebugUtilsMessengerEXT *pMessenger)
+{
+ VK_FROM_HANDLE(vk_instance, instance, _instance);
+
+ struct vk_debug_utils_messenger *messenger =
+ vk_alloc2(&instance->alloc, pAllocator,
+ sizeof(struct vk_debug_utils_messenger), 8,
+ VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
+
+ if (!messenger)
+ return VK_ERROR_OUT_OF_HOST_MEMORY;
+
+ if (pAllocator)
+ messenger->alloc = *pAllocator;
+ else
+ messenger->alloc = instance->alloc;
+
+ vk_object_base_init(NULL, &messenger->base,
+ VK_OBJECT_TYPE_DEBUG_UTILS_MESSENGER_EXT);
+
+ messenger->severity = pCreateInfo->messageSeverity;
+ messenger->type = pCreateInfo->messageType;
+ messenger->callback = pCreateInfo->pfnUserCallback;
+ messenger->data = pCreateInfo->pUserData;
+
+ mtx_lock(&instance->debug_utils.callbacks_mutex);
+ list_addtail(&messenger->link, &instance->debug_utils.callbacks);
+ mtx_unlock(&instance->debug_utils.callbacks_mutex);
+
+ *pMessenger = vk_debug_utils_messenger_to_handle(messenger);
+
+ return VK_SUCCESS;
+}
+
+VKAPI_ATTR void VKAPI_CALL
+vk_common_SubmitDebugUtilsMessageEXT(
+ VkInstance _instance,
+ VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
+ VkDebugUtilsMessageTypeFlagsEXT messageTypes,
+ const VkDebugUtilsMessengerCallbackDataEXT *pCallbackData)
+{
+ VK_FROM_HANDLE(vk_instance, instance, _instance);
+
+ vk_debug_message(instance, messageSeverity, messageTypes, pCallbackData);
+}
+
+VKAPI_ATTR void VKAPI_CALL
+vk_common_DestroyDebugUtilsMessengerEXT(
+ VkInstance _instance,
+ VkDebugUtilsMessengerEXT _messenger,
+ const VkAllocationCallbacks *pAllocator)
+{
+ VK_FROM_HANDLE(vk_instance, instance, _instance);
+ VK_FROM_HANDLE(vk_debug_utils_messenger, messenger, _messenger);
+
+ if (messenger == NULL)
+ return;
+
+ mtx_lock(&instance->debug_utils.callbacks_mutex);
+ list_del(&messenger->link);
+ mtx_unlock(&instance->debug_utils.callbacks_mutex);
+
+ vk_object_base_finish(&messenger->base);
+ vk_free2(&instance->alloc, pAllocator, messenger);
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL
+vk_common_SetDebugUtilsObjectNameEXT(
+ VkDevice _device,
+ const VkDebugUtilsObjectNameInfoEXT *pNameInfo)
+{
+ VK_FROM_HANDLE(vk_device, device, _device);
+ struct vk_object_base *object =
+ vk_object_base_from_u64_handle(pNameInfo->objectHandle,
+ pNameInfo->objectType);
+
+ if (object->object_name) {
+ vk_free(&device->alloc, object->object_name);
+ object->object_name = NULL;
+ }
+ object->object_name = vk_strdup(&device->alloc, pNameInfo->pObjectName,
+ VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
+ if (!object->object_name)
+ return VK_ERROR_OUT_OF_HOST_MEMORY;
+
+ return VK_SUCCESS;
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL
+vk_common_SetDebugUtilsObjectTagEXT(
+ VkDevice _device,
+ const VkDebugUtilsObjectTagInfoEXT *pTagInfo)
+{
+ /* no-op */
+ return VK_SUCCESS;
+}
+
+VKAPI_ATTR void VKAPI_CALL
+vk_common_CmdBeginDebugUtilsLabelEXT(
+ VkCommandBuffer _commandBuffer,
+ const VkDebugUtilsLabelEXT *pLabelInfo)
+{
+ VK_FROM_HANDLE(vk_command_buffer, command_buffer, _commandBuffer);
+
+ /* If the latest label was submitted by CmdInsertDebugUtilsLabelEXT, we
+ * should remove it first.
+ */
+ if (!command_buffer->region_begin)
+ (void)util_dynarray_pop(&command_buffer->labels, VkDebugUtilsLabelEXT);
+
+ util_dynarray_append(&command_buffer->labels, VkDebugUtilsLabelEXT,
+ *pLabelInfo);
+ command_buffer->region_begin = true;
+}
+
+VKAPI_ATTR void VKAPI_CALL
+vk_common_CmdEndDebugUtilsLabelEXT(VkCommandBuffer _commandBuffer)
+{
+ VK_FROM_HANDLE(vk_command_buffer, command_buffer, _commandBuffer);
+
+ /* If the latest label was submitted by CmdInsertDebugUtilsLabelEXT, we
+ * should remove it first.
+ */
+ if (!command_buffer->region_begin)
+ (void)util_dynarray_pop(&command_buffer->labels, VkDebugUtilsLabelEXT);
+
+ (void)util_dynarray_pop(&command_buffer->labels, VkDebugUtilsLabelEXT);
+ command_buffer->region_begin = true;
+}
+
+VKAPI_ATTR void VKAPI_CALL
+vk_common_CmdInsertDebugUtilsLabelEXT(
+ VkCommandBuffer _commandBuffer,
+ const VkDebugUtilsLabelEXT *pLabelInfo)
+{
+ VK_FROM_HANDLE(vk_command_buffer, command_buffer, _commandBuffer);
+
+ /* If the latest label was submitted by CmdInsertDebugUtilsLabelEXT, we
+ * should remove it first.
+ */
+ if (!command_buffer->region_begin)
+ (void)util_dynarray_pop(&command_buffer->labels, VkDebugUtilsLabelEXT);
+
+ util_dynarray_append(&command_buffer->labels, VkDebugUtilsLabelEXT,
+ *pLabelInfo);
+ command_buffer->region_begin = false;
+}
+
+VKAPI_ATTR void VKAPI_CALL
+vk_common_QueueBeginDebugUtilsLabelEXT(
+ VkQueue _queue,
+ const VkDebugUtilsLabelEXT *pLabelInfo)
+{
+ VK_FROM_HANDLE(vk_queue, queue, _queue);
+
+ /* If the latest label was submitted by QueueInsertDebugUtilsLabelEXT, we
+ * should remove it first.
+ */
+ if (!queue->region_begin)
+ (void)util_dynarray_pop(&queue->labels, VkDebugUtilsLabelEXT);
+
+ util_dynarray_append(&queue->labels, VkDebugUtilsLabelEXT, *pLabelInfo);
+ queue->region_begin = true;
+}
+
+VKAPI_ATTR void VKAPI_CALL
+vk_common_QueueEndDebugUtilsLabelEXT(VkQueue _queue)
+{
+ VK_FROM_HANDLE(vk_queue, queue, _queue);
+
+ /* If the latest label was submitted by QueueInsertDebugUtilsLabelEXT, we
+ * should remove it first.
+ */
+ if (!queue->region_begin)
+ (void)util_dynarray_pop(&queue->labels, VkDebugUtilsLabelEXT);
+
+ (void)util_dynarray_pop(&queue->labels, VkDebugUtilsLabelEXT);
+ queue->region_begin = true;
+}
+
+VKAPI_ATTR void VKAPI_CALL
+vk_common_QueueInsertDebugUtilsLabelEXT(
+ VkQueue _queue,
+ const VkDebugUtilsLabelEXT *pLabelInfo)
+{
+ VK_FROM_HANDLE(vk_queue, queue, _queue);
+
+ /* If the latest label was submitted by QueueInsertDebugUtilsLabelEXT, we
+ * should remove it first.
+ */
+ if (!queue->region_begin)
+ (void)util_dynarray_pop(&queue->labels, VkDebugUtilsLabelEXT);
+
+ util_dynarray_append(&queue->labels, VkDebugUtilsLabelEXT, *pLabelInfo);
+ queue->region_begin = false;
+}
diff --git a/lib/mesa/src/vulkan/util/vk_debug_utils.h b/lib/mesa/src/vulkan/util/vk_debug_utils.h
new file mode 100644
index 000000000..0ffb4b38c
--- /dev/null
+++ b/lib/mesa/src/vulkan/util/vk_debug_utils.h
@@ -0,0 +1,67 @@
+/*
+ * 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_DEBUG_UTILS_H
+#define VK_DEBUG_UTILS_H
+
+#include "vk_instance.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct vk_debug_utils_messenger {
+ struct vk_object_base base;
+ VkAllocationCallbacks alloc;
+
+ struct list_head link;
+
+ VkDebugUtilsMessageSeverityFlagsEXT severity;
+ VkDebugUtilsMessageTypeFlagsEXT type;
+ PFN_vkDebugUtilsMessengerCallbackEXT callback;
+ void *data;
+};
+
+VK_DEFINE_NONDISP_HANDLE_CASTS(vk_debug_utils_messenger, base,
+ VkDebugUtilsMessengerEXT,
+ VK_OBJECT_TYPE_DEBUG_UTILS_MESSENGER_EXT)
+
+void
+vk_debug_message(struct vk_instance *instance,
+ VkDebugUtilsMessageSeverityFlagBitsEXT severity,
+ VkDebugUtilsMessageTypeFlagsEXT types,
+ const VkDebugUtilsMessengerCallbackDataEXT *pCallbackData);
+
+void
+vk_debug_message_instance(struct vk_instance *instance,
+ VkDebugUtilsMessageSeverityFlagBitsEXT severity,
+ VkDebugUtilsMessageTypeFlagsEXT types,
+ const char *pMessageIdName,
+ int32_t messageIdNumber,
+ const char *pMessage);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* VK_DEBUG_UTILS_H */
diff --git a/lib/mesa/src/vulkan/util/vk_device.c b/lib/mesa/src/vulkan/util/vk_device.c
index cfaebc58d..e3617507b 100644
--- a/lib/mesa/src/vulkan/util/vk_device.c
+++ b/lib/mesa/src/vulkan/util/vk_device.c
@@ -25,7 +25,10 @@
#include "vk_common_entrypoints.h"
#include "vk_instance.h"
+#include "vk_log.h"
#include "vk_physical_device.h"
+#include "vk_queue.h"
+#include "vk_util.h"
#include "util/hash_table.h"
#include "util/ralloc.h"
@@ -60,21 +63,35 @@ vk_device_init(struct vk_device *device,
}
if (idx >= VK_DEVICE_EXTENSION_COUNT)
- return VK_ERROR_EXTENSION_NOT_PRESENT;
+ return vk_errorf(physical_device, VK_ERROR_EXTENSION_NOT_PRESENT,
+ "%s not supported",
+ pCreateInfo->ppEnabledExtensionNames[i]);
if (!physical_device->supported_extensions.extensions[idx])
- return VK_ERROR_EXTENSION_NOT_PRESENT;
+ return vk_errorf(physical_device, VK_ERROR_EXTENSION_NOT_PRESENT,
+ "%s not supported",
+ pCreateInfo->ppEnabledExtensionNames[i]);
#ifdef ANDROID
if (!vk_android_allowed_device_extensions.extensions[idx])
- return VK_ERROR_EXTENSION_NOT_PRESENT;
+ return vk_errorf(physical_device, VK_ERROR_EXTENSION_NOT_PRESENT,
+ "%s not supported",
+ pCreateInfo->ppEnabledExtensionNames[i]);
#endif
device->enabled_extensions.extensions[idx] = true;
}
+ VkResult result =
+ vk_physical_device_check_device_features(physical_device,
+ pCreateInfo);
+ if (result != VK_SUCCESS)
+ return result;
+
p_atomic_set(&device->private_data_next_index, 0);
+ list_inithead(&device->queues);
+
#ifdef ANDROID
mtx_init(&device->swapchain_private_mtx, mtx_plain);
device->swapchain_private = NULL;
@@ -86,6 +103,9 @@ vk_device_init(struct vk_device *device,
void
vk_device_finish(UNUSED struct vk_device *device)
{
+ /* Drivers should tear down their own queues */
+ assert(list_is_empty(&device->queues));
+
#ifdef ANDROID
if (device->swapchain_private) {
hash_table_foreach(device->swapchain_private, entry)
@@ -147,6 +167,35 @@ vk_common_GetDeviceQueue(VkDevice _device,
}
VKAPI_ATTR void VKAPI_CALL
+vk_common_GetDeviceQueue2(VkDevice _device,
+ const VkDeviceQueueInfo2 *pQueueInfo,
+ VkQueue *pQueue)
+{
+ VK_FROM_HANDLE(vk_device, device, _device);
+
+ struct vk_queue *queue = NULL;
+ vk_foreach_queue(iter, device) {
+ if (iter->queue_family_index == pQueueInfo->queueFamilyIndex &&
+ iter->index_in_family == pQueueInfo->queueIndex) {
+ queue = iter;
+ break;
+ }
+ }
+
+ /* From the Vulkan 1.1.70 spec:
+ *
+ * "The queue returned by vkGetDeviceQueue2 must have the same flags
+ * value from this structure as that used at device creation time in a
+ * VkDeviceQueueCreateInfo instance. If no matching flags were specified
+ * at device creation time then pQueue will return VK_NULL_HANDLE."
+ */
+ if (queue && queue->flags == pQueueInfo->flags)
+ *pQueue = vk_queue_to_handle(queue);
+ else
+ *pQueue = VK_NULL_HANDLE;
+}
+
+VKAPI_ATTR void VKAPI_CALL
vk_common_GetBufferMemoryRequirements(VkDevice _device,
VkBuffer buffer,
VkMemoryRequirements *pMemoryRequirements)
@@ -219,3 +268,410 @@ vk_common_BindImageMemory(VkDevice _device,
return device->dispatch_table.BindImageMemory2(_device, 1, &bind);
}
+
+VKAPI_ATTR void VKAPI_CALL
+vk_common_GetImageSparseMemoryRequirements(VkDevice _device,
+ VkImage image,
+ uint32_t *pSparseMemoryRequirementCount,
+ VkSparseImageMemoryRequirements *pSparseMemoryRequirements)
+{
+ VK_FROM_HANDLE(vk_device, device, _device);
+
+ VkImageSparseMemoryRequirementsInfo2 info = {
+ .sType = VK_STRUCTURE_TYPE_IMAGE_SPARSE_MEMORY_REQUIREMENTS_INFO_2,
+ .image = image,
+ };
+
+ if (!pSparseMemoryRequirements) {
+ device->dispatch_table.GetImageSparseMemoryRequirements2(_device,
+ &info,
+ pSparseMemoryRequirementCount,
+ NULL);
+ return;
+ }
+
+ STACK_ARRAY(VkSparseImageMemoryRequirements2, mem_reqs2, *pSparseMemoryRequirementCount);
+
+ for (unsigned i = 0; i < *pSparseMemoryRequirementCount; ++i) {
+ mem_reqs2[i].sType = VK_STRUCTURE_TYPE_SPARSE_IMAGE_MEMORY_REQUIREMENTS_2;
+ mem_reqs2[i].pNext = NULL;
+ }
+
+ device->dispatch_table.GetImageSparseMemoryRequirements2(_device,
+ &info,
+ pSparseMemoryRequirementCount,
+ mem_reqs2);
+
+ for (unsigned i = 0; i < *pSparseMemoryRequirementCount; ++i)
+ pSparseMemoryRequirements[i] = mem_reqs2[i].memoryRequirements;
+
+ STACK_ARRAY_FINISH(mem_reqs2);
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL
+vk_common_DeviceWaitIdle(VkDevice _device)
+{
+ VK_FROM_HANDLE(vk_device, device, _device);
+ const struct vk_device_dispatch_table *disp = &device->dispatch_table;
+
+ vk_foreach_queue(queue, device) {
+ VkResult result = disp->QueueWaitIdle(vk_queue_to_handle(queue));
+ if (result != VK_SUCCESS)
+ return result;
+ }
+
+ return VK_SUCCESS;
+}
+
+static void
+copy_vk_struct_guts(VkBaseOutStructure *dst, VkBaseInStructure *src, size_t struct_size)
+{
+ STATIC_ASSERT(sizeof(*dst) == sizeof(*src));
+ memcpy(dst + 1, src + 1, struct_size - sizeof(VkBaseOutStructure));
+}
+
+#define CORE_FEATURE(feature) features->feature = core->feature
+
+bool
+vk_get_physical_device_core_1_1_feature_ext(struct VkBaseOutStructure *ext,
+ const VkPhysicalDeviceVulkan11Features *core)
+{
+
+ switch (ext->sType) {
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES: {
+ VkPhysicalDevice16BitStorageFeatures *features = (void *)ext;
+ CORE_FEATURE(storageBuffer16BitAccess);
+ CORE_FEATURE(uniformAndStorageBuffer16BitAccess);
+ CORE_FEATURE(storagePushConstant16);
+ CORE_FEATURE(storageInputOutput16);
+ return true;
+ }
+
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES: {
+ VkPhysicalDeviceMultiviewFeatures *features = (void *)ext;
+ CORE_FEATURE(multiview);
+ CORE_FEATURE(multiviewGeometryShader);
+ CORE_FEATURE(multiviewTessellationShader);
+ return true;
+ }
+
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_FEATURES: {
+ VkPhysicalDeviceProtectedMemoryFeatures *features = (void *)ext;
+ CORE_FEATURE(protectedMemory);
+ return true;
+ }
+
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES: {
+ VkPhysicalDeviceSamplerYcbcrConversionFeatures *features = (void *) ext;
+ CORE_FEATURE(samplerYcbcrConversion);
+ return true;
+ }
+
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DRAW_PARAMETERS_FEATURES: {
+ VkPhysicalDeviceShaderDrawParametersFeatures *features = (void *)ext;
+ CORE_FEATURE(shaderDrawParameters);
+ return true;
+ }
+
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTERS_FEATURES: {
+ VkPhysicalDeviceVariablePointersFeatures *features = (void *)ext;
+ CORE_FEATURE(variablePointersStorageBuffer);
+ CORE_FEATURE(variablePointers);
+ return true;
+ }
+
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_FEATURES:
+ copy_vk_struct_guts(ext, (void *)core, sizeof(*core));
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+bool
+vk_get_physical_device_core_1_2_feature_ext(struct VkBaseOutStructure *ext,
+ const VkPhysicalDeviceVulkan12Features *core)
+{
+
+ switch (ext->sType) {
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_8BIT_STORAGE_FEATURES_KHR: {
+ VkPhysicalDevice8BitStorageFeaturesKHR *features = (void *)ext;
+ CORE_FEATURE(storageBuffer8BitAccess);
+ CORE_FEATURE(uniformAndStorageBuffer8BitAccess);
+ CORE_FEATURE(storagePushConstant8);
+ return true;
+ }
+
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES_KHR: {
+ VkPhysicalDeviceBufferDeviceAddressFeaturesKHR *features = (void *)ext;
+ CORE_FEATURE(bufferDeviceAddress);
+ CORE_FEATURE(bufferDeviceAddressCaptureReplay);
+ CORE_FEATURE(bufferDeviceAddressMultiDevice);
+ return true;
+ }
+
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_FEATURES_EXT: {
+ VkPhysicalDeviceDescriptorIndexingFeaturesEXT *features = (void *)ext;
+ CORE_FEATURE(shaderInputAttachmentArrayDynamicIndexing);
+ CORE_FEATURE(shaderUniformTexelBufferArrayDynamicIndexing);
+ CORE_FEATURE(shaderStorageTexelBufferArrayDynamicIndexing);
+ CORE_FEATURE(shaderUniformBufferArrayNonUniformIndexing);
+ CORE_FEATURE(shaderSampledImageArrayNonUniformIndexing);
+ CORE_FEATURE(shaderStorageBufferArrayNonUniformIndexing);
+ CORE_FEATURE(shaderStorageImageArrayNonUniformIndexing);
+ CORE_FEATURE(shaderInputAttachmentArrayNonUniformIndexing);
+ CORE_FEATURE(shaderUniformTexelBufferArrayNonUniformIndexing);
+ CORE_FEATURE(shaderStorageTexelBufferArrayNonUniformIndexing);
+ CORE_FEATURE(descriptorBindingUniformBufferUpdateAfterBind);
+ CORE_FEATURE(descriptorBindingSampledImageUpdateAfterBind);
+ CORE_FEATURE(descriptorBindingStorageImageUpdateAfterBind);
+ CORE_FEATURE(descriptorBindingStorageBufferUpdateAfterBind);
+ CORE_FEATURE(descriptorBindingUniformTexelBufferUpdateAfterBind);
+ CORE_FEATURE(descriptorBindingStorageTexelBufferUpdateAfterBind);
+ CORE_FEATURE(descriptorBindingUpdateUnusedWhilePending);
+ CORE_FEATURE(descriptorBindingPartiallyBound);
+ CORE_FEATURE(descriptorBindingVariableDescriptorCount);
+ CORE_FEATURE(runtimeDescriptorArray);
+ return true;
+ }
+
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FLOAT16_INT8_FEATURES_KHR: {
+ VkPhysicalDeviceFloat16Int8FeaturesKHR *features = (void *)ext;
+ CORE_FEATURE(shaderFloat16);
+ CORE_FEATURE(shaderInt8);
+ return true;
+ }
+
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_QUERY_RESET_FEATURES_EXT: {
+ VkPhysicalDeviceHostQueryResetFeaturesEXT *features = (void *)ext;
+ CORE_FEATURE(hostQueryReset);
+ return true;
+ }
+
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGELESS_FRAMEBUFFER_FEATURES_KHR: {
+ VkPhysicalDeviceImagelessFramebufferFeaturesKHR *features = (void *)ext;
+ CORE_FEATURE(imagelessFramebuffer);
+ return true;
+ }
+
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SCALAR_BLOCK_LAYOUT_FEATURES_EXT: {
+ VkPhysicalDeviceScalarBlockLayoutFeaturesEXT *features =(void *)ext;
+ CORE_FEATURE(scalarBlockLayout);
+ return true;
+ }
+
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SEPARATE_DEPTH_STENCIL_LAYOUTS_FEATURES_KHR: {
+ VkPhysicalDeviceSeparateDepthStencilLayoutsFeaturesKHR *features = (void *)ext;
+ CORE_FEATURE(separateDepthStencilLayouts);
+ return true;
+ }
+
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_INT64_FEATURES_KHR: {
+ VkPhysicalDeviceShaderAtomicInt64FeaturesKHR *features = (void *)ext;
+ CORE_FEATURE(shaderBufferInt64Atomics);
+ CORE_FEATURE(shaderSharedInt64Atomics);
+ return true;
+ }
+
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_SUBGROUP_EXTENDED_TYPES_FEATURES_KHR: {
+ VkPhysicalDeviceShaderSubgroupExtendedTypesFeaturesKHR *features = (void *)ext;
+ CORE_FEATURE(shaderSubgroupExtendedTypes);
+ return true;
+ }
+
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_FEATURES_KHR: {
+ VkPhysicalDeviceTimelineSemaphoreFeaturesKHR *features = (void *) ext;
+ CORE_FEATURE(timelineSemaphore);
+ return true;
+ }
+
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_UNIFORM_BUFFER_STANDARD_LAYOUT_FEATURES_KHR: {
+ VkPhysicalDeviceUniformBufferStandardLayoutFeaturesKHR *features = (void *)ext;
+ CORE_FEATURE(uniformBufferStandardLayout);
+ return true;
+ }
+
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_MEMORY_MODEL_FEATURES_KHR: {
+ VkPhysicalDeviceVulkanMemoryModelFeaturesKHR *features = (void *)ext;
+ CORE_FEATURE(vulkanMemoryModel);
+ CORE_FEATURE(vulkanMemoryModelDeviceScope);
+ CORE_FEATURE(vulkanMemoryModelAvailabilityVisibilityChains);
+ return true;
+ }
+
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES:
+ copy_vk_struct_guts(ext, (void *)core, sizeof(*core));
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+#undef CORE_FEATURE
+
+#define CORE_RENAMED_PROPERTY(ext_property, core_property) \
+ memcpy(&properties->ext_property, &core->core_property, sizeof(core->core_property))
+
+#define CORE_PROPERTY(property) CORE_RENAMED_PROPERTY(property, property)
+
+bool
+vk_get_physical_device_core_1_1_property_ext(struct VkBaseOutStructure *ext,
+ const VkPhysicalDeviceVulkan11Properties *core)
+{
+ switch (ext->sType) {
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES: {
+ VkPhysicalDeviceIDProperties *properties = (void *)ext;
+ CORE_PROPERTY(deviceUUID);
+ CORE_PROPERTY(driverUUID);
+ CORE_PROPERTY(deviceLUID);
+ CORE_PROPERTY(deviceLUIDValid);
+ return true;
+ }
+
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_3_PROPERTIES: {
+ VkPhysicalDeviceMaintenance3Properties *properties = (void *)ext;
+ CORE_PROPERTY(maxPerSetDescriptors);
+ CORE_PROPERTY(maxMemoryAllocationSize);
+ return true;
+ }
+
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PROPERTIES: {
+ VkPhysicalDeviceMultiviewProperties *properties = (void *)ext;
+ CORE_PROPERTY(maxMultiviewViewCount);
+ CORE_PROPERTY(maxMultiviewInstanceIndex);
+ return true;
+ }
+
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_POINT_CLIPPING_PROPERTIES: {
+ VkPhysicalDevicePointClippingProperties *properties = (void *) ext;
+ CORE_PROPERTY(pointClippingBehavior);
+ return true;
+ }
+
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_PROPERTIES: {
+ VkPhysicalDeviceProtectedMemoryProperties *properties = (void *)ext;
+ CORE_PROPERTY(protectedNoFault);
+ return true;
+ }
+
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_PROPERTIES: {
+ VkPhysicalDeviceSubgroupProperties *properties = (void *)ext;
+ CORE_PROPERTY(subgroupSize);
+ CORE_RENAMED_PROPERTY(supportedStages,
+ subgroupSupportedStages);
+ CORE_RENAMED_PROPERTY(supportedOperations,
+ subgroupSupportedOperations);
+ CORE_RENAMED_PROPERTY(quadOperationsInAllStages,
+ subgroupQuadOperationsInAllStages);
+ return true;
+ }
+
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_PROPERTIES:
+ copy_vk_struct_guts(ext, (void *)core, sizeof(*core));
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+bool
+vk_get_physical_device_core_1_2_property_ext(struct VkBaseOutStructure *ext,
+ const VkPhysicalDeviceVulkan12Properties *core)
+{
+ switch (ext->sType) {
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_STENCIL_RESOLVE_PROPERTIES_KHR: {
+ VkPhysicalDeviceDepthStencilResolvePropertiesKHR *properties = (void *)ext;
+ CORE_PROPERTY(supportedDepthResolveModes);
+ CORE_PROPERTY(supportedStencilResolveModes);
+ CORE_PROPERTY(independentResolveNone);
+ CORE_PROPERTY(independentResolve);
+ return true;
+ }
+
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_PROPERTIES_EXT: {
+ VkPhysicalDeviceDescriptorIndexingPropertiesEXT *properties = (void *)ext;
+ CORE_PROPERTY(maxUpdateAfterBindDescriptorsInAllPools);
+ CORE_PROPERTY(shaderUniformBufferArrayNonUniformIndexingNative);
+ CORE_PROPERTY(shaderSampledImageArrayNonUniformIndexingNative);
+ CORE_PROPERTY(shaderStorageBufferArrayNonUniformIndexingNative);
+ CORE_PROPERTY(shaderStorageImageArrayNonUniformIndexingNative);
+ CORE_PROPERTY(shaderInputAttachmentArrayNonUniformIndexingNative);
+ CORE_PROPERTY(robustBufferAccessUpdateAfterBind);
+ CORE_PROPERTY(quadDivergentImplicitLod);
+ CORE_PROPERTY(maxPerStageDescriptorUpdateAfterBindSamplers);
+ CORE_PROPERTY(maxPerStageDescriptorUpdateAfterBindUniformBuffers);
+ CORE_PROPERTY(maxPerStageDescriptorUpdateAfterBindStorageBuffers);
+ CORE_PROPERTY(maxPerStageDescriptorUpdateAfterBindSampledImages);
+ CORE_PROPERTY(maxPerStageDescriptorUpdateAfterBindStorageImages);
+ CORE_PROPERTY(maxPerStageDescriptorUpdateAfterBindInputAttachments);
+ CORE_PROPERTY(maxPerStageUpdateAfterBindResources);
+ CORE_PROPERTY(maxDescriptorSetUpdateAfterBindSamplers);
+ CORE_PROPERTY(maxDescriptorSetUpdateAfterBindUniformBuffers);
+ CORE_PROPERTY(maxDescriptorSetUpdateAfterBindUniformBuffersDynamic);
+ CORE_PROPERTY(maxDescriptorSetUpdateAfterBindStorageBuffers);
+ CORE_PROPERTY(maxDescriptorSetUpdateAfterBindStorageBuffersDynamic);
+ CORE_PROPERTY(maxDescriptorSetUpdateAfterBindSampledImages);
+ CORE_PROPERTY(maxDescriptorSetUpdateAfterBindStorageImages);
+ CORE_PROPERTY(maxDescriptorSetUpdateAfterBindInputAttachments);
+ return true;
+ }
+
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES_KHR: {
+ VkPhysicalDeviceDriverPropertiesKHR *properties = (void *) ext;
+ CORE_PROPERTY(driverID);
+ CORE_PROPERTY(driverName);
+ CORE_PROPERTY(driverInfo);
+ CORE_PROPERTY(conformanceVersion);
+ return true;
+ }
+
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_FILTER_MINMAX_PROPERTIES_EXT: {
+ VkPhysicalDeviceSamplerFilterMinmaxPropertiesEXT *properties = (void *)ext;
+ CORE_PROPERTY(filterMinmaxImageComponentMapping);
+ CORE_PROPERTY(filterMinmaxSingleComponentFormats);
+ return true;
+ }
+
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FLOAT_CONTROLS_PROPERTIES_KHR : {
+ VkPhysicalDeviceFloatControlsPropertiesKHR *properties = (void *)ext;
+ CORE_PROPERTY(denormBehaviorIndependence);
+ CORE_PROPERTY(roundingModeIndependence);
+ CORE_PROPERTY(shaderDenormFlushToZeroFloat16);
+ CORE_PROPERTY(shaderDenormPreserveFloat16);
+ CORE_PROPERTY(shaderRoundingModeRTEFloat16);
+ CORE_PROPERTY(shaderRoundingModeRTZFloat16);
+ CORE_PROPERTY(shaderSignedZeroInfNanPreserveFloat16);
+ CORE_PROPERTY(shaderDenormFlushToZeroFloat32);
+ CORE_PROPERTY(shaderDenormPreserveFloat32);
+ CORE_PROPERTY(shaderRoundingModeRTEFloat32);
+ CORE_PROPERTY(shaderRoundingModeRTZFloat32);
+ CORE_PROPERTY(shaderSignedZeroInfNanPreserveFloat32);
+ CORE_PROPERTY(shaderDenormFlushToZeroFloat64);
+ CORE_PROPERTY(shaderDenormPreserveFloat64);
+ CORE_PROPERTY(shaderRoundingModeRTEFloat64);
+ CORE_PROPERTY(shaderRoundingModeRTZFloat64);
+ CORE_PROPERTY(shaderSignedZeroInfNanPreserveFloat64);
+ return true;
+ }
+
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_PROPERTIES_KHR: {
+ VkPhysicalDeviceTimelineSemaphorePropertiesKHR *properties = (void *) ext;
+ CORE_PROPERTY(maxTimelineSemaphoreValueDifference);
+ return true;
+ }
+
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_PROPERTIES:
+ copy_vk_struct_guts(ext, (void *)core, sizeof(*core));
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+#undef CORE_RENAMED_PROPERTY
+#undef CORE_PROPERTY
+
diff --git a/lib/mesa/src/vulkan/util/vk_device.h b/lib/mesa/src/vulkan/util/vk_device.h
index e31688475..3bb0347e0 100644
--- a/lib/mesa/src/vulkan/util/vk_device.h
+++ b/lib/mesa/src/vulkan/util/vk_device.h
@@ -27,6 +27,8 @@
#include "vk_extensions.h"
#include "vk_object.h"
+#include "util/list.h"
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -43,6 +45,8 @@ struct vk_device {
/* For VK_EXT_private_data */
uint32_t private_data_next_index;
+ struct list_head queues;
+
#ifdef ANDROID
mtx_t swapchain_private_mtx;
struct hash_table *swapchain_private;
@@ -66,6 +70,16 @@ PFN_vkVoidFunction
vk_device_get_proc_addr(const struct vk_device *device,
const char *name);
+bool vk_get_physical_device_core_1_1_feature_ext(struct VkBaseOutStructure *ext,
+ const VkPhysicalDeviceVulkan11Features *core);
+bool vk_get_physical_device_core_1_2_feature_ext(struct VkBaseOutStructure *ext,
+ const VkPhysicalDeviceVulkan12Features *core);
+
+bool vk_get_physical_device_core_1_1_property_ext(struct VkBaseOutStructure *ext,
+ const VkPhysicalDeviceVulkan11Properties *core);
+bool vk_get_physical_device_core_1_2_property_ext(struct VkBaseOutStructure *ext,
+ const VkPhysicalDeviceVulkan12Properties *core);
+
#ifdef __cplusplus
}
#endif
diff --git a/lib/mesa/src/vulkan/util/vk_dispatch_table_gen.py b/lib/mesa/src/vulkan/util/vk_dispatch_table_gen.py
index 7b566ba0f..eb6b0cd28 100644
--- a/lib/mesa/src/vulkan/util/vk_dispatch_table_gen.py
+++ b/lib/mesa/src/vulkan/util/vk_dispatch_table_gen.py
@@ -55,6 +55,7 @@ TEMPLATE_H = Template(COPYRIGHT + """\
/* Windows api conflict */
#ifdef _WIN32
+#include <windows.h>
#ifdef CreateSemaphore
#undef CreateSemaphore
#endif
@@ -67,8 +68,11 @@ TEMPLATE_H = Template(COPYRIGHT + """\
extern "C" {
#endif
-<%def name="dispatch_table(type, entrypoints)">
-struct vk_${type}_dispatch_table {
+#ifdef _MSC_VER
+VKAPI_ATTR void VKAPI_CALL vk_entrypoint_stub(void);
+#endif
+
+<%def name="dispatch_table(entrypoints)">
% for e in entrypoints:
% if e.alias:
<% continue %>
@@ -101,8 +105,9 @@ struct vk_${type}_dispatch_table {
#endif
% endif
% endfor
-};
+</%def>
+<%def name="entrypoint_table(type, entrypoints)">
struct vk_${type}_entrypoint_table {
% for e in entrypoints:
% if e.guard is not None:
@@ -118,9 +123,37 @@ struct vk_${type}_entrypoint_table {
};
</%def>
-${dispatch_table('instance', instance_entrypoints)}
-${dispatch_table('physical_device', physical_device_entrypoints)}
-${dispatch_table('device', device_entrypoints)}
+struct vk_instance_dispatch_table {
+ ${dispatch_table(instance_entrypoints)}
+};
+
+struct vk_physical_device_dispatch_table {
+ ${dispatch_table(physical_device_entrypoints)}
+};
+
+struct vk_device_dispatch_table {
+ ${dispatch_table(device_entrypoints)}
+};
+
+struct vk_dispatch_table {
+ union {
+ struct {
+ struct vk_instance_dispatch_table instance;
+ struct vk_physical_device_dispatch_table physical_device;
+ struct vk_device_dispatch_table device;
+ };
+
+ struct {
+ ${dispatch_table(instance_entrypoints)}
+ ${dispatch_table(physical_device_entrypoints)}
+ ${dispatch_table(device_entrypoints)}
+ };
+ };
+};
+
+${entrypoint_table('instance', instance_entrypoints)}
+${entrypoint_table('physical_device', physical_device_entrypoints)}
+${entrypoint_table('device', device_entrypoints)}
void
vk_instance_dispatch_table_load(struct vk_instance_dispatch_table *table,
@@ -192,7 +225,7 @@ extern struct vk_device_dispatch_table vk_device_trampolines;
#endif
#endif /* VK_DISPATCH_TABLE_H */
-""", output_encoding='utf-8')
+""")
TEMPLATE_C = Template(COPYRIGHT + """\
/* This file generated from ${filename}, don't edit directly. */
@@ -435,6 +468,13 @@ vk_device_entrypoint_is_enabled(int index, uint32_t core_version,
}
}
+#ifdef _MSC_VER
+VKAPI_ATTR void VKAPI_CALL vk_entrypoint_stub(void)
+{
+ unreachable(!"Entrypoint not implemented");
+}
+#endif
+
<%def name="dispatch_table_from_entrypoints(type)">
void vk_${type}_dispatch_table_from_entrypoints(
struct vk_${type}_dispatch_table *dispatch_table,
@@ -448,8 +488,8 @@ void vk_${type}_dispatch_table_from_entrypoints(
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)
+ assert(entry[i] != NULL);
+ if (entry[i] == vk_entrypoint_stub)
#else
if (entry[i] == NULL)
#endif
@@ -461,7 +501,12 @@ void vk_${type}_dispatch_table_from_entrypoints(
} else {
for (unsigned i = 0; i < ARRAY_SIZE(${type}_compaction_table); i++) {
unsigned disp_index = ${type}_compaction_table[i];
+#ifdef _MSC_VER
+ assert(entry[i] != NULL);
+ if (disp[disp_index] == NULL && entry[i] != vk_entrypoint_stub)
+#else
if (disp[disp_index] == NULL)
+#endif
disp[disp_index] = entry[i];
}
}
@@ -638,7 +683,7 @@ struct vk_device_dispatch_table vk_device_trampolines = {
% endif
% endfor
};
-""", output_encoding='utf-8')
+""")
U32_MASK = 2**32 - 1
@@ -697,7 +742,7 @@ class StringIntMap(object):
self.collisions[min(level, 9)] += 1
self.mapping[h & self.hash_mask] = idx
-EntrypointParam = namedtuple('EntrypointParam', 'type name decl')
+EntrypointParam = namedtuple('EntrypointParam', 'type name decl len')
class EntrypointBase(object):
def __init__(self, name):
@@ -782,7 +827,8 @@ def get_entrypoints(doc, entrypoints_to_defines):
params = [EntrypointParam(
type=p.find('./type').text,
name=p.find('./name').text,
- decl=''.join(p.itertext())
+ decl=''.join(p.itertext()),
+ len=p.attrib.get('len', None)
) for p in command.findall('./param')]
guard = entrypoints_to_defines.get(name)
# They really need to be unique
@@ -898,13 +944,13 @@ def main():
# per entry point.
try:
if args.out_h:
- with open(args.out_h, 'wb') as f:
+ with open(args.out_h, 'w') 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:
+ with open(args.out_c, 'w') as f:
f.write(TEMPLATE_C.render(instance_entrypoints=instance_entrypoints,
physical_device_entrypoints=physical_device_entrypoints,
device_entrypoints=device_entrypoints,
diff --git a/lib/mesa/src/vulkan/util/vk_entrypoints_gen.py b/lib/mesa/src/vulkan/util/vk_entrypoints_gen.py
index a663d10e1..078b6daec 100644
--- a/lib/mesa/src/vulkan/util/vk_entrypoints_gen.py
+++ b/lib/mesa/src/vulkan/util/vk_entrypoints_gen.py
@@ -99,7 +99,7 @@ extern const struct vk_device_entrypoint_table ${p}_device_entrypoints;
#endif
#endif /* ${guard} */
-""", output_encoding='utf-8')
+""")
TEMPLATE_C = Template(COPYRIGHT + """
/* This file generated from ${filename}, don't edit directly. */
@@ -123,13 +123,12 @@ TEMPLATE_C = Template(COPYRIGHT + """
% 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")
+ #pragma comment(linker, "/alternatename:_${p}_${e.name}@${args_size}=_vk_entrypoint_stub@0")
% endfor
#else
- #pragma comment(linker, "/alternatename:${p}_${e.name}=${p}_${e.name}_Null")
+ #pragma comment(linker, "/alternatename:${p}_${e.name}=vk_entrypoint_stub")
#endif
#else
VKAPI_ATTR ${e.return_type} VKAPI_CALL ${p}_${e.name}(${e.decl_params()}) __attribute__ ((weak));
@@ -149,6 +148,8 @@ const struct vk_${type}_entrypoint_table ${p}_${type}_entrypoints = {
% endif
.${e.name} = ${p}_${e.name},
% if e.guard is not None:
+#elif defined(_MSC_VER)
+ .${e.name} = (PFN_vkVoidFunction)vk_entrypoint_stub,
#endif // ${e.guard}
% endif
% endfor
@@ -159,7 +160,7 @@ const struct vk_${type}_entrypoint_table ${p}_${type}_entrypoints = {
${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."""
@@ -236,10 +237,10 @@ def main():
# For outputting entrypoints.h we generate a anv_EntryPoint() prototype
# per entry point.
try:
- with open(args.out_h, 'wb') as f:
+ with open(args.out_h, 'w') 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:
+ with open(args.out_c, 'w') as f:
f.write(TEMPLATE_C.render(**environment))
except Exception:
diff --git a/lib/mesa/src/vulkan/util/vk_extensions.py b/lib/mesa/src/vulkan/util/vk_extensions.py
index 852951f05..75bdf3dd9 100644
--- a/lib/mesa/src/vulkan/util/vk_extensions.py
+++ b/lib/mesa/src/vulkan/util/vk_extensions.py
@@ -104,8 +104,10 @@ def get_all_exts_from_xml(xml):
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'])
+ # Skip alias SPEC_VERSIONs
+ if 'value' in enum_elem.attrib:
+ assert version is None
+ version = int(enum_elem.attrib['value'])
ext = Extension(name, version, True)
extensions.append(Extension(name, version, True))
diff --git a/lib/mesa/src/vulkan/util/vk_format.h b/lib/mesa/src/vulkan/util/vk_format.h
index 813ec4c36..f03a35e2a 100644
--- a/lib/mesa/src/vulkan/util/vk_format.h
+++ b/lib/mesa/src/vulkan/util/vk_format.h
@@ -28,6 +28,10 @@
#include <vulkan/vulkan_core.h>
#include "util/format/u_format.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
enum pipe_format
vk_format_to_pipe_format(enum VkFormat vkformat);
@@ -61,4 +65,31 @@ vk_format_has_stencil(VkFormat format)
return aspects & VK_IMAGE_ASPECT_STENCIL_BIT;
}
+static inline VkFormat
+vk_format_depth_only(VkFormat format)
+{
+ assert(vk_format_has_depth(format));
+ switch (format) {
+ case VK_FORMAT_D16_UNORM_S8_UINT:
+ return VK_FORMAT_D16_UNORM;
+ case VK_FORMAT_D24_UNORM_S8_UINT:
+ return VK_FORMAT_X8_D24_UNORM_PACK32;
+ case VK_FORMAT_D32_SFLOAT_S8_UINT:
+ return VK_FORMAT_D32_SFLOAT;
+ default:
+ return format;
+ }
+}
+
+static inline VkFormat
+vk_format_stencil_only(VkFormat format)
+{
+ assert(vk_format_has_stencil(format));
+ return VK_FORMAT_S8_UINT;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
#endif
diff --git a/lib/mesa/src/vulkan/util/vk_image.c b/lib/mesa/src/vulkan/util/vk_image.c
new file mode 100644
index 000000000..5e6db91dc
--- /dev/null
+++ b/lib/mesa/src/vulkan/util/vk_image.c
@@ -0,0 +1,617 @@
+/*
+ * 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_image.h"
+
+#include <vulkan/vulkan_android.h>
+
+#ifndef _WIN32
+#include <drm-uapi/drm_fourcc.h>
+#endif
+
+#include "vk_alloc.h"
+#include "vk_common_entrypoints.h"
+#include "vk_device.h"
+#include "vk_format.h"
+#include "vk_util.h"
+#include "vulkan/wsi/wsi_common.h"
+
+static VkExtent3D
+sanitize_image_extent(const VkImageType imageType,
+ const VkExtent3D imageExtent)
+{
+ switch (imageType) {
+ case VK_IMAGE_TYPE_1D:
+ return (VkExtent3D) { imageExtent.width, 1, 1 };
+ case VK_IMAGE_TYPE_2D:
+ return (VkExtent3D) { imageExtent.width, imageExtent.height, 1 };
+ case VK_IMAGE_TYPE_3D:
+ return imageExtent;
+ default:
+ unreachable("invalid image type");
+ }
+}
+
+void
+vk_image_init(struct vk_device *device,
+ struct vk_image *image,
+ const VkImageCreateInfo *pCreateInfo)
+{
+ vk_object_base_init(device, &image->base, VK_OBJECT_TYPE_IMAGE);
+
+ assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO);
+ assert(pCreateInfo->mipLevels > 0);
+ assert(pCreateInfo->arrayLayers > 0);
+ assert(pCreateInfo->samples > 0);
+ assert(pCreateInfo->extent.width > 0);
+ assert(pCreateInfo->extent.height > 0);
+ assert(pCreateInfo->extent.depth > 0);
+
+ if (pCreateInfo->flags & VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT)
+ assert(pCreateInfo->imageType == VK_IMAGE_TYPE_2D);
+ if (pCreateInfo->flags & VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT)
+ assert(pCreateInfo->imageType == VK_IMAGE_TYPE_3D);
+
+ image->create_flags = pCreateInfo->flags;
+ image->image_type = pCreateInfo->imageType;
+ vk_image_set_format(image, pCreateInfo->format);
+ image->extent = sanitize_image_extent(pCreateInfo->imageType,
+ pCreateInfo->extent);
+ image->mip_levels = pCreateInfo->mipLevels;
+ image->array_layers = pCreateInfo->arrayLayers;
+ image->samples = pCreateInfo->samples;
+ image->tiling = pCreateInfo->tiling;
+ image->usage = pCreateInfo->usage;
+
+ if (image->aspects & VK_IMAGE_ASPECT_STENCIL_BIT) {
+ const VkImageStencilUsageCreateInfoEXT *stencil_usage_info =
+ vk_find_struct_const(pCreateInfo->pNext,
+ IMAGE_STENCIL_USAGE_CREATE_INFO_EXT);
+ image->stencil_usage =
+ stencil_usage_info ? stencil_usage_info->stencilUsage :
+ pCreateInfo->usage;
+ } else {
+ image->stencil_usage = 0;
+ }
+
+ const VkExternalMemoryImageCreateInfo *ext_mem_info =
+ vk_find_struct_const(pCreateInfo->pNext, EXTERNAL_MEMORY_IMAGE_CREATE_INFO);
+ if (ext_mem_info)
+ image->external_handle_types = ext_mem_info->handleTypes;
+ else
+ image->external_handle_types = 0;
+
+ const struct wsi_image_create_info *wsi_info =
+ vk_find_struct_const(pCreateInfo->pNext, WSI_IMAGE_CREATE_INFO_MESA);
+ image->wsi_legacy_scanout = wsi_info && wsi_info->scanout;
+
+#ifndef _WIN32
+ image->drm_format_mod = ((1ULL << 56) - 1) /* DRM_FORMAT_MOD_INVALID */;
+#endif
+
+#ifdef ANDROID
+ const VkExternalFormatANDROID *ext_format =
+ vk_find_struct_const(pCreateInfo->pNext, EXTERNAL_FORMAT_ANDROID);
+ if (ext_format && ext_format->externalFormat != 0) {
+ assert(image->format == VK_FORMAT_UNDEFINED);
+ assert(image->external_handle_types &
+ VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID);
+ image->android_external_format = ext_format->externalFormat;
+ } else {
+ image->android_external_format = 0;
+ }
+#endif
+}
+
+void *
+vk_image_create(struct vk_device *device,
+ const VkImageCreateInfo *pCreateInfo,
+ const VkAllocationCallbacks *alloc,
+ size_t size)
+{
+ struct vk_image *image =
+ vk_zalloc2(&device->alloc, alloc, size, 8,
+ VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
+ if (image == NULL)
+ return NULL;
+
+ vk_image_init(device, image, pCreateInfo);
+
+ return image;
+}
+
+void
+vk_image_finish(struct vk_image *image)
+{
+ vk_object_base_finish(&image->base);
+}
+
+void
+vk_image_destroy(struct vk_device *device,
+ const VkAllocationCallbacks *alloc,
+ struct vk_image *image)
+{
+ vk_object_free(device, alloc, image);
+}
+
+#ifndef _WIN32
+VKAPI_ATTR VkResult VKAPI_CALL
+vk_common_GetImageDrmFormatModifierPropertiesEXT(UNUSED VkDevice device,
+ VkImage _image,
+ VkImageDrmFormatModifierPropertiesEXT *pProperties)
+{
+ VK_FROM_HANDLE(vk_image, image, _image);
+
+ assert(pProperties->sType ==
+ VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_PROPERTIES_EXT);
+
+ assert(image->tiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT);
+ pProperties->drmFormatModifier = image->drm_format_mod;
+
+ return VK_SUCCESS;
+}
+#endif
+
+void
+vk_image_set_format(struct vk_image *image, VkFormat format)
+{
+ image->format = format;
+ image->aspects = vk_format_aspects(format);
+}
+
+VkImageUsageFlags
+vk_image_usage(const struct vk_image *image,
+ VkImageAspectFlags aspect_mask)
+{
+ assert(!(aspect_mask & ~image->aspects));
+
+ /* From the Vulkan 1.2.131 spec:
+ *
+ * "If the image was has a depth-stencil format and was created with
+ * a VkImageStencilUsageCreateInfo structure included in the pNext
+ * chain of VkImageCreateInfo, the usage is calculated based on the
+ * subresource.aspectMask provided:
+ *
+ * - If aspectMask includes only VK_IMAGE_ASPECT_STENCIL_BIT, the
+ * implicit usage is equal to
+ * VkImageStencilUsageCreateInfo::stencilUsage.
+ *
+ * - If aspectMask includes only VK_IMAGE_ASPECT_DEPTH_BIT, the
+ * implicit usage is equal to VkImageCreateInfo::usage.
+ *
+ * - If both aspects are included in aspectMask, the implicit usage
+ * is equal to the intersection of VkImageCreateInfo::usage and
+ * VkImageStencilUsageCreateInfo::stencilUsage.
+ */
+ if (aspect_mask == VK_IMAGE_ASPECT_STENCIL_BIT) {
+ return image->stencil_usage;
+ } else if (aspect_mask == (VK_IMAGE_ASPECT_DEPTH_BIT |
+ VK_IMAGE_ASPECT_STENCIL_BIT)) {
+ return image->usage & image->stencil_usage;
+ } else {
+ /* This also handles the color case */
+ return image->usage;
+ }
+}
+
+#define VK_IMAGE_ASPECT_ANY_COLOR_MASK_MESA ( \
+ VK_IMAGE_ASPECT_COLOR_BIT | \
+ VK_IMAGE_ASPECT_PLANE_0_BIT | \
+ VK_IMAGE_ASPECT_PLANE_1_BIT | \
+ VK_IMAGE_ASPECT_PLANE_2_BIT)
+
+/** Expands the given aspect mask relative to the image
+ *
+ * If the image has color plane aspects VK_IMAGE_ASPECT_COLOR_BIT has been
+ * requested, this returns the aspects of the underlying image.
+ *
+ * For example,
+ *
+ * VK_IMAGE_ASPECT_COLOR_BIT
+ *
+ * will be converted to
+ *
+ * VK_IMAGE_ASPECT_PLANE_0_BIT |
+ * VK_IMAGE_ASPECT_PLANE_1_BIT |
+ * VK_IMAGE_ASPECT_PLANE_2_BIT
+ *
+ * for an image of format VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM.
+ */
+VkImageAspectFlags
+vk_image_expand_aspect_mask(const struct vk_image *image,
+ VkImageAspectFlags aspect_mask)
+{
+ if (aspect_mask == VK_IMAGE_ASPECT_COLOR_BIT) {
+ assert(image->aspects & VK_IMAGE_ASPECT_ANY_COLOR_MASK_MESA);
+ return image->aspects;
+ } else {
+ assert(aspect_mask && !(aspect_mask & ~image->aspects));
+ return aspect_mask;
+ }
+}
+
+static VkComponentSwizzle
+remap_swizzle(VkComponentSwizzle swizzle, VkComponentSwizzle component)
+{
+ return swizzle == VK_COMPONENT_SWIZZLE_IDENTITY ? component : swizzle;
+}
+
+void
+vk_image_view_init(struct vk_device *device,
+ struct vk_image_view *image_view,
+ const VkImageViewCreateInfo *pCreateInfo)
+{
+ vk_object_base_init(device, &image_view->base, VK_OBJECT_TYPE_IMAGE_VIEW);
+
+ assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO);
+ VK_FROM_HANDLE(vk_image, image, pCreateInfo->image);
+
+ image_view->create_flags = pCreateInfo->flags;
+ image_view->image = image;
+ image_view->view_type = pCreateInfo->viewType;
+
+ switch (image_view->view_type) {
+ case VK_IMAGE_VIEW_TYPE_1D:
+ case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
+ assert(image->image_type == VK_IMAGE_TYPE_1D);
+ break;
+ case VK_IMAGE_VIEW_TYPE_2D:
+ case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
+ if (image->create_flags & VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT)
+ assert(image->image_type == VK_IMAGE_TYPE_3D);
+ else
+ assert(image->image_type == VK_IMAGE_TYPE_2D);
+ break;
+ case VK_IMAGE_VIEW_TYPE_3D:
+ assert(image->image_type == VK_IMAGE_TYPE_3D);
+ break;
+ case VK_IMAGE_VIEW_TYPE_CUBE:
+ case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
+ assert(image->image_type == VK_IMAGE_TYPE_2D);
+ assert(image->create_flags & VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT);
+ break;
+ default:
+ unreachable("Invalid image view type");
+ }
+
+ const VkImageSubresourceRange *range = &pCreateInfo->subresourceRange;
+
+ /* Some drivers may want to create color views of depth/stencil images
+ * to implement certain operations, which is not strictly allowed by the
+ * Vulkan spec, so handle this case separately.
+ */
+ bool is_color_view_of_depth_stencil =
+ vk_format_is_depth_or_stencil(image->format) &&
+ vk_format_is_color(pCreateInfo->format);
+ if (is_color_view_of_depth_stencil) {
+ assert(range->aspectMask == VK_IMAGE_ASPECT_COLOR_BIT);
+ assert(util_format_get_blocksize(vk_format_to_pipe_format(image->format)) ==
+ util_format_get_blocksize(vk_format_to_pipe_format(pCreateInfo->format)));
+ image_view->aspects = range->aspectMask;
+ } else {
+ image_view->aspects =
+ vk_image_expand_aspect_mask(image, range->aspectMask);
+
+ /* From the Vulkan 1.2.184 spec:
+ *
+ * "If the image has a multi-planar format and
+ * subresourceRange.aspectMask is VK_IMAGE_ASPECT_COLOR_BIT, and image
+ * has been created with a usage value not containing any of the
+ * VK_IMAGE_USAGE_VIDEO_DECODE_DST_BIT_KHR,
+ * VK_IMAGE_USAGE_VIDEO_DECODE_SRC_BIT_KHR,
+ * VK_IMAGE_USAGE_VIDEO_DECODE_DPB_BIT_KHR,
+ * VK_IMAGE_USAGE_VIDEO_ENCODE_DST_BIT_KHR,
+ * VK_IMAGE_USAGE_VIDEO_ENCODE_SRC_BIT_KHR, and
+ * VK_IMAGE_USAGE_VIDEO_ENCODE_DPB_BIT_KHR flags, then the format must
+ * be identical to the image format, and the sampler to be used with the
+ * image view must enable sampler Y′CBCR conversion."
+ *
+ * Since no one implements video yet, we can ignore the bits about video
+ * create flags and assume YCbCr formats match.
+ */
+ if ((image->aspects & VK_IMAGE_ASPECT_PLANE_1_BIT) &&
+ (range->aspectMask == VK_IMAGE_ASPECT_COLOR_BIT))
+ assert(pCreateInfo->format == image->format);
+
+ /* From the Vulkan 1.2.184 spec:
+ *
+ * "Each depth/stencil format is only compatible with itself."
+ */
+ if (image_view->aspects & (VK_IMAGE_ASPECT_DEPTH_BIT |
+ VK_IMAGE_ASPECT_STENCIL_BIT))
+ assert(pCreateInfo->format == image->format);
+
+ if (!(image->create_flags & VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT))
+ assert(pCreateInfo->format == image->format);
+ }
+
+ /* Restrict the format to only the planes chosen.
+ *
+ * For combined depth and stencil images, this means the depth-only or
+ * stencil-only format if only one aspect is chosen and the full combined
+ * format if both aspects are chosen.
+ *
+ * For single-plane color images, we just take the format as-is. For
+ * multi-plane views of multi-plane images, this means we want the full
+ * multi-plane format. For single-plane views of multi-plane images, we
+ * want a format compatible with the one plane. Fortunately, this is
+ * already what the client gives us. The Vulkan 1.2.184 spec says:
+ *
+ * "If image was created with the VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT and
+ * the image has a multi-planar format, and if
+ * subresourceRange.aspectMask is VK_IMAGE_ASPECT_PLANE_0_BIT,
+ * VK_IMAGE_ASPECT_PLANE_1_BIT, or VK_IMAGE_ASPECT_PLANE_2_BIT, format
+ * must be compatible with the corresponding plane of the image, and the
+ * sampler to be used with the image view must not enable sampler Y′CBCR
+ * conversion."
+ */
+ if (image_view->aspects == VK_IMAGE_ASPECT_STENCIL_BIT) {
+ image_view->format = vk_format_stencil_only(pCreateInfo->format);
+ } else if (image_view->aspects == VK_IMAGE_ASPECT_DEPTH_BIT) {
+ image_view->format = vk_format_depth_only(pCreateInfo->format);
+ } else {
+ image_view->format = pCreateInfo->format;
+ }
+
+ image_view->swizzle = (VkComponentMapping) {
+ .r = remap_swizzle(pCreateInfo->components.r, VK_COMPONENT_SWIZZLE_R),
+ .g = remap_swizzle(pCreateInfo->components.g, VK_COMPONENT_SWIZZLE_G),
+ .b = remap_swizzle(pCreateInfo->components.b, VK_COMPONENT_SWIZZLE_B),
+ .a = remap_swizzle(pCreateInfo->components.a, VK_COMPONENT_SWIZZLE_A),
+ };
+
+ assert(range->layerCount > 0);
+ assert(range->baseMipLevel < image->mip_levels);
+
+ image_view->base_mip_level = range->baseMipLevel;
+ image_view->level_count = vk_image_subresource_level_count(image, range);
+ image_view->base_array_layer = range->baseArrayLayer;
+ image_view->layer_count = vk_image_subresource_layer_count(image, range);
+
+ image_view->extent =
+ vk_image_mip_level_extent(image, image_view->base_mip_level);
+
+ assert(image_view->base_mip_level + image_view->level_count
+ <= image->mip_levels);
+ switch (image->image_type) {
+ default:
+ unreachable("bad VkImageType");
+ case VK_IMAGE_TYPE_1D:
+ case VK_IMAGE_TYPE_2D:
+ assert(image_view->base_array_layer + image_view->layer_count
+ <= image->array_layers);
+ break;
+ case VK_IMAGE_TYPE_3D:
+ assert(image_view->base_array_layer + image_view->layer_count
+ <= image_view->extent.depth);
+ break;
+ }
+
+ /* If we are creating a color view from a depth/stencil image we compute
+ * usage from the underlying depth/stencil aspects.
+ */
+ const VkImageUsageFlags image_usage = is_color_view_of_depth_stencil ?
+ vk_image_usage(image, image->aspects) :
+ vk_image_usage(image, image_view->aspects);
+ const VkImageViewUsageCreateInfo *usage_info =
+ vk_find_struct_const(pCreateInfo, IMAGE_VIEW_USAGE_CREATE_INFO);
+ image_view->usage = usage_info ? usage_info->usage : image_usage;
+ assert(!(image_view->usage & ~image_usage));
+}
+
+void
+vk_image_view_finish(struct vk_image_view *image_view)
+{
+ vk_object_base_finish(&image_view->base);
+}
+
+void *
+vk_image_view_create(struct vk_device *device,
+ const VkImageViewCreateInfo *pCreateInfo,
+ const VkAllocationCallbacks *alloc,
+ size_t size)
+{
+ struct vk_image_view *image_view =
+ vk_zalloc2(&device->alloc, alloc, size, 8,
+ VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
+ if (image_view == NULL)
+ return NULL;
+
+ vk_image_view_init(device, image_view, pCreateInfo);
+
+ return image_view;
+}
+
+void
+vk_image_view_destroy(struct vk_device *device,
+ const VkAllocationCallbacks *alloc,
+ struct vk_image_view *image_view)
+{
+ vk_object_free(device, alloc, image_view);
+}
+
+bool
+vk_image_layout_is_read_only(VkImageLayout layout,
+ VkImageAspectFlagBits aspect)
+{
+ assert(util_bitcount(aspect) == 1);
+
+ switch (layout) {
+ case VK_IMAGE_LAYOUT_UNDEFINED:
+ case VK_IMAGE_LAYOUT_PREINITIALIZED:
+ return true; /* These are only used for layout transitions */
+
+ case VK_IMAGE_LAYOUT_GENERAL:
+ case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL:
+ case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL:
+ case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL:
+ case VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR:
+ case VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL:
+ case VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL:
+ case VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL_KHR:
+ return false;
+
+ case VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL:
+ case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL:
+ case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL:
+ case VK_IMAGE_LAYOUT_PRESENT_SRC_KHR:
+ case VK_IMAGE_LAYOUT_SHADING_RATE_OPTIMAL_NV:
+ case VK_IMAGE_LAYOUT_FRAGMENT_DENSITY_MAP_OPTIMAL_EXT:
+ case VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL:
+ case VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL:
+ case VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL_KHR:
+ return true;
+
+ case VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL:
+ return aspect == VK_IMAGE_ASPECT_DEPTH_BIT;
+
+ case VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL:
+ return aspect == VK_IMAGE_ASPECT_STENCIL_BIT;
+
+ case VK_IMAGE_LAYOUT_MAX_ENUM:
+ unreachable("Invalid image layout.");
+ }
+
+ unreachable("Invalid image layout.");
+}
+
+VkImageUsageFlags
+vk_image_layout_to_usage_flags(VkImageLayout layout,
+ VkImageAspectFlagBits aspect)
+{
+ assert(util_bitcount(aspect) == 1);
+
+ switch (layout) {
+ case VK_IMAGE_LAYOUT_UNDEFINED:
+ case VK_IMAGE_LAYOUT_PREINITIALIZED:
+ return 0u;
+
+ case VK_IMAGE_LAYOUT_GENERAL:
+ return ~0u;
+
+ case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL:
+ assert(aspect & VK_IMAGE_ASPECT_ANY_COLOR_MASK_MESA);
+ return VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
+
+ case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL:
+ assert(aspect & (VK_IMAGE_ASPECT_DEPTH_BIT |
+ VK_IMAGE_ASPECT_STENCIL_BIT));
+ return VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
+
+ case VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL:
+ assert(aspect & VK_IMAGE_ASPECT_DEPTH_BIT);
+ return vk_image_layout_to_usage_flags(
+ VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, aspect);
+
+ case VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL:
+ assert(aspect & VK_IMAGE_ASPECT_STENCIL_BIT);
+ return vk_image_layout_to_usage_flags(
+ VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, aspect);
+
+ case VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL:
+ assert(aspect & (VK_IMAGE_ASPECT_DEPTH_BIT |
+ VK_IMAGE_ASPECT_STENCIL_BIT));
+ return VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT |
+ VK_IMAGE_USAGE_SAMPLED_BIT |
+ VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
+
+ case VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL:
+ assert(aspect & VK_IMAGE_ASPECT_DEPTH_BIT);
+ return vk_image_layout_to_usage_flags(
+ VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL, aspect);
+
+ case VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL:
+ assert(aspect & VK_IMAGE_ASPECT_STENCIL_BIT);
+ return vk_image_layout_to_usage_flags(
+ VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL, aspect);
+
+ case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL:
+ return VK_IMAGE_USAGE_SAMPLED_BIT |
+ VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
+
+ case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL:
+ return VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
+
+ case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL:
+ return VK_IMAGE_USAGE_TRANSFER_DST_BIT;
+
+ case VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL:
+ if (aspect == VK_IMAGE_ASPECT_DEPTH_BIT) {
+ return vk_image_layout_to_usage_flags(
+ VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL, aspect);
+ } else if (aspect == VK_IMAGE_ASPECT_STENCIL_BIT) {
+ return vk_image_layout_to_usage_flags(
+ VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, aspect);
+ } else {
+ assert(!"Must be a depth/stencil aspect");
+ return 0;
+ }
+
+ case VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL:
+ if (aspect == VK_IMAGE_ASPECT_DEPTH_BIT) {
+ return vk_image_layout_to_usage_flags(
+ VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, aspect);
+ } else if (aspect == VK_IMAGE_ASPECT_STENCIL_BIT) {
+ return vk_image_layout_to_usage_flags(
+ VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL, aspect);
+ } else {
+ assert(!"Must be a depth/stencil aspect");
+ return 0;
+ }
+
+ case VK_IMAGE_LAYOUT_PRESENT_SRC_KHR:
+ assert(aspect == VK_IMAGE_ASPECT_COLOR_BIT);
+ /* This needs to be handled specially by the caller */
+ return 0;
+
+ case VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR:
+ assert(aspect == VK_IMAGE_ASPECT_COLOR_BIT);
+ return vk_image_layout_to_usage_flags(VK_IMAGE_LAYOUT_GENERAL, aspect);
+
+ case VK_IMAGE_LAYOUT_SHADING_RATE_OPTIMAL_NV:
+ assert(aspect == VK_IMAGE_ASPECT_COLOR_BIT);
+ return VK_IMAGE_USAGE_SHADING_RATE_IMAGE_BIT_NV;
+
+ case VK_IMAGE_LAYOUT_FRAGMENT_DENSITY_MAP_OPTIMAL_EXT:
+ assert(aspect == VK_IMAGE_ASPECT_COLOR_BIT);
+ return VK_IMAGE_USAGE_FRAGMENT_DENSITY_MAP_BIT_EXT;
+
+ case VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL_KHR:
+ if (aspect == VK_IMAGE_ASPECT_DEPTH_BIT ||
+ aspect == VK_IMAGE_ASPECT_STENCIL_BIT) {
+ return VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
+ } else {
+ assert(aspect == VK_IMAGE_ASPECT_COLOR_BIT);
+ return VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
+ }
+
+ case VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL_KHR:
+ return VK_IMAGE_USAGE_SAMPLED_BIT |
+ VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
+
+ case VK_IMAGE_LAYOUT_MAX_ENUM:
+ unreachable("Invalid image layout.");
+ }
+
+ unreachable("Invalid image layout.");
+}
diff --git a/lib/mesa/src/vulkan/util/vk_image.h b/lib/mesa/src/vulkan/util/vk_image.h
new file mode 100644
index 000000000..beb260647
--- /dev/null
+++ b/lib/mesa/src/vulkan/util/vk_image.h
@@ -0,0 +1,231 @@
+/*
+ * 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_IMAGE_H
+#define VK_IMAGE_H
+
+#include "vk_object.h"
+
+#include "util/u_math.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct vk_image {
+ struct vk_object_base base;
+
+ VkImageCreateFlags create_flags;
+ VkImageType image_type;
+ VkFormat format;
+ VkExtent3D extent;
+ uint32_t mip_levels;
+ uint32_t array_layers;
+ VkSampleCountFlagBits samples;
+ VkImageTiling tiling;
+ VkImageUsageFlags usage;
+
+ /* Derived from format */
+ VkImageAspectFlags aspects;
+
+ /* VK_EXT_separate_stencil_usage */
+ VkImageUsageFlags stencil_usage;
+
+ /* VK_KHR_external_memory */
+ VkExternalMemoryHandleTypeFlags external_handle_types;
+
+ /* wsi_image_create_info::scanout */
+ bool wsi_legacy_scanout;
+
+#ifndef _WIN32
+ /* VK_EXT_drm_format_modifier
+ *
+ * Initialized by vk_image_create/init() to DRM_FORMAT_MOD_INVALID. It's
+ * the job of the driver to parse the VK_EXT_drm_format_modifier extension
+ * structs and choose the actual modifier.
+ *
+ * Must be DRM_FORMAT_MOD_INVALID unless tiling is
+ * VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT.
+ */
+ uint64_t drm_format_mod;
+#endif
+
+#ifdef ANDROID
+ /* VK_ANDROID_external_memory_android_hardware_buffer */
+ uint64_t android_external_format;
+#endif
+};
+VK_DEFINE_NONDISP_HANDLE_CASTS(vk_image, base, VkImage,
+ VK_OBJECT_TYPE_IMAGE);
+
+void vk_image_init(struct vk_device *device,
+ struct vk_image *image,
+ const VkImageCreateInfo *pCreateInfo);
+void vk_image_finish(struct vk_image *image);
+
+void *vk_image_create(struct vk_device *device,
+ const VkImageCreateInfo *pCreateInfo,
+ const VkAllocationCallbacks *alloc,
+ size_t size);
+void vk_image_destroy(struct vk_device *device,
+ const VkAllocationCallbacks *alloc,
+ struct vk_image *image);
+
+void vk_image_set_format(struct vk_image *image, VkFormat format);
+
+VkImageUsageFlags vk_image_usage(const struct vk_image *image,
+ VkImageAspectFlags aspect_mask);
+
+VkImageAspectFlags vk_image_expand_aspect_mask(const struct vk_image *image,
+ VkImageAspectFlags aspect_mask);
+
+static inline VkExtent3D
+vk_image_mip_level_extent(const struct vk_image *image,
+ uint32_t mip_level)
+{
+ const VkExtent3D extent = {
+ u_minify(image->extent.width, mip_level),
+ u_minify(image->extent.height, mip_level),
+ u_minify(image->extent.depth, mip_level),
+ };
+ return extent;
+}
+
+/* This is defined as a macro so that it works for both
+ * VkImageSubresourceRange and VkImageSubresourceLayers
+ */
+#define vk_image_subresource_layer_count(_image, _range) \
+ ((_range)->layerCount == VK_REMAINING_ARRAY_LAYERS ? \
+ (_image)->array_layers - (_range)->baseArrayLayer : (_range)->layerCount)
+
+static inline uint32_t
+vk_image_subresource_level_count(const struct vk_image *image,
+ const VkImageSubresourceRange *range)
+{
+ return range->levelCount == VK_REMAINING_MIP_LEVELS ?
+ image->mip_levels - range->baseMipLevel : range->levelCount;
+}
+
+struct vk_image_view {
+ struct vk_object_base base;
+
+ VkImageViewCreateFlags create_flags;
+ struct vk_image *image;
+ VkImageViewType view_type;
+
+ /** Image view format, relative to the selected aspects
+ *
+ * For a depth/stencil image:
+ *
+ * - If vk_image_view::aspects contains both depth and stencil, this will
+ * be the full depth/stencil format of the image.
+ *
+ * - If only one aspect is selected, this will be the depth-only or
+ * stencil-only format, as per the selected aspect.
+ *
+ * For color images, we have three cases:
+ *
+ * 1. It's a single-plane image in which case this is the unmodified
+ * format provided to VkImageViewCreateInfo::format.
+ *
+ * 2. It's a YCbCr view of a multi-plane image in which case the
+ * client will have asked for VK_IMAGE_ASPECT_COLOR_BIT and the
+ * format provided will be the full planar format. In this case,
+ * the format will be the full format containing all the planes.
+ *
+ * 3. It's a single-plane view of a multi-plane image in which case
+ * the client will have asked for VK_IMAGE_ASPECT_PLANE_N_BIT and
+ * will have provided a format compatible with that specific
+ * plane of the multi-planar format. In this case, the format will be
+ * the plane-compatible format requested by the client.
+ */
+ VkFormat format;
+
+ /* Component mapping, aka swizzle
+ *
+ * Unlike the swizzle provided via VkImageViewCreateInfo::components, this
+ * will never contain VK_COMPONENT_SWIZZLE_IDENTITY. It will be resolved
+ * to VK_COMPONENT_SWIZZLE_R/G/B/A, as appropriate.
+ */
+ VkComponentMapping swizzle;
+
+ /** Aspects from the image represented by this view
+ *
+ * For depth/stencil images, this is the aspectMask provided by
+ * VkImageViewCreateinfo::subresourceRange::aspectMask.
+ *
+ * For color images, we have three cases:
+ *
+ * 1. It's a single-plane image in which case this only aspect is
+ * VK_IMAGE_ASPECT_COLOR_BIT.
+ *
+ * 2. It's a YCbCr view of a multi-plane image in which case the
+ * client will have asked for VK_IMAGE_ASPECT_COLOR_BIT and the
+ * format provided will be the full planar format. In this case,
+ * aspects will be the full set of plane aspects in the image.
+ *
+ * 3. It's a single-plane view of a multi-plane image in which case
+ * the client will have asked for VK_IMAGE_ASPECT_PLANE_N_BIT and
+ * will have provided a format compatible with that specific
+ * plane of the multi-planar format. In this case, aspects will be
+ * VK_IMAGE_ASPECT_PLANE_N_BIT where N is the selected plane.
+ *
+ * This seems almost backwards from the API but ensures that
+ * vk_image_view::aspects is always a subset of vk_image::aspects.
+ */
+ VkImageAspectFlags aspects;
+
+ uint32_t base_mip_level;
+ uint32_t level_count;
+ uint32_t base_array_layer;
+ uint32_t layer_count;
+
+ /* Image extent at LOD 0 */
+ VkExtent3D extent;
+
+ /* VK_KHR_maintenance2 */
+ VkImageUsageFlags usage;
+};
+
+void vk_image_view_init(struct vk_device *device,
+ struct vk_image_view *image_view,
+ const VkImageViewCreateInfo *pCreateInfo);
+void vk_image_view_finish(struct vk_image_view *image_view);
+
+void *vk_image_view_create(struct vk_device *device,
+ const VkImageViewCreateInfo *pCreateInfo,
+ const VkAllocationCallbacks *alloc,
+ size_t size);
+void vk_image_view_destroy(struct vk_device *device,
+ const VkAllocationCallbacks *alloc,
+ struct vk_image_view *image_view);
+
+bool vk_image_layout_is_read_only(VkImageLayout layout,
+ VkImageAspectFlagBits aspect);
+VkImageUsageFlags vk_image_layout_to_usage_flags(VkImageLayout layout,
+ VkImageAspectFlagBits aspect);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* VK_IMAGE_H */
diff --git a/lib/mesa/src/vulkan/util/vk_instance.c b/lib/mesa/src/vulkan/util/vk_instance.c
index 5787be170..931071509 100644
--- a/lib/mesa/src/vulkan/util/vk_instance.c
+++ b/lib/mesa/src/vulkan/util/vk_instance.c
@@ -25,7 +25,9 @@
#include "vk_alloc.h"
#include "vk_common_entrypoints.h"
+#include "vk_log.h"
#include "vk_util.h"
+#include "vk_debug_utils.h"
#include "compiler/glsl_types.h"
@@ -40,6 +42,38 @@ vk_instance_init(struct vk_instance *instance,
vk_object_base_init(NULL, &instance->base, VK_OBJECT_TYPE_INSTANCE);
instance->alloc = *alloc;
+ /* VK_EXT_debug_utils */
+ /* These messengers will only be used during vkCreateInstance or
+ * vkDestroyInstance calls. We do this first so that it's safe to use
+ * vk_errorf and friends.
+ */
+ list_inithead(&instance->debug_utils.instance_callbacks);
+ vk_foreach_struct_const(ext, pCreateInfo->pNext) {
+ if (ext->sType ==
+ VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT) {
+ const VkDebugUtilsMessengerCreateInfoEXT *debugMessengerCreateInfo =
+ (const VkDebugUtilsMessengerCreateInfoEXT *)ext;
+ struct vk_debug_utils_messenger *messenger =
+ vk_alloc2(alloc, alloc, sizeof(struct vk_debug_utils_messenger), 8,
+ VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
+
+ if (!messenger)
+ return vk_error(instance, VK_ERROR_OUT_OF_HOST_MEMORY);
+
+ vk_object_base_init(NULL, &messenger->base,
+ VK_OBJECT_TYPE_DEBUG_UTILS_MESSENGER_EXT);
+
+ messenger->alloc = *alloc;
+ messenger->severity = debugMessengerCreateInfo->messageSeverity;
+ messenger->type = debugMessengerCreateInfo->messageType;
+ messenger->callback = debugMessengerCreateInfo->pfnUserCallback;
+ messenger->data = debugMessengerCreateInfo->pUserData;
+
+ list_addtail(&messenger->link,
+ &instance->debug_utils.instance_callbacks);
+ }
+ }
+
instance->app_info = (struct vk_app_info) { .api_version = 0 };
if (pCreateInfo->pApplicationInfo) {
const VkApplicationInfo *app = pCreateInfo->pApplicationInfo;
@@ -69,14 +103,20 @@ vk_instance_init(struct vk_instance *instance,
}
if (idx >= VK_INSTANCE_EXTENSION_COUNT)
- return VK_ERROR_EXTENSION_NOT_PRESENT;
+ return vk_errorf(instance, VK_ERROR_EXTENSION_NOT_PRESENT,
+ "%s not supported",
+ pCreateInfo->ppEnabledExtensionNames[i]);
if (!supported_extensions->extensions[idx])
- return VK_ERROR_EXTENSION_NOT_PRESENT;
+ return vk_errorf(instance, VK_ERROR_EXTENSION_NOT_PRESENT,
+ "%s not supported",
+ pCreateInfo->ppEnabledExtensionNames[i]);
#ifdef ANDROID
if (!vk_android_allowed_instance_extensions.extensions[idx])
- return VK_ERROR_EXTENSION_NOT_PRESENT;
+ return vk_errorf(instance, VK_ERROR_EXTENSION_NOT_PRESENT,
+ "%s not supported",
+ pCreateInfo->ppEnabledExtensionNames[i]);
#endif
instance->enabled_extensions.extensions[idx] = true;
@@ -89,10 +129,17 @@ vk_instance_init(struct vk_instance *instance,
&instance->dispatch_table, &vk_common_instance_entrypoints, false);
if (mtx_init(&instance->debug_report.callbacks_mutex, mtx_plain) != 0)
- return VK_ERROR_INITIALIZATION_FAILED;
+ return vk_error(instance, VK_ERROR_INITIALIZATION_FAILED);
list_inithead(&instance->debug_report.callbacks);
+ if (mtx_init(&instance->debug_utils.callbacks_mutex, mtx_plain) != 0) {
+ mtx_destroy(&instance->debug_report.callbacks_mutex);
+ return vk_error(instance, VK_ERROR_INITIALIZATION_FAILED);
+ }
+
+ list_inithead(&instance->debug_utils.callbacks);
+
glsl_type_singleton_init_or_ref();
return VK_SUCCESS;
@@ -102,7 +149,25 @@ void
vk_instance_finish(struct vk_instance *instance)
{
glsl_type_singleton_decref();
+ if (unlikely(!list_is_empty(&instance->debug_utils.callbacks))) {
+ list_for_each_entry_safe(struct vk_debug_utils_messenger, messenger,
+ &instance->debug_utils.callbacks, link) {
+ list_del(&messenger->link);
+ vk_object_base_finish(&messenger->base);
+ vk_free2(&instance->alloc, &messenger->alloc, messenger);
+ }
+ }
+ if (unlikely(!list_is_empty(&instance->debug_utils.instance_callbacks))) {
+ list_for_each_entry_safe(struct vk_debug_utils_messenger, messenger,
+ &instance->debug_utils.instance_callbacks,
+ link) {
+ list_del(&messenger->link);
+ vk_object_base_finish(&messenger->base);
+ vk_free2(&instance->alloc, &messenger->alloc, messenger);
+ }
+ }
mtx_destroy(&instance->debug_report.callbacks_mutex);
+ mtx_destroy(&instance->debug_utils.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);
diff --git a/lib/mesa/src/vulkan/util/vk_instance.h b/lib/mesa/src/vulkan/util/vk_instance.h
index 5f195ca0d..88af1a6b4 100644
--- a/lib/mesa/src/vulkan/util/vk_instance.h
+++ b/lib/mesa/src/vulkan/util/vk_instance.h
@@ -56,6 +56,17 @@ struct vk_instance {
mtx_t callbacks_mutex;
struct list_head callbacks;
} debug_report;
+
+ /* VK_EXT_debug_utils */
+ struct {
+ /* These callbacks are only used while creating or destroying an
+ * instance
+ */
+ struct list_head instance_callbacks;
+ mtx_t callbacks_mutex;
+ /* Persistent callbacks */
+ struct list_head callbacks;
+ } debug_utils;
};
VK_DEFINE_HANDLE_CASTS(vk_instance, base, VkInstance,
diff --git a/lib/mesa/src/vulkan/util/vk_log.c b/lib/mesa/src/vulkan/util/vk_log.c
new file mode 100644
index 000000000..b085b369f
--- /dev/null
+++ b/lib/mesa/src/vulkan/util/vk_log.c
@@ -0,0 +1,339 @@
+/*
+ * 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_log.h"
+#include "vk_debug_utils.h"
+#include "vk_debug_report.h"
+
+#include "vk_command_buffer.h"
+#include "vk_enum_to_str.h"
+#include "vk_queue.h"
+#include "vk_device.h"
+#include "vk_physical_device.h"
+
+#include "ralloc.h"
+
+#include "log.h"
+
+static struct vk_device *
+vk_object_to_device(struct vk_object_base *obj)
+{
+ assert(obj->device);
+ return obj->device;
+}
+
+static struct vk_physical_device *
+vk_object_to_physical_device(struct vk_object_base *obj)
+{
+ switch (obj->type) {
+ case VK_OBJECT_TYPE_INSTANCE:
+ unreachable("Unsupported object type");
+ case VK_OBJECT_TYPE_PHYSICAL_DEVICE:
+ return container_of(obj, struct vk_physical_device, base);
+ case VK_OBJECT_TYPE_SURFACE_KHR:
+ case VK_OBJECT_TYPE_DISPLAY_KHR:
+ case VK_OBJECT_TYPE_DISPLAY_MODE_KHR:
+ case VK_OBJECT_TYPE_DEBUG_REPORT_CALLBACK_EXT:
+ case VK_OBJECT_TYPE_DEBUG_UTILS_MESSENGER_EXT:
+ unreachable("Unsupported object type");
+ default:
+ return vk_object_to_device(obj)->physical;
+ }
+}
+
+static struct vk_instance *
+vk_object_to_instance(struct vk_object_base *obj)
+{
+ if (obj == NULL)
+ return NULL;
+
+ if (obj->type == VK_OBJECT_TYPE_INSTANCE) {
+ return container_of(obj, struct vk_instance, base);
+ } else {
+ return vk_object_to_physical_device(obj)->instance;
+ }
+}
+
+void
+__vk_log_impl(VkDebugUtilsMessageSeverityFlagBitsEXT severity,
+ VkDebugUtilsMessageTypeFlagsEXT types,
+ int object_count,
+ const void **objects_or_instance,
+ const char *file,
+ int line,
+ const char *format,
+ ...)
+{
+ struct vk_instance *instance = NULL;
+ struct vk_object_base **objects = NULL;
+ if (object_count == 0) {
+ instance = (struct vk_instance *) objects_or_instance;
+ } else {
+ objects = (struct vk_object_base **) objects_or_instance;
+ instance = vk_object_to_instance(objects[0]);
+ assert(instance->base.client_visible);
+ }
+
+#ifndef DEBUG
+ if (unlikely(!instance) ||
+ (likely(list_is_empty(&instance->debug_utils.callbacks)) &&
+ likely(list_is_empty(&instance->debug_report.callbacks))))
+ return;
+#endif
+
+ va_list va;
+ char *message = NULL;
+
+ va_start(va, format);
+ message = ralloc_vasprintf(NULL, format, va);
+ va_end(va);
+
+ char *message_idname = ralloc_asprintf(NULL, "%s:%d", file, line);
+
+#if DEBUG
+ switch (severity) {
+ case VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT:
+ mesa_logd("%s: %s", message_idname, message);
+ break;
+ case VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT:
+ mesa_logi("%s: %s", message_idname, message);
+ break;
+ case VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT:
+ if (types & VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT)
+ mesa_logw("%s: PERF: %s", message_idname, message);
+ else
+ mesa_logw("%s: %s", message_idname, message);
+ break;
+ case VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT:
+ mesa_loge("%s: %s", message_idname, message);
+ break;
+ default:
+ unreachable("Invalid debug message severity");
+ break;
+ }
+
+ if (!instance) {
+ ralloc_free(message);
+ ralloc_free(message_idname);
+ return;
+ }
+#endif
+
+ if (!instance->base.client_visible) {
+ vk_debug_message_instance(instance, severity, types,
+ message_idname, 0, message);
+ ralloc_free(message);
+ ralloc_free(message_idname);
+ return;
+ }
+
+ /* If VK_EXT_debug_utils messengers have been set up, form the
+ * message */
+ if (!list_is_empty(&instance->debug_utils.callbacks)) {
+ VkDebugUtilsMessengerCallbackDataEXT cb_data = {
+ .sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CALLBACK_DATA_EXT,
+ .pMessageIdName = message_idname,
+ .messageIdNumber = 0,
+ .pMessage = message,
+ };
+
+ VkDebugUtilsObjectNameInfoEXT *object_name_infos =
+ ralloc_array(NULL, VkDebugUtilsObjectNameInfoEXT, object_count);
+
+ ASSERTED int cmdbuf_n = 0, queue_n = 0;
+ for (int i = 0; i < object_count; i++) {
+ struct vk_object_base *base = objects[i];
+ assert(base->client_visible);
+
+ switch (base->type) {
+ case VK_OBJECT_TYPE_COMMAND_BUFFER: {
+ /* We allow at most one command buffer to be submitted at a time */
+ assert(++cmdbuf_n <= 1);
+ struct vk_command_buffer *cmd_buffer =
+ (struct vk_command_buffer *)base;
+ if (cmd_buffer->labels.size > 0) {
+ cb_data.cmdBufLabelCount = util_dynarray_num_elements(
+ &cmd_buffer->labels, VkDebugUtilsLabelEXT);
+ cb_data.pCmdBufLabels = cmd_buffer->labels.data;
+ }
+ break;
+ }
+
+ case VK_OBJECT_TYPE_QUEUE: {
+ /* We allow at most one queue to be submitted at a time */
+ assert(++queue_n <= 1);
+ struct vk_queue *queue = (struct vk_queue *)base;
+ if (queue->labels.size > 0) {
+ cb_data.queueLabelCount =
+ util_dynarray_num_elements(&queue->labels, VkDebugUtilsLabelEXT);
+ cb_data.pQueueLabels = queue->labels.data;
+ }
+ break;
+ }
+ default:
+ break;
+ }
+
+ object_name_infos[i] = (VkDebugUtilsObjectNameInfoEXT){
+ .sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT,
+ .pNext = NULL,
+ .objectType = base->type,
+ .objectHandle = (uint64_t)(uintptr_t)base,
+ .pObjectName = base->object_name,
+ };
+ }
+ cb_data.objectCount = object_count;
+ cb_data.pObjects = object_name_infos;
+
+ vk_debug_message(instance, severity, types, &cb_data);
+
+ ralloc_free(object_name_infos);
+ }
+
+ /* If VK_EXT_debug_report callbacks also have been set up, forward
+ * the message there as well */
+ if (!list_is_empty(&instance->debug_report.callbacks)) {
+ VkDebugReportFlagsEXT flags = 0;
+
+ switch (severity) {
+ case VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT:
+ flags |= VK_DEBUG_REPORT_DEBUG_BIT_EXT;
+ break;
+ case VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT:
+ flags |= VK_DEBUG_REPORT_INFORMATION_BIT_EXT;
+ break;
+ case VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT:
+ if (types & VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT)
+ flags |= VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT;
+ else
+ flags |= VK_DEBUG_REPORT_WARNING_BIT_EXT;
+ break;
+ case VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT:
+ flags |= VK_DEBUG_REPORT_ERROR_BIT_EXT;
+ break;
+ default:
+ unreachable("Invalid debug message severity");
+ break;
+ }
+
+ /* VK_EXT_debug_report-provided callback accepts only one object
+ * related to the message. Since they are given to us in
+ * decreasing order of importance, we're forwarding the first
+ * one.
+ */
+ vk_debug_report(instance, flags, object_count ? objects[0] : NULL, 0,
+ 0, message_idname, message);
+ }
+
+ ralloc_free(message);
+ ralloc_free(message_idname);
+}
+
+static struct vk_object_base *
+vk_object_for_error(struct vk_object_base *obj, VkResult error)
+{
+ if (obj == NULL)
+ return NULL;
+
+ switch (error) {
+ case VK_ERROR_OUT_OF_HOST_MEMORY:
+ case VK_ERROR_LAYER_NOT_PRESENT:
+ case VK_ERROR_EXTENSION_NOT_PRESENT:
+ case VK_ERROR_UNKNOWN:
+ return &vk_object_to_instance(obj)->base;
+ case VK_ERROR_FEATURE_NOT_PRESENT:
+ return &vk_object_to_physical_device(obj)->base;
+ case VK_ERROR_OUT_OF_DEVICE_MEMORY:
+ case VK_ERROR_MEMORY_MAP_FAILED:
+ case VK_ERROR_TOO_MANY_OBJECTS:
+ return &vk_object_to_device(obj)->base;
+ default:
+ return obj;
+ }
+}
+
+VkResult
+__vk_errorv(const void *_obj, VkResult error,
+ const char *file, int line,
+ const char *format, va_list va)
+{
+ struct vk_object_base *object = (struct vk_object_base *)_obj;
+ struct vk_instance *instance = vk_object_to_instance(object);
+ object = vk_object_for_error(object, error);
+
+ /* If object->client_visible isn't set then the object hasn't been fully
+ * constructed and we shouldn't hand it back to the client. This typically
+ * happens if an error is thrown during object construction. This is safe
+ * to do as long as vk_object_base_init() has already been called.
+ */
+ if (object && !object->client_visible)
+ object = NULL;
+
+ const char *error_str = vk_Result_to_str(error);
+
+ if (format) {
+ char *message = ralloc_vasprintf(NULL, format, va);
+
+ if (object) {
+ __vk_log(VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT,
+ VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT,
+ VK_LOG_OBJS(object), file, line,
+ "%s (%s)", message, error_str);
+ } else {
+ __vk_log(VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT,
+ VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT,
+ VK_LOG_NO_OBJS(instance), file, line,
+ "%s (%s)", message, error_str);
+ }
+
+ ralloc_free(message);
+ } else {
+ if (object) {
+ __vk_log(VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT,
+ VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT,
+ VK_LOG_OBJS(object), file, line,
+ "%s", error_str);
+ } else {
+ __vk_log(VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT,
+ VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT,
+ VK_LOG_NO_OBJS(instance), file, line,
+ "%s", error_str);
+ }
+ }
+
+ return error;
+}
+
+VkResult
+__vk_errorf(const void *_obj, VkResult error,
+ const char *file, int line,
+ const char *format, ...)
+{
+ va_list va;
+
+ va_start(va, format);
+ VkResult result = __vk_errorv(_obj, error, file, line, format, va);
+ va_end(va);
+
+ return result;
+}
diff --git a/lib/mesa/src/vulkan/util/vk_log.h b/lib/mesa/src/vulkan/util/vk_log.h
new file mode 100644
index 000000000..3f6a127e4
--- /dev/null
+++ b/lib/mesa/src/vulkan/util/vk_log.h
@@ -0,0 +1,89 @@
+/*
+ * 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"
+
+/* __VK_ARG_N(...) returns the number of arguments provided to it */
+#define __VK_ARG_SEQ(_1,_2,_3,_4,_5,_6,_7,_8,N,...) N
+#define __VK_ARG_N(...) __VK_ARG_SEQ(__VA_ARGS__,8,7,6,5,4,3,2,1,0)
+
+#define VK_LOG_OBJS(...) \
+ __VK_ARG_N(__VA_ARGS__), (const void*[]){__VA_ARGS__}
+
+#define VK_LOG_NO_OBJS(instance) 0, (const void**)instance
+
+#define vk_logd(objects_macro, format, ...) \
+ __vk_log(VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT, \
+ VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT, \
+ objects_macro, __FILE__, __LINE__, format, ## __VA_ARGS__)
+
+#define vk_logi(objects_macro, format, ...) \
+ __vk_log(VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT, \
+ VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT, \
+ objects_macro, __FILE__, __LINE__, format, ## __VA_ARGS__)
+
+#define vk_logw(objects_macro, format, ...) \
+ __vk_log(VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT, \
+ VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT, \
+ objects_macro, __FILE__, __LINE__, format, ## __VA_ARGS__)
+
+#define vk_loge(objects_macro, format, ...) \
+ __vk_log(VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT, \
+ VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT, \
+ objects_macro, __FILE__, __LINE__, format, ## __VA_ARGS__)
+
+#define vk_perf(objects_macro, format, ...) \
+ __vk_log(VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT, \
+ VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT, \
+ objects_macro, __FILE__, __LINE__, format, ## __VA_ARGS__)
+
+#define __vk_log(severity, type, object_count, \
+ objects_or_instance, file, line, format, ...) \
+ __vk_log_impl(severity, type, object_count, objects_or_instance, \
+ file, line, format, ## __VA_ARGS__)
+
+void PRINTFLIKE(7, 8)
+__vk_log_impl(VkDebugUtilsMessageSeverityFlagBitsEXT severity,
+ VkDebugUtilsMessageTypeFlagsEXT types,
+ int object_count,
+ const void **objects_or_instance,
+ const char *file,
+ int line,
+ const char *format,
+ ...);
+
+#define vk_error(obj, error) \
+ __vk_errorf(obj, error, __FILE__, __LINE__, NULL)
+
+#define vk_errorf(obj, error, ...) \
+ __vk_errorf(obj, error, __FILE__, __LINE__, __VA_ARGS__)
+
+VkResult
+__vk_errorv(const void *_obj, VkResult error,
+ const char *file, int line,
+ const char *format, va_list va);
+
+VkResult PRINTFLIKE(5, 6)
+__vk_errorf(const void *_obj, VkResult error,
+ const char *file, int line,
+ const char *format, ...);
diff --git a/lib/mesa/src/vulkan/util/vk_object.c b/lib/mesa/src/vulkan/util/vk_object.c
index af2c72ba9..52dbeaedd 100644
--- a/lib/mesa/src/vulkan/util/vk_object.c
+++ b/lib/mesa/src/vulkan/util/vk_object.c
@@ -28,35 +28,28 @@
#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);
-}
+#include "vk_enum_to_str.h"
void
vk_object_base_init(struct vk_device *device,
struct vk_object_base *base,
UNUSED VkObjectType obj_type)
{
- vk_object_base_reinit(base);
+ base->_loader_data.loaderMagic = ICD_LOADER_MAGIC;
base->type = obj_type;
base->device = device;
+ base->client_visible = false;
+ base->object_name = NULL;
+ util_sparse_array_init(&base->private_data, sizeof(uint64_t), 8);
}
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);
+ if (base->object_name != NULL)
+ vk_free(&base->device->alloc, base->object_name);
}
void *
@@ -113,12 +106,11 @@ vk_object_multizalloc(struct vk_device *device,
const VkAllocationCallbacks *alloc,
VkObjectType obj_type)
{
- void *ptr = vk_multialloc_alloc2(ma, &device->alloc, alloc,
- VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
+ void *ptr = vk_multialloc_zalloc2(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;
@@ -323,3 +315,18 @@ vk_common_GetPrivateDataEXT(VkDevice _device,
objectType, objectHandle,
privateDataSlot, pData);
}
+
+const char *
+vk_object_base_name(struct vk_object_base *obj)
+{
+ if (obj->object_name)
+ return obj->object_name;
+
+ obj->object_name = vk_asprintf(&obj->device->alloc,
+ VK_SYSTEM_ALLOCATION_SCOPE_DEVICE,
+ "%s(0x%"PRIx64")",
+ vk_ObjectType_to_ObjectName(obj->type),
+ (uint64_t)(uintptr_t)obj);
+
+ return obj->object_name;
+}
diff --git a/lib/mesa/src/vulkan/util/vk_object.h b/lib/mesa/src/vulkan/util/vk_object.h
index c9c751ae2..5b968d90f 100644
--- a/lib/mesa/src/vulkan/util/vk_object.h
+++ b/lib/mesa/src/vulkan/util/vk_object.h
@@ -44,15 +44,20 @@ struct vk_object_base {
struct vk_device *device;
+ /* True if this object is fully constructed and visible to the client */
+ bool client_visible;
+
/* For VK_EXT_private_data */
struct util_sparse_array private_data;
+
+ /* VK_EXT_debug_utils */
+ char *object_name;
};
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,
@@ -83,6 +88,8 @@ vk_object_base_from_u64_handle(uint64_t handle, VkObjectType obj_type)
__driver_type ## _to_handle(struct __driver_type *_obj) \
{ \
vk_object_base_assert_valid(&_obj->__base, __VK_TYPE); \
+ if (_obj != NULL) \
+ _obj->__base.client_visible = true; \
return (__VkType) _obj; \
}
@@ -101,6 +108,8 @@ vk_object_base_from_u64_handle(uint64_t handle, VkObjectType obj_type)
__driver_type ## _to_handle(struct __driver_type *_obj) \
{ \
vk_object_base_assert_valid(&_obj->__base, __VK_TYPE); \
+ if (_obj != NULL) \
+ _obj->__base.client_visible = true; \
return (__VkType)(uintptr_t) _obj; \
}
@@ -170,6 +179,9 @@ vk_object_base_get_private_data(struct vk_device *device,
VkPrivateDataSlotEXT privateDataSlot,
uint64_t *pData);
+const char *
+vk_object_base_name(struct vk_object_base *obj);
+
#ifdef __cplusplus
}
#endif
diff --git a/lib/mesa/src/vulkan/util/vk_physical_device.c b/lib/mesa/src/vulkan/util/vk_physical_device.c
index 18cab2e87..e6504c88e 100644
--- a/lib/mesa/src/vulkan/util/vk_physical_device.c
+++ b/lib/mesa/src/vulkan/util/vk_physical_device.c
@@ -139,7 +139,21 @@ vk_common_GetPhysicalDeviceMemoryProperties(VkPhysicalDevice physicalDevice,
pdevice->dispatch_table.GetPhysicalDeviceMemoryProperties2(physicalDevice,
&props2);
- *pMemoryProperties = props2.memoryProperties;
+ /* dEQP-VK.api.info.get_physical_device_properties2.memory_properties memsets
+ * the struct to 0xcd and expects that the unused array elements are
+ * untouched.
+ */
+ pMemoryProperties->memoryHeapCount = props2.memoryProperties.memoryHeapCount;
+ for (int i = 0; i < pMemoryProperties->memoryHeapCount; i++) {
+ pMemoryProperties->memoryHeaps[i].flags = props2.memoryProperties.memoryHeaps[i].flags;
+ pMemoryProperties->memoryHeaps[i].size = props2.memoryProperties.memoryHeaps[i].size;
+ }
+
+ pMemoryProperties->memoryTypeCount = props2.memoryProperties.memoryTypeCount;
+ for (int i = 0; i < pMemoryProperties->memoryTypeCount; i++) {
+ pMemoryProperties->memoryTypes[i].heapIndex = props2.memoryProperties.memoryTypes[i].heapIndex;
+ pMemoryProperties->memoryTypes[i].propertyFlags = props2.memoryProperties.memoryTypes[i].propertyFlags;
+ }
}
VKAPI_ATTR void VKAPI_CALL
@@ -191,3 +205,50 @@ vk_common_GetPhysicalDeviceImageFormatProperties(VkPhysicalDevice physicalDevice
return result;
}
+
+VKAPI_ATTR void VKAPI_CALL
+vk_common_GetPhysicalDeviceSparseImageFormatProperties(VkPhysicalDevice physicalDevice,
+ VkFormat format,
+ VkImageType type,
+ uint32_t samples,
+ VkImageUsageFlags usage,
+ VkImageTiling tiling,
+ uint32_t *pNumProperties,
+ VkSparseImageFormatProperties *pProperties)
+{
+ VK_FROM_HANDLE(vk_physical_device, pdevice, physicalDevice);
+
+ VkPhysicalDeviceSparseImageFormatInfo2 info = {
+ .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SPARSE_IMAGE_FORMAT_INFO_2,
+ .format = format,
+ .type = type,
+ .samples = samples,
+ .usage = usage,
+ .tiling = tiling
+ };
+
+ if (!pProperties) {
+ pdevice->dispatch_table.GetPhysicalDeviceSparseImageFormatProperties2(physicalDevice,
+ &info,
+ pNumProperties,
+ NULL);
+ return;
+ }
+
+ STACK_ARRAY(VkSparseImageFormatProperties2, props2, *pNumProperties);
+
+ for (unsigned i = 0; i < *pNumProperties; ++i) {
+ props2[i].sType = VK_STRUCTURE_TYPE_SPARSE_IMAGE_FORMAT_PROPERTIES_2;
+ props2[i].pNext = NULL;
+ }
+
+ pdevice->dispatch_table.GetPhysicalDeviceSparseImageFormatProperties2(physicalDevice,
+ &info,
+ pNumProperties,
+ props2);
+
+ for (unsigned i = 0; i < *pNumProperties; ++i)
+ pProperties[i] = props2[i].properties;
+
+ STACK_ARRAY_FINISH(props2);
+}
diff --git a/lib/mesa/src/vulkan/util/vk_physical_device.h b/lib/mesa/src/vulkan/util/vk_physical_device.h
index fea39ae9d..e66d86882 100644
--- a/lib/mesa/src/vulkan/util/vk_physical_device.h
+++ b/lib/mesa/src/vulkan/util/vk_physical_device.h
@@ -31,6 +31,8 @@
extern "C" {
#endif
+struct wsi_device;
+
struct vk_physical_device {
struct vk_object_base base;
struct vk_instance *instance;
@@ -38,6 +40,8 @@ struct vk_physical_device {
struct vk_device_extension_table supported_extensions;
struct vk_physical_device_dispatch_table dispatch_table;
+
+ struct wsi_device *wsi_device;
};
VK_DEFINE_HANDLE_CASTS(vk_physical_device, base, VkPhysicalDevice,
@@ -52,6 +56,10 @@ vk_physical_device_init(struct vk_physical_device *physical_device,
void
vk_physical_device_finish(struct vk_physical_device *physical_device);
+VkResult
+vk_physical_device_check_device_features(struct vk_physical_device *physical_device,
+ const VkDeviceCreateInfo *pCreateInfo);
+
#ifdef __cplusplus
}
#endif
diff --git a/lib/mesa/src/vulkan/util/vk_physical_device_features.py b/lib/mesa/src/vulkan/util/vk_physical_device_features.py
new file mode 100644
index 000000000..b9665e564
--- /dev/null
+++ b/lib/mesa/src/vulkan/util/vk_physical_device_features.py
@@ -0,0 +1,250 @@
+# coding=utf-8
+COPYRIGHT=u"""
+/* 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.
+ */
+"""
+
+import argparse
+import os
+from collections import OrderedDict, namedtuple
+import xml.etree.ElementTree as et
+
+from mako.template import Template
+
+TEMPLATE_C = Template(COPYRIGHT + """
+/* This file generated from ${filename}, don't edit directly. */
+
+#include "vk_log.h"
+#include "vk_physical_device.h"
+#include "vk_util.h"
+
+static VkResult
+check_physical_device_features(struct vk_physical_device *physical_device,
+ const VkPhysicalDeviceFeatures *supported,
+ const VkPhysicalDeviceFeatures *enabled,
+ const char *struct_name)
+{
+% for flag in pdev_features:
+ if (enabled->${flag} && !supported->${flag})
+ return vk_errorf(physical_device, VK_ERROR_FEATURE_NOT_PRESENT,
+ "%s.%s not supported", struct_name, "${flag}");
+% endfor
+
+ return VK_SUCCESS;
+}
+
+VkResult
+vk_physical_device_check_device_features(struct vk_physical_device *physical_device,
+ const VkDeviceCreateInfo *pCreateInfo)
+{
+ VkPhysicalDevice vk_physical_device =
+ vk_physical_device_to_handle(physical_device);
+
+ /* Query the device what kind of features are supported. */
+ VkPhysicalDeviceFeatures2 supported_features2 = {
+ .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2,
+ };
+
+% for f in features:
+ ${f.name} supported_${f.name} = { .pNext = NULL };
+% endfor
+
+ vk_foreach_struct_const(feat, pCreateInfo->pNext) {
+ VkBaseOutStructure *supported = NULL;
+ switch (feat->sType) {
+% for f in features:
+ case ${f.vk_type}:
+ supported = (VkBaseOutStructure *) &supported_${f.name};
+ break;
+% endfor
+ default:
+ break;
+ }
+
+ /* Not a feature struct. */
+ if (!supported)
+ continue;
+
+ /* Check for cycles in the list */
+ if (supported->pNext != NULL || supported->sType != 0)
+ return VK_ERROR_UNKNOWN;
+
+ supported->sType = feat->sType;
+ __vk_append_struct(&supported_features2, supported);
+ }
+
+ physical_device->dispatch_table.GetPhysicalDeviceFeatures2(
+ vk_physical_device, &supported_features2);
+
+ if (pCreateInfo->pEnabledFeatures) {
+ VkResult result =
+ check_physical_device_features(physical_device,
+ &supported_features2.features,
+ pCreateInfo->pEnabledFeatures,
+ "VkPhysicalDeviceFeatures");
+ if (result != VK_SUCCESS)
+ return result;
+ }
+
+ /* Iterate through additional feature structs */
+ vk_foreach_struct_const(feat, pCreateInfo->pNext) {
+ /* Check each feature boolean for given structure. */
+ switch (feat->sType) {
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2: {
+ const VkPhysicalDeviceFeatures2 *features2 = (const void *)feat;
+ VkResult result =
+ check_physical_device_features(physical_device,
+ &supported_features2.features,
+ &features2->features,
+ "VkPhysicalDeviceFeatures2.features");
+ if (result != VK_SUCCESS)
+ return result;
+ break;
+ }
+% for f in features:
+ case ${f.vk_type} : {
+ ${f.name} *a = &supported_${f.name};
+ ${f.name} *b = (${f.name} *) feat;
+% for flag in f.vk_flags:
+ if (b->${flag} && !a->${flag})
+ return vk_errorf(physical_device, VK_ERROR_FEATURE_NOT_PRESENT,
+ "%s.%s not supported", "${f.name}", "${flag}");
+% endfor
+ break;
+ }
+% endfor
+ default:
+ break;
+ }
+ } // for each extension structure
+ return VK_SUCCESS;
+}
+
+""", output_encoding='utf-8')
+
+Feature = namedtuple('Feature', 'name vk_type vk_flags')
+
+def get_pdev_features(doc):
+ for _type in doc.findall('./types/type'):
+ if _type.attrib.get('name') != 'VkPhysicalDeviceFeatures':
+ continue
+
+ flags = []
+
+ for p in _type.findall('./member'):
+ assert p.find('./type').text == 'VkBool32'
+ flags.append(p.find('./name').text)
+
+ return flags
+
+ return None
+
+def get_features(doc):
+ features = OrderedDict()
+
+ provisional_structs = set()
+
+ # we want to ignore struct types that are part of provisional extensions
+ for _extension in doc.findall('./extensions/extension'):
+ if _extension.attrib.get('provisional') != 'true':
+ continue
+ for p in _extension.findall('./require/type'):
+ provisional_structs.add(p.attrib.get('name'))
+
+ # parse all struct types where structextends VkPhysicalDeviceFeatures2
+ for _type in doc.findall('./types/type'):
+ if _type.attrib.get('category') != 'struct':
+ continue
+ if _type.attrib.get('structextends') != 'VkPhysicalDeviceFeatures2,VkDeviceCreateInfo':
+ continue
+ if _type.attrib.get('name') in provisional_structs:
+ continue
+
+ # find Vulkan structure type
+ for elem in _type:
+ if "STRUCTURE_TYPE" in str(elem.attrib):
+ s_type = elem.attrib.get('values')
+
+ # collect a list of feature flags
+ flags = []
+
+ for p in _type.findall('./member'):
+ m_name = p.find('./name').text
+ if m_name == 'pNext':
+ pass
+ elif m_name == 'sType':
+ s_type = p.attrib.get('values')
+ else:
+ assert p.find('./type').text == 'VkBool32'
+ flags.append(m_name)
+
+ feat = Feature(name=_type.attrib.get('name'), vk_type=s_type, vk_flags=flags)
+ features[_type.attrib.get('name')] = feat
+
+ return features.values()
+
+def get_features_from_xml(xml_files):
+ pdev_features = None
+ features = []
+
+ for filename in xml_files:
+ doc = et.parse(filename)
+ features += get_features(doc)
+ if not pdev_features:
+ pdev_features = get_pdev_features(doc)
+
+ return pdev_features, features
+
+
+def main():
+ parser = argparse.ArgumentParser()
+ parser.add_argument('--out-c', required=True, help='Output C file.')
+ parser.add_argument('--xml',
+ help='Vulkan API XML file.',
+ required=True, action='append', dest='xml_files')
+ args = parser.parse_args()
+
+ pdev_features, features = get_features_from_xml(args.xml_files)
+
+ environment = {
+ 'filename': os.path.basename(__file__),
+ 'pdev_features': pdev_features,
+ 'features': features,
+ }
+
+ try:
+ 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_queue.c b/lib/mesa/src/vulkan/util/vk_queue.c
new file mode 100644
index 000000000..d1c0351ce
--- /dev/null
+++ b/lib/mesa/src/vulkan/util/vk_queue.c
@@ -0,0 +1,56 @@
+/*
+ * 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_queue.h"
+
+#include "vk_device.h"
+
+VkResult
+vk_queue_init(struct vk_queue *queue, struct vk_device *device,
+ const VkDeviceQueueCreateInfo *pCreateInfo,
+ uint32_t index_in_family)
+{
+ memset(queue, 0, sizeof(*queue));
+ vk_object_base_init(device, &queue->base, VK_OBJECT_TYPE_QUEUE);
+
+ list_addtail(&queue->link, &device->queues);
+
+ queue->flags = pCreateInfo->flags;
+ queue->queue_family_index = pCreateInfo->queueFamilyIndex;
+
+ assert(index_in_family < pCreateInfo->queueCount);
+ queue->index_in_family = index_in_family;
+
+ util_dynarray_init(&queue->labels, NULL);
+ queue->region_begin = true;
+
+ return VK_SUCCESS;
+}
+
+void
+vk_queue_finish(struct vk_queue *queue)
+{
+ util_dynarray_fini(&queue->labels);
+ list_del(&queue->link);
+ vk_object_base_finish(&queue->base);
+}
diff --git a/lib/mesa/src/vulkan/util/vk_queue.h b/lib/mesa/src/vulkan/util/vk_queue.h
new file mode 100644
index 000000000..1a63b1f9d
--- /dev/null
+++ b/lib/mesa/src/vulkan/util/vk_queue.h
@@ -0,0 +1,112 @@
+/*
+ * 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_QUEUE_H
+#define VK_QUEUE_H
+
+#include "vk_object.h"
+
+#include "util/list.h"
+#include "util/u_dynarray.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct vk_queue {
+ struct vk_object_base base;
+
+ /* Link in vk_device::queues */
+ struct list_head link;
+
+ /* VkDeviceQueueCreateInfo::flags */
+ VkDeviceQueueCreateFlags flags;
+
+ /* VkDeviceQueueCreateInfo::queueFamilyIndex */
+ uint32_t queue_family_index;
+
+ /* Which queue this is within the queue family */
+ uint32_t index_in_family;
+
+ /**
+ * VK_EXT_debug_utils
+ *
+ * The next two fields represent debug labels storage.
+ *
+ * VK_EXT_debug_utils spec requires that upon triggering a debug message
+ * with a queue attached to it, all "active" labels will also be provided
+ * to the callback. The spec describes two distinct ways of attaching a
+ * debug label to the queue: opening a label region and inserting a single
+ * label.
+ *
+ * Label region is active between the corresponding `*BeginDebugUtilsLabel`
+ * and `*EndDebugUtilsLabel` calls. The spec doesn't mention any limits on
+ * nestedness of label regions. This implementation assumes that there
+ * aren't any.
+ *
+ * The spec, however, doesn't explain the lifetime of a label submitted by
+ * an `*InsertDebugUtilsLabel` call. The LunarG whitepaper [1] (pp 12-15)
+ * provides a more detailed explanation along with some examples. According
+ * to those, such label remains active until the next `*DebugUtilsLabel`
+ * call. This means that there can be no more than one such label at a
+ * time.
+ *
+ * \c labels contains all active labels at this point in order of submission
+ * \c region_begin denotes whether the most recent label opens a new region
+ * If \t labels is empty \t region_begin must be true.
+ *
+ * Anytime we modify labels, we first check for \c region_begin. If it's
+ * false, it means that the most recent label was submitted by
+ * `*InsertDebugUtilsLabel` and we need to remove it before doing anything
+ * else.
+ *
+ * See the discussion here:
+ * https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/10318#note_1061317
+ *
+ * [1] https://www.lunarg.com/wp-content/uploads/2018/05/Vulkan-Debug-Utils_05_18_v1.pdf
+ */
+ struct util_dynarray labels;
+ bool region_begin;
+};
+
+VK_DEFINE_HANDLE_CASTS(vk_queue, base, VkQueue, VK_OBJECT_TYPE_QUEUE)
+
+VkResult MUST_CHECK
+vk_queue_init(struct vk_queue *queue, struct vk_device *device,
+ const VkDeviceQueueCreateInfo *pCreateInfo,
+ uint32_t index_in_family);
+
+void
+vk_queue_finish(struct vk_queue *queue);
+
+#define vk_foreach_queue(queue, device) \
+ list_for_each_entry(struct vk_queue, queue, &(device)->queues, link)
+
+#define vk_foreach_queue_safe(queue, device) \
+ list_for_each_entry_safe(struct vk_queue, queue, &(device)->queues, link)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* VK_QUEUE_H */
diff --git a/lib/mesa/src/vulkan/util/vk_shader_module.h b/lib/mesa/src/vulkan/util/vk_shader_module.h
index d4e64dfc3..8140a49d0 100644
--- a/lib/mesa/src/vulkan/util/vk_shader_module.h
+++ b/lib/mesa/src/vulkan/util/vk_shader_module.h
@@ -46,7 +46,7 @@ VK_DEFINE_NONDISP_HANDLE_CASTS(vk_shader_module, base, VkShaderModule,
/* 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) { \
+ ((VkShaderModule)(uintptr_t)&(struct vk_shader_module) { \
.base.type = VK_OBJECT_TYPE_SHADER_MODULE, \
.nir = _nir, \
})
diff --git a/lib/mesa/src/vulkan/util/vk_synchronization2.c b/lib/mesa/src/vulkan/util/vk_synchronization2.c
new file mode 100644
index 000000000..0ad796c7b
--- /dev/null
+++ b/lib/mesa/src/vulkan/util/vk_synchronization2.c
@@ -0,0 +1,405 @@
+/*
+ * 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_alloc.h"
+#include "vk_command_buffer.h"
+#include "vk_common_entrypoints.h"
+#include "vk_device.h"
+#include "vk_queue.h"
+#include "vk_util.h"
+#include "../wsi/wsi_common.h"
+
+VKAPI_ATTR void VKAPI_CALL
+vk_common_CmdWriteTimestamp(
+ VkCommandBuffer commandBuffer,
+ VkPipelineStageFlagBits pipelineStage,
+ VkQueryPool queryPool,
+ uint32_t query)
+{
+ VK_FROM_HANDLE(vk_command_buffer, cmd_buffer, commandBuffer);
+ struct vk_device *device = cmd_buffer->base.device;
+
+ device->dispatch_table.CmdWriteTimestamp2KHR(commandBuffer,
+ (VkPipelineStageFlags2KHR) pipelineStage,
+ queryPool,
+ query);
+}
+
+static VkMemoryBarrier2KHR
+upgrade_memory_barrier(const VkMemoryBarrier *barrier,
+ VkPipelineStageFlags2KHR src_stage_mask2,
+ VkPipelineStageFlags2KHR dst_stage_mask2)
+{
+ return (VkMemoryBarrier2KHR) {
+ .sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER_2_KHR,
+ .srcStageMask = src_stage_mask2,
+ .srcAccessMask = (VkAccessFlags2KHR) barrier->srcAccessMask,
+ .dstStageMask = dst_stage_mask2,
+ .dstAccessMask = (VkAccessFlags2KHR) barrier->dstAccessMask,
+ };
+}
+
+static VkBufferMemoryBarrier2KHR
+upgrade_buffer_memory_barrier(const VkBufferMemoryBarrier *barrier,
+ VkPipelineStageFlags2KHR src_stage_mask2,
+ VkPipelineStageFlags2KHR dst_stage_mask2)
+{
+ return (VkBufferMemoryBarrier2KHR) {
+ .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER_2_KHR,
+ .srcStageMask = src_stage_mask2,
+ .srcAccessMask = (VkAccessFlags2KHR) barrier->srcAccessMask,
+ .dstStageMask = dst_stage_mask2,
+ .dstAccessMask = (VkAccessFlags2KHR) barrier->dstAccessMask,
+ .srcQueueFamilyIndex = barrier->srcQueueFamilyIndex,
+ .dstQueueFamilyIndex = barrier->dstQueueFamilyIndex,
+ .buffer = barrier->buffer,
+ .offset = barrier->offset,
+ .size = barrier->size,
+ };
+}
+
+static VkImageMemoryBarrier2KHR
+upgrade_image_memory_barrier(const VkImageMemoryBarrier *barrier,
+ VkPipelineStageFlags2KHR src_stage_mask2,
+ VkPipelineStageFlags2KHR dst_stage_mask2)
+{
+ return (VkImageMemoryBarrier2KHR) {
+ .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2_KHR,
+ .srcStageMask = src_stage_mask2,
+ .srcAccessMask = (VkAccessFlags2KHR) barrier->srcAccessMask,
+ .dstStageMask = dst_stage_mask2,
+ .dstAccessMask = (VkAccessFlags2KHR) barrier->dstAccessMask,
+ .oldLayout = barrier->oldLayout,
+ .newLayout = barrier->newLayout,
+ .srcQueueFamilyIndex = barrier->srcQueueFamilyIndex,
+ .dstQueueFamilyIndex = barrier->dstQueueFamilyIndex,
+ .image = barrier->image,
+ .subresourceRange = barrier->subresourceRange,
+ };
+}
+
+VKAPI_ATTR void VKAPI_CALL
+vk_common_CmdPipelineBarrier(
+ VkCommandBuffer commandBuffer,
+ VkPipelineStageFlags srcStageMask,
+ VkPipelineStageFlags dstStageMask,
+ VkDependencyFlags dependencyFlags,
+ uint32_t memoryBarrierCount,
+ const VkMemoryBarrier* pMemoryBarriers,
+ uint32_t bufferMemoryBarrierCount,
+ const VkBufferMemoryBarrier* pBufferMemoryBarriers,
+ uint32_t imageMemoryBarrierCount,
+ const VkImageMemoryBarrier* pImageMemoryBarriers)
+{
+ VK_FROM_HANDLE(vk_command_buffer, cmd_buffer, commandBuffer);
+ struct vk_device *device = cmd_buffer->base.device;
+
+ STACK_ARRAY(VkMemoryBarrier2KHR, memory_barriers, memoryBarrierCount);
+ STACK_ARRAY(VkBufferMemoryBarrier2KHR, buffer_barriers, bufferMemoryBarrierCount);
+ STACK_ARRAY(VkImageMemoryBarrier2KHR, image_barriers, imageMemoryBarrierCount);
+
+ VkPipelineStageFlags2KHR src_stage_mask2 = (VkPipelineStageFlags2KHR) srcStageMask;
+ VkPipelineStageFlags2KHR dst_stage_mask2 = (VkPipelineStageFlags2KHR) dstStageMask;
+
+ for (uint32_t i = 0; i < memoryBarrierCount; i++) {
+ memory_barriers[i] = upgrade_memory_barrier(&pMemoryBarriers[i],
+ src_stage_mask2,
+ dst_stage_mask2);
+ }
+ for (uint32_t i = 0; i < bufferMemoryBarrierCount; i++) {
+ buffer_barriers[i] = upgrade_buffer_memory_barrier(&pBufferMemoryBarriers[i],
+ src_stage_mask2,
+ dst_stage_mask2);
+ }
+ for (uint32_t i = 0; i < imageMemoryBarrierCount; i++) {
+ image_barriers[i] = upgrade_image_memory_barrier(&pImageMemoryBarriers[i],
+ src_stage_mask2,
+ dst_stage_mask2);
+ }
+
+ VkDependencyInfoKHR dep_info = {
+ .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO_KHR,
+ .memoryBarrierCount = memoryBarrierCount,
+ .pMemoryBarriers = memory_barriers,
+ .bufferMemoryBarrierCount = bufferMemoryBarrierCount,
+ .pBufferMemoryBarriers = buffer_barriers,
+ .imageMemoryBarrierCount = imageMemoryBarrierCount,
+ .pImageMemoryBarriers = image_barriers,
+ };
+
+ device->dispatch_table.CmdPipelineBarrier2KHR(commandBuffer, &dep_info);
+
+ STACK_ARRAY_FINISH(memory_barriers);
+ STACK_ARRAY_FINISH(buffer_barriers);
+ STACK_ARRAY_FINISH(image_barriers);
+}
+
+VKAPI_ATTR void VKAPI_CALL
+vk_common_CmdSetEvent(
+ VkCommandBuffer commandBuffer,
+ VkEvent event,
+ VkPipelineStageFlags stageMask)
+{
+ VK_FROM_HANDLE(vk_command_buffer, cmd_buffer, commandBuffer);
+ struct vk_device *device = cmd_buffer->base.device;
+
+ VkMemoryBarrier2KHR mem_barrier = {
+ .sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER_2_KHR,
+ .srcStageMask = (VkPipelineStageFlags2KHR) stageMask,
+ .dstStageMask = (VkPipelineStageFlags2KHR) stageMask,
+ };
+ VkDependencyInfoKHR dep_info = {
+ .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO_KHR,
+ .memoryBarrierCount = 1,
+ .pMemoryBarriers = &mem_barrier,
+ };
+
+ device->dispatch_table.CmdSetEvent2KHR(commandBuffer, event, &dep_info);
+}
+
+VKAPI_ATTR void VKAPI_CALL
+vk_common_CmdResetEvent(
+ VkCommandBuffer commandBuffer,
+ VkEvent event,
+ VkPipelineStageFlags stageMask)
+{
+ VK_FROM_HANDLE(vk_command_buffer, cmd_buffer, commandBuffer);
+ struct vk_device *device = cmd_buffer->base.device;
+
+ device->dispatch_table.CmdResetEvent2KHR(commandBuffer,
+ event,
+ (VkPipelineStageFlags2KHR) stageMask);
+}
+
+VKAPI_ATTR void VKAPI_CALL
+vk_common_CmdWaitEvents(
+ VkCommandBuffer commandBuffer,
+ uint32_t eventCount,
+ const VkEvent* pEvents,
+ VkPipelineStageFlags srcStageMask,
+ VkPipelineStageFlags destStageMask,
+ uint32_t memoryBarrierCount,
+ const VkMemoryBarrier* pMemoryBarriers,
+ uint32_t bufferMemoryBarrierCount,
+ const VkBufferMemoryBarrier* pBufferMemoryBarriers,
+ uint32_t imageMemoryBarrierCount,
+ const VkImageMemoryBarrier* pImageMemoryBarriers)
+{
+ VK_FROM_HANDLE(vk_command_buffer, cmd_buffer, commandBuffer);
+ struct vk_device *device = cmd_buffer->base.device;
+
+ STACK_ARRAY(VkDependencyInfoKHR, deps, eventCount);
+
+ /* Note that dstStageMask and srcStageMask in the CmdWaitEvent2() call
+ * are the same. This is to match the CmdSetEvent2() call from
+ * vk_common_CmdSetEvent(). The actual src->dst stage barrier will
+ * happen as part of the CmdPipelineBarrier() call below.
+ */
+ VkMemoryBarrier2KHR stage_barrier = {
+ .sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER_2_KHR,
+ .srcStageMask = srcStageMask,
+ .dstStageMask = srcStageMask,
+ };
+
+ for (uint32_t i = 0; i < eventCount; i++) {
+ deps[i] = (VkDependencyInfoKHR) {
+ .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO_KHR,
+ .memoryBarrierCount = 1,
+ .pMemoryBarriers = &stage_barrier,
+ };
+ }
+ device->dispatch_table.CmdWaitEvents2KHR(commandBuffer, eventCount, pEvents, deps);
+
+ STACK_ARRAY_FINISH(deps);
+
+ /* Setting dependency to 0 because :
+ *
+ * - For BY_REGION_BIT and VIEW_LOCAL_BIT, events are not allowed inside a
+ * render pass so these don't apply.
+ *
+ * - For DEVICE_GROUP_BIT, we have the following bit of spec text:
+ *
+ * "Semaphore and event dependencies are device-local and only
+ * execute on the one physical device that performs the
+ * dependency."
+ */
+ const VkDependencyFlags dep_flags = 0;
+
+ device->dispatch_table.CmdPipelineBarrier(commandBuffer,
+ srcStageMask, destStageMask,
+ dep_flags,
+ memoryBarrierCount, pMemoryBarriers,
+ bufferMemoryBarrierCount, pBufferMemoryBarriers,
+ imageMemoryBarrierCount, pImageMemoryBarriers);
+}
+
+VKAPI_ATTR void VKAPI_CALL
+vk_common_CmdWriteBufferMarkerAMD(
+ VkCommandBuffer commandBuffer,
+ VkPipelineStageFlagBits pipelineStage,
+ VkBuffer dstBuffer,
+ VkDeviceSize dstOffset,
+ uint32_t marker)
+{
+ VK_FROM_HANDLE(vk_command_buffer, cmd_buffer, commandBuffer);
+ struct vk_device *device = cmd_buffer->base.device;
+
+ device->dispatch_table.CmdWriteBufferMarker2AMD(commandBuffer,
+ (VkPipelineStageFlags2KHR) pipelineStage,
+ dstBuffer,
+ dstOffset,
+ marker);
+}
+
+VKAPI_ATTR void VKAPI_CALL
+vk_common_GetQueueCheckpointDataNV(
+ VkQueue queue,
+ uint32_t* pCheckpointDataCount,
+ VkCheckpointDataNV* pCheckpointData)
+{
+ unreachable("Entrypoint not implemented");
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL
+vk_common_QueueSubmit(
+ VkQueue _queue,
+ uint32_t submitCount,
+ const VkSubmitInfo* pSubmits,
+ VkFence fence)
+{
+ VK_FROM_HANDLE(vk_queue, queue, _queue);
+ struct vk_device *device = queue->base.device;
+
+ STACK_ARRAY(VkSubmitInfo2KHR, submit_info_2, submitCount);
+ STACK_ARRAY(VkPerformanceQuerySubmitInfoKHR, perf_query_submit_info, submitCount);
+ STACK_ARRAY(struct wsi_memory_signal_submit_info, wsi_mem_submit_info, submitCount);
+
+ uint32_t n_wait_semaphores = 0;
+ uint32_t n_command_buffers = 0;
+ uint32_t n_signal_semaphores = 0;
+ for (uint32_t s = 0; s < submitCount; s++) {
+ n_wait_semaphores += pSubmits[s].waitSemaphoreCount;
+ n_command_buffers += pSubmits[s].commandBufferCount;
+ n_signal_semaphores += pSubmits[s].signalSemaphoreCount;
+ }
+
+ STACK_ARRAY(VkSemaphoreSubmitInfoKHR, wait_semaphores, n_wait_semaphores);
+ STACK_ARRAY(VkCommandBufferSubmitInfoKHR, command_buffers, n_command_buffers);
+ STACK_ARRAY(VkSemaphoreSubmitInfoKHR, signal_semaphores, n_signal_semaphores);
+
+ n_wait_semaphores = 0;
+ n_command_buffers = 0;
+ n_signal_semaphores = 0;
+
+ for (uint32_t s = 0; s < submitCount; s++) {
+ const VkTimelineSemaphoreSubmitInfoKHR *timeline_info =
+ vk_find_struct_const(pSubmits[s].pNext,
+ TIMELINE_SEMAPHORE_SUBMIT_INFO_KHR);
+ const uint64_t *wait_values =
+ timeline_info && timeline_info->waitSemaphoreValueCount ?
+ timeline_info->pWaitSemaphoreValues : NULL;
+ const uint64_t *signal_values =
+ timeline_info && timeline_info->signalSemaphoreValueCount ?
+ timeline_info->pSignalSemaphoreValues : NULL;
+
+ const VkDeviceGroupSubmitInfo *group_info =
+ vk_find_struct_const(pSubmits[s].pNext, DEVICE_GROUP_SUBMIT_INFO);
+
+ for (uint32_t i = 0; i < pSubmits[s].waitSemaphoreCount; i++) {
+ wait_semaphores[n_wait_semaphores + i] = (VkSemaphoreSubmitInfoKHR) {
+ .sType = VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO_KHR,
+ .semaphore = pSubmits[s].pWaitSemaphores[i],
+ .value = wait_values ? wait_values[i] : 0,
+ .stageMask = pSubmits[s].pWaitDstStageMask[i],
+ .deviceIndex = group_info ? group_info->pWaitSemaphoreDeviceIndices[i] : 0,
+ };
+ }
+ for (uint32_t i = 0; i < pSubmits[s].commandBufferCount; i++) {
+ command_buffers[n_command_buffers + i] = (VkCommandBufferSubmitInfoKHR) {
+ .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_SUBMIT_INFO_KHR,
+ .commandBuffer = pSubmits[s].pCommandBuffers[i],
+ .deviceMask = group_info ? group_info->pCommandBufferDeviceMasks[i] : 0,
+ };
+ }
+ for (uint32_t i = 0; i < pSubmits[s].signalSemaphoreCount; i++) {
+ signal_semaphores[n_signal_semaphores + i] = (VkSemaphoreSubmitInfoKHR) {
+ .sType = VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO_KHR,
+ .semaphore = pSubmits[s].pSignalSemaphores[i],
+ .value = signal_values ? signal_values[i] : 0,
+ .stageMask = 0,
+ .deviceIndex = group_info ? group_info->pSignalSemaphoreDeviceIndices[i] : 0,
+ };
+ }
+
+ const VkProtectedSubmitInfo *protected_info =
+ vk_find_struct_const(pSubmits[s].pNext, PROTECTED_SUBMIT_INFO);
+
+ submit_info_2[s] = (VkSubmitInfo2KHR) {
+ .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO_2_KHR,
+ .flags = ((protected_info && protected_info->protectedSubmit) ?
+ VK_SUBMIT_PROTECTED_BIT_KHR : 0),
+ .waitSemaphoreInfoCount = pSubmits[s].waitSemaphoreCount,
+ .pWaitSemaphoreInfos = &wait_semaphores[n_wait_semaphores],
+ .commandBufferInfoCount = pSubmits[s].commandBufferCount,
+ .pCommandBufferInfos = &command_buffers[n_command_buffers],
+ .signalSemaphoreInfoCount = pSubmits[s].signalSemaphoreCount,
+ .pSignalSemaphoreInfos = &signal_semaphores[n_signal_semaphores],
+ };
+
+ const VkPerformanceQuerySubmitInfoKHR *query_info =
+ vk_find_struct_const(pSubmits[s].pNext,
+ PERFORMANCE_QUERY_SUBMIT_INFO_KHR);
+ if (query_info) {
+ perf_query_submit_info[s] = *query_info;
+ perf_query_submit_info[s].pNext = NULL;
+ __vk_append_struct(&submit_info_2[s], &perf_query_submit_info[s]);
+ }
+
+ const struct wsi_memory_signal_submit_info *mem_signal_info =
+ vk_find_struct_const(pSubmits[s].pNext,
+ WSI_MEMORY_SIGNAL_SUBMIT_INFO_MESA);
+ if (mem_signal_info) {
+ wsi_mem_submit_info[s] = *mem_signal_info;
+ wsi_mem_submit_info[s].pNext = NULL;
+ __vk_append_struct(&submit_info_2[s], &wsi_mem_submit_info[s]);
+ }
+
+ n_wait_semaphores += pSubmits[s].waitSemaphoreCount;
+ n_command_buffers += pSubmits[s].commandBufferCount;
+ n_signal_semaphores += pSubmits[s].signalSemaphoreCount;
+ }
+
+ VkResult result = device->dispatch_table.QueueSubmit2KHR(_queue,
+ submitCount,
+ submit_info_2,
+ fence);
+
+ STACK_ARRAY_FINISH(wait_semaphores);
+ STACK_ARRAY_FINISH(command_buffers);
+ STACK_ARRAY_FINISH(signal_semaphores);
+ STACK_ARRAY_FINISH(submit_info_2);
+ STACK_ARRAY_FINISH(perf_query_submit_info);
+ STACK_ARRAY_FINISH(wsi_mem_submit_info);
+
+ return result;
+}
diff --git a/lib/mesa/src/vulkan/wsi/meson.build b/lib/mesa/src/vulkan/wsi/meson.build
index 1deafa0c5..d2a823a70 100644
--- a/lib/mesa/src/vulkan/wsi/meson.build
+++ b/lib/mesa/src/vulkan/wsi/meson.build
@@ -31,8 +31,6 @@ endif
if with_platform_wayland
files_vulkan_wsi += files('wsi_common_wayland.c')
files_vulkan_wsi += [
- wayland_drm_client_protocol_h,
- wayland_drm_protocol_c,
linux_dmabuf_unstable_v1_client_protocol_h,
linux_dmabuf_unstable_v1_protocol_c,
]
@@ -46,12 +44,46 @@ if system_has_kms_drm and not with_platform_android
files_vulkan_wsi += files('wsi_common_display.c')
endif
+wsi_entrypoints = custom_target(
+ 'wsi_entrypoints',
+ input : [vk_entrypoints_gen, vk_api_xml],
+ output : ['wsi_common_entrypoints.h', 'wsi_common_entrypoints.c'],
+ command : [
+ prog_python, '@INPUT0@', '--xml', '@INPUT1@', '--proto', '--weak',
+ '--out-h', '@OUTPUT0@', '--out-c', '@OUTPUT1@', '--prefix', 'wsi',
+ ],
+ depend_files : vk_entrypoints_gen_depend_files,
+)
+
libvulkan_wsi = static_library(
'vulkan_wsi',
- files_vulkan_wsi,
+ [files_vulkan_wsi, wsi_entrypoints],
include_directories : [inc_include, inc_src],
- dependencies : [vulkan_wsi_deps, dep_libdrm, idep_vulkan_util, idep_xmlconfig],
+ dependencies : [
+ vulkan_wsi_deps, dep_libdrm, idep_vulkan_util_headers, idep_xmlconfig,
+ ],
c_args : [vulkan_wsi_args],
gnu_symbol_visibility : 'hidden',
build_by_default : false,
)
+
+idep_vulkan_wsi_headers = declare_dependency(
+ include_directories : include_directories('.')
+)
+
+# 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_wsi = declare_dependency(
+ link_with : libvulkan_wsi,
+ dependencies : idep_vulkan_wsi_headers
+ )
+else
+ idep_vulkan_wsi = declare_dependency(
+ # Instruct users of this library to link with --whole-archive. Otherwise,
+ # our weak function overloads may not resolve properly.
+ link_whole : libvulkan_wsi,
+ dependencies : idep_vulkan_wsi_headers
+ )
+endif
diff --git a/lib/mesa/src/vulkan/wsi/wsi_common.c b/lib/mesa/src/vulkan/wsi/wsi_common.c
index b1360edb9..8df55f5f9 100644
--- a/lib/mesa/src/vulkan/wsi/wsi_common.c
+++ b/lib/mesa/src/vulkan/wsi/wsi_common.c
@@ -22,10 +22,15 @@
*/
#include "wsi_common_private.h"
+#include "wsi_common_entrypoints.h"
#include "util/macros.h"
#include "util/os_file.h"
#include "util/os_time.h"
#include "util/xmlconfig.h"
+#include "vk_device.h"
+#include "vk_instance.h"
+#include "vk_physical_device.h"
+#include "vk_queue.h"
#include "vk_util.h"
#include <time.h>
@@ -184,6 +189,20 @@ wsi_device_finish(struct wsi_device *wsi,
#endif
}
+VKAPI_ATTR void VKAPI_CALL
+wsi_DestroySurfaceKHR(VkInstance _instance,
+ VkSurfaceKHR _surface,
+ const VkAllocationCallbacks *pAllocator)
+{
+ VK_FROM_HANDLE(vk_instance, instance, _instance);
+ ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, _surface);
+
+ if (!surface)
+ return;
+
+ vk_free2(&instance->alloc, pAllocator, surface);
+}
+
VkResult
wsi_swapchain_init(const struct wsi_device *wsi,
struct wsi_swapchain *chain,
@@ -320,25 +339,30 @@ wsi_destroy_image(const struct wsi_swapchain *chain,
wsi->DestroyBuffer(chain->device, image->prime.buffer, &chain->alloc);
}
-VkResult
-wsi_common_get_surface_support(struct wsi_device *wsi_device,
- uint32_t queueFamilyIndex,
- VkSurfaceKHR _surface,
- VkBool32* pSupported)
+VKAPI_ATTR VkResult VKAPI_CALL
+wsi_GetPhysicalDeviceSurfaceSupportKHR(VkPhysicalDevice physicalDevice,
+ uint32_t queueFamilyIndex,
+ VkSurfaceKHR _surface,
+ VkBool32 *pSupported)
{
+ VK_FROM_HANDLE(vk_physical_device, device, physicalDevice);
ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, _surface);
+ struct wsi_device *wsi_device = device->wsi_device;
struct wsi_interface *iface = wsi_device->wsi[surface->platform];
return iface->get_support(surface, wsi_device,
queueFamilyIndex, pSupported);
}
-VkResult
-wsi_common_get_surface_capabilities(struct wsi_device *wsi_device,
- VkSurfaceKHR _surface,
- VkSurfaceCapabilitiesKHR *pSurfaceCapabilities)
+VKAPI_ATTR VkResult VKAPI_CALL
+wsi_GetPhysicalDeviceSurfaceCapabilitiesKHR(
+ VkPhysicalDevice physicalDevice,
+ VkSurfaceKHR _surface,
+ VkSurfaceCapabilitiesKHR *pSurfaceCapabilities)
{
+ VK_FROM_HANDLE(vk_physical_device, device, physicalDevice);
ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, _surface);
+ struct wsi_device *wsi_device = device->wsi_device;
struct wsi_interface *iface = wsi_device->wsi[surface->platform];
VkSurfaceCapabilities2KHR caps2 = {
@@ -353,25 +377,30 @@ wsi_common_get_surface_capabilities(struct wsi_device *wsi_device,
return result;
}
-VkResult
-wsi_common_get_surface_capabilities2(struct wsi_device *wsi_device,
- const VkPhysicalDeviceSurfaceInfo2KHR *pSurfaceInfo,
- VkSurfaceCapabilities2KHR *pSurfaceCapabilities)
+VKAPI_ATTR VkResult VKAPI_CALL
+wsi_GetPhysicalDeviceSurfaceCapabilities2KHR(
+ VkPhysicalDevice physicalDevice,
+ const VkPhysicalDeviceSurfaceInfo2KHR *pSurfaceInfo,
+ VkSurfaceCapabilities2KHR *pSurfaceCapabilities)
{
+ VK_FROM_HANDLE(vk_physical_device, device, physicalDevice);
ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, pSurfaceInfo->surface);
+ struct wsi_device *wsi_device = device->wsi_device;
struct wsi_interface *iface = wsi_device->wsi[surface->platform];
return iface->get_capabilities2(surface, wsi_device, pSurfaceInfo->pNext,
pSurfaceCapabilities);
}
-VkResult
-wsi_common_get_surface_capabilities2ext(
- struct wsi_device *wsi_device,
+VKAPI_ATTR VkResult VKAPI_CALL
+wsi_GetPhysicalDeviceSurfaceCapabilities2EXT(
+ VkPhysicalDevice physicalDevice,
VkSurfaceKHR _surface,
VkSurfaceCapabilities2EXT *pSurfaceCapabilities)
{
+ VK_FROM_HANDLE(vk_physical_device, device, physicalDevice);
ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, _surface);
+ struct wsi_device *wsi_device = device->wsi_device;
struct wsi_interface *iface = wsi_device->wsi[surface->platform];
assert(pSurfaceCapabilities->sType ==
@@ -410,81 +439,96 @@ wsi_common_get_surface_capabilities2ext(
return result;
}
-VkResult
-wsi_common_get_surface_formats(struct wsi_device *wsi_device,
- VkSurfaceKHR _surface,
- uint32_t *pSurfaceFormatCount,
- VkSurfaceFormatKHR *pSurfaceFormats)
+VKAPI_ATTR VkResult VKAPI_CALL
+wsi_GetPhysicalDeviceSurfaceFormatsKHR(VkPhysicalDevice physicalDevice,
+ VkSurfaceKHR _surface,
+ uint32_t *pSurfaceFormatCount,
+ VkSurfaceFormatKHR *pSurfaceFormats)
{
+ VK_FROM_HANDLE(vk_physical_device, device, physicalDevice);
ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, _surface);
+ struct wsi_device *wsi_device = device->wsi_device;
struct wsi_interface *iface = wsi_device->wsi[surface->platform];
return iface->get_formats(surface, wsi_device,
pSurfaceFormatCount, pSurfaceFormats);
}
-VkResult
-wsi_common_get_surface_formats2(struct wsi_device *wsi_device,
- const VkPhysicalDeviceSurfaceInfo2KHR *pSurfaceInfo,
- uint32_t *pSurfaceFormatCount,
- VkSurfaceFormat2KHR *pSurfaceFormats)
+VKAPI_ATTR VkResult VKAPI_CALL
+wsi_GetPhysicalDeviceSurfaceFormats2KHR(VkPhysicalDevice physicalDevice,
+ const VkPhysicalDeviceSurfaceInfo2KHR * pSurfaceInfo,
+ uint32_t *pSurfaceFormatCount,
+ VkSurfaceFormat2KHR *pSurfaceFormats)
{
+ VK_FROM_HANDLE(vk_physical_device, device, physicalDevice);
ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, pSurfaceInfo->surface);
+ struct wsi_device *wsi_device = device->wsi_device;
struct wsi_interface *iface = wsi_device->wsi[surface->platform];
return iface->get_formats2(surface, wsi_device, pSurfaceInfo->pNext,
pSurfaceFormatCount, pSurfaceFormats);
}
-VkResult
-wsi_common_get_surface_present_modes(struct wsi_device *wsi_device,
- VkSurfaceKHR _surface,
- uint32_t *pPresentModeCount,
- VkPresentModeKHR *pPresentModes)
+VKAPI_ATTR VkResult VKAPI_CALL
+wsi_GetPhysicalDeviceSurfacePresentModesKHR(VkPhysicalDevice physicalDevice,
+ VkSurfaceKHR _surface,
+ uint32_t *pPresentModeCount,
+ VkPresentModeKHR *pPresentModes)
{
+ VK_FROM_HANDLE(vk_physical_device, device, physicalDevice);
ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, _surface);
+ struct wsi_device *wsi_device = device->wsi_device;
struct wsi_interface *iface = wsi_device->wsi[surface->platform];
return iface->get_present_modes(surface, pPresentModeCount,
pPresentModes);
}
-VkResult
-wsi_common_get_present_rectangles(struct wsi_device *wsi_device,
- VkSurfaceKHR _surface,
- uint32_t* pRectCount,
- VkRect2D* pRects)
+VKAPI_ATTR VkResult VKAPI_CALL
+wsi_GetPhysicalDevicePresentRectanglesKHR(VkPhysicalDevice physicalDevice,
+ VkSurfaceKHR _surface,
+ uint32_t *pRectCount,
+ VkRect2D *pRects)
{
+ VK_FROM_HANDLE(vk_physical_device, device, physicalDevice);
ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, _surface);
+ struct wsi_device *wsi_device = device->wsi_device;
struct wsi_interface *iface = wsi_device->wsi[surface->platform];
return iface->get_present_rectangles(surface, wsi_device,
pRectCount, pRects);
}
-VkResult
-wsi_common_create_swapchain(struct wsi_device *wsi,
- VkDevice device,
- const VkSwapchainCreateInfoKHR *pCreateInfo,
- const VkAllocationCallbacks *pAllocator,
- VkSwapchainKHR *pSwapchain)
+VKAPI_ATTR VkResult VKAPI_CALL
+wsi_CreateSwapchainKHR(VkDevice _device,
+ const VkSwapchainCreateInfoKHR *pCreateInfo,
+ const VkAllocationCallbacks *pAllocator,
+ VkSwapchainKHR *pSwapchain)
{
+ VK_FROM_HANDLE(vk_device, device, _device);
ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, pCreateInfo->surface);
- struct wsi_interface *iface = wsi->wsi[surface->platform];
+ struct wsi_device *wsi_device = device->physical->wsi_device;
+ struct wsi_interface *iface = wsi_device->wsi[surface->platform];
+ const VkAllocationCallbacks *alloc;
struct wsi_swapchain *swapchain;
- VkResult result = iface->create_swapchain(surface, device, wsi,
- pCreateInfo, pAllocator,
+ if (pAllocator)
+ alloc = pAllocator;
+ else
+ alloc = &device->alloc;
+
+ VkResult result = iface->create_swapchain(surface, _device, wsi_device,
+ pCreateInfo, alloc,
&swapchain);
if (result != VK_SUCCESS)
return result;
- swapchain->fences = vk_zalloc(pAllocator,
+ swapchain->fences = vk_zalloc(alloc,
sizeof (*swapchain->fences) * swapchain->image_count,
sizeof (*swapchain->fences),
VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
if (!swapchain->fences) {
- swapchain->destroy(swapchain, pAllocator);
+ swapchain->destroy(swapchain, alloc);
return VK_ERROR_OUT_OF_HOST_MEMORY;
}
@@ -493,16 +537,24 @@ wsi_common_create_swapchain(struct wsi_device *wsi,
return VK_SUCCESS;
}
-void
-wsi_common_destroy_swapchain(VkDevice device,
- VkSwapchainKHR _swapchain,
- const VkAllocationCallbacks *pAllocator)
+VKAPI_ATTR void VKAPI_CALL
+wsi_DestroySwapchainKHR(VkDevice _device,
+ VkSwapchainKHR _swapchain,
+ const VkAllocationCallbacks *pAllocator)
{
+ VK_FROM_HANDLE(vk_device, device, _device);
VK_FROM_HANDLE(wsi_swapchain, swapchain, _swapchain);
+ const VkAllocationCallbacks *alloc;
+
if (!swapchain)
return;
- swapchain->destroy(swapchain, pAllocator);
+ if (pAllocator)
+ alloc = pAllocator;
+ else
+ alloc = &device->alloc;
+
+ swapchain->destroy(swapchain, alloc);
}
VkResult
@@ -522,6 +574,40 @@ wsi_common_get_images(VkSwapchainKHR _swapchain,
return vk_outarray_status(&images);
}
+VKAPI_ATTR VkResult VKAPI_CALL
+wsi_GetSwapchainImagesKHR(VkDevice device,
+ VkSwapchainKHR swapchain,
+ uint32_t *pSwapchainImageCount,
+ VkImage *pSwapchainImages)
+{
+ return wsi_common_get_images(swapchain,
+ pSwapchainImageCount,
+ pSwapchainImages);
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL
+wsi_AcquireNextImageKHR(VkDevice _device,
+ VkSwapchainKHR swapchain,
+ uint64_t timeout,
+ VkSemaphore semaphore,
+ VkFence fence,
+ uint32_t *pImageIndex)
+{
+ VK_FROM_HANDLE(vk_device, device, _device);
+
+ const VkAcquireNextImageInfoKHR acquire_info = {
+ .sType = VK_STRUCTURE_TYPE_ACQUIRE_NEXT_IMAGE_INFO_KHR,
+ .swapchain = swapchain,
+ .timeout = timeout,
+ .semaphore = semaphore,
+ .fence = fence,
+ .deviceMask = 0,
+ };
+
+ return device->dispatch_table.AcquireNextImage2KHR(_device, &acquire_info,
+ pImageIndex);
+}
+
VkResult
wsi_common_acquire_next_image2(const struct wsi_device *wsi,
VkDevice device,
@@ -559,6 +645,17 @@ wsi_common_acquire_next_image2(const struct wsi_device *wsi,
return result;
}
+VKAPI_ATTR VkResult VKAPI_CALL
+wsi_AcquireNextImage2KHR(VkDevice _device,
+ const VkAcquireNextImageInfoKHR *pAcquireInfo,
+ uint32_t *pImageIndex)
+{
+ VK_FROM_HANDLE(vk_device, device, _device);
+
+ return wsi_common_acquire_next_image2(device->physical->wsi_device,
+ _device, pAcquireInfo, pImageIndex);
+}
+
VkResult
wsi_common_queue_present(const struct wsi_device *wsi,
VkDevice device,
@@ -653,6 +750,10 @@ wsi_common_queue_present(const struct wsi_device *wsi,
if (result != VK_SUCCESS)
goto fail_present;
+ if (wsi->sw)
+ wsi->WaitForFences(device, 1, &swapchain->fences[image_index],
+ true, ~0ull);
+
const VkPresentRegionKHR *region = NULL;
if (regions && regions->pRegions)
region = &regions->pRegions[i];
@@ -678,8 +779,42 @@ wsi_common_queue_present(const struct wsi_device *wsi,
return final_result;
}
+VKAPI_ATTR VkResult VKAPI_CALL
+wsi_QueuePresentKHR(VkQueue _queue, const VkPresentInfoKHR *pPresentInfo)
+{
+ VK_FROM_HANDLE(vk_queue, queue, _queue);
+
+ return wsi_common_queue_present(queue->base.device->physical->wsi_device,
+ vk_device_to_handle(queue->base.device),
+ _queue,
+ queue->queue_family_index,
+ pPresentInfo);
+}
+
uint64_t
wsi_common_get_current_time(void)
{
return os_time_get_nano();
}
+
+VKAPI_ATTR VkResult VKAPI_CALL
+wsi_GetDeviceGroupPresentCapabilitiesKHR(VkDevice device,
+ VkDeviceGroupPresentCapabilitiesKHR *pCapabilities)
+{
+ memset(pCapabilities->presentMask, 0,
+ sizeof(pCapabilities->presentMask));
+ pCapabilities->presentMask[0] = 0x1;
+ pCapabilities->modes = VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_BIT_KHR;
+
+ return VK_SUCCESS;
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL
+wsi_GetDeviceGroupSurfacePresentModesKHR(VkDevice device,
+ VkSurfaceKHR surface,
+ VkDeviceGroupPresentModeFlagsKHR *pModes)
+{
+ *pModes = VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_BIT_KHR;
+
+ return VK_SUCCESS;
+}
diff --git a/lib/mesa/src/vulkan/wsi/wsi_common_display.c b/lib/mesa/src/vulkan/wsi/wsi_common_display.c
index e25dc1a3f..a8d0353c5 100644
--- a/lib/mesa/src/vulkan/wsi/wsi_common_display.c
+++ b/lib/mesa/src/vulkan/wsi/wsi_common_display.c
@@ -40,7 +40,11 @@
#include "util/hash_table.h"
#include "util/list.h"
+#include "vk_device.h"
+#include "vk_instance.h"
+#include "vk_physical_device.h"
#include "vk_util.h"
+#include "wsi_common_entrypoints.h"
#include "wsi_common_private.h"
#include "wsi_common_display.h"
#include "wsi_common_queue.h"
@@ -282,16 +286,17 @@ wsi_display_alloc_connector(struct wsi_display *wsi,
static struct wsi_display_connector *
wsi_display_get_connector(struct wsi_device *wsi_device,
+ int drm_fd,
uint32_t connector_id)
{
struct wsi_display *wsi =
(struct wsi_display *) wsi_device->wsi[VK_ICD_WSI_PLATFORM_DISPLAY];
- if (wsi->fd < 0)
+ if (drm_fd < 0)
return NULL;
drmModeConnectorPtr drm_connector =
- drmModeGetConnector(wsi->fd, connector_id);
+ drmModeGetConnector(drm_fd, connector_id);
if (!drm_connector)
return NULL;
@@ -314,7 +319,7 @@ wsi_display_get_connector(struct wsi_device *wsi_device,
for (int p = 0; connector->dpms_property == 0 &&
p < drm_connector->count_props; p++)
{
- drmModePropertyPtr prop = drmModeGetProperty(wsi->fd,
+ drmModePropertyPtr prop = drmModeGetProperty(drm_fd,
drm_connector->props[p]);
if (!prop)
continue;
@@ -409,22 +414,20 @@ wsi_display_fill_in_display_properties(struct wsi_device *wsi_device,
properties->persistentContent = VK_FALSE;
}
-/*
- * Implement vkGetPhysicalDeviceDisplayPropertiesKHR (VK_KHR_display)
- */
-VkResult
-wsi_display_get_physical_device_display_properties(
- VkPhysicalDevice physical_device,
- struct wsi_device *wsi_device,
- uint32_t *property_count,
- VkDisplayPropertiesKHR *properties)
+VKAPI_ATTR VkResult VKAPI_CALL
+wsi_GetPhysicalDeviceDisplayPropertiesKHR(VkPhysicalDevice physicalDevice,
+ uint32_t *pPropertyCount,
+ VkDisplayPropertiesKHR *pProperties)
{
+ VK_FROM_HANDLE(vk_physical_device, pdevice, physicalDevice);
+ struct wsi_device *wsi_device = pdevice->wsi_device;
struct wsi_display *wsi =
(struct wsi_display *) wsi_device->wsi[VK_ICD_WSI_PLATFORM_DISPLAY];
- if (properties == NULL) {
- return wsi_display_get_physical_device_display_properties2(
- physical_device, wsi_device, property_count, NULL);
+ if (pProperties == NULL) {
+ return wsi_GetPhysicalDeviceDisplayProperties2KHR(physicalDevice,
+ pPropertyCount,
+ NULL);
} else {
/* If we're actually returning properties, allocate a temporary array of
* VkDisplayProperties2KHR structs, call properties2 to fill them out,
@@ -434,20 +437,21 @@ wsi_display_get_physical_device_display_properties(
* allocations so this should get lost in the noise.
*/
VkDisplayProperties2KHR *props2 =
- vk_zalloc(wsi->alloc, sizeof(*props2) * *property_count, 8,
+ vk_zalloc(wsi->alloc, sizeof(*props2) * *pPropertyCount, 8,
VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
if (props2 == NULL)
return VK_ERROR_OUT_OF_HOST_MEMORY;
- for (uint32_t i = 0; i < *property_count; i++)
+ for (uint32_t i = 0; i < *pPropertyCount; i++)
props2[i].sType = VK_STRUCTURE_TYPE_DISPLAY_PROPERTIES_2_KHR;
- VkResult result = wsi_display_get_physical_device_display_properties2(
- physical_device, wsi_device, property_count, props2);
+ VkResult result =
+ wsi_GetPhysicalDeviceDisplayProperties2KHR(physicalDevice,
+ pPropertyCount, props2);
if (result == VK_SUCCESS || result == VK_INCOMPLETE) {
- for (uint32_t i = 0; i < *property_count; i++)
- properties[i] = props2[i].displayProperties;
+ for (uint32_t i = 0; i < *pPropertyCount; i++)
+ pProperties[i] = props2[i].displayProperties;
}
vk_free(wsi->alloc, props2);
@@ -456,13 +460,13 @@ wsi_display_get_physical_device_display_properties(
}
}
-VkResult
-wsi_display_get_physical_device_display_properties2(
- VkPhysicalDevice physical_device,
- struct wsi_device *wsi_device,
- uint32_t *property_count,
- VkDisplayProperties2KHR *properties)
+VKAPI_ATTR VkResult VKAPI_CALL
+wsi_GetPhysicalDeviceDisplayProperties2KHR(VkPhysicalDevice physicalDevice,
+ uint32_t *pPropertyCount,
+ VkDisplayProperties2KHR *pProperties)
{
+ VK_FROM_HANDLE(vk_physical_device, pdevice, physicalDevice);
+ struct wsi_device *wsi_device = pdevice->wsi_device;
struct wsi_display *wsi =
(struct wsi_display *) wsi_device->wsi[VK_ICD_WSI_PLATFORM_DISPLAY];
@@ -474,13 +478,14 @@ wsi_display_get_physical_device_display_properties2(
if (!mode_res)
goto bail;
- VK_OUTARRAY_MAKE(conn, properties, property_count);
+ VK_OUTARRAY_MAKE(conn, pProperties, pPropertyCount);
/* Get current information */
for (int c = 0; c < mode_res->count_connectors; c++) {
struct wsi_display_connector *connector =
- wsi_display_get_connector(wsi_device, mode_res->connectors[c]);
+ wsi_display_get_connector(wsi_device, wsi->fd,
+ mode_res->connectors[c]);
if (!connector) {
drmModeFreeResources(mode_res);
@@ -501,7 +506,7 @@ wsi_display_get_physical_device_display_properties2(
return vk_outarray_status(&conn);
bail:
- *property_count = 0;
+ *pPropertyCount = 0;
return VK_SUCCESS;
}
@@ -526,17 +531,17 @@ wsi_display_fill_in_display_plane_properties(
}
}
-VkResult
-wsi_display_get_physical_device_display_plane_properties(
- VkPhysicalDevice physical_device,
- struct wsi_device *wsi_device,
- uint32_t *property_count,
- VkDisplayPlanePropertiesKHR *properties)
+VKAPI_ATTR VkResult VKAPI_CALL
+wsi_GetPhysicalDeviceDisplayPlanePropertiesKHR(VkPhysicalDevice physicalDevice,
+ uint32_t *pPropertyCount,
+ VkDisplayPlanePropertiesKHR *pProperties)
{
+ VK_FROM_HANDLE(vk_physical_device, pdevice, physicalDevice);
+ struct wsi_device *wsi_device = pdevice->wsi_device;
struct wsi_display *wsi =
(struct wsi_display *) wsi_device->wsi[VK_ICD_WSI_PLATFORM_DISPLAY];
- VK_OUTARRAY_MAKE(conn, properties, property_count);
+ VK_OUTARRAY_MAKE(conn, pProperties, pPropertyCount);
wsi_for_each_connector(connector, wsi) {
vk_outarray_append(&conn, prop) {
@@ -551,17 +556,17 @@ wsi_display_get_physical_device_display_plane_properties(
return vk_outarray_status(&conn);
}
-VkResult
-wsi_display_get_physical_device_display_plane_properties2(
- VkPhysicalDevice physical_device,
- struct wsi_device *wsi_device,
- uint32_t *property_count,
- VkDisplayPlaneProperties2KHR *properties)
+VKAPI_ATTR VkResult VKAPI_CALL
+wsi_GetPhysicalDeviceDisplayPlaneProperties2KHR(VkPhysicalDevice physicalDevice,
+ uint32_t *pPropertyCount,
+ VkDisplayPlaneProperties2KHR *pProperties)
{
+ VK_FROM_HANDLE(vk_physical_device, pdevice, physicalDevice);
+ struct wsi_device *wsi_device = pdevice->wsi_device;
struct wsi_display *wsi =
(struct wsi_display *) wsi_device->wsi[VK_ICD_WSI_PLATFORM_DISPLAY];
- VK_OUTARRAY_MAKE(conn, properties, property_count);
+ VK_OUTARRAY_MAKE(conn, pProperties, pPropertyCount);
wsi_for_each_connector(connector, wsi) {
vk_outarray_append(&conn, prop) {
@@ -576,23 +581,23 @@ wsi_display_get_physical_device_display_plane_properties2(
* Implement vkGetDisplayPlaneSupportedDisplaysKHR (VK_KHR_display)
*/
-VkResult
-wsi_display_get_display_plane_supported_displays(
- VkPhysicalDevice physical_device,
- struct wsi_device *wsi_device,
- uint32_t plane_index,
- uint32_t *display_count,
- VkDisplayKHR *displays)
+VKAPI_ATTR VkResult VKAPI_CALL
+wsi_GetDisplayPlaneSupportedDisplaysKHR(VkPhysicalDevice physicalDevice,
+ uint32_t planeIndex,
+ uint32_t *pDisplayCount,
+ VkDisplayKHR *pDisplays)
{
+ VK_FROM_HANDLE(vk_physical_device, pdevice, physicalDevice);
+ struct wsi_device *wsi_device = pdevice->wsi_device;
struct wsi_display *wsi =
(struct wsi_display *) wsi_device->wsi[VK_ICD_WSI_PLATFORM_DISPLAY];
- VK_OUTARRAY_MAKE(conn, displays, display_count);
+ VK_OUTARRAY_MAKE(conn, pDisplays, pDisplayCount);
int c = 0;
wsi_for_each_connector(connector, wsi) {
- if (c == plane_index && connector->connected) {
+ if (c == planeIndex && connector->connected) {
vk_outarray_append(&conn, display) {
*display = wsi_display_connector_to_handle(connector);
}
@@ -622,17 +627,18 @@ wsi_display_fill_in_display_mode_properties(
(uint32_t) (wsi_display_mode_refresh(display_mode) * 1000 + 0.5);
}
-VkResult
-wsi_display_get_display_mode_properties(VkPhysicalDevice physical_device,
- struct wsi_device *wsi_device,
- VkDisplayKHR display,
- uint32_t *property_count,
- VkDisplayModePropertiesKHR *properties)
+VKAPI_ATTR VkResult VKAPI_CALL
+wsi_GetDisplayModePropertiesKHR(VkPhysicalDevice physicalDevice,
+ VkDisplayKHR display,
+ uint32_t *pPropertyCount,
+ VkDisplayModePropertiesKHR *pProperties)
{
+ VK_FROM_HANDLE(vk_physical_device, pdevice, physicalDevice);
+ struct wsi_device *wsi_device = pdevice->wsi_device;
struct wsi_display_connector *connector =
wsi_display_connector_from_handle(display);
- VK_OUTARRAY_MAKE(conn, properties, property_count);
+ VK_OUTARRAY_MAKE(conn, pProperties, pPropertyCount);
wsi_for_each_display_mode(display_mode, connector) {
if (!display_mode->valid)
@@ -650,17 +656,18 @@ wsi_display_get_display_mode_properties(VkPhysicalDevice physical_device,
return vk_outarray_status(&conn);
}
-VkResult
-wsi_display_get_display_mode_properties2(VkPhysicalDevice physical_device,
- struct wsi_device *wsi_device,
- VkDisplayKHR display,
- uint32_t *property_count,
- VkDisplayModeProperties2KHR *properties)
+VKAPI_ATTR VkResult VKAPI_CALL
+wsi_GetDisplayModeProperties2KHR(VkPhysicalDevice physicalDevice,
+ VkDisplayKHR display,
+ uint32_t *pPropertyCount,
+ VkDisplayModeProperties2KHR *pProperties)
{
+ VK_FROM_HANDLE(vk_physical_device, pdevice, physicalDevice);
+ struct wsi_device *wsi_device = pdevice->wsi_device;
struct wsi_display_connector *connector =
wsi_display_connector_from_handle(display);
- VK_OUTARRAY_MAKE(conn, properties, property_count);
+ VK_OUTARRAY_MAKE(conn, pProperties, pPropertyCount);
wsi_for_each_display_mode(display_mode, connector) {
if (!display_mode->valid)
@@ -686,18 +693,17 @@ wsi_display_mode_matches_vk(wsi_display_mode *wsi,
/*
* Implement vkCreateDisplayModeKHR (VK_KHR_display)
*/
-VkResult
-wsi_display_create_display_mode(VkPhysicalDevice physical_device,
- struct wsi_device *wsi_device,
- VkDisplayKHR display,
- const VkDisplayModeCreateInfoKHR *create_info,
- const VkAllocationCallbacks *allocator,
- VkDisplayModeKHR *mode)
+VKAPI_ATTR VkResult VKAPI_CALL
+wsi_CreateDisplayModeKHR(VkPhysicalDevice physicalDevice,
+ VkDisplayKHR display,
+ const VkDisplayModeCreateInfoKHR *pCreateInfo,
+ const VkAllocationCallbacks *pAllocator,
+ VkDisplayModeKHR *pMode)
{
struct wsi_display_connector *connector =
wsi_display_connector_from_handle(display);
- if (create_info->flags != 0)
+ if (pCreateInfo->flags != 0)
return VK_ERROR_INITIALIZATION_FAILED;
/* Check and see if the requested mode happens to match an existing one and
@@ -707,8 +713,8 @@ wsi_display_create_display_mode(VkPhysicalDevice physical_device,
*/
wsi_for_each_display_mode(display_mode, connector) {
if (display_mode->valid) {
- if (wsi_display_mode_matches_vk(display_mode, &create_info->parameters)) {
- *mode = wsi_display_mode_to_handle(display_mode);
+ if (wsi_display_mode_matches_vk(display_mode, &pCreateInfo->parameters)) {
+ *pMode = wsi_display_mode_to_handle(display_mode);
return VK_SUCCESS;
}
}
@@ -719,53 +725,50 @@ wsi_display_create_display_mode(VkPhysicalDevice physical_device,
/*
* Implement vkGetDisplayPlaneCapabilities
*/
-VkResult
-wsi_get_display_plane_capabilities(VkPhysicalDevice physical_device,
- struct wsi_device *wsi_device,
- VkDisplayModeKHR mode_khr,
- uint32_t plane_index,
- VkDisplayPlaneCapabilitiesKHR *capabilities)
+VKAPI_ATTR VkResult VKAPI_CALL
+wsi_GetDisplayPlaneCapabilitiesKHR(VkPhysicalDevice physicalDevice,
+ VkDisplayModeKHR _mode,
+ uint32_t planeIndex,
+ VkDisplayPlaneCapabilitiesKHR *pCapabilities)
{
- struct wsi_display_mode *mode = wsi_display_mode_from_handle(mode_khr);
+ struct wsi_display_mode *mode = wsi_display_mode_from_handle(_mode);
/* XXX use actual values */
- capabilities->supportedAlpha = VK_DISPLAY_PLANE_ALPHA_OPAQUE_BIT_KHR;
- capabilities->minSrcPosition.x = 0;
- capabilities->minSrcPosition.y = 0;
- capabilities->maxSrcPosition.x = 0;
- capabilities->maxSrcPosition.y = 0;
- capabilities->minSrcExtent.width = mode->hdisplay;
- capabilities->minSrcExtent.height = mode->vdisplay;
- capabilities->maxSrcExtent.width = mode->hdisplay;
- capabilities->maxSrcExtent.height = mode->vdisplay;
- capabilities->minDstPosition.x = 0;
- capabilities->minDstPosition.y = 0;
- capabilities->maxDstPosition.x = 0;
- capabilities->maxDstPosition.y = 0;
- capabilities->minDstExtent.width = mode->hdisplay;
- capabilities->minDstExtent.height = mode->vdisplay;
- capabilities->maxDstExtent.width = mode->hdisplay;
- capabilities->maxDstExtent.height = mode->vdisplay;
+ pCapabilities->supportedAlpha = VK_DISPLAY_PLANE_ALPHA_OPAQUE_BIT_KHR;
+ pCapabilities->minSrcPosition.x = 0;
+ pCapabilities->minSrcPosition.y = 0;
+ pCapabilities->maxSrcPosition.x = 0;
+ pCapabilities->maxSrcPosition.y = 0;
+ pCapabilities->minSrcExtent.width = mode->hdisplay;
+ pCapabilities->minSrcExtent.height = mode->vdisplay;
+ pCapabilities->maxSrcExtent.width = mode->hdisplay;
+ pCapabilities->maxSrcExtent.height = mode->vdisplay;
+ pCapabilities->minDstPosition.x = 0;
+ pCapabilities->minDstPosition.y = 0;
+ pCapabilities->maxDstPosition.x = 0;
+ pCapabilities->maxDstPosition.y = 0;
+ pCapabilities->minDstExtent.width = mode->hdisplay;
+ pCapabilities->minDstExtent.height = mode->vdisplay;
+ pCapabilities->maxDstExtent.width = mode->hdisplay;
+ pCapabilities->maxDstExtent.height = mode->vdisplay;
return VK_SUCCESS;
}
-VkResult
-wsi_get_display_plane_capabilities2(
- VkPhysicalDevice physical_device,
- struct wsi_device *wsi_device,
- const VkDisplayPlaneInfo2KHR *pDisplayPlaneInfo,
- VkDisplayPlaneCapabilities2KHR *capabilities)
+VKAPI_ATTR VkResult VKAPI_CALL
+wsi_GetDisplayPlaneCapabilities2KHR(VkPhysicalDevice physicalDevice,
+ const VkDisplayPlaneInfo2KHR *pDisplayPlaneInfo,
+ VkDisplayPlaneCapabilities2KHR *pCapabilities)
{
- assert(capabilities->sType ==
+ assert(pCapabilities->sType ==
VK_STRUCTURE_TYPE_DISPLAY_PLANE_CAPABILITIES_2_KHR);
VkResult result =
- wsi_get_display_plane_capabilities(physical_device, wsi_device,
+ wsi_GetDisplayPlaneCapabilitiesKHR(physicalDevice,
pDisplayPlaneInfo->mode,
pDisplayPlaneInfo->planeIndex,
- &capabilities->capabilities);
+ &pCapabilities->capabilities);
- vk_foreach_struct(ext, capabilities->pNext) {
+ vk_foreach_struct(ext, pCapabilities->pNext) {
switch (ext->sType) {
case VK_STRUCTURE_TYPE_SURFACE_PROTECTED_CAPABILITIES_KHR: {
VkSurfaceProtectedCapabilitiesKHR *protected = (void *)ext;
@@ -782,33 +785,37 @@ wsi_get_display_plane_capabilities2(
return result;
}
-VkResult
-wsi_create_display_surface(VkInstance instance,
- const VkAllocationCallbacks *allocator,
- const VkDisplaySurfaceCreateInfoKHR *create_info,
- VkSurfaceKHR *surface_khr)
+VKAPI_ATTR VkResult VKAPI_CALL
+wsi_CreateDisplayPlaneSurfaceKHR(VkInstance _instance,
+ const VkDisplaySurfaceCreateInfoKHR *pCreateInfo,
+ const VkAllocationCallbacks *pAllocator,
+ VkSurfaceKHR *pSurface)
{
- VkIcdSurfaceDisplay *surface = vk_zalloc(allocator, sizeof *surface, 8,
- VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
+ VK_FROM_HANDLE(vk_instance, instance, _instance);
+ VkIcdSurfaceDisplay *surface;
+
+ assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_DISPLAY_SURFACE_CREATE_INFO_KHR);
+ surface = vk_zalloc2(&instance->alloc, pAllocator, 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_DISPLAY;
- surface->displayMode = create_info->displayMode;
- surface->planeIndex = create_info->planeIndex;
- surface->planeStackIndex = create_info->planeStackIndex;
- surface->transform = create_info->transform;
- surface->globalAlpha = create_info->globalAlpha;
- surface->alphaMode = create_info->alphaMode;
- surface->imageExtent = create_info->imageExtent;
+ surface->displayMode = pCreateInfo->displayMode;
+ surface->planeIndex = pCreateInfo->planeIndex;
+ surface->planeStackIndex = pCreateInfo->planeStackIndex;
+ surface->transform = pCreateInfo->transform;
+ surface->globalAlpha = pCreateInfo->globalAlpha;
+ surface->alphaMode = pCreateInfo->alphaMode;
+ surface->imageExtent = pCreateInfo->imageExtent;
+
+ *pSurface = VkIcdSurfaceBase_to_handle(&surface->base);
- *surface_khr = VkIcdSurfaceBase_to_handle(&surface->base);
return VK_SUCCESS;
}
-
static VkResult
wsi_display_surface_get_support(VkIcdSurfaceBase *surface,
struct wsi_device *wsi_device,
@@ -1029,7 +1036,7 @@ wsi_display_image_init(VkDevice device_h,
return VK_ERROR_DEVICE_LOST;
VkResult result = wsi_create_native_image(&chain->base, create_info,
- 0, NULL, NULL,
+ 0, NULL, NULL, NULL,
&image->base);
if (result != VK_SUCCESS)
return result;
@@ -1980,11 +1987,12 @@ wsi_display_finish_wsi(struct wsi_device *wsi_device,
/*
* Implement vkReleaseDisplay
*/
-VkResult
-wsi_release_display(VkPhysicalDevice physical_device,
- struct wsi_device *wsi_device,
- VkDisplayKHR display)
+VKAPI_ATTR VkResult VKAPI_CALL
+wsi_ReleaseDisplayEXT(VkPhysicalDevice physicalDevice,
+ VkDisplayKHR display)
{
+ VK_FROM_HANDLE(vk_physical_device, pdevice, physicalDevice);
+ struct wsi_device *wsi_device = pdevice->wsi_device;
struct wsi_display *wsi =
(struct wsi_display *) wsi_device->wsi[VK_ICD_WSI_PLATFORM_DISPLAY];
@@ -2398,12 +2406,13 @@ wsi_display_find_crtc_for_output(xcb_connection_t *connection,
return idle_crtc;
}
-VkResult
-wsi_acquire_xlib_display(VkPhysicalDevice physical_device,
- struct wsi_device *wsi_device,
- Display *dpy,
- VkDisplayKHR display)
+VKAPI_ATTR VkResult VKAPI_CALL
+wsi_AcquireXlibDisplayEXT(VkPhysicalDevice physicalDevice,
+ Display *dpy,
+ VkDisplayKHR display)
{
+ VK_FROM_HANDLE(vk_physical_device, pdevice, physicalDevice);
+ struct wsi_device *wsi_device = pdevice->wsi_device;
struct wsi_display *wsi =
(struct wsi_display *) wsi_device->wsi[VK_ICD_WSI_PLATFORM_DISPLAY];
xcb_connection_t *connection = XGetXCBConnection(dpy);
@@ -2461,33 +2470,36 @@ wsi_acquire_xlib_display(VkPhysicalDevice physical_device,
return VK_SUCCESS;
}
-VkResult
-wsi_get_randr_output_display(VkPhysicalDevice physical_device,
- struct wsi_device *wsi_device,
+VKAPI_ATTR VkResult VKAPI_CALL
+wsi_GetRandROutputDisplayEXT(VkPhysicalDevice physicalDevice,
Display *dpy,
- RROutput output,
- VkDisplayKHR *display)
+ RROutput rrOutput,
+ VkDisplayKHR *pDisplay)
{
+ VK_FROM_HANDLE(vk_physical_device, pdevice, physicalDevice);
+ struct wsi_device *wsi_device = pdevice->wsi_device;
xcb_connection_t *connection = XGetXCBConnection(dpy);
struct wsi_display_connector *connector =
- wsi_display_get_output(wsi_device, connection, (xcb_randr_output_t) output);
+ wsi_display_get_output(wsi_device, connection,
+ (xcb_randr_output_t) rrOutput);
if (connector)
- *display = wsi_display_connector_to_handle(connector);
+ *pDisplay = wsi_display_connector_to_handle(connector);
else
- *display = VK_NULL_HANDLE;
+ *pDisplay = VK_NULL_HANDLE;
return VK_SUCCESS;
}
#endif
/* VK_EXT_display_control */
-VkResult
-wsi_display_power_control(VkDevice device,
- struct wsi_device *wsi_device,
- VkDisplayKHR display,
- const VkDisplayPowerInfoEXT *display_power_info)
+VKAPI_ATTR VkResult VKAPI_CALL
+wsi_DisplayPowerControlEXT(VkDevice _device,
+ VkDisplayKHR display,
+ const VkDisplayPowerInfoEXT *pDisplayPowerInfo)
{
+ VK_FROM_HANDLE(vk_device, device, _device);
+ struct wsi_device *wsi_device = device->physical->wsi_device;
struct wsi_display *wsi =
(struct wsi_display *) wsi_device->wsi[VK_ICD_WSI_PLATFORM_DISPLAY];
struct wsi_display_connector *connector =
@@ -2497,7 +2509,7 @@ wsi_display_power_control(VkDevice device,
if (wsi->fd < 0)
return VK_ERROR_INITIALIZATION_FAILED;
- switch (display_power_info->powerState) {
+ switch (pDisplayPowerInfo->powerState) {
case VK_DISPLAY_POWER_STATE_OFF_EXT:
mode = DRM_MODE_DPMS_OFF;
break;
@@ -2526,6 +2538,15 @@ wsi_register_device_event(VkDevice device,
return VK_ERROR_FEATURE_NOT_PRESENT;
}
+VKAPI_ATTR VkResult VKAPI_CALL
+wsi_RegisterDeviceEventEXT(VkDevice device,
+ const VkDeviceEventInfoEXT *pDeviceEventInfo,
+ const VkAllocationCallbacks *pAllocator,
+ VkFence *pFence)
+{
+ unreachable("Not enough common infrastructure to implement this yet");
+}
+
VkResult
wsi_register_display_event(VkDevice device,
struct wsi_device *wsi_device,
@@ -2571,14 +2592,24 @@ wsi_register_display_event(VkDevice device,
return ret;
}
+VKAPI_ATTR VkResult VKAPI_CALL
+wsi_RegisterDisplayEventEXT(VkDevice device,
+ VkDisplayKHR display,
+ const VkDisplayEventInfoEXT *pDisplayEventInfo,
+ const VkAllocationCallbacks *pAllocator,
+ VkFence *pFence)
+{
+ unreachable("Not enough common infrastructure to implement this yet");
+}
-VkResult
-wsi_get_swapchain_counter(VkDevice device,
- struct wsi_device *wsi_device,
- VkSwapchainKHR _swapchain,
- VkSurfaceCounterFlagBitsEXT flag_bits,
- uint64_t *value)
+VKAPI_ATTR VkResult VKAPI_CALL
+wsi_GetSwapchainCounterEXT(VkDevice _device,
+ VkSwapchainKHR _swapchain,
+ VkSurfaceCounterFlagBitsEXT counter,
+ uint64_t *pCounterValue)
{
+ VK_FROM_HANDLE(vk_device, device, _device);
+ struct wsi_device *wsi_device = device->physical->wsi_device;
struct wsi_display *wsi =
(struct wsi_display *) wsi_device->wsi[VK_ICD_WSI_PLATFORM_DISPLAY];
struct wsi_display_swapchain *swapchain =
@@ -2590,14 +2621,71 @@ wsi_get_swapchain_counter(VkDevice device,
return VK_ERROR_INITIALIZATION_FAILED;
if (!connector->active) {
- *value = 0;
+ *pCounterValue = 0;
return VK_SUCCESS;
}
- int ret = drmCrtcGetSequence(wsi->fd, connector->crtc_id, value, NULL);
+ int ret = drmCrtcGetSequence(wsi->fd, connector->crtc_id,
+ pCounterValue, NULL);
if (ret)
- *value = 0;
+ *pCounterValue = 0;
return VK_SUCCESS;
}
+VKAPI_ATTR VkResult VKAPI_CALL
+wsi_AcquireDrmDisplayEXT(VkPhysicalDevice physicalDevice,
+ int32_t drmFd,
+ VkDisplayKHR display)
+{
+ VK_FROM_HANDLE(vk_physical_device, pdevice, physicalDevice);
+ struct wsi_device *wsi_device = pdevice->wsi_device;
+
+ if (!wsi_device_matches_drm_fd(wsi_device, drmFd))
+ return VK_ERROR_UNKNOWN;
+
+ struct wsi_display *wsi =
+ (struct wsi_display *) wsi_device->wsi[VK_ICD_WSI_PLATFORM_DISPLAY];
+
+ /* XXX no support for mulitple leases yet */
+ if (wsi->fd >= 0 || !local_drmIsMaster(drmFd))
+ return VK_ERROR_INITIALIZATION_FAILED;
+
+ struct wsi_display_connector *connector =
+ wsi_display_connector_from_handle(display);
+
+ drmModeConnectorPtr drm_connector =
+ drmModeGetConnectorCurrent(drmFd, connector->id);
+
+ if (!drm_connector)
+ return VK_ERROR_INITIALIZATION_FAILED;
+
+ drmModeFreeConnector(drm_connector);
+
+ wsi->fd = drmFd;
+ return VK_SUCCESS;
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL
+wsi_GetDrmDisplayEXT(VkPhysicalDevice physicalDevice,
+ int32_t drmFd,
+ uint32_t connectorId,
+ VkDisplayKHR *pDisplay)
+{
+ VK_FROM_HANDLE(vk_physical_device, pdevice, physicalDevice);
+ struct wsi_device *wsi_device = pdevice->wsi_device;
+
+ if (!wsi_device_matches_drm_fd(wsi_device, drmFd))
+ return VK_ERROR_UNKNOWN;
+
+ struct wsi_display_connector *connector =
+ wsi_display_get_connector(wsi_device, drmFd, connectorId);
+
+ if (!connector) {
+ *pDisplay = VK_NULL_HANDLE;
+ return VK_ERROR_UNKNOWN;
+ }
+
+ *pDisplay = wsi_display_connector_to_handle(connector);
+ return VK_SUCCESS;
+}
diff --git a/lib/mesa/src/vulkan/wsi/wsi_common_display.h b/lib/mesa/src/vulkan/wsi/wsi_common_display.h
index d65517ab9..26a49f8e1 100644
--- a/lib/mesa/src/vulkan/wsi/wsi_common_display.h
+++ b/lib/mesa/src/vulkan/wsi/wsi_common_display.h
@@ -27,113 +27,8 @@
#include <xf86drm.h>
#include <xf86drmMode.h>
-VkResult
-wsi_display_get_physical_device_display_properties(
- VkPhysicalDevice physical_device,
- struct wsi_device *wsi_device,
- uint32_t *property_count,
- VkDisplayPropertiesKHR *properties);
-
-VkResult
-wsi_display_get_physical_device_display_properties2(
- VkPhysicalDevice physical_device,
- struct wsi_device *wsi_device,
- uint32_t *pPropertyCount,
- VkDisplayProperties2KHR *pProperties);
-
-VkResult
-wsi_display_get_physical_device_display_plane_properties(
- VkPhysicalDevice physical_device,
- struct wsi_device *wsi_device,
- uint32_t *property_count,
- VkDisplayPlanePropertiesKHR *properties);
-
-VkResult
-wsi_display_get_physical_device_display_plane_properties2(
- VkPhysicalDevice physical_device,
- struct wsi_device *wsi_device,
- uint32_t *property_count,
- VkDisplayPlaneProperties2KHR *properties);
-
-VkResult
-wsi_display_get_display_plane_supported_displays(
- VkPhysicalDevice physical_device,
- struct wsi_device *wsi_device,
- uint32_t plane_index,
- uint32_t *display_count,
- VkDisplayKHR *displays);
-
-VkResult
-wsi_display_get_display_mode_properties(VkPhysicalDevice physical_device,
- struct wsi_device *wsi_device,
- VkDisplayKHR display,
- uint32_t *property_count,
- VkDisplayModePropertiesKHR *properties);
-
-VkResult
-wsi_display_get_display_mode_properties2(VkPhysicalDevice physical_device,
- struct wsi_device *wsi_device,
- VkDisplayKHR display,
- uint32_t *property_count,
- VkDisplayModeProperties2KHR *properties);
-
-VkResult
-wsi_display_create_display_mode(VkPhysicalDevice physical_device,
- struct wsi_device *wsi_device,
- VkDisplayKHR display,
- const VkDisplayModeCreateInfoKHR *create_info,
- const VkAllocationCallbacks *allocator,
- VkDisplayModeKHR *mode);
-
-VkResult
-wsi_get_display_plane_capabilities(VkPhysicalDevice physical_device,
- struct wsi_device *wsi_device,
- VkDisplayModeKHR mode_khr,
- uint32_t plane_index,
- VkDisplayPlaneCapabilitiesKHR *capabilities);
-
-VkResult
-wsi_get_display_plane_capabilities2(VkPhysicalDevice physical_device,
- struct wsi_device *wsi_device,
- const VkDisplayPlaneInfo2KHR *pDisplayPlaneInfo,
- VkDisplayPlaneCapabilities2KHR *capabilities);
-
-VkResult
-wsi_create_display_surface(VkInstance instance,
- const VkAllocationCallbacks *pAllocator,
- const VkDisplaySurfaceCreateInfoKHR *pCreateInfo,
- VkSurfaceKHR *pSurface);
-
-VkResult
-wsi_release_display(VkPhysicalDevice physical_device,
- struct wsi_device *wsi_device,
- VkDisplayKHR display);
-
-
-#ifdef VK_USE_PLATFORM_XLIB_XRANDR_EXT
-VkResult
-wsi_acquire_xlib_display(VkPhysicalDevice physical_device,
- struct wsi_device *wsi_device,
- Display *dpy,
- VkDisplayKHR display);
-
-VkResult
-wsi_get_randr_output_display(VkPhysicalDevice physical_device,
- struct wsi_device *wsi_device,
- Display *dpy,
- RROutput output,
- VkDisplayKHR *display);
-
-#endif /* VK_USE_PLATFORM_XLIB_XRANDR_EXT */
-
/* VK_EXT_display_control */
VkResult
-wsi_display_power_control(VkDevice device,
- struct wsi_device *wsi_device,
- VkDisplayKHR display,
- const VkDisplayPowerInfoEXT *display_power_info);
-
-VkResult
wsi_register_device_event(VkDevice device,
struct wsi_device *wsi_device,
const VkDeviceEventInfoEXT *device_event_info,
@@ -150,11 +45,4 @@ wsi_register_display_event(VkDevice device,
struct wsi_fence **fence,
int sync_fd);
-VkResult
-wsi_get_swapchain_counter(VkDevice device,
- struct wsi_device *wsi_device,
- VkSwapchainKHR swapchain,
- VkSurfaceCounterFlagBitsEXT flag_bits,
- uint64_t *value);
-
#endif
diff --git a/lib/mesa/src/vulkan/wsi/wsi_common_drm.c b/lib/mesa/src/vulkan/wsi/wsi_common_drm.c
index 1f81a92ff..347fc6e25 100644
--- a/lib/mesa/src/vulkan/wsi/wsi_common_drm.c
+++ b/lib/mesa/src/vulkan/wsi/wsi_common_drm.c
@@ -37,6 +37,9 @@
bool
wsi_device_matches_drm_fd(const struct wsi_device *wsi, int drm_fd)
{
+ if (wsi->can_present_on_device)
+ return wsi->can_present_on_device(wsi->pdevice, drm_fd);
+
drmDevicePtr fd_device;
int ret = drmGetDevice2(drm_fd, 0, &fd_device);
if (ret)
@@ -62,13 +65,25 @@ wsi_device_matches_drm_fd(const struct wsi_device *wsi, int drm_fd)
static uint32_t
select_memory_type(const struct wsi_device *wsi,
- VkMemoryPropertyFlags props,
+ bool want_device_local,
uint32_t type_bits)
{
+ assert(type_bits);
+
+ bool all_local = true;
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)
+ bool local = type.propertyFlags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
+
+ if ((type_bits & (1 << i)) && local == want_device_local)
return i;
+ all_local &= local;
+ }
+
+ /* ignore want_device_local when all memory types are device-local */
+ if (all_local) {
+ assert(!want_device_local);
+ return ffs(type_bits) - 1;
}
unreachable("No memory type found");
@@ -92,6 +107,7 @@ wsi_create_native_image(const struct wsi_swapchain *chain,
uint32_t num_modifier_lists,
const uint32_t *num_modifiers,
const uint64_t *const *modifiers,
+ uint8_t *(alloc_shm)(struct wsi_image *image, unsigned size),
struct wsi_image *image)
{
const struct wsi_device *wsi = chain->wsi;
@@ -101,8 +117,18 @@ wsi_create_native_image(const struct wsi_swapchain *chain,
for (int i = 0; i < ARRAY_SIZE(image->fds); i++)
image->fds[i] = -1;
+ struct wsi_image_create_info image_wsi_info = {
+ .sType = VK_STRUCTURE_TYPE_WSI_IMAGE_CREATE_INFO_MESA,
+ };
+ VkExternalMemoryImageCreateInfo ext_mem_image_create_info = {
+ .sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO,
+ .pNext = &image_wsi_info,
+ .handleTypes = wsi->sw ? VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT :
+ VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT,
+ };
VkImageCreateInfo image_info = {
.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
+ .pNext = &ext_mem_image_create_info,
.flags = 0,
.imageType = VK_IMAGE_TYPE_2D,
.format = pCreateInfo->imageFormat,
@@ -145,7 +171,6 @@ wsi_create_native_image(const struct wsi_swapchain *chain,
__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;
@@ -153,11 +178,7 @@ wsi_create_native_image(const struct wsi_swapchain *chain,
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);
+ image_wsi_info.scanout = true;
} else {
/* The winsys can't request modifiers if we don't support them. */
assert(wsi->supports_modifiers);
@@ -283,6 +304,19 @@ wsi_create_native_image(const struct wsi_swapchain *chain,
VkMemoryRequirements reqs;
wsi->GetImageMemoryRequirements(chain->device, image->image, &reqs);
+ void *sw_host_ptr = NULL;
+ if (alloc_shm) {
+ VkSubresourceLayout layout;
+
+ wsi->GetImageSubresourceLayout(chain->device, image->image,
+ &(VkImageSubresource) {
+ .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
+ .mipLevel = 0,
+ .arrayLayer = 0,
+ }, &layout);
+ sw_host_ptr = (*alloc_shm)(image, layout.size);
+ }
+
const struct wsi_memory_allocate_info memory_wsi_info = {
.sType = VK_STRUCTURE_TYPE_WSI_MEMORY_ALLOCATE_INFO_MESA,
.pNext = NULL,
@@ -291,7 +325,8 @@ wsi_create_native_image(const struct wsi_swapchain *chain,
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,
+ .handleTypes = wsi->sw ? VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT :
+ VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT,
};
const VkMemoryDedicatedAllocateInfo memory_dedicated_info = {
.sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO,
@@ -299,12 +334,17 @@ wsi_create_native_image(const struct wsi_swapchain *chain,
.image = image->image,
.buffer = VK_NULL_HANDLE,
};
+ const VkImportMemoryHostPointerInfoEXT host_ptr_info = {
+ .sType = VK_STRUCTURE_TYPE_IMPORT_MEMORY_HOST_POINTER_INFO_EXT,
+ .pNext = &memory_dedicated_info,
+ .pHostPointer = sw_host_ptr,
+ .handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT,
+ };
const VkMemoryAllocateInfo memory_info = {
.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
- .pNext = &memory_dedicated_info,
+ .pNext = sw_host_ptr ? (void *)&host_ptr_info : (void *)&memory_dedicated_info,
.allocationSize = reqs.size,
- .memoryTypeIndex = select_memory_type(wsi, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
- reqs.memoryTypeBits),
+ .memoryTypeIndex = select_memory_type(wsi, true, reqs.memoryTypeBits),
};
result = wsi->AllocateMemory(chain->device, &memory_info,
&chain->alloc, &image->memory);
@@ -475,7 +515,7 @@ wsi_create_prime_image(const struct wsi_swapchain *chain,
.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
.pNext = &prime_memory_dedicated_info,
.allocationSize = linear_size,
- .memoryTypeIndex = select_memory_type(wsi, 0, reqs.memoryTypeBits),
+ .memoryTypeIndex = select_memory_type(wsi, false, reqs.memoryTypeBits),
};
result = wsi->AllocateMemory(chain->device, &prime_memory_info,
&chain->alloc, &image->prime.memory);
@@ -487,9 +527,13 @@ wsi_create_prime_image(const struct wsi_swapchain *chain,
if (result != VK_SUCCESS)
goto fail;
- const VkImageCreateInfo image_info = {
+ const struct wsi_image_create_info image_wsi_info = {
+ .sType = VK_STRUCTURE_TYPE_WSI_IMAGE_CREATE_INFO_MESA,
+ .prime_blit_src = true,
+ };
+ VkImageCreateInfo image_info = {
.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
- .pNext = NULL,
+ .pNext = &image_wsi_info,
.flags = 0,
.imageType = VK_IMAGE_TYPE_2D,
.format = pCreateInfo->imageFormat,
@@ -508,6 +552,10 @@ wsi_create_prime_image(const struct wsi_swapchain *chain,
.pQueueFamilyIndices = pCreateInfo->pQueueFamilyIndices,
.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED,
};
+ 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;
+ }
result = wsi->CreateImage(chain->device, &image_info,
&chain->alloc, &image->image);
if (result != VK_SUCCESS)
@@ -525,8 +573,7 @@ wsi_create_prime_image(const struct wsi_swapchain *chain,
.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),
+ .memoryTypeIndex = select_memory_type(wsi, true, reqs.memoryTypeBits),
};
result = wsi->AllocateMemory(chain->device, &memory_info,
&chain->alloc, &image->memory);
diff --git a/lib/mesa/src/vulkan/wsi/wsi_common_private.h b/lib/mesa/src/vulkan/wsi/wsi_common_private.h
index 1fe8211f9..f08002abf 100644
--- a/lib/mesa/src/vulkan/wsi/wsi_common_private.h
+++ b/lib/mesa/src/vulkan/wsi/wsi_common_private.h
@@ -94,6 +94,7 @@ wsi_create_native_image(const struct wsi_swapchain *chain,
uint32_t num_modifier_lists,
const uint32_t *num_modifiers,
const uint64_t *const *modifiers,
+ uint8_t *(alloc_shm)(struct wsi_image *image, unsigned size),
struct wsi_image *image);
VkResult
diff --git a/lib/mesa/src/vulkan/wsi/wsi_common_queue.h b/lib/mesa/src/vulkan/wsi/wsi_common_queue.h
index 6d489cbf1..3676876b9 100644
--- a/lib/mesa/src/vulkan/wsi/wsi_common_queue.h
+++ b/lib/mesa/src/vulkan/wsi/wsi_common_queue.h
@@ -39,12 +39,10 @@ wsi_queue_init(struct wsi_queue *queue, int length)
{
int ret;
- uint32_t length_pow2 = 4;
- while (length_pow2 < length)
- length_pow2 *= 2;
+ if (length < 4)
+ length = 4;
- ret = u_vector_init(&queue->vector, sizeof(uint32_t),
- sizeof(uint32_t) * length_pow2);
+ ret = u_vector_init(&queue->vector, length, sizeof(uint32_t));
if (!ret)
return ENOMEM;
diff --git a/lib/mesa/src/vulkan/wsi/wsi_common_win32.c b/lib/mesa/src/vulkan/wsi/wsi_common_win32.c
index 82731f5f9..90456590b 100644
--- a/lib/mesa/src/vulkan/wsi/wsi_common_win32.c
+++ b/lib/mesa/src/vulkan/wsi/wsi_common_win32.c
@@ -26,7 +26,10 @@
#include <stdio.h>
#include <string.h>
+#include "vk_instance.h"
+#include "vk_physical_device.h"
#include "vk_util.h"
+#include "wsi_common_entrypoints.h"
#include "wsi_common_private.h"
#include "wsi_common_win32.h"
@@ -73,6 +76,15 @@ wsi_win32_get_presentation_support(struct wsi_device *wsi_device)
return TRUE;
}
+VKAPI_ATTR VkBool32 VKAPI_CALL
+wsi_GetPhysicalDeviceWin32PresentationSupportKHR(VkPhysicalDevice physicalDevice,
+ uint32_t queueFamilyIndex)
+{
+ VK_FROM_HANDLE(vk_physical_device, device, physicalDevice);
+
+ return wsi_win32_get_presentation_support(device->wsi_device);
+}
+
VkResult
wsi_create_win32_surface(VkInstance instance,
const VkAllocationCallbacks *allocator,
@@ -94,6 +106,25 @@ wsi_create_win32_surface(VkInstance instance,
return VK_SUCCESS;
}
+VKAPI_ATTR VkResult VKAPI_CALL
+wsi_CreateWin32SurfaceKHR(VkInstance _instance,
+ const VkWin32SurfaceCreateInfoKHR *pCreateInfo,
+ const VkAllocationCallbacks *pAllocator,
+ VkSurfaceKHR *pSurface)
+{
+ VK_FROM_HANDLE(vk_instance, instance, _instance);
+ const VkAllocationCallbacks *alloc;
+
+ assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR);
+
+ if (pAllocator)
+ alloc = pAllocator;
+ else
+ alloc = &instance->alloc;
+
+ return wsi_create_win32_surface(_instance, alloc, pCreateInfo, pSurface);
+}
+
static VkResult
wsi_win32_surface_get_support(VkIcdSurfaceBase *surface,
struct wsi_device *wsi_device,
@@ -301,6 +332,7 @@ wsi_create_native_image(const struct wsi_swapchain *chain,
uint32_t num_modifier_lists,
const uint32_t *num_modifiers,
const uint64_t *const *modifiers,
+ uint8_t *(alloc_shm)(struct wsi_image *image, unsigned size),
struct wsi_image *image)
{
const struct wsi_device *wsi = chain->wsi;
@@ -310,8 +342,12 @@ wsi_create_native_image(const struct wsi_swapchain *chain,
for (int i = 0; i < ARRAY_SIZE(image->fds); i++)
image->fds[i] = -1;
+ const struct wsi_image_create_info image_wsi_info = {
+ .sType = VK_STRUCTURE_TYPE_WSI_IMAGE_CREATE_INFO_MESA,
+ };
VkImageCreateInfo image_info = {
.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
+ .pNext = &image_wsi_info,
.flags = 0,
.imageType = VK_IMAGE_TYPE_2D,
.format = pCreateInfo->imageFormat,
@@ -428,7 +464,7 @@ wsi_win32_image_init(VkDevice device_h,
struct wsi_win32_swapchain *chain = (struct wsi_win32_swapchain *) drv_chain;
VkResult result = wsi_create_native_image(&chain->base, create_info,
- 0, NULL, NULL,
+ 0, NULL, NULL, NULL,
&image->base);
if (result != VK_SUCCESS)
return result;