Skip to content

Commit 3636d64

Browse files
committed
Pass through direct to driver for no-op intercepts
1 parent 34fef5a commit 3636d64

28 files changed

+18182
-6005
lines changed

generator/generate_vulkan_common.py

Lines changed: 195 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -508,40 +508,112 @@ def generate_instance_decls(
508508
if plat_define:
509509
lines.append(f'#if defined({plat_define})\n')
510510

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

518519
for i, (ptype, pname, array) in enumerate(command.params):
519520
ending = ','
520521
if i == len(command.params) - 1:
521-
ending = ');'
522+
ending = ') = delete;'
522523
parl = f' {ptype} {pname}{array}{ending}'
523524
lines.append(parl)
524525
lines.append('')
525526

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

533534
for i, (ptype, pname, array) in enumerate(command.params):
534535
ending = ','
535536
if i == len(command.params) - 1:
536-
ending = ''
537+
ending = ');'
537538
parl = f' {ptype} {pname}{array}{ending}'
538539
lines.append(parl)
540+
lines.append('')
539541

540-
parmfwd = ', '.join([x[1] for x in command.params])
541-
retfwd = 'return ' if command.rtype != 'void' else ''
542-
lines.append(') {')
543-
lines.append(f' {retfwd}layer_{command.name}_default({parmfwd});')
544-
lines.append('}\n')
542+
if plat_define:
543+
lines.append('#endif\n')
544+
545+
file.write('\n'.join(lines))
546+
file.write('\n')
547+
548+
file.write('// clang-format on\n')
549+
550+
551+
def generate_instance_queries(
552+
file: TextIO, mapping: VersionInfo, commands: list[Command]) -> None:
553+
'''
554+
Generate the instance intercept declarations header.
555+
556+
Args:
557+
file: The file to write.
558+
mapping: The version mapping information for the commands.
559+
commands: The list of commands read from the spec.
560+
'''
561+
# Write the copyright header to the file
562+
write_copyright_header(file)
563+
564+
file.write('#pragma once\n')
565+
file.write('\n')
566+
567+
file.write('// clang-format off\n')
568+
file.write('\n')
569+
570+
file.write('#include <vulkan/vulkan.h>\n')
571+
file.write('\n')
572+
573+
# Create a listing of API versions and API extensions
574+
for command in commands:
575+
if command.dispatch_type != 'instance':
576+
continue
577+
578+
lines = []
579+
assert command.name
580+
581+
plat_define = mapping.get_platform_define(command.name)
582+
if plat_define:
583+
lines.append(f'#if defined({plat_define})\n')
584+
585+
# Define the concept to test if user_tag specialization exists
586+
plist = []
587+
nlist = []
588+
for i, (ptype, pname, array) in enumerate(command.params):
589+
plist.append(f'{ptype} {pname}{array}')
590+
nlist.append(pname)
591+
plistStr = ', '.join(plist)
592+
nlistStr = ', '.join(nlist)
593+
594+
lines.append('/* Test for user_tag availability. */')
595+
decl = f'template <typename T>\n' \
596+
f'concept hasLayerPtr_{command.name} = ' \
597+
f'requires(\n {plistStr}\n) {{\n layer_{command.name}<T>({nlistStr});\n}};'
598+
lines.append(decl)
599+
lines.append('')
600+
601+
# Define the function pointer resolution
602+
lines.append('/* Function pointer resolution. */')
603+
decl = f'constexpr PFN_{command.name} getLayerPtr_{command.name}()\n' \
604+
f'{{\n' \
605+
f' return [] <typename T>\n' \
606+
f' {{\n' \
607+
f' if constexpr(hasLayerPtr_{command.name}<T>)\n' \
608+
f' {{\n' \
609+
f' return layer_{command.name}<T>;\n' \
610+
f' }}\n' \
611+
f'\n' \
612+
f' return layer_{command.name}<default_tag>;\n' \
613+
f' }}.operator()<user_tag>();\n' \
614+
f'}}'
615+
lines.append(decl)
616+
lines.append('')
545617

546618
if plat_define:
547619
lines.append('#endif\n')
@@ -582,8 +654,9 @@ def generate_instance_defs(
582654
lines.append(f'#if defined({plat_define})\n')
583655

584656
lines.append('/* See Vulkan API for documentation. */')
585-
decl = f'VKAPI_ATTR {command.rtype} ' \
586-
f'VKAPI_CALL layer_{command.name}_default('
657+
decl = f'template <>\n' \
658+
f'VKAPI_ATTR {command.rtype} ' \
659+
f'VKAPI_CALL layer_{command.name}<default_tag>('
587660
lines.append(decl)
588661

589662
for i, (ptype, pname, array) in enumerate(command.params):
@@ -691,7 +764,8 @@ def generate_device_decls(
691764
file.write('// clang-format off\n')
692765
file.write('\n')
693766

694-
file.write('#include <vulkan/vulkan.h>\n')
767+
file.write('#include <vulkan/vulkan.h>\n\n')
768+
file.write('#include "framework/utils.hpp"\n')
695769
file.write('\n')
696770

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

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

715791
for i, (ptype, pname, array) in enumerate(command.params):
716792
ending = ','
717793
if i == len(command.params) - 1:
718-
ending = ');'
794+
ending = ') = delete;'
719795
parl = f' {ptype} {pname}{array}{ending}'
720796
lines.append(parl)
721797
lines.append('')
722798

723-
# Define the default tag dispatch handler
724-
lines.append('/* Match-all template to use default implementation. */')
725-
decl = 'template <typename T>'
726-
lines.append(decl)
727-
decl = f'VKAPI_ATTR {command.rtype} VKAPI_CALL layer_{command.name}('
799+
# Define the default_tag template
800+
lines.append('/* Default common code implementation. */')
801+
decl = f'template <>\n' \
802+
f'VKAPI_ATTR {command.rtype} ' \
803+
f'VKAPI_CALL layer_{command.name}<default_tag>('
728804
lines.append(decl)
729805

730806
for i, (ptype, pname, array) in enumerate(command.params):
731807
ending = ','
732808
if i == len(command.params) - 1:
733-
ending = ''
809+
ending = ');'
734810
parl = f' {ptype} {pname}{array}{ending}'
735811
lines.append(parl)
736-
737-
parmfwd = ', '.join([x[1] for x in command.params])
738-
retfwd = 'return ' if command.rtype != 'void' else ''
739-
lines.append(') {')
740-
lines.append(f' {retfwd}layer_{command.name}_default({parmfwd});')
741-
lines.append('}\n')
812+
lines.append('')
742813

743814
if plat_define:
744815
lines.append('#endif\n')
@@ -779,9 +850,9 @@ def generate_device_defs(
779850
lines.append(f'#if defined({plat_define})\n')
780851

781852
lines.append('/* See Vulkan API for documentation. */')
782-
783-
decl = f'VKAPI_ATTR {command.rtype} ' \
784-
f'VKAPI_CALL layer_{command.name}_default('
853+
decl = f'template <>\n' \
854+
f'VKAPI_ATTR {command.rtype} ' \
855+
f'VKAPI_CALL layer_{command.name}<default_tag>('
785856
lines.append(decl)
786857

787858
for i, (ptype, pname, array) in enumerate(command.params):
@@ -815,6 +886,84 @@ def generate_device_defs(
815886
file.write(data)
816887

817888

889+
def generate_device_queries(
890+
file: TextIO, mapping: VersionInfo, commands: list[Command]) -> None:
891+
'''
892+
Generate the device intercept queries header.
893+
894+
Args:
895+
file: The file to write.
896+
mapping: The version mapping information for the commands.
897+
commands: The list of commands read from the spec.
898+
'''
899+
900+
# Write the copyright header to the file
901+
write_copyright_header(file)
902+
903+
file.write('#pragma once\n')
904+
file.write('\n')
905+
906+
file.write('// clang-format off\n')
907+
file.write('\n')
908+
909+
file.write('#include <vulkan/vulkan.h>\n\n')
910+
file.write('#include "framework/utils.hpp"\n')
911+
file.write('\n')
912+
913+
# Create a listing of API versions and API extensions
914+
for command in commands:
915+
if command.dispatch_type != 'device':
916+
continue
917+
918+
assert command.name
919+
920+
lines = []
921+
plat_define = mapping.get_platform_define(command.name)
922+
if plat_define:
923+
lines.append(f'#if defined({plat_define})\n')
924+
925+
# Define the concept to test if user_tag specialization exists
926+
plist = []
927+
nlist = []
928+
for i, (ptype, pname, array) in enumerate(command.params):
929+
plist.append(f'{ptype} {pname}{array}')
930+
nlist.append(pname)
931+
plistStr = ', '.join(plist)
932+
nlistStr = ', '.join(nlist)
933+
934+
lines.append('/* Test for user_tag availability. */')
935+
decl = f'template <typename T>\n' \
936+
f'concept hasLayerPtr_{command.name} = ' \
937+
f'requires(\n {plistStr}\n) {{\n layer_{command.name}<T>({nlistStr});\n}};'
938+
lines.append(decl)
939+
lines.append('')
940+
941+
# Define the function pointer resolution
942+
lines.append('/* Function pointer resolution. */')
943+
decl = f'constexpr PFN_{command.name} getLayerPtr_{command.name}()\n' \
944+
f'{{\n' \
945+
f' return [] <typename T>\n' \
946+
f' {{\n' \
947+
f' if constexpr(hasLayerPtr_{command.name}<T>)\n' \
948+
f' {{\n' \
949+
f' return layer_{command.name}<T>;\n' \
950+
f' }}\n' \
951+
f'\n' \
952+
f' return layer_{command.name}<default_tag>;\n' \
953+
f' }}.operator()<user_tag>();\n' \
954+
f'}}'
955+
lines.append(decl)
956+
lines.append('')
957+
958+
if plat_define:
959+
lines.append('#endif\n')
960+
961+
file.write('\n'.join(lines))
962+
file.write('\n')
963+
964+
file.write('// clang-format on\n')
965+
966+
818967
def main() -> int:
819968
'''
820969
Tool main function.
@@ -867,6 +1016,10 @@ def main() -> int:
8671016
with open(outfile, 'w', encoding='utf-8', newline='\n') as handle:
8681017
generate_instance_decls(handle, mapping, commands)
8691018

1019+
outfile = os.path.join(outdir, 'instance_functions_query.hpp')
1020+
with open(outfile, 'w', encoding='utf-8', newline='\n') as handle:
1021+
generate_instance_queries(handle, mapping, commands)
1022+
8701023
outfile = os.path.join(outdir, 'instance_functions.cpp')
8711024
with open(outfile, 'w', encoding='utf-8', newline='\n') as handle:
8721025
generate_instance_defs(handle, mapping, commands)
@@ -879,6 +1032,10 @@ def main() -> int:
8791032
with open(outfile, 'w', encoding='utf-8', newline='\n') as handle:
8801033
generate_device_decls(handle, mapping, commands)
8811034

1035+
outfile = os.path.join(outdir, 'device_functions_query.hpp')
1036+
with open(outfile, 'w', encoding='utf-8', newline='\n') as handle:
1037+
generate_device_queries(handle, mapping, commands)
1038+
8821039
outfile = os.path.join(outdir, 'device_functions.cpp')
8831040
with open(outfile, 'w', encoding='utf-8', newline='\n') as handle:
8841041
generate_device_defs(handle, mapping, commands)

generator/vk_codegen/device_dispatch_table.txt

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@
1212
#include "layer_device_functions.hpp"
1313
#endif
1414

15+
// These must be after the layer_*_functions.hpp includes
16+
#include "framework/device_functions_query.hpp"
17+
1518
/**
1619
* @brief Interception table lookup entry.
1720
*/
@@ -26,9 +29,14 @@ struct DeviceInterceptTableEntry
2629
* @brief The layer function pointer.
2730
*/
2831
PFN_vkVoidFunction function;
32+
33+
/**
34+
* @brief Did the layer provide a specialization?
35+
*/
36+
bool hasLayerSpecialization;
2937
};
3038

31-
#define ENTRY(fnc) { STR(fnc), reinterpret_cast<PFN_vkVoidFunction>(layer_##fnc<user_tag>) }
39+
#define ENTRY(fnc) { STR(fnc), reinterpret_cast<PFN_vkVoidFunction>(getLayerPtr_##fnc()), hasLayerPtr_##fnc<user_tag> }
3240

3341
/**
3442
* @brief The device dispatch table used to call the driver.

generator/vk_codegen/instance_dispatch_table.txt

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@
1313
#include "layer_instance_functions.hpp"
1414
#endif
1515

16+
// These must be after the layer_*_functions.hpp includes
17+
#include "framework/device_functions_query.hpp"
18+
#include "framework/instance_functions_query.hpp"
19+
1620
/**
1721
* @brief Interception table lookup entry.
1822
*/
@@ -27,9 +31,14 @@ struct InstanceInterceptTableEntry
2731
* @brief The layer function pointer.
2832
*/
2933
PFN_vkVoidFunction function;
34+
35+
/**
36+
* @brief Did the layer provide a specialization?
37+
*/
38+
bool hasLayerSpecialization;
3039
};
3140

32-
#define ENTRY(fnc) { STR(fnc), reinterpret_cast<PFN_vkVoidFunction>(layer_##fnc<user_tag>) }
41+
#define ENTRY(fnc) { STR(fnc), reinterpret_cast<PFN_vkVoidFunction>(getLayerPtr_##fnc()), hasLayerPtr_##fnc<user_tag> }
3342

3443
/**
3544
* @brief The instance dispatch table used to call the driver.

generator/vk_codegen/root_CMakeLists.txt

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,10 @@ project({PROJECT_NAME} VERSION 1.0.0)
3030

3131
# Common configuration
3232
set(LGL_LOG_TAG "{LAYER_NAME}")
33-
set(LGL_CONFIG_TRACE 0)
34-
set(LGL_CONFIG_LOG 1)
33+
34+
option(LGL_CONFIG_TRACE "Enable Vulkan entrypoint logging")
35+
option(LGL_CONFIG_OPTIMIZE_DISPATCH "Enable Vulkan entrypoint dispatch optimization" ON)
36+
option(LGL_CONFIG_LOG "Enable general layer logging" ON)
3537

3638
include(../source_common/compiler_helper.cmake)
3739
include(../cmake/clang-tools.cmake)

generator/vk_layer/source/instance.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ class Instance
128128
VkInstance instance;
129129

130130
/**
131-
* @brief The next layer's \c vkGetInstanceProcAddr() function pointer.
131+
* @brief The next layer's @c vkGetInstanceProcAddr() function pointer.
132132
*/
133133
PFN_vkGetInstanceProcAddr nlayerGetProcAddress;
134134

0 commit comments

Comments
 (0)