diff --git a/gapir/cc/context.cpp b/gapir/cc/context.cpp index 16adc9343a..236073070f 100644 --- a/gapir/cc/context.cpp +++ b/gapir/cc/context.cpp @@ -321,8 +321,8 @@ void Context::registerCallbacks(Interpreter* interpreter) { } uint32_t result = Vulkan::VkResult::VK_SUCCESS; - if (api->replayCreateVkInstance(stack, pCreateInfo, pAllocator, - pInstance, false, &result)) { + if (api->replayCreateVkInstanceImpl(stack, pCreateInfo, pAllocator, + pInstance, false, &result)) { if (result == Vulkan::VkResult::VK_SUCCESS) { if (pushReturn) { stack->push(result); @@ -330,22 +330,34 @@ void Context::registerCallbacks(Interpreter* interpreter) { return true; } } - // Failed to create instance with validation layer by GAPID, - // fallback to not adding the validation layer. - onDebugMessage(LOG_LEVEL_WARNING, Vulkan::INDEX, - "Failed to create VkInstance, drop validation layers (if any) and try again"); - if (api->replayCreateVkInstance(stack, pCreateInfo, pAllocator, - pInstance, true, &result)) { - if (pushReturn) { - stack->push(result); + // If validation layers and debug report extension are enabled, + // drop them and try to create VkInstance again. + if (Vulkan::hasValidationLayers(pCreateInfo->ppEnabledLayerNames, + pCreateInfo->enabledLayerCount) || + Vulkan::hasDebugReportExtension( + pCreateInfo->ppEnabledExtensionNames, + pCreateInfo->enabledExtensionCount)) { + onDebugMessage( + LOG_LEVEL_WARNING, Vulkan::INDEX, + "Failed to create VkInstance with validation layers and " + "debug report extension, drop them and try again"); + if (api->replayCreateVkInstanceImpl(stack, pCreateInfo, + pAllocator, pInstance, true, + &result)) { + if (pushReturn) { + stack->push(result); + } + return true; } - return true; } - onDebugMessage(LOG_LEVEL_FATAL, Vulkan::INDEX, "cannot find underlying 'vkCreateInstance'"); + onDebugMessage(LOG_LEVEL_FATAL, Vulkan::INDEX, "Failed to create 'VkInstance'"); return false; } else { - GAPID_WARNING("[%u]replayCreateVkInstance called without a bound Vulkan renderer", label); - return false; + GAPID_WARNING( + "[%u]replayCreateVkInstance called without a bound Vulkan " + "renderer", + label); + return false; } }); @@ -364,8 +376,9 @@ void Context::registerCallbacks(Interpreter* interpreter) { } uint32_t result = Vulkan::VkResult::VK_SUCCESS; - if (api->replayCreateVkDevice(stack, physicalDevice, pCreateInfo, - pAllocator, pDevice, false, &result)) { + if (api->replayCreateVkDeviceImpl(stack, physicalDevice, + pCreateInfo, pAllocator, pDevice, + false, &result)) { if (result == Vulkan::VkResult::VK_SUCCESS) { if (pushReturn) { stack->push(result); @@ -373,22 +386,30 @@ void Context::registerCallbacks(Interpreter* interpreter) { return true; } } - // Failed to create device with the validation layer added by GAPID, - // fallback to not adding the validation layer. - onDebugMessage(LOG_LEVEL_WARNING, Vulkan::INDEX, - "Failed to create vkDevice, drop validation layers (if any) and try again"); - if (api->replayCreateVkDevice(stack, physicalDevice, pCreateInfo, - pAllocator, pDevice, true, &result)) { - if (pushReturn) { - stack->push(result); + // If validation layers are enabled, drop them and try to create + // VkInstance again. + if (Vulkan::hasValidationLayers(pCreateInfo->ppEnabledLayerNames, + pCreateInfo->enabledLayerCount)) { + onDebugMessage( + LOG_LEVEL_WARNING, Vulkan::INDEX, + "Failed to create VkDevice with validation layers, " + "drop them and try again"); + if (api->replayCreateVkDeviceImpl(stack, physicalDevice, + pCreateInfo, pAllocator, + pDevice, true, &result)) { + if (pushReturn) { + stack->push(result); + } + return true; } - return true; } - onDebugMessage(LOG_LEVEL_FATAL, Vulkan::INDEX, "cannot find underlying 'vkCreateDevice'"); + onDebugMessage(LOG_LEVEL_FATAL, Vulkan::INDEX, "Failed to create 'VkDevice'"); return false; } else { - GAPID_WARNING("[%u]replayCreateVkDevice called without a bound Vulkan renderer", label); - return false; + GAPID_WARNING( + "[%u]replayCreateVkDevice called without a bound Vulkan renderer", + label); + return false; } }); diff --git a/gapir/cc/vulkan_gfx_api.inc b/gapir/cc/vulkan_gfx_api.inc index d0486ded42..23e215787e 100644 --- a/gapir/cc/vulkan_gfx_api.inc +++ b/gapir/cc/vulkan_gfx_api.inc @@ -36,14 +36,14 @@ IndirectMaps mIndirectMaps; // Function for wrapping around the normal vkCreateInstance to inject // virtual swapchain as an additional enabled layer. -bool replayCreateVkInstance( +bool replayCreateVkInstanceImpl( Stack* stack, const VkInstanceCreateInfo* pCreateInfo, VkAllocationCallbacks* pAllocator, VkInstance* pInstance, bool dropValidationLayersAndDebugReport, uint32_t* result); // Function for wrapping around the normal vkCreateDevice to null the // pNext field in VkDeviceCreateInfo. -bool replayCreateVkDevice(Stack* stack, size_val physicalDevice, +bool replayCreateVkDeviceImpl(Stack* stack, size_val physicalDevice, const VkDeviceCreateInfo* pCreateInfo, VkAllocationCallbacks* pAllocator, VkDevice* pDevice, bool dropValidationLayers, uint32_t* result); @@ -119,12 +119,12 @@ bool replayCreateVkDebugReportCallback(Stack* stack, bool pushReturn); bool replayDestroyVkDebugReportCallback(Stack* stack); -static bool replayDebugReportCallback( - uint32_t flags, - uint32_t objectType, - uint64_t object, - size_t location, - int32_t messageCode, - const char* pLayerPrefix, - const char* pMessage, - void* pUserData); +static bool replayDebugReportCallback(uint32_t flags, uint32_t objectType, + uint64_t object, size_t location, + int32_t messageCode, + const char* pLayerPrefix, + const char* pMessage, void* pUserData); + +static bool hasValidationLayers(const char* const* layers, uint32_t count); + +static bool hasDebugReportExtension(const char* const* extensions, uint32_t count); diff --git a/gapis/api/templates/vulkan_gfx_api_extras.tmpl b/gapis/api/templates/vulkan_gfx_api_extras.tmpl index 0106c235b5..dabaa17685 100644 --- a/gapis/api/templates/vulkan_gfx_api_extras.tmpl +++ b/gapis/api/templates/vulkan_gfx_api_extras.tmpl @@ -93,12 +93,12 @@ ¶ »} // anonymous namespace ¶ -bool Vulkan::replayCreateVkInstance(Stack* stack, - const VkInstanceCreateInfo* pCreateInfo, - VkAllocationCallbacks* pAllocator, - VkInstance* pInstance, - bool dropValidationLayersAndDebugReport, - uint32_t* result) { +bool Vulkan::replayCreateVkInstanceImpl(Stack* stack, + const VkInstanceCreateInfo* pCreateInfo, + VkAllocationCallbacks* pAllocator, + VkInstance* pInstance, + bool dropValidationLayersAndDebugReport, + uint32_t* result) { std::vector layers( pCreateInfo->ppEnabledLayerNames, pCreateInfo->ppEnabledLayerNames + pCreateInfo->enabledLayerCount); @@ -156,11 +156,11 @@ bool Vulkan::replayCreateVkInstance(Stack* stack, return false; } ¶ -bool Vulkan::replayCreateVkDevice(Stack* stack, size_val physicalDevice, - const VkDeviceCreateInfo* pCreateInfo, - VkAllocationCallbacks* pAllocator, - VkDevice* pDevice, bool dropValidationLayers, - uint32_t* result) { +bool Vulkan::replayCreateVkDeviceImpl(Stack* stack, size_val physicalDevice, + const VkDeviceCreateInfo* pCreateInfo, + VkAllocationCallbacks* pAllocator, + VkDevice* pDevice, bool dropValidationLayers, + uint32_t* result) { std::vector layers( pCreateInfo->ppEnabledLayerNames, pCreateInfo->ppEnabledLayerNames + pCreateInfo->enabledLayerCount); @@ -604,9 +604,11 @@ bool Vulkan::replayDebugReportCallback(uint32_t flags, uint32_t objectType, return false; } - // Skip benign error reports caused by virtual swapchain as validation layers - // does not recognize virtual swapchain layer - if (strstr(pMessage, "vkCreateSwapchainKHR: pCreateInfo->pNext chain includes a structure with unknown VkStructureType (-86);") != nullptr) { + // Skip the benign error due to validation layers does not recognize the + // virtual swapchain layer + if (strstr(pMessage, + "vkCreateSwapchainKHR: pCreateInfo->pNext chain includes a " + "structure with unknown VkStructureType (-86);") != nullptr) { return false; } @@ -618,6 +620,23 @@ bool Vulkan::replayDebugReportCallback(uint32_t flags, uint32_t objectType, ctx->onDebugMessage(sev, Vulkan::INDEX, ss.str().c_str()); return false; } +¶ +bool Vulkan::hasValidationLayers(const char* const* layers, uint32_t count) { + return std::any_of(layers, layers + count, [](const char* layer) -> bool { + return std::any_of( + std::begin(kValidationLayerNames), std::end(kValidationLayerNames), + [layer](const char* val) -> bool { + return strcmp(layer, val) == 0; + }) || strcmp(layer, kValidationMetaLayerName) == 0; + }); +} +¶ +bool Vulkan::hasDebugReportExtension(const char* const* extensions, uint32_t count) { + return std::any_of( + extensions, extensions + count, [](const char* ext) -> bool { + return strcmp(ext, kDebugReportExtensionName) == 0; + }); +} ¶ »} // namespace gapir ¶