const VkAllocationCallbacks* pAllocator,
VkDevice* pDevice);
VKAPI_ATTR VkResult VKAPI_CALL terminator_EnumerateInstanceExtensionProperties(
+ const char* pLayerName,
+ uint32_t* pPropertyCount,
+ VkExtensionProperties* pProperties);
+VKAPI_ATTR VkResult VKAPI_CALL terminator_pre_instance_EnumerateInstanceExtensionProperties(
const VkEnumerateInstanceExtensionPropertiesChain* chain,
const char* pLayerName,
uint32_t* pPropertyCount,
uint32_t* pPropertyCount,
VkExtensionProperties* pProperties);
VKAPI_ATTR VkResult VKAPI_CALL terminator_EnumerateInstanceLayerProperties(
+ uint32_t* pPropertyCount,
+ VkLayerProperties* pProperties);
+VKAPI_ATTR VkResult VKAPI_CALL terminator_pre_instance_EnumerateInstanceLayerProperties(
const VkEnumerateInstanceLayerPropertiesChain* chain,
uint32_t* pPropertyCount,
VkLayerProperties* pProperties);
uint32_t* pPropertyCount,
VkSparseImageFormatProperties* pProperties);
VKAPI_ATTR VkResult VKAPI_CALL terminator_EnumerateInstanceVersion(
+ uint32_t* pApiVersion);
+VKAPI_ATTR VkResult VKAPI_CALL terminator_pre_instance_EnumerateInstanceVersion(
const VkEnumerateInstanceVersionChain* chain,
uint32_t* pApiVersion);
VKAPI_ATTR VkResult VKAPI_CALL terminator_EnumeratePhysicalDeviceGroups(
if (!strcmp(pName, "vkCreateInstance")) {
return (PFN_vkVoidFunction)terminator_CreateInstance;
}
+ // If a layer is querying pre-instance functions using vkGetInstanceProcAddr, we need to return function pointers that match the
+ // Vulkan API
+ if (!strcmp(pName, "vkEnumerateInstanceLayerProperties")) {
+ return (PFN_vkVoidFunction)terminator_EnumerateInstanceLayerProperties;
+ }
+ if (!strcmp(pName, "vkEnumerateInstanceExtensionProperties")) {
+ return (PFN_vkVoidFunction)terminator_EnumerateInstanceExtensionProperties;
+ }
+ if (!strcmp(pName, "vkEnumerateInstanceVersion")) {
+ return (PFN_vkVoidFunction)terminator_EnumerateInstanceVersion;
+ }
// While the spec is very clear that querying vkCreateDevice requires a valid VkInstance, because the loader allowed querying
// with a NULL VkInstance handle for a long enough time, it is impractical to fix this bug in the loader
return result;
}
-VKAPI_ATTR VkResult VKAPI_CALL terminator_EnumerateInstanceVersion(const VkEnumerateInstanceVersionChain *chain,
- uint32_t *pApiVersion) {
- (void)chain;
+VKAPI_ATTR VkResult VKAPI_CALL terminator_EnumerateInstanceVersion(uint32_t *pApiVersion) {
// NOTE: The Vulkan WG doesn't want us checking pApiVersion for NULL, but instead
// prefers us crashing.
*pApiVersion = VK_HEADER_VERSION_COMPLETE;
return VK_SUCCESS;
}
-VKAPI_ATTR VkResult VKAPI_CALL
-terminator_EnumerateInstanceExtensionProperties(const VkEnumerateInstanceExtensionPropertiesChain *chain, const char *pLayerName,
- uint32_t *pPropertyCount, VkExtensionProperties *pProperties) {
+VKAPI_ATTR VkResult VKAPI_CALL terminator_pre_instance_EnumerateInstanceVersion(const VkEnumerateInstanceVersionChain *chain,
+ uint32_t *pApiVersion) {
(void)chain;
+ return terminator_EnumerateInstanceVersion(pApiVersion);
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL terminator_EnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pPropertyCount,
+ VkExtensionProperties *pProperties) {
struct loader_extension_list *global_ext_list = NULL;
struct loader_layer_list instance_layers;
struct loader_extension_list local_ext_list;
return res;
}
-VKAPI_ATTR VkResult VKAPI_CALL terminator_EnumerateInstanceLayerProperties(const VkEnumerateInstanceLayerPropertiesChain *chain,
- uint32_t *pPropertyCount,
- VkLayerProperties *pProperties) {
+VKAPI_ATTR VkResult VKAPI_CALL terminator_pre_instance_EnumerateInstanceExtensionProperties(
+ const VkEnumerateInstanceExtensionPropertiesChain *chain, const char *pLayerName, uint32_t *pPropertyCount,
+ VkExtensionProperties *pProperties) {
(void)chain;
+ return terminator_EnumerateInstanceExtensionProperties(pLayerName, pPropertyCount, pProperties);
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL terminator_EnumerateInstanceLayerProperties(uint32_t *pPropertyCount,
+ VkLayerProperties *pProperties) {
VkResult result = VK_SUCCESS;
struct loader_layer_list instance_layer_list;
struct loader_envvar_all_filters layer_filters = {0};
return result;
}
+VKAPI_ATTR VkResult VKAPI_CALL terminator_pre_instance_EnumerateInstanceLayerProperties(
+ const VkEnumerateInstanceLayerPropertiesChain *chain, uint32_t *pPropertyCount, VkLayerProperties *pProperties) {
+ (void)chain;
+ return terminator_EnumerateInstanceLayerProperties(pPropertyCount, pProperties);
+}
+
// ---- Vulkan Core 1.1 terminators
VKAPI_ATTR VkResult VKAPI_CALL terminator_EnumeratePhysicalDeviceGroups(
.version = VK_CURRENT_CHAIN_VERSION,
.size = sizeof(chain_tail),
},
- .pfnNextLayer = &terminator_EnumerateInstanceExtensionProperties,
+ .pfnNextLayer = &terminator_pre_instance_EnumerateInstanceExtensionProperties,
.pNextLink = NULL,
};
VkEnumerateInstanceExtensionPropertiesChain *chain_head = &chain_tail;
.version = VK_CURRENT_CHAIN_VERSION,
.size = sizeof(chain_tail),
},
- .pfnNextLayer = &terminator_EnumerateInstanceLayerProperties,
+ .pfnNextLayer = &terminator_pre_instance_EnumerateInstanceLayerProperties,
.pNextLink = NULL,
};
VkEnumerateInstanceLayerPropertiesChain *chain_head = &chain_tail;
.version = VK_CURRENT_CHAIN_VERSION,
.size = sizeof(chain_tail),
},
- .pfnNextLayer = &terminator_EnumerateInstanceVersion,
+ .pfnNextLayer = &terminator_pre_instance_EnumerateInstanceVersion,
.pNextLink = NULL,
};
VkEnumerateInstanceVersionChain *chain_head = &chain_tail;
mod_string = new_terminator.replace("VKAPI_CALL vk", "VKAPI_CALL terminator_")
if cur_cmd.name in PRE_INSTANCE_FUNCTIONS:
+ pre_instance_basic_version = mod_string
+ mod_string = mod_string.replace("terminator_", "terminator_pre_instance_")
mod_string = mod_string.replace(cur_cmd.name[2:] + '(\n', cur_cmd.name[2:] + '(\n const Vk' + cur_cmd.name[2:] + 'Chain* chain,\n')
- if (cur_cmd.protect is not None):
+ if cur_cmd.protect is not None:
terminators += '#if defined(%s)\n' % cur_cmd.protect
+ if cur_cmd.name in PRE_INSTANCE_FUNCTIONS:
+ terminators += pre_instance_basic_version
+ terminators += '\n'
+
terminators += mod_string
terminators += '\n'
- if (cur_cmd.protect is not None):
+ if cur_cmd.protect is not None:
terminators += '#endif // %s\n' % cur_cmd.protect
terminators += '\n'
if (layer.clobber_pInstance) {
memset(*pInstance, 0, 128);
}
+ PFN_vkEnumerateInstanceLayerProperties fpEnumerateInstanceLayerProperties{};
+ PFN_vkEnumerateInstanceExtensionProperties fpEnumerateInstanceExtensionProperties{};
+ PFN_vkEnumerateInstanceVersion fpEnumerateInstanceVersion{};
+
+ if (layer.query_vkEnumerateInstanceLayerProperties) {
+ fpEnumerateInstanceLayerProperties = reinterpret_cast<PFN_vkEnumerateInstanceLayerProperties>(
+ fpGetInstanceProcAddr(nullptr, "vkEnumerateInstanceLayerProperties"));
+ uint32_t count = 0;
+ fpEnumerateInstanceLayerProperties(&count, nullptr);
+ if (count == 0) return VK_ERROR_LAYER_NOT_PRESENT;
+ std::vector<VkLayerProperties> layers{count, VkLayerProperties{}};
+ fpEnumerateInstanceLayerProperties(&count, layers.data());
+ if (count == 0) return VK_ERROR_LAYER_NOT_PRESENT;
+ }
+ if (layer.query_vkEnumerateInstanceExtensionProperties) {
+ fpEnumerateInstanceExtensionProperties = reinterpret_cast<PFN_vkEnumerateInstanceExtensionProperties>(
+ fpGetInstanceProcAddr(nullptr, "vkEnumerateInstanceExtensionProperties"));
+ uint32_t count = 0;
+ fpEnumerateInstanceExtensionProperties(nullptr, &count, nullptr);
+ if (count == 0) return VK_ERROR_LAYER_NOT_PRESENT;
+ std::vector<VkExtensionProperties> extensions{count, VkExtensionProperties{}};
+ fpEnumerateInstanceExtensionProperties(nullptr, &count, extensions.data());
+ if (count == 0) return VK_ERROR_LAYER_NOT_PRESENT;
+ }
+ if (layer.query_vkEnumerateInstanceVersion) {
+ fpEnumerateInstanceVersion =
+ reinterpret_cast<PFN_vkEnumerateInstanceVersion>(fpGetInstanceProcAddr(nullptr, "vkEnumerateInstanceVersion"));
+ uint32_t version = 0;
+ fpEnumerateInstanceVersion(&version);
+ if (version == 0) return VK_ERROR_LAYER_NOT_PRESENT;
+ }
// Continue call down the chain
VkResult result = fpCreateInstance(create_info_pointer, pAllocator, pInstance);
// Clober the data pointed to by pDevice to overwrite the magic value
BUILDER_VALUE(TestLayer, bool, clobber_pDevice, false)
+ BUILDER_VALUE(TestLayer, bool, query_vkEnumerateInstanceLayerProperties, false)
+ BUILDER_VALUE(TestLayer, bool, query_vkEnumerateInstanceExtensionProperties, false)
+ BUILDER_VALUE(TestLayer, bool, query_vkEnumerateInstanceVersion, false)
+
PFN_vkGetInstanceProcAddr next_vkGetInstanceProcAddr = VK_NULL_HANDLE;
PFN_GetPhysicalDeviceProcAddr next_GetPhysicalDeviceProcAddr = VK_NULL_HANDLE;
PFN_vkGetDeviceProcAddr next_vkGetDeviceProcAddr = VK_NULL_HANDLE;
ASSERT_TRUE(string_eq(layers.at(0).layerName, explicit_layer_name));
}
+TEST(ExplicitLayers, CallsPreInstanceFunctionsInCreateInstance) {
+ FrameworkEnvironment env;
+ env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA)).add_physical_device({});
+ const char* explicit_layer_name = "VK_LAYER_enabled_by_override";
+
+ env.add_explicit_layer(
+ ManifestLayer{}.set_file_format_version({1, 1, 2}).add_layer(
+ ManifestLayer::LayerDescription{}.set_name(explicit_layer_name).set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)),
+ "explicit_test_layer.json");
+
+ auto& layer = env.get_test_layer(0);
+ layer.set_query_vkEnumerateInstanceLayerProperties(true);
+ layer.set_query_vkEnumerateInstanceExtensionProperties(true);
+ layer.set_query_vkEnumerateInstanceVersion(true);
+
+ InstWrapper inst{env.vulkan_functions};
+ inst.create_info.add_layer(explicit_layer_name);
+ inst.CheckCreate();
+
+ auto layers = inst.GetActiveLayers(inst.GetPhysDev(), 1);
+ ASSERT_TRUE(string_eq(layers.at(0).layerName, explicit_layer_name));
+}
+
// This test makes sure that any layer calling GetPhysicalDeviceProperties2 inside of CreateInstance
// succeeds and doesn't crash.
TEST(LayerCreateInstance, GetPhysicalDeviceProperties2) {