Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .pylintrc
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ ignore-patterns=^\.#
# manipulated during runtime and thus existing member attributes cannot be
# deduced by static analysis). It supports qualified module names, as well as
# Unix pattern matching.
ignored-modules=cairo,protos
ignored-modules=cairo,protos,lglpy.timeline.protos.*

# Python code to execute, usually for sys.path manipulation such as
# pygtk.require().
Expand Down
239 changes: 201 additions & 38 deletions generator/generate_vulkan_common.py
Original file line number Diff line number Diff line change
Expand Up @@ -508,40 +508,115 @@ def generate_instance_decls(
if plat_define:
lines.append(f'#if defined({plat_define})\n')

# Declare the default implementation
# Explicitly delete the generic primary template
lines.append('/* See Vulkan API for documentation. */')
lines.append('/* Default common code pass-through implementation. */')
decl = f'VKAPI_ATTR {command.rtype} ' \
f'VKAPI_CALL layer_{command.name}_default('
lines.append('/* Delete the generic match-all */')
decl = f'template <typename T>\n' \
f'VKAPI_ATTR {command.rtype} ' \
f'VKAPI_CALL layer_{command.name}('
lines.append(decl)

for i, (ptype, pname, array) in enumerate(command.params):
ending = ','
if i == len(command.params) - 1:
ending = ');'
ending = ') = delete;'
parl = f' {ptype} {pname}{array}{ending}'
lines.append(parl)
lines.append('')

# Define the default tag dispatch handler
lines.append('/* Match-all template to use default implementation. */')
decl = 'template <typename T>'
lines.append(decl)
decl = f'VKAPI_ATTR {command.rtype} VKAPI_CALL layer_{command.name}('
# Define the default_tag template
lines.append('/* Default common code implementation. */')
decl = f'template <>\n' \
f'VKAPI_ATTR {command.rtype} ' \
f'VKAPI_CALL layer_{command.name}<default_tag>('
lines.append(decl)

for i, (ptype, pname, array) in enumerate(command.params):
ending = ','
if i == len(command.params) - 1:
ending = ''
ending = ');'
parl = f' {ptype} {pname}{array}{ending}'
lines.append(parl)
lines.append('')

parmfwd = ', '.join([x[1] for x in command.params])
retfwd = 'return ' if command.rtype != 'void' else ''
lines.append(') {')
lines.append(f' {retfwd}layer_{command.name}_default({parmfwd});')
lines.append('}\n')
if plat_define:
lines.append('#endif\n')

file.write('\n'.join(lines))
file.write('\n')

file.write('// clang-format on\n')


def generate_instance_queries(
file: TextIO, mapping: VersionInfo, commands: list[Command]) -> None:
'''
Generate the instance intercept declarations header.

Args:
file: The file to write.
mapping: The version mapping information for the commands.
commands: The list of commands read from the spec.
'''
# Write the copyright header to the file
write_copyright_header(file)

file.write('#pragma once\n')
file.write('\n')

file.write('// clang-format off\n')
file.write('\n')

file.write('#include <vulkan/vulkan.h>\n')
file.write('\n')

# Create a listing of API versions and API extensions
for command in commands:
if command.dispatch_type != 'instance':
continue

lines = []
assert command.name

plat_define = mapping.get_platform_define(command.name)
if plat_define:
lines.append(f'#if defined({plat_define})\n')

# Define the concept to test if user_tag specialization exists
plist = []
nlist = []
for (ptype, pname, array) in command.params:
plist.append(f'{ptype} {pname}{array}')
nlist.append(pname)
plist_str = ', '.join(plist)
nlist_str = ', '.join(nlist)

lines.append('/* Test for user_tag availability. */')
decl = f'template <typename T>\n' \
f'concept hasLayerPtr_{command.name} = requires(\n' \
f' {plist_str}\n' \
f') {{\n' \
f' layer_{command.name}<T>({nlist_str});\n' \
f'}};'
lines.append(decl)
lines.append('')

# Define the function pointer resolution
lines.append('/* Function pointer resolution. */')
decl = f'constexpr PFN_{command.name} getLayerPtr_{command.name}()\n' \
f'{{\n' \
f' return [] <typename T>\n' \
f' {{\n' \
f' if constexpr(hasLayerPtr_{command.name}<T>)\n' \
f' {{\n' \
f' return layer_{command.name}<T>;\n' \
f' }}\n' \
f'\n' \
f' return layer_{command.name}<default_tag>;\n' \
f' }}.operator()<user_tag>();\n' \
f'}}'
lines.append(decl)
lines.append('')

if plat_define:
lines.append('#endif\n')
Expand Down Expand Up @@ -582,8 +657,9 @@ def generate_instance_defs(
lines.append(f'#if defined({plat_define})\n')

lines.append('/* See Vulkan API for documentation. */')
decl = f'VKAPI_ATTR {command.rtype} ' \
f'VKAPI_CALL layer_{command.name}_default('
decl = f'template <>\n' \
f'VKAPI_ATTR {command.rtype} ' \
f'VKAPI_CALL layer_{command.name}<default_tag>('
lines.append(decl)

for i, (ptype, pname, array) in enumerate(command.params):
Expand Down Expand Up @@ -691,7 +767,8 @@ def generate_device_decls(
file.write('// clang-format off\n')
file.write('\n')

file.write('#include <vulkan/vulkan.h>\n')
file.write('#include <vulkan/vulkan.h>\n\n')
file.write('#include "framework/utils.hpp"\n')
file.write('\n')

# Create a listing of API versions and API extensions
Expand All @@ -706,39 +783,36 @@ def generate_device_decls(
if plat_define:
lines.append(f'#if defined({plat_define})\n')

# Explicitly delete the generic primary template
lines.append('/* See Vulkan API for documentation. */')
lines.append('/* Default common code pass-through implementation. */')
decl = f'VKAPI_ATTR {command.rtype} ' \
f'VKAPI_CALL layer_{command.name}_default('
lines.append('/* Delete the generic match-all */')
decl = f'template <typename T>\n' \
f'VKAPI_ATTR {command.rtype} ' \
f'VKAPI_CALL layer_{command.name}('
lines.append(decl)

for i, (ptype, pname, array) in enumerate(command.params):
ending = ','
if i == len(command.params) - 1:
ending = ');'
ending = ') = delete;'
parl = f' {ptype} {pname}{array}{ending}'
lines.append(parl)
lines.append('')

# Define the default tag dispatch handler
lines.append('/* Match-all template to use default implementation. */')
decl = 'template <typename T>'
lines.append(decl)
decl = f'VKAPI_ATTR {command.rtype} VKAPI_CALL layer_{command.name}('
# Define the default_tag template
lines.append('/* Default common code implementation. */')
decl = f'template <>\n' \
f'VKAPI_ATTR {command.rtype} ' \
f'VKAPI_CALL layer_{command.name}<default_tag>('
lines.append(decl)

for i, (ptype, pname, array) in enumerate(command.params):
ending = ','
if i == len(command.params) - 1:
ending = ''
ending = ');'
parl = f' {ptype} {pname}{array}{ending}'
lines.append(parl)

parmfwd = ', '.join([x[1] for x in command.params])
retfwd = 'return ' if command.rtype != 'void' else ''
lines.append(') {')
lines.append(f' {retfwd}layer_{command.name}_default({parmfwd});')
lines.append('}\n')
lines.append('')

if plat_define:
lines.append('#endif\n')
Expand Down Expand Up @@ -779,9 +853,9 @@ def generate_device_defs(
lines.append(f'#if defined({plat_define})\n')

lines.append('/* See Vulkan API for documentation. */')

decl = f'VKAPI_ATTR {command.rtype} ' \
f'VKAPI_CALL layer_{command.name}_default('
decl = f'template <>\n' \
f'VKAPI_ATTR {command.rtype} ' \
f'VKAPI_CALL layer_{command.name}<default_tag>('
lines.append(decl)

for i, (ptype, pname, array) in enumerate(command.params):
Expand Down Expand Up @@ -815,6 +889,87 @@ def generate_device_defs(
file.write(data)


def generate_device_queries(
file: TextIO, mapping: VersionInfo, commands: list[Command]) -> None:
'''
Generate the device intercept queries header.

Args:
file: The file to write.
mapping: The version mapping information for the commands.
commands: The list of commands read from the spec.
'''

# Write the copyright header to the file
write_copyright_header(file)

file.write('#pragma once\n')
file.write('\n')

file.write('// clang-format off\n')
file.write('\n')

file.write('#include <vulkan/vulkan.h>\n\n')
file.write('#include "framework/utils.hpp"\n')
file.write('\n')

# Create a listing of API versions and API extensions
for command in commands:
if command.dispatch_type != 'device':
continue

assert command.name

lines = []
plat_define = mapping.get_platform_define(command.name)
if plat_define:
lines.append(f'#if defined({plat_define})\n')

# Define the concept to test if user_tag specialization exists
plist = []
nlist = []
for (ptype, pname, array) in command.params:
plist.append(f'{ptype} {pname}{array}')
nlist.append(pname)
plist_str = ', '.join(plist)
nlist_str = ', '.join(nlist)

lines.append('/* Test for user_tag availability. */')
decl = f'template <typename T>\n' \
f'concept hasLayerPtr_{command.name} = requires(\n' \
f' {plist_str}\n' \
f') {{\n' \
f' layer_{command.name}<T>({nlist_str});\n' \
f'}};'
lines.append(decl)
lines.append('')

# Define the function pointer resolution
lines.append('/* Function pointer resolution. */')
decl = f'constexpr PFN_{command.name} getLayerPtr_{command.name}()\n' \
f'{{\n' \
f' return [] <typename T>\n' \
f' {{\n' \
f' if constexpr(hasLayerPtr_{command.name}<T>)\n' \
f' {{\n' \
f' return layer_{command.name}<T>;\n' \
f' }}\n' \
f'\n' \
f' return layer_{command.name}<default_tag>;\n' \
f' }}.operator()<user_tag>();\n' \
f'}}'
lines.append(decl)
lines.append('')

if plat_define:
lines.append('#endif\n')

file.write('\n'.join(lines))
file.write('\n')

file.write('// clang-format on\n')


def main() -> int:
'''
Tool main function.
Expand Down Expand Up @@ -867,6 +1022,10 @@ def main() -> int:
with open(outfile, 'w', encoding='utf-8', newline='\n') as handle:
generate_instance_decls(handle, mapping, commands)

outfile = os.path.join(outdir, 'instance_functions_query.hpp')
with open(outfile, 'w', encoding='utf-8', newline='\n') as handle:
generate_instance_queries(handle, mapping, commands)

outfile = os.path.join(outdir, 'instance_functions.cpp')
with open(outfile, 'w', encoding='utf-8', newline='\n') as handle:
generate_instance_defs(handle, mapping, commands)
Expand All @@ -879,6 +1038,10 @@ def main() -> int:
with open(outfile, 'w', encoding='utf-8', newline='\n') as handle:
generate_device_decls(handle, mapping, commands)

outfile = os.path.join(outdir, 'device_functions_query.hpp')
with open(outfile, 'w', encoding='utf-8', newline='\n') as handle:
generate_device_queries(handle, mapping, commands)

outfile = os.path.join(outdir, 'device_functions.cpp')
with open(outfile, 'w', encoding='utf-8', newline='\n') as handle:
generate_device_defs(handle, mapping, commands)
Expand Down
10 changes: 9 additions & 1 deletion generator/vk_codegen/device_dispatch_table.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@
#include "layer_device_functions.hpp"
#endif

// These must be after the layer_*_functions.hpp includes
#include "framework/device_functions_query.hpp"

/**
* @brief Interception table lookup entry.
*/
Expand All @@ -26,9 +29,14 @@ struct DeviceInterceptTableEntry
* @brief The layer function pointer.
*/
PFN_vkVoidFunction function;

/**
* @brief Did the layer provide a specialization?
*/
bool hasLayerSpecialization;
};

#define ENTRY(fnc) { STR(fnc), reinterpret_cast<PFN_vkVoidFunction>(layer_##fnc<user_tag>) }
#define ENTRY(fnc) { STR(fnc), reinterpret_cast<PFN_vkVoidFunction>(getLayerPtr_##fnc()), hasLayerPtr_##fnc<user_tag> }

/**
* @brief The device dispatch table used to call the driver.
Expand Down
11 changes: 10 additions & 1 deletion generator/vk_codegen/instance_dispatch_table.txt
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@
#include "layer_instance_functions.hpp"
#endif

// These must be after the layer_*_functions.hpp includes
#include "framework/device_functions_query.hpp"
#include "framework/instance_functions_query.hpp"

/**
* @brief Interception table lookup entry.
*/
Expand All @@ -27,9 +31,14 @@ struct InstanceInterceptTableEntry
* @brief The layer function pointer.
*/
PFN_vkVoidFunction function;

/**
* @brief Did the layer provide a specialization?
*/
bool hasLayerSpecialization;
};

#define ENTRY(fnc) { STR(fnc), reinterpret_cast<PFN_vkVoidFunction>(layer_##fnc<user_tag>) }
#define ENTRY(fnc) { STR(fnc), reinterpret_cast<PFN_vkVoidFunction>(getLayerPtr_##fnc()), hasLayerPtr_##fnc<user_tag> }

/**
* @brief The instance dispatch table used to call the driver.
Expand Down
Loading