[Impeller] Vulkan: Don't fail initialization if stencil-only textures aren't supported. (flutter/engine#50455)
Closes https://github.com/flutter/flutter/issues/137108 We don't rely on stencil-only textures anymore in the 2D renderer.
This commit is contained in:
@@ -254,7 +254,6 @@ static bool PhysicalDeviceSupportsRequiredFormats(
|
||||
const auto has_color_format =
|
||||
HasSuitableColorFormat(device, vk::Format::eB8G8R8A8Unorm);
|
||||
const auto has_stencil_format =
|
||||
HasSuitableDepthStencilFormat(device, vk::Format::eS8Uint) ||
|
||||
HasSuitableDepthStencilFormat(device, vk::Format::eD32SfloatS8Uint) ||
|
||||
HasSuitableDepthStencilFormat(device, vk::Format::eD24UnormS8Uint);
|
||||
return has_color_format && has_stencil_format;
|
||||
@@ -351,10 +350,8 @@ bool CapabilitiesVK::SetPhysicalDevice(const vk::PhysicalDevice& device) {
|
||||
|
||||
if (HasSuitableDepthStencilFormat(device, vk::Format::eS8Uint)) {
|
||||
default_stencil_format_ = PixelFormat::kS8UInt;
|
||||
} else if (default_stencil_format_ != PixelFormat::kUnknown) {
|
||||
} else if (default_depth_stencil_format_ != PixelFormat::kUnknown) {
|
||||
default_stencil_format_ = default_depth_stencil_format_;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
device_properties_ = device.getProperties();
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
#include "flutter/fml/synchronization/waitable_event.h"
|
||||
#include "flutter/testing/testing.h" // IWYU pragma: keep
|
||||
#include "impeller/base/validation.h"
|
||||
#include "impeller/renderer/backend/vulkan/command_pool_vk.h"
|
||||
#include "impeller/renderer/backend/vulkan/context_vk.h"
|
||||
#include "impeller/renderer/backend/vulkan/test/mock_vulkan.h"
|
||||
@@ -143,5 +144,58 @@ TEST(ContextVKTest, CanCreateContextWithValidationLayers) {
|
||||
ASSERT_TRUE(capabilites_vk->AreValidationsEnabled());
|
||||
}
|
||||
|
||||
// In Impeller's 2D renderer, we no longer use stencil-only formats. They're
|
||||
// less widely supported than combined depth-stencil formats, so make sure we
|
||||
// don't fail initialization if we can't find a suitable stencil format.
|
||||
TEST(CapabilitiesVKTest, ContextInitializesWithNoStencilFormat) {
|
||||
const std::shared_ptr<ContextVK> context =
|
||||
MockVulkanContextBuilder()
|
||||
.SetPhysicalDeviceFormatPropertiesCallback(
|
||||
[](VkPhysicalDevice physicalDevice, VkFormat format,
|
||||
VkFormatProperties* pFormatProperties) {
|
||||
if (format == VK_FORMAT_B8G8R8A8_UNORM) {
|
||||
pFormatProperties->optimalTilingFeatures =
|
||||
static_cast<VkFormatFeatureFlags>(
|
||||
vk::FormatFeatureFlagBits::eColorAttachment);
|
||||
} else if (format == VK_FORMAT_D32_SFLOAT_S8_UINT) {
|
||||
pFormatProperties->optimalTilingFeatures =
|
||||
static_cast<VkFormatFeatureFlags>(
|
||||
vk::FormatFeatureFlagBits::eDepthStencilAttachment);
|
||||
}
|
||||
// Ignore just the stencil format.
|
||||
})
|
||||
.Build();
|
||||
ASSERT_NE(context, nullptr);
|
||||
const CapabilitiesVK* capabilites_vk =
|
||||
reinterpret_cast<const CapabilitiesVK*>(context->GetCapabilities().get());
|
||||
ASSERT_EQ(capabilites_vk->GetDefaultDepthStencilFormat(),
|
||||
PixelFormat::kD32FloatS8UInt);
|
||||
ASSERT_EQ(capabilites_vk->GetDefaultStencilFormat(),
|
||||
PixelFormat::kD32FloatS8UInt);
|
||||
}
|
||||
|
||||
// Impeller's 2D renderer relies on hardware support for a combined
|
||||
// depth-stencil format (widely supported). So fail initialization if a suitable
|
||||
// one couldn't be found. That way we have an opportunity to fallback to
|
||||
// OpenGLES.
|
||||
TEST(CapabilitiesVKTest,
|
||||
ContextFailsInitializationForNoCombinedDepthStencilFormat) {
|
||||
ScopedValidationDisable disable_validation;
|
||||
const std::shared_ptr<ContextVK> context =
|
||||
MockVulkanContextBuilder()
|
||||
.SetPhysicalDeviceFormatPropertiesCallback(
|
||||
[](VkPhysicalDevice physicalDevice, VkFormat format,
|
||||
VkFormatProperties* pFormatProperties) {
|
||||
if (format == VK_FORMAT_B8G8R8A8_UNORM) {
|
||||
pFormatProperties->optimalTilingFeatures =
|
||||
static_cast<VkFormatFeatureFlags>(
|
||||
vk::FormatFeatureFlagBits::eColorAttachment);
|
||||
}
|
||||
// Ignore combined depth-stencil formats.
|
||||
})
|
||||
.Build();
|
||||
ASSERT_EQ(context, nullptr);
|
||||
}
|
||||
|
||||
} // namespace testing
|
||||
} // namespace impeller
|
||||
|
||||
@@ -153,19 +153,16 @@ VkResult vkEnumeratePhysicalDevices(VkInstance instance,
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
static thread_local std::function<void(VkPhysicalDevice physicalDevice,
|
||||
VkFormat format,
|
||||
VkFormatProperties* pFormatProperties)>
|
||||
g_format_properties_callback;
|
||||
|
||||
void vkGetPhysicalDeviceFormatProperties(
|
||||
VkPhysicalDevice physicalDevice,
|
||||
VkFormat format,
|
||||
VkFormatProperties* pFormatProperties) {
|
||||
if (format == VK_FORMAT_B8G8R8A8_UNORM) {
|
||||
pFormatProperties->optimalTilingFeatures =
|
||||
static_cast<VkFormatFeatureFlags>(
|
||||
vk::FormatFeatureFlagBits::eColorAttachment);
|
||||
} else if (format == VK_FORMAT_S8_UINT) {
|
||||
pFormatProperties->optimalTilingFeatures =
|
||||
static_cast<VkFormatFeatureFlags>(
|
||||
vk::FormatFeatureFlagBits::eDepthStencilAttachment);
|
||||
}
|
||||
g_format_properties_callback(physicalDevice, format, pFormatProperties);
|
||||
}
|
||||
|
||||
void vkGetPhysicalDeviceProperties(VkPhysicalDevice physicalDevice,
|
||||
@@ -813,7 +810,24 @@ PFN_vkVoidFunction GetMockVulkanProcAddress(VkInstance instance,
|
||||
} // namespace
|
||||
|
||||
MockVulkanContextBuilder::MockVulkanContextBuilder()
|
||||
: instance_extensions_({"VK_KHR_surface", "VK_MVK_macos_surface"}) {}
|
||||
: instance_extensions_({"VK_KHR_surface", "VK_MVK_macos_surface"}),
|
||||
format_properties_callback_([](VkPhysicalDevice physicalDevice,
|
||||
VkFormat format,
|
||||
VkFormatProperties* pFormatProperties) {
|
||||
if (format == VK_FORMAT_B8G8R8A8_UNORM) {
|
||||
pFormatProperties->optimalTilingFeatures =
|
||||
static_cast<VkFormatFeatureFlags>(
|
||||
vk::FormatFeatureFlagBits::eColorAttachment);
|
||||
} else if (format == VK_FORMAT_D32_SFLOAT_S8_UINT) {
|
||||
pFormatProperties->optimalTilingFeatures =
|
||||
static_cast<VkFormatFeatureFlags>(
|
||||
vk::FormatFeatureFlagBits::eDepthStencilAttachment);
|
||||
} else if (format == VK_FORMAT_S8_UINT) {
|
||||
pFormatProperties->optimalTilingFeatures =
|
||||
static_cast<VkFormatFeatureFlags>(
|
||||
vk::FormatFeatureFlagBits::eDepthStencilAttachment);
|
||||
}
|
||||
}) {}
|
||||
|
||||
std::shared_ptr<ContextVK> MockVulkanContextBuilder::Build() {
|
||||
auto message_loop = fml::ConcurrentMessageLoop::Create();
|
||||
@@ -824,6 +838,7 @@ std::shared_ptr<ContextVK> MockVulkanContextBuilder::Build() {
|
||||
}
|
||||
g_instance_extensions = instance_extensions_;
|
||||
g_instance_layers = instance_layers_;
|
||||
g_format_properties_callback = format_properties_callback_;
|
||||
std::shared_ptr<ContextVK> result = ContextVK::Create(std::move(settings));
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
|
||||
#include "impeller/base/thread.h"
|
||||
#include "impeller/renderer/backend/vulkan/context_vk.h"
|
||||
#include "vulkan/vulkan_core.h"
|
||||
#include "vulkan/vulkan_enums.hpp"
|
||||
|
||||
namespace impeller {
|
||||
@@ -88,10 +89,25 @@ class MockVulkanContextBuilder {
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// Set the behavior of vkGetPhysicalDeviceFormatProperties, which needs to
|
||||
/// respond differently for different formats.
|
||||
MockVulkanContextBuilder& SetPhysicalDeviceFormatPropertiesCallback(
|
||||
std::function<void(VkPhysicalDevice physicalDevice,
|
||||
VkFormat format,
|
||||
VkFormatProperties* pFormatProperties)>
|
||||
format_properties_callback) {
|
||||
format_properties_callback_ = std::move(format_properties_callback);
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
std::function<void(ContextVK::Settings&)> settings_callback_;
|
||||
std::vector<std::string> instance_extensions_;
|
||||
std::vector<std::string> instance_layers_;
|
||||
std::function<void(VkPhysicalDevice physicalDevice,
|
||||
VkFormat format,
|
||||
VkFormatProperties* pFormatProperties)>
|
||||
format_properties_callback_;
|
||||
};
|
||||
|
||||
/// @brief Override the image size returned by all swapchain images.
|
||||
|
||||
Reference in New Issue
Block a user