Skip to content

Commit 6424ea5

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

26 files changed

+15907
-6003
lines changed

generator/generate_vulkan_common.py

Lines changed: 179 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -508,40 +508,104 @@ 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+
lines.append('/* Test for user_tag availability. */')
587+
decl = f'template <typename T>\n' \
588+
f'concept hasLayerPtr_{command.name} = ' \
589+
f'requires {{ layer_{command.name}<T>(); }};'
590+
lines.append(decl)
591+
lines.append('')
592+
593+
# Define the function pointer resolution
594+
lines.append('/* Function pointer resolution. */')
595+
decl = f'constexpr PFN_{command.name} getLayerPtr_{command.name}()\n' \
596+
f'{{\n' \
597+
f' return [] <typename T>\n' \
598+
f' {{\n' \
599+
f' if constexpr(hasLayerPtr_{command.name}<T>)\n' \
600+
f' {{\n' \
601+
f' return layer_{command.name}<T>;\n' \
602+
f' }}\n' \
603+
f'\n' \
604+
f' return layer_{command.name}<default_tag>;\n' \
605+
f' }}.operator()<user_tag>();\n' \
606+
f'}}'
607+
lines.append(decl)
608+
lines.append('')
545609

546610
if plat_define:
547611
lines.append('#endif\n')
@@ -582,8 +646,9 @@ def generate_instance_defs(
582646
lines.append(f'#if defined({plat_define})\n')
583647

584648
lines.append('/* See Vulkan API for documentation. */')
585-
decl = f'VKAPI_ATTR {command.rtype} ' \
586-
f'VKAPI_CALL layer_{command.name}_default('
649+
decl = f'template <>\n' \
650+
f'VKAPI_ATTR {command.rtype} ' \
651+
f'VKAPI_CALL layer_{command.name}<default_tag>('
587652
lines.append(decl)
588653

589654
for i, (ptype, pname, array) in enumerate(command.params):
@@ -691,7 +756,8 @@ def generate_device_decls(
691756
file.write('// clang-format off\n')
692757
file.write('\n')
693758

694-
file.write('#include <vulkan/vulkan.h>\n')
759+
file.write('#include <vulkan/vulkan.h>\n\n')
760+
file.write('#include "framework/utils.hpp"\n')
695761
file.write('\n')
696762

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

775+
# Explicitly delete the generic primary template
709776
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('
777+
lines.append('/* Delete the generic match-all */')
778+
decl = f'template <typename T>\n' \
779+
f'VKAPI_ATTR {command.rtype} ' \
780+
f'VKAPI_CALL layer_{command.name}('
713781
lines.append(decl)
714782

715783
for i, (ptype, pname, array) in enumerate(command.params):
716784
ending = ','
717785
if i == len(command.params) - 1:
718-
ending = ');'
786+
ending = ') = delete;'
719787
parl = f' {ptype} {pname}{array}{ending}'
720788
lines.append(parl)
721789
lines.append('')
722790

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}('
791+
# Define the default_tag template
792+
lines.append('/* Default common code implementation. */')
793+
decl = f'template <>\n' \
794+
f'VKAPI_ATTR {command.rtype} ' \
795+
f'VKAPI_CALL layer_{command.name}<default_tag>('
728796
lines.append(decl)
729797

730798
for i, (ptype, pname, array) in enumerate(command.params):
731799
ending = ','
732800
if i == len(command.params) - 1:
733-
ending = ''
801+
ending = ');'
734802
parl = f' {ptype} {pname}{array}{ending}'
735803
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')
804+
lines.append('')
742805

743806
if plat_define:
744807
lines.append('#endif\n')
@@ -779,9 +842,9 @@ def generate_device_defs(
779842
lines.append(f'#if defined({plat_define})\n')
780843

781844
lines.append('/* See Vulkan API for documentation. */')
782-
783-
decl = f'VKAPI_ATTR {command.rtype} ' \
784-
f'VKAPI_CALL layer_{command.name}_default('
845+
decl = f'template <>\n' \
846+
f'VKAPI_ATTR {command.rtype} ' \
847+
f'VKAPI_CALL layer_{command.name}<default_tag>('
785848
lines.append(decl)
786849

787850
for i, (ptype, pname, array) in enumerate(command.params):
@@ -815,6 +878,76 @@ def generate_device_defs(
815878
file.write(data)
816879

817880

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

1003+
outfile = os.path.join(outdir, 'instance_functions_query.hpp')
1004+
with open(outfile, 'w', encoding='utf-8', newline='\n') as handle:
1005+
generate_instance_queries(handle, mapping, commands)
1006+
8701007
outfile = os.path.join(outdir, 'instance_functions.cpp')
8711008
with open(outfile, 'w', encoding='utf-8', newline='\n') as handle:
8721009
generate_instance_defs(handle, mapping, commands)
@@ -879,6 +1016,10 @@ def main() -> int:
8791016
with open(outfile, 'w', encoding='utf-8', newline='\n') as handle:
8801017
generate_device_decls(handle, mapping, commands)
8811018

1019+
outfile = os.path.join(outdir, 'device_functions_query.hpp')
1020+
with open(outfile, 'w', encoding='utf-8', newline='\n') as handle:
1021+
generate_device_queries(handle, mapping, commands)
1022+
8821023
outfile = os.path.join(outdir, 'device_functions.cpp')
8831024
with open(outfile, 'w', encoding='utf-8', newline='\n') as handle:
8841025
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

layer_example/CMakeLists.txt

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,11 @@ project(VkLayerExample VERSION 1.0.0)
3030

3131
# Common configuration
3232
set(LGL_LOG_TAG "VkLayerExample")
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)
37+
3538

3639
include(../source_common/compiler_helper.cmake)
3740
include(../cmake/clang-tools.cmake)

0 commit comments

Comments
 (0)