Skip to content

Commit e181c48

Browse files
authored
Fix vkGetInstanceProcAddr() interception (#20)
1 parent 036b0da commit e181c48

File tree

3 files changed

+89
-47
lines changed

3 files changed

+89
-47
lines changed

generator/generate_vulkan_common.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -340,6 +340,7 @@ def generate_layer_instance_dispatch_table(file, mapping, commands):
340340
itable_members = []
341341
dispatch_table_members = []
342342
dispatch_table_inits = []
343+
343344
for command in commands:
344345
# Skip commands that are not instance commands
345346
if command.dispatch_type != 'instance':
@@ -369,7 +370,6 @@ def generate_layer_instance_dispatch_table(file, mapping, commands):
369370
dispatch_table_members.append('#endif')
370371
dispatch_table_inits.append('#endif')
371372

372-
373373
data = data.replace('{ITABLE_MEMBERS}', '\n'.join(itable_members))
374374
data = data.replace('{DTABLE_MEMBERS}', '\n'.join(dispatch_table_members))
375375
data = data.replace('{DTABLE_INITS}', '\n'.join(dispatch_table_inits))

generator/vk_common/entry_utils.hpp

Lines changed: 44 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -98,26 +98,42 @@ struct DispatchTableEntry
9898
* \return The layer function pointer, or \c nullptr if the layer doesn't
9999
* intercept the function.
100100
*/
101-
static PFN_vkVoidFunction get_instance_layer_function(
101+
static PFN_vkVoidFunction get_fixed_instance_layer_function(
102102
const char* name
103103
) {
104-
static const DispatchTableEntry layer_functions[] = {
104+
static const DispatchTableEntry layerFunctions[] = {
105105
VK_TABLE_ENTRY(vkGetInstanceProcAddr),
106+
VK_TABLE_ENTRY(vkEnumerateDeviceLayerProperties),
107+
VK_TABLE_ENTRY(vkEnumerateDeviceExtensionProperties),
106108
VK_TABLE_ENTRY(vkEnumerateInstanceLayerProperties),
107109
VK_TABLE_ENTRY(vkEnumerateInstanceExtensionProperties),
108110
};
109111

110-
for (auto &function : instanceIntercepts)
112+
for (auto &function : layerFunctions)
111113
{
112114
if (!strcmp(function.name, name))
113115
{
114116
return function.function;
115117
}
116118
}
117119

118-
for (auto &function : layer_functions)
120+
return nullptr;
121+
}
122+
123+
/**
124+
* @brief Fetch the layer function for a given instance entrypoint name.
125+
*
126+
* @param name The layer entry point name.
127+
*
128+
* \return The layer function pointer, or \c nullptr if the layer doesn't
129+
* intercept the function.
130+
*/
131+
static PFN_vkVoidFunction get_instance_layer_function(
132+
const char* name
133+
) {
134+
for (auto &function : instanceIntercepts)
119135
{
120-
if (strcmp(function.name, name) == 0)
136+
if (!strcmp(function.name, name))
121137
{
122138
return function.function;
123139
}
@@ -136,21 +152,21 @@ static PFN_vkVoidFunction get_instance_layer_function(
136152
static PFN_vkVoidFunction get_device_layer_function(
137153
const char* name
138154
) {
139-
static const DispatchTableEntry layer_functions[] = {
155+
static const DispatchTableEntry layerFunctions[] = {
140156
VK_TABLE_ENTRY(vkGetDeviceProcAddr),
141157
VK_TABLE_ENTRY(vkEnumerateDeviceExtensionProperties),
142158
VK_TABLE_ENTRY(vkEnumerateDeviceLayerProperties),
143159
};
144160

145-
for (auto &function : deviceIntercepts)
161+
for (auto &function : layerFunctions)
146162
{
147163
if (!strcmp(function.name, name))
148164
{
149165
return function.function;
150166
}
151167
}
152168

153-
for (auto &function : layer_functions)
169+
for (auto &function : deviceIntercepts)
154170
{
155171
if (!strcmp(function.name, name))
156172
{
@@ -175,12 +191,14 @@ static PFN_vkVoidFunction vkGetDeviceProcAddr_default(
175191
// queryable interface behavior seen by the application
176192
auto driver_function = layer->driver.vkGetDeviceProcAddr(device, pName);
177193
auto layer_function = get_device_layer_function(pName);
194+
195+
// If driver exposes it and the layer has one, use the layer function
178196
if (driver_function && layer_function)
179197
{
180198
return layer_function;
181199
}
182200

183-
// This may be nullptr if the driver doesn't expose the function
201+
// Otherwise just use the driver function, which may be nullptr
184202
return driver_function;
185203
}
186204

@@ -189,32 +207,35 @@ static PFN_vkVoidFunction vkGetInstanceProcAddr_default(
189207
VkInstance instance,
190208
const char* pName
191209
) {
192-
// Always return layer instance functions
193-
auto layer_function = get_instance_layer_function(pName);
194-
if (layer_function)
210+
// Always expose these functions ...
211+
PFN_vkVoidFunction layerFunction = get_fixed_instance_layer_function(pName);
212+
if (layerFunction)
195213
{
196-
return layer_function;
214+
return layerFunction;
197215
}
198216

199-
// If this is an instance method hold the lock to access layer-wide global store
200-
PFN_vkVoidFunction driver_function { nullptr };
217+
// Otherwise, only expose functions that the driver exposes to avoid
218+
// changing queryable interface behavior seen by the application
219+
layerFunction = get_instance_layer_function(pName);
201220
if (instance) {
202221
std::unique_lock<std::mutex> lock { g_vulkanLock };
203222
auto* layer = Instance::retrieve(instance);
204223

205224
// Don't hold the lock while calling the driver
206225
lock.unlock();
207-
driver_function = layer->nlayerGetProcAddress(layer->instance, pName);
208-
}
226+
PFN_vkVoidFunction driverFunction = layer->nlayerGetProcAddress(layer->instance, pName);
209227

210-
layer_function = get_device_layer_function(pName);
211-
if ((!instance || driver_function) && layer_function)
212-
{
213-
return layer_function;
228+
// If driver exposes it and the layer has one, use the layer function
229+
if (driverFunction && layerFunction)
230+
{
231+
return layerFunction;
232+
}
233+
234+
// Otherwise just use the driver function, which may be nullptr
235+
return driverFunction;
214236
}
215237

216-
// This may be nullptr if the driver doesn't expose the function
217-
return driver_function;
238+
return layerFunction;
218239
}
219240

220241
/** See Vulkan API for documentation. */

source_common/framework/entry_utils.hpp

Lines changed: 44 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -98,26 +98,42 @@ struct DispatchTableEntry
9898
* \return The layer function pointer, or \c nullptr if the layer doesn't
9999
* intercept the function.
100100
*/
101-
static PFN_vkVoidFunction get_instance_layer_function(
101+
static PFN_vkVoidFunction get_fixed_instance_layer_function(
102102
const char* name
103103
) {
104-
static const DispatchTableEntry layer_functions[] = {
104+
static const DispatchTableEntry layerFunctions[] = {
105105
VK_TABLE_ENTRY(vkGetInstanceProcAddr),
106+
VK_TABLE_ENTRY(vkEnumerateDeviceLayerProperties),
107+
VK_TABLE_ENTRY(vkEnumerateDeviceExtensionProperties),
106108
VK_TABLE_ENTRY(vkEnumerateInstanceLayerProperties),
107109
VK_TABLE_ENTRY(vkEnumerateInstanceExtensionProperties),
108110
};
109111

110-
for (auto &function : instanceIntercepts)
112+
for (auto &function : layerFunctions)
111113
{
112114
if (!strcmp(function.name, name))
113115
{
114116
return function.function;
115117
}
116118
}
117119

118-
for (auto &function : layer_functions)
120+
return nullptr;
121+
}
122+
123+
/**
124+
* @brief Fetch the layer function for a given instance entrypoint name.
125+
*
126+
* @param name The layer entry point name.
127+
*
128+
* \return The layer function pointer, or \c nullptr if the layer doesn't
129+
* intercept the function.
130+
*/
131+
static PFN_vkVoidFunction get_instance_layer_function(
132+
const char* name
133+
) {
134+
for (auto &function : instanceIntercepts)
119135
{
120-
if (strcmp(function.name, name) == 0)
136+
if (!strcmp(function.name, name))
121137
{
122138
return function.function;
123139
}
@@ -136,21 +152,21 @@ static PFN_vkVoidFunction get_instance_layer_function(
136152
static PFN_vkVoidFunction get_device_layer_function(
137153
const char* name
138154
) {
139-
static const DispatchTableEntry layer_functions[] = {
155+
static const DispatchTableEntry layerFunctions[] = {
140156
VK_TABLE_ENTRY(vkGetDeviceProcAddr),
141157
VK_TABLE_ENTRY(vkEnumerateDeviceExtensionProperties),
142158
VK_TABLE_ENTRY(vkEnumerateDeviceLayerProperties),
143159
};
144160

145-
for (auto &function : deviceIntercepts)
161+
for (auto &function : layerFunctions)
146162
{
147163
if (!strcmp(function.name, name))
148164
{
149165
return function.function;
150166
}
151167
}
152168

153-
for (auto &function : layer_functions)
169+
for (auto &function : deviceIntercepts)
154170
{
155171
if (!strcmp(function.name, name))
156172
{
@@ -175,12 +191,14 @@ static PFN_vkVoidFunction vkGetDeviceProcAddr_default(
175191
// queryable interface behavior seen by the application
176192
auto driver_function = layer->driver.vkGetDeviceProcAddr(device, pName);
177193
auto layer_function = get_device_layer_function(pName);
194+
195+
// If driver exposes it and the layer has one, use the layer function
178196
if (driver_function && layer_function)
179197
{
180198
return layer_function;
181199
}
182200

183-
// This may be nullptr if the driver doesn't expose the function
201+
// Otherwise just use the driver function, which may be nullptr
184202
return driver_function;
185203
}
186204

@@ -189,32 +207,35 @@ static PFN_vkVoidFunction vkGetInstanceProcAddr_default(
189207
VkInstance instance,
190208
const char* pName
191209
) {
192-
// Always return layer instance functions
193-
auto layer_function = get_instance_layer_function(pName);
194-
if (layer_function)
210+
// Always expose these functions ...
211+
PFN_vkVoidFunction layerFunction = get_fixed_instance_layer_function(pName);
212+
if (layerFunction)
195213
{
196-
return layer_function;
214+
return layerFunction;
197215
}
198216

199-
// If this is an instance method hold the lock to access layer-wide global store
200-
PFN_vkVoidFunction driver_function { nullptr };
217+
// Otherwise, only expose functions that the driver exposes to avoid
218+
// changing queryable interface behavior seen by the application
219+
layerFunction = get_instance_layer_function(pName);
201220
if (instance) {
202221
std::unique_lock<std::mutex> lock { g_vulkanLock };
203222
auto* layer = Instance::retrieve(instance);
204223

205224
// Don't hold the lock while calling the driver
206225
lock.unlock();
207-
driver_function = layer->nlayerGetProcAddress(layer->instance, pName);
208-
}
226+
PFN_vkVoidFunction driverFunction = layer->nlayerGetProcAddress(layer->instance, pName);
209227

210-
layer_function = get_device_layer_function(pName);
211-
if ((!instance || driver_function) && layer_function)
212-
{
213-
return layer_function;
228+
// If driver exposes it and the layer has one, use the layer function
229+
if (driverFunction && layerFunction)
230+
{
231+
return layerFunction;
232+
}
233+
234+
// Otherwise just use the driver function, which may be nullptr
235+
return driverFunction;
214236
}
215237

216-
// This may be nullptr if the driver doesn't expose the function
217-
return driver_function;
238+
return layerFunction;
218239
}
219240

220241
/** See Vulkan API for documentation. */

0 commit comments

Comments
 (0)