mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2025-12-23 17:40:11 +01:00
vulkan: Add some auto-generated synchronization helpers
These are helpful for drivers to implement synchronization rules Reviewed-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com> Reviewed-by: Konstantin Seurer <konstantin.seurer@gmail.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/26407>
This commit is contained in:
parent
9ad51980de
commit
fe12c1c29e
4 changed files with 299 additions and 1 deletions
|
|
@ -109,6 +109,7 @@ vulkan_runtime_files = files(
|
|||
'vk_sync_timeline.c',
|
||||
'vk_sync_timeline.h',
|
||||
'vk_synchronization.c',
|
||||
'vk_synchronization.h',
|
||||
'vk_texcompress_etc2.c',
|
||||
'vk_texcompress_etc2.h',
|
||||
'vk_video.c',
|
||||
|
|
@ -218,6 +219,18 @@ vk_physical_device_properties = custom_target(
|
|||
depend_files : vk_physical_device_properties_gen_depend_files,
|
||||
)
|
||||
|
||||
vk_synchronization_helpers = custom_target(
|
||||
'vk_synchronization_helpers',
|
||||
input : [vk_synchronization_helpers_gen, vk_api_xml],
|
||||
output : ['vk_synchronization_helpers.c', 'vk_synchronization_helpers.h'],
|
||||
command : [
|
||||
prog_python, '@INPUT0@', '--xml', '@INPUT1@',
|
||||
'--out-c', '@OUTPUT0@',
|
||||
'--beta', with_vulkan_beta.to_string()
|
||||
],
|
||||
depend_files : vk_synchronization_helpers_gen_depend_files,
|
||||
)
|
||||
|
||||
vk_format_info = custom_target(
|
||||
'vk_format_info',
|
||||
input : ['vk_format_info_gen.py', vk_api_xml],
|
||||
|
|
@ -233,7 +246,8 @@ libvulkan_runtime = static_library(
|
|||
[vulkan_runtime_files, vk_common_entrypoints,
|
||||
vk_cmd_queue, vk_cmd_enqueue_entrypoints,
|
||||
vk_dispatch_trampolines, vk_physical_device_features,
|
||||
vk_physical_device_properties, vk_format_info],
|
||||
vk_physical_device_properties, vk_synchronization_helpers,
|
||||
vk_format_info],
|
||||
include_directories : [inc_include, inc_src],
|
||||
dependencies : vulkan_runtime_deps,
|
||||
c_args : c_msvc_compat_args,
|
||||
|
|
|
|||
55
src/vulkan/runtime/vk_synchronization.h
Normal file
55
src/vulkan/runtime/vk_synchronization.h
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
* Copyright © 2023 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.
|
||||
*/
|
||||
#ifndef VK_SYNCHRONIZATION_H
|
||||
#define VK_SYNCHRONIZATION_H
|
||||
|
||||
#include <vulkan/vulkan_core.h>
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** Expands pipeline stage group flags
|
||||
*
|
||||
* Some stages like VK_PIPELINE_SHADER_STAGE_2_ALL_GRAPHICS_BIT represent more
|
||||
* than one stage. This helper expands any such bits out to the full set of
|
||||
* individual stages bits they represent.
|
||||
*/
|
||||
VkPipelineStageFlags2
|
||||
vk_expand_pipeline_stage_flags2(VkPipelineStageFlags2 stages);
|
||||
|
||||
/** Returns the set of read accesses allowed in the given stages */
|
||||
VkAccessFlags2
|
||||
vk_read_access2_for_pipeline_stage_flags2(VkPipelineStageFlags2 stages);
|
||||
|
||||
/** Returns the set of write accesses allowed in the given stages */
|
||||
VkAccessFlags2
|
||||
vk_write_access2_for_pipeline_stage_flags2(VkPipelineStageFlags2 stages);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* VK_SYNCHRONIZATION_H */
|
||||
|
|
@ -52,6 +52,9 @@ vk_physical_device_features_gen_depend_files = [
|
|||
vk_physical_device_properties_gen_depend_files = [
|
||||
files('vk_extensions.py'),
|
||||
]
|
||||
vk_synchronization_helpers_gen_depend_files = [
|
||||
files('vk_extensions.py'),
|
||||
]
|
||||
|
||||
vk_entrypoints_gen = files('vk_entrypoints_gen.py')
|
||||
vk_extensions_gen = files('vk_extensions_gen.py')
|
||||
|
|
@ -60,6 +63,7 @@ vk_cmd_queue_gen = files('vk_cmd_queue_gen.py')
|
|||
vk_dispatch_trampolines_gen = files('vk_dispatch_trampolines_gen.py')
|
||||
vk_physical_device_features_gen = files('vk_physical_device_features_gen.py')
|
||||
vk_physical_device_properties_gen = files('vk_physical_device_properties_gen.py')
|
||||
vk_synchronization_helpers_gen = files('vk_synchronization_helpers_gen.py')
|
||||
|
||||
files_vulkan_util = files(
|
||||
'vk_alloc.c',
|
||||
|
|
|
|||
225
src/vulkan/util/vk_synchronization_helpers_gen.py
Normal file
225
src/vulkan/util/vk_synchronization_helpers_gen.py
Normal file
|
|
@ -0,0 +1,225 @@
|
|||
COPYRIGHT=u"""
|
||||
/* Copyright © 2023 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 textwrap
|
||||
import xml.etree.ElementTree as et
|
||||
|
||||
from mako.template import Template
|
||||
from vk_extensions import get_api_list
|
||||
|
||||
TEMPLATE_C = Template(COPYRIGHT + """\
|
||||
#include "vk_synchronization.h"
|
||||
|
||||
VkPipelineStageFlags2
|
||||
vk_expand_pipeline_stage_flags2(VkPipelineStageFlags2 stages)
|
||||
{
|
||||
% for (group_stage, stages) in group_stages.items():
|
||||
if (stages & ${group_stage})
|
||||
stages |= ${' |\\n '.join(stages)};
|
||||
|
||||
% endfor
|
||||
if (stages & VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT) {
|
||||
% for (guard, stage) in all_commands_stages:
|
||||
% if guard is not None:
|
||||
#ifdef ${guard}
|
||||
% endif
|
||||
stages |= ${stage};
|
||||
% if guard is not None:
|
||||
#endif
|
||||
% endif
|
||||
% endfor
|
||||
}
|
||||
|
||||
return stages;
|
||||
}
|
||||
|
||||
VkAccessFlags2
|
||||
vk_read_access2_for_pipeline_stage_flags2(VkPipelineStageFlags2 stages)
|
||||
{
|
||||
VkAccessFlags2 access = 0;
|
||||
|
||||
% for ((guard, stages), access) in stages_read_access.items():
|
||||
% if guard is not None:
|
||||
#ifdef ${guard}
|
||||
% endif
|
||||
if (stages & (${' |\\n '.join(stages)}))
|
||||
access |= ${' |\\n '.join(access)};
|
||||
% if guard is not None:
|
||||
#endif
|
||||
% endif
|
||||
|
||||
% endfor
|
||||
return access;
|
||||
}
|
||||
|
||||
VkAccessFlags2
|
||||
vk_write_access2_for_pipeline_stage_flags2(VkPipelineStageFlags2 stages)
|
||||
{
|
||||
VkAccessFlags2 access = 0;
|
||||
|
||||
% for ((guard, stages), access) in stages_write_access.items():
|
||||
% if guard is not None:
|
||||
#ifdef ${guard}
|
||||
% endif
|
||||
if (stages & (${' |\\n '.join(stages)}))
|
||||
access |= ${' |\\n '.join(access)};
|
||||
% if guard is not None:
|
||||
#endif
|
||||
% endif
|
||||
|
||||
% endfor
|
||||
return access;
|
||||
}
|
||||
""")
|
||||
|
||||
def get_guards(xml, api):
|
||||
guards = {}
|
||||
for ext_elem in xml.findall('./extensions/extension'):
|
||||
supported = get_api_list(ext_elem.attrib['supported'])
|
||||
if api not in supported:
|
||||
continue
|
||||
|
||||
for enum in ext_elem.findall('./require/enum[@extends]'):
|
||||
if enum.attrib['extends'] not in ('VkPipelineStageFlagBits2',
|
||||
'VkAccessFlagBits2'):
|
||||
continue
|
||||
|
||||
if 'protect' not in enum.attrib:
|
||||
continue
|
||||
|
||||
name = enum.attrib['name']
|
||||
guard = enum.attrib['protect']
|
||||
guards[name] = guard
|
||||
|
||||
return guards
|
||||
|
||||
def get_all_commands_stages(xml, guards):
|
||||
stages = []
|
||||
for stage in xml.findall('./sync/syncstage'):
|
||||
stage_name = stage.attrib['name']
|
||||
|
||||
exclude = [
|
||||
# This isn't a real stage
|
||||
'VK_PIPELINE_STAGE_2_NONE',
|
||||
|
||||
# These are real stages but they're a bit weird to include in
|
||||
# ALL_COMMANDS because they're context-dependent, depending on
|
||||
# whether they're part of srcStagesMask or dstStagesMask.
|
||||
#
|
||||
# We could avoid all grouped stages but then if someone adds
|
||||
# another group later, the behavior of this function may change in
|
||||
# a backwards-compatible way. Also, the other ones aren't really
|
||||
# hurting anything if we add them in.
|
||||
'VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT',
|
||||
'VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT',
|
||||
|
||||
# This is all COMMANDS, not host.
|
||||
'VK_PIPELINE_STAGE_2_HOST_BIT',
|
||||
]
|
||||
if stage_name in exclude:
|
||||
continue
|
||||
|
||||
guard = guards.get(stage_name, None)
|
||||
stages.append((guard, stage_name))
|
||||
|
||||
return stages
|
||||
|
||||
def get_group_stages(xml):
|
||||
group_stages = {}
|
||||
for stage in xml.findall('./sync/syncstage'):
|
||||
name = stage.attrib['name']
|
||||
equiv = stage.find('./syncequivalent')
|
||||
if equiv is not None:
|
||||
stages = equiv.attrib['stage'].split(',')
|
||||
group_stages[name] = stages
|
||||
|
||||
return group_stages
|
||||
|
||||
def access_is_read(name):
|
||||
if 'READ' in name:
|
||||
assert 'WRITE' not in name
|
||||
return True
|
||||
elif 'WRITE' in name:
|
||||
return False
|
||||
else:
|
||||
print(name)
|
||||
assert False, "Invalid access bit name"
|
||||
|
||||
def get_stages_access(xml, read, guards):
|
||||
stages_access = {}
|
||||
for access in xml.findall('./sync/syncaccess'):
|
||||
access_name = access.attrib['name']
|
||||
if access_name == 'VK_ACCESS_2_NONE':
|
||||
continue
|
||||
|
||||
if access_is_read(access_name) != read:
|
||||
continue
|
||||
|
||||
guard = guards.get(access_name, None)
|
||||
support = access.find('./syncsupport')
|
||||
if support is not None:
|
||||
stages = support.attrib['stage'].split(',')
|
||||
stages.sort()
|
||||
key = (guard, tuple(stages))
|
||||
if key in stages_access:
|
||||
stages_access[key].append(access_name)
|
||||
else:
|
||||
stages_access[key] = [access_name]
|
||||
|
||||
return stages_access
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('--beta', required=True, help='Enable beta extensions.')
|
||||
parser.add_argument('--xml', required=True, help='Vulkan API XML file')
|
||||
parser.add_argument('--out-c', required=True, help='Output C file.')
|
||||
args = parser.parse_args()
|
||||
|
||||
xml = et.parse(args.xml);
|
||||
|
||||
guards = get_guards(xml, 'vulkan')
|
||||
environment = {
|
||||
'all_commands_stages': get_all_commands_stages(xml, guards),
|
||||
'group_stages': get_group_stages(xml),
|
||||
'stages_read_access': get_stages_access(xml, True, guards),
|
||||
'stages_write_access': get_stages_access(xml, False, guards),
|
||||
}
|
||||
|
||||
try:
|
||||
with open(args.out_c, 'w') 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
|
||||
import sys
|
||||
from mako import exceptions
|
||||
print(exceptions.text_error_template().render(), file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
Loading…
Add table
Reference in a new issue