@@ -508,40 +508,115 @@ 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 (ptype , pname , array ) in command .params :
589+ plist .append (f'{ ptype } { pname } { array } ' )
590+ nlist .append (pname )
591+ plist_str = ', ' .join (plist )
592+ nlist_str = ', ' .join (nlist )
593+
594+ lines .append ('/* Test for user_tag availability. */' )
595+ decl = f'template <typename T>\n ' \
596+ f'concept hasLayerPtr_{ command .name } = requires(\n ' \
597+ f' { plist_str } \n ' \
598+ f') {{\n ' \
599+ f' layer_{ command .name } <T>({ nlist_str } );\n ' \
600+ f'}};'
601+ lines .append (decl )
602+ lines .append ('' )
603+
604+ # Define the function pointer resolution
605+ lines .append ('/* Function pointer resolution. */' )
606+ decl = f'constexpr PFN_{ command .name } getLayerPtr_{ command .name } ()\n ' \
607+ f'{{\n ' \
608+ f' return [] <typename T>\n ' \
609+ f' {{\n ' \
610+ f' if constexpr(hasLayerPtr_{ command .name } <T>)\n ' \
611+ f' {{\n ' \
612+ f' return layer_{ command .name } <T>;\n ' \
613+ f' }}\n ' \
614+ f'\n ' \
615+ f' return layer_{ command .name } <default_tag>;\n ' \
616+ f' }}.operator()<user_tag>();\n ' \
617+ f'}}'
618+ lines .append (decl )
619+ lines .append ('' )
545620
546621 if plat_define :
547622 lines .append ('#endif\n ' )
@@ -582,8 +657,9 @@ def generate_instance_defs(
582657 lines .append (f'#if defined({ plat_define } )\n ' )
583658
584659 lines .append ('/* See Vulkan API for documentation. */' )
585- decl = f'VKAPI_ATTR { command .rtype } ' \
586- f'VKAPI_CALL layer_{ command .name } _default('
660+ decl = f'template <>\n ' \
661+ f'VKAPI_ATTR { command .rtype } ' \
662+ f'VKAPI_CALL layer_{ command .name } <default_tag>('
587663 lines .append (decl )
588664
589665 for i , (ptype , pname , array ) in enumerate (command .params ):
@@ -691,7 +767,8 @@ def generate_device_decls(
691767 file .write ('// clang-format off\n ' )
692768 file .write ('\n ' )
693769
694- file .write ('#include <vulkan/vulkan.h>\n ' )
770+ file .write ('#include <vulkan/vulkan.h>\n \n ' )
771+ file .write ('#include "framework/utils.hpp"\n ' )
695772 file .write ('\n ' )
696773
697774 # Create a listing of API versions and API extensions
@@ -706,39 +783,36 @@ def generate_device_decls(
706783 if plat_define :
707784 lines .append (f'#if defined({ plat_define } )\n ' )
708785
786+ # Explicitly delete the generic primary template
709787 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('
788+ lines .append ('/* Delete the generic match-all */' )
789+ decl = f'template <typename T>\n ' \
790+ f'VKAPI_ATTR { command .rtype } ' \
791+ f'VKAPI_CALL layer_{ command .name } ('
713792 lines .append (decl )
714793
715794 for i , (ptype , pname , array ) in enumerate (command .params ):
716795 ending = ','
717796 if i == len (command .params ) - 1 :
718- ending = ');'
797+ ending = ') = delete ;'
719798 parl = f' { ptype } { pname } { array } { ending } '
720799 lines .append (parl )
721800 lines .append ('' )
722801
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 } ('
802+ # Define the default_tag template
803+ lines .append ('/* Default common code implementation. */' )
804+ decl = f 'template <> \n ' \
805+ f'VKAPI_ATTR { command . rtype } ' \
806+ f' VKAPI_CALL layer_{ command .name } <default_tag> ('
728807 lines .append (decl )
729808
730809 for i , (ptype , pname , array ) in enumerate (command .params ):
731810 ending = ','
732811 if i == len (command .params ) - 1 :
733- ending = ''
812+ ending = '); '
734813 parl = f' { ptype } { pname } { array } { ending } '
735814 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 ' )
815+ lines .append ('' )
742816
743817 if plat_define :
744818 lines .append ('#endif\n ' )
@@ -779,9 +853,9 @@ def generate_device_defs(
779853 lines .append (f'#if defined({ plat_define } )\n ' )
780854
781855 lines .append ('/* See Vulkan API for documentation. */' )
782-
783- decl = f'VKAPI_ATTR { command .rtype } ' \
784- f'VKAPI_CALL layer_{ command .name } _default ('
856+ decl = f'template <> \n ' \
857+ f'VKAPI_ATTR { command .rtype } ' \
858+ f'VKAPI_CALL layer_{ command .name } <default_tag> ('
785859 lines .append (decl )
786860
787861 for i , (ptype , pname , array ) in enumerate (command .params ):
@@ -815,6 +889,87 @@ def generate_device_defs(
815889 file .write (data )
816890
817891
892+ def generate_device_queries (
893+ file : TextIO , mapping : VersionInfo , commands : list [Command ]) -> None :
894+ '''
895+ Generate the device intercept queries header.
896+
897+ Args:
898+ file: The file to write.
899+ mapping: The version mapping information for the commands.
900+ commands: The list of commands read from the spec.
901+ '''
902+
903+ # Write the copyright header to the file
904+ write_copyright_header (file )
905+
906+ file .write ('#pragma once\n ' )
907+ file .write ('\n ' )
908+
909+ file .write ('// clang-format off\n ' )
910+ file .write ('\n ' )
911+
912+ file .write ('#include <vulkan/vulkan.h>\n \n ' )
913+ file .write ('#include "framework/utils.hpp"\n ' )
914+ file .write ('\n ' )
915+
916+ # Create a listing of API versions and API extensions
917+ for command in commands :
918+ if command .dispatch_type != 'device' :
919+ continue
920+
921+ assert command .name
922+
923+ lines = []
924+ plat_define = mapping .get_platform_define (command .name )
925+ if plat_define :
926+ lines .append (f'#if defined({ plat_define } )\n ' )
927+
928+ # Define the concept to test if user_tag specialization exists
929+ plist = []
930+ nlist = []
931+ for (ptype , pname , array ) in command .params :
932+ plist .append (f'{ ptype } { pname } { array } ' )
933+ nlist .append (pname )
934+ plist_str = ', ' .join (plist )
935+ nlist_str = ', ' .join (nlist )
936+
937+ lines .append ('/* Test for user_tag availability. */' )
938+ decl = f'template <typename T>\n ' \
939+ f'concept hasLayerPtr_{ command .name } = requires(\n ' \
940+ f' { plist_str } \n ' \
941+ f') {{\n ' \
942+ f' layer_{ command .name } <T>({ nlist_str } );\n ' \
943+ f'}};'
944+ lines .append (decl )
945+ lines .append ('' )
946+
947+ # Define the function pointer resolution
948+ lines .append ('/* Function pointer resolution. */' )
949+ decl = f'constexpr PFN_{ command .name } getLayerPtr_{ command .name } ()\n ' \
950+ f'{{\n ' \
951+ f' return [] <typename T>\n ' \
952+ f' {{\n ' \
953+ f' if constexpr(hasLayerPtr_{ command .name } <T>)\n ' \
954+ f' {{\n ' \
955+ f' return layer_{ command .name } <T>;\n ' \
956+ f' }}\n ' \
957+ f'\n ' \
958+ f' return layer_{ command .name } <default_tag>;\n ' \
959+ f' }}.operator()<user_tag>();\n ' \
960+ f'}}'
961+ lines .append (decl )
962+ lines .append ('' )
963+
964+ if plat_define :
965+ lines .append ('#endif\n ' )
966+
967+ file .write ('\n ' .join (lines ))
968+ file .write ('\n ' )
969+
970+ file .write ('// clang-format on\n ' )
971+
972+
818973def main () -> int :
819974 '''
820975 Tool main function.
@@ -867,6 +1022,10 @@ def main() -> int:
8671022 with open (outfile , 'w' , encoding = 'utf-8' , newline = '\n ' ) as handle :
8681023 generate_instance_decls (handle , mapping , commands )
8691024
1025+ outfile = os .path .join (outdir , 'instance_functions_query.hpp' )
1026+ with open (outfile , 'w' , encoding = 'utf-8' , newline = '\n ' ) as handle :
1027+ generate_instance_queries (handle , mapping , commands )
1028+
8701029 outfile = os .path .join (outdir , 'instance_functions.cpp' )
8711030 with open (outfile , 'w' , encoding = 'utf-8' , newline = '\n ' ) as handle :
8721031 generate_instance_defs (handle , mapping , commands )
@@ -879,6 +1038,10 @@ def main() -> int:
8791038 with open (outfile , 'w' , encoding = 'utf-8' , newline = '\n ' ) as handle :
8801039 generate_device_decls (handle , mapping , commands )
8811040
1041+ outfile = os .path .join (outdir , 'device_functions_query.hpp' )
1042+ with open (outfile , 'w' , encoding = 'utf-8' , newline = '\n ' ) as handle :
1043+ generate_device_queries (handle , mapping , commands )
1044+
8821045 outfile = os .path .join (outdir , 'device_functions.cpp' )
8831046 with open (outfile , 'w' , encoding = 'utf-8' , newline = '\n ' ) as handle :
8841047 generate_device_defs (handle , mapping , commands )
0 commit comments