summaryrefslogtreecommitdiff
path: root/lib/mesa/src/vulkan/util
diff options
context:
space:
mode:
authorJonathan Gray <jsg@cvs.openbsd.org>2022-02-24 01:57:18 +0000
committerJonathan Gray <jsg@cvs.openbsd.org>2022-02-24 01:57:18 +0000
commitb24b5b9049e889ee4eb39b565bcc8d48bd45ab48 (patch)
tree658ca4e6b41655f49463c85edbaeda48979c394c /lib/mesa/src/vulkan/util
parent57768bbb154c2879d34ec20e401b19472e77aaf7 (diff)
Import Mesa 21.3.7
Diffstat (limited to 'lib/mesa/src/vulkan/util')
-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
30 files changed, 4056 insertions, 63 deletions
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;
+}