2929 * implemented as library code which can be swapped for alternative
3030 * implementations on a per-layer basis if needed.
3131 */
32+
3233#include < vulkan/utility/vk_struct_helper.hpp>
3334
3435#include " framework/manual_functions.hpp"
@@ -111,7 +112,35 @@ VkLayerDeviceCreateInfo* getChainInfo(const VkDeviceCreateInfo* pCreateInfo)
111112}
112113
113114/* See header for documentation. */
114- std::pair<bool , PFN_vkVoidFunction> getInstanceLayerFunction (const char * name)
115+ bool isFunctionAlwaysExported (const char * name)
116+ {
117+ const std::array<const char *, 11 > alwaysExportedFunctions {
118+ " vkGetInstanceProcAddr" ,
119+ " vkGetDeviceProcAddr" ,
120+ " vkEnumerateInstanceExtensionProperties" ,
121+ " vkEnumerateDeviceExtensionProperties" ,
122+ " vkEnumerateInstanceLayerProperties" ,
123+ " vkEnumerateDeviceLayerProperties" ,
124+ " vkCreateInstance" ,
125+ " vkDestroyInstance" ,
126+ " vkCreateDevice" ,
127+ " vkDestroyDevice" ,
128+ " vkGetDeviceImageMemoryRequirementsKHR" ,
129+ };
130+
131+ for (const char * functionName : alwaysExportedFunctions)
132+ {
133+ if (!strcmp (functionName, name))
134+ {
135+ return true ;
136+ }
137+ }
138+
139+ return false ;
140+ }
141+
142+ /* See header for documentation. */
143+ std::tuple<bool , PFN_vkVoidFunction, PFN_vkVoidFunction> getInstanceLayerFunction (const char * name)
115144{
116145 const std::array<const char *, 5 > globalFunctions {
117146 // Supported since Vulkan 1.0
@@ -125,7 +154,7 @@ std::pair<bool, PFN_vkVoidFunction> getInstanceLayerFunction(const char* name)
125154 };
126155
127156 bool isGlobal {false };
128- for (const auto * globalName : globalFunctions)
157+ for (const char * globalName : globalFunctions)
129158 {
130159 if (!strcmp (globalName, name))
131160 {
@@ -138,25 +167,25 @@ std::pair<bool, PFN_vkVoidFunction> getInstanceLayerFunction(const char* name)
138167 {
139168 if (!strcmp (function.name , name))
140169 {
141- return { isGlobal, function.function } ;
170+ return std::make_tuple ( isGlobal, function.function , function. defaultFunction ) ;
142171 }
143172 }
144173
145- return { isGlobal, nullptr } ;
174+ return std::make_tuple ( isGlobal, nullptr , nullptr ) ;
146175}
147176
148177/* See header for documentation. */
149- PFN_vkVoidFunction getDeviceLayerFunction (const char * name)
178+ std::pair< PFN_vkVoidFunction, PFN_vkVoidFunction> getDeviceLayerFunction (const char * name)
150179{
151180 for (auto & function : deviceIntercepts)
152181 {
153182 if (!strcmp (function.name , name))
154183 {
155- return function.function ;
184+ return { function.function , function. defaultFunction } ;
156185 }
157186 }
158187
159- return nullptr ;
188+ return { nullptr , nullptr } ;
160189}
161190
162191/* See header for documentation. */
@@ -497,7 +526,7 @@ void enableDeviceVkExtImageCompressionControl(Instance& instance,
497526/* * See Vulkan API for documentation. */
498527PFN_vkVoidFunction layer_vkGetInstanceProcAddr_default (VkInstance instance, const char * pName)
499528{
500- auto [isGlobal, layerFunction] = getInstanceLayerFunction (pName);
529+ auto [isGlobal, layerFunction, layerDefaultFunction ] = getInstanceLayerFunction (pName);
501530
502531 // Global functions must be exposed and do not require the caller to pass
503532 // a valid instance pointer, although it is required to be nullptr in
@@ -507,6 +536,15 @@ PFN_vkVoidFunction layer_vkGetInstanceProcAddr_default(VkInstance instance, cons
507536 return layerFunction;
508537 }
509538
539+ // Function is not exported because layer doesn't implement it at all
540+ bool exportLayerFunction { layerFunction != nullptr };
541+
542+ // Function is not exported because layer doesn't specialize a user_tag version
543+ if (!isFunctionAlwaysExported (pName) && layerFunction == layerDefaultFunction)
544+ {
545+ exportLayerFunction = false ;
546+ }
547+
510548 // For other functions, only expose functions that the driver exposes to
511549 // avoid changing queryable interface behavior seen by the application
512550 if (instance)
@@ -519,7 +557,7 @@ PFN_vkVoidFunction layer_vkGetInstanceProcAddr_default(VkInstance instance, cons
519557 PFN_vkVoidFunction driverFunction = layer->nlayerGetProcAddress (instance, pName);
520558
521559 // If driver exposes it and the layer has one, use the layer function
522- if (driverFunction && layerFunction )
560+ if (driverFunction && exportLayerFunction )
523561 {
524562 return layerFunction;
525563 }
@@ -542,10 +580,19 @@ PFN_vkVoidFunction layer_vkGetDeviceProcAddr_default(VkDevice device, const char
542580 // Only expose functions that the driver exposes to avoid changing
543581 // queryable interface behavior seen by the application
544582 auto driverFunction = layer->driver .vkGetDeviceProcAddr (device, pName);
545- auto layerFunction = getDeviceLayerFunction (pName);
583+ auto [layerFunction, layerDefaultFunction] = getDeviceLayerFunction (pName);
584+
585+ // Function is not exported because layer doesn't implement it at all
586+ bool exportLayerFunction { layerFunction != nullptr };
587+
588+ // Function is not exported because layer doesn't specialize a user_tag version
589+ if (!isFunctionAlwaysExported (pName) && layerFunction == layerDefaultFunction)
590+ {
591+ exportLayerFunction = false ;
592+ }
546593
547594 // If driver exposes it and the layer has one, use the layer function
548- if (driverFunction && layerFunction )
595+ if (driverFunction && exportLayerFunction )
549596 {
550597 return layerFunction;
551598 }
0 commit comments