[Impeller] Add buffer-to-texture blit capability check; fix GL+VK playgrounds on macOS (flutter/engine#41320)
GL/VK playgrounds that load image fixtures are currently broken on macOS.
This commit is contained in:
@@ -395,82 +395,82 @@ std::optional<DecompressedImage> Playground::DecodeImageRGBA(
|
||||
return image;
|
||||
}
|
||||
|
||||
namespace {
|
||||
std::shared_ptr<Texture> CreateTextureForDecompressedImage(
|
||||
static std::shared_ptr<Texture> CreateTextureForDecompressedImage(
|
||||
const std::shared_ptr<Context>& context,
|
||||
DecompressedImage& decompressed_image,
|
||||
bool enable_mipmapping) {
|
||||
// TODO(https://github.com/flutter/flutter/issues/123468): copying buffers to
|
||||
// textures is not implemented for GLES/Vulkan.
|
||||
#if FML_OS_MACOSX
|
||||
impeller::TextureDescriptor texture_descriptor;
|
||||
texture_descriptor.storage_mode = impeller::StorageMode::kDevicePrivate;
|
||||
texture_descriptor.format = PixelFormat::kR8G8B8A8UNormInt;
|
||||
texture_descriptor.size = decompressed_image.GetSize();
|
||||
texture_descriptor.mip_count =
|
||||
enable_mipmapping ? decompressed_image.GetSize().MipCount() : 1u;
|
||||
if (context->GetCapabilities()->SupportsBufferToTextureBlits()) {
|
||||
impeller::TextureDescriptor texture_descriptor;
|
||||
texture_descriptor.storage_mode = impeller::StorageMode::kDevicePrivate;
|
||||
texture_descriptor.format = PixelFormat::kR8G8B8A8UNormInt;
|
||||
texture_descriptor.size = decompressed_image.GetSize();
|
||||
texture_descriptor.mip_count =
|
||||
enable_mipmapping ? decompressed_image.GetSize().MipCount() : 1u;
|
||||
|
||||
auto dest_texture =
|
||||
context->GetResourceAllocator()->CreateTexture(texture_descriptor);
|
||||
if (!dest_texture) {
|
||||
FML_DLOG(ERROR) << "Could not create Impeller texture.";
|
||||
return nullptr;
|
||||
auto dest_texture =
|
||||
context->GetResourceAllocator()->CreateTexture(texture_descriptor);
|
||||
if (!dest_texture) {
|
||||
FML_DLOG(ERROR) << "Could not create Impeller texture.";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto buffer = context->GetResourceAllocator()->CreateBufferWithCopy(
|
||||
*decompressed_image.GetAllocation().get());
|
||||
|
||||
dest_texture->SetLabel(
|
||||
impeller::SPrintF("ui.Image(%p)", dest_texture.get()).c_str());
|
||||
|
||||
auto command_buffer = context->CreateCommandBuffer();
|
||||
if (!command_buffer) {
|
||||
FML_DLOG(ERROR)
|
||||
<< "Could not create command buffer for mipmap generation.";
|
||||
return nullptr;
|
||||
}
|
||||
command_buffer->SetLabel("Mipmap Command Buffer");
|
||||
|
||||
auto blit_pass = command_buffer->CreateBlitPass();
|
||||
if (!blit_pass) {
|
||||
FML_DLOG(ERROR) << "Could not create blit pass for mipmap generation.";
|
||||
return nullptr;
|
||||
}
|
||||
blit_pass->SetLabel("Mipmap Blit Pass");
|
||||
blit_pass->AddCopy(buffer->AsBufferView(), dest_texture);
|
||||
if (enable_mipmapping) {
|
||||
blit_pass->GenerateMipmap(dest_texture);
|
||||
}
|
||||
|
||||
blit_pass->EncodeCommands(context->GetResourceAllocator());
|
||||
if (!command_buffer->SubmitCommands()) {
|
||||
FML_DLOG(ERROR) << "Failed to submit blit pass command buffer.";
|
||||
return nullptr;
|
||||
}
|
||||
return dest_texture;
|
||||
} else { // Doesn't support buffer-to-texture blits.
|
||||
auto texture_descriptor = TextureDescriptor{};
|
||||
texture_descriptor.storage_mode = StorageMode::kHostVisible;
|
||||
texture_descriptor.format = PixelFormat::kR8G8B8A8UNormInt;
|
||||
texture_descriptor.size = decompressed_image.GetSize();
|
||||
texture_descriptor.mip_count =
|
||||
enable_mipmapping ? decompressed_image.GetSize().MipCount() : 1u;
|
||||
|
||||
auto texture =
|
||||
context->GetResourceAllocator()->CreateTexture(texture_descriptor);
|
||||
if (!texture) {
|
||||
VALIDATION_LOG << "Could not allocate texture for fixture.";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto uploaded = texture->SetContents(decompressed_image.GetAllocation());
|
||||
if (!uploaded) {
|
||||
VALIDATION_LOG
|
||||
<< "Could not upload texture to device memory for fixture.";
|
||||
return nullptr;
|
||||
}
|
||||
return texture;
|
||||
}
|
||||
|
||||
auto buffer = context->GetResourceAllocator()->CreateBufferWithCopy(
|
||||
*decompressed_image.GetAllocation().get());
|
||||
|
||||
dest_texture->SetLabel(
|
||||
impeller::SPrintF("ui.Image(%p)", dest_texture.get()).c_str());
|
||||
|
||||
auto command_buffer = context->CreateCommandBuffer();
|
||||
if (!command_buffer) {
|
||||
FML_DLOG(ERROR) << "Could not create command buffer for mipmap generation.";
|
||||
return nullptr;
|
||||
}
|
||||
command_buffer->SetLabel("Mipmap Command Buffer");
|
||||
|
||||
auto blit_pass = command_buffer->CreateBlitPass();
|
||||
if (!blit_pass) {
|
||||
FML_DLOG(ERROR) << "Could not create blit pass for mipmap generation.";
|
||||
return nullptr;
|
||||
}
|
||||
blit_pass->SetLabel("Mipmap Blit Pass");
|
||||
blit_pass->AddCopy(buffer->AsBufferView(), dest_texture);
|
||||
if (enable_mipmapping) {
|
||||
blit_pass->GenerateMipmap(dest_texture);
|
||||
}
|
||||
|
||||
blit_pass->EncodeCommands(context->GetResourceAllocator());
|
||||
if (!command_buffer->SubmitCommands()) {
|
||||
FML_DLOG(ERROR) << "Failed to submit blit pass command buffer.";
|
||||
return nullptr;
|
||||
}
|
||||
return dest_texture;
|
||||
#else
|
||||
auto texture_descriptor = TextureDescriptor{};
|
||||
texture_descriptor.storage_mode = StorageMode::kHostVisible;
|
||||
texture_descriptor.format = PixelFormat::kR8G8B8A8UNormInt;
|
||||
texture_descriptor.size = decompressed_image.GetSize();
|
||||
texture_descriptor.mip_count =
|
||||
enable_mipmapping ? decompressed_image.GetSize().MipCount() : 1u;
|
||||
|
||||
auto texture =
|
||||
context->GetResourceAllocator()->CreateTexture(texture_descriptor);
|
||||
if (!texture) {
|
||||
VALIDATION_LOG << "Could not allocate texture for fixture.";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto uploaded = texture->SetContents(decompressed_image.GetAllocation());
|
||||
if (!uploaded) {
|
||||
VALIDATION_LOG << "Could not upload texture to device memory for fixture.";
|
||||
return nullptr;
|
||||
}
|
||||
return texture;
|
||||
#endif // FML_OS_MACOS
|
||||
}
|
||||
} // namespace
|
||||
|
||||
std::shared_ptr<Texture> Playground::CreateTextureForMapping(
|
||||
const std::shared_ptr<Context>& context,
|
||||
|
||||
@@ -65,6 +65,7 @@ ContextGLES::ContextGLES(std::unique_ptr<ProcTableGLES> gl,
|
||||
.SetHasThreadingRestrictions(true)
|
||||
.SetSupportsOffscreenMSAA(false)
|
||||
.SetSupportsSSBO(false)
|
||||
.SetSupportsBufferToTextureBlits(false)
|
||||
.SetSupportsTextureToTextureBlits(
|
||||
reactor_->GetProcTable().BlitFramebuffer.IsAvailable())
|
||||
.SetSupportsFramebufferFetch(false)
|
||||
|
||||
@@ -52,6 +52,7 @@ static std::unique_ptr<Capabilities> InferMetalCapabilities(
|
||||
.SetHasThreadingRestrictions(false)
|
||||
.SetSupportsOffscreenMSAA(true)
|
||||
.SetSupportsSSBO(true)
|
||||
.SetSupportsBufferToTextureBlits(true)
|
||||
.SetSupportsTextureToTextureBlits(true)
|
||||
.SetSupportsDecalTileMode(true)
|
||||
.SetSupportsFramebufferFetch(DeviceSupportsFramebufferFetch(device))
|
||||
|
||||
@@ -313,6 +313,11 @@ bool CapabilitiesVK::SupportsSSBO() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
// |Capabilities|
|
||||
bool CapabilitiesVK::SupportsBufferToTextureBlits() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
// |Capabilities|
|
||||
bool CapabilitiesVK::SupportsTextureToTextureBlits() const {
|
||||
return true;
|
||||
|
||||
@@ -55,6 +55,9 @@ class CapabilitiesVK final : public Capabilities,
|
||||
// |Capabilities|
|
||||
bool SupportsSSBO() const override;
|
||||
|
||||
// |Capabilities|
|
||||
bool SupportsBufferToTextureBlits() const override;
|
||||
|
||||
// |Capabilities|
|
||||
bool SupportsTextureToTextureBlits() const override;
|
||||
|
||||
|
||||
@@ -28,6 +28,11 @@ class StandardCapabilities final : public Capabilities {
|
||||
// |Capabilities|
|
||||
bool SupportsSSBO() const override { return supports_ssbo_; }
|
||||
|
||||
// |Capabilities|
|
||||
bool SupportsBufferToTextureBlits() const override {
|
||||
return supports_buffer_to_texture_blits_;
|
||||
}
|
||||
|
||||
// |Capabilities|
|
||||
bool SupportsTextureToTextureBlits() const override {
|
||||
return supports_texture_to_texture_blits_;
|
||||
@@ -75,6 +80,7 @@ class StandardCapabilities final : public Capabilities {
|
||||
StandardCapabilities(bool has_threading_restrictions,
|
||||
bool supports_offscreen_msaa,
|
||||
bool supports_ssbo,
|
||||
bool supports_buffer_to_texture_blits,
|
||||
bool supports_texture_to_texture_blits,
|
||||
bool supports_framebuffer_fetch,
|
||||
bool supports_compute,
|
||||
@@ -87,6 +93,7 @@ class StandardCapabilities final : public Capabilities {
|
||||
: has_threading_restrictions_(has_threading_restrictions),
|
||||
supports_offscreen_msaa_(supports_offscreen_msaa),
|
||||
supports_ssbo_(supports_ssbo),
|
||||
supports_buffer_to_texture_blits_(supports_buffer_to_texture_blits),
|
||||
supports_texture_to_texture_blits_(supports_texture_to_texture_blits),
|
||||
supports_framebuffer_fetch_(supports_framebuffer_fetch),
|
||||
supports_compute_(supports_compute),
|
||||
@@ -103,6 +110,7 @@ class StandardCapabilities final : public Capabilities {
|
||||
bool has_threading_restrictions_ = false;
|
||||
bool supports_offscreen_msaa_ = false;
|
||||
bool supports_ssbo_ = false;
|
||||
bool supports_buffer_to_texture_blits_ = false;
|
||||
bool supports_texture_to_texture_blits_ = false;
|
||||
bool supports_framebuffer_fetch_ = false;
|
||||
bool supports_compute_ = false;
|
||||
@@ -136,6 +144,12 @@ CapabilitiesBuilder& CapabilitiesBuilder::SetSupportsSSBO(bool value) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
CapabilitiesBuilder& CapabilitiesBuilder::SetSupportsBufferToTextureBlits(
|
||||
bool value) {
|
||||
supports_buffer_to_texture_blits_ = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
CapabilitiesBuilder& CapabilitiesBuilder::SetSupportsTextureToTextureBlits(
|
||||
bool value) {
|
||||
supports_texture_to_texture_blits_ = value;
|
||||
@@ -189,6 +203,7 @@ std::unique_ptr<Capabilities> CapabilitiesBuilder::Build() {
|
||||
has_threading_restrictions_, //
|
||||
supports_offscreen_msaa_, //
|
||||
supports_ssbo_, //
|
||||
supports_buffer_to_texture_blits_, //
|
||||
supports_texture_to_texture_blits_, //
|
||||
supports_framebuffer_fetch_, //
|
||||
supports_compute_, //
|
||||
|
||||
@@ -21,6 +21,8 @@ class Capabilities {
|
||||
|
||||
virtual bool SupportsSSBO() const = 0;
|
||||
|
||||
virtual bool SupportsBufferToTextureBlits() const = 0;
|
||||
|
||||
virtual bool SupportsTextureToTextureBlits() const = 0;
|
||||
|
||||
virtual bool SupportsFramebufferFetch() const = 0;
|
||||
@@ -57,6 +59,8 @@ class CapabilitiesBuilder {
|
||||
|
||||
CapabilitiesBuilder& SetSupportsSSBO(bool value);
|
||||
|
||||
CapabilitiesBuilder& SetSupportsBufferToTextureBlits(bool value);
|
||||
|
||||
CapabilitiesBuilder& SetSupportsTextureToTextureBlits(bool value);
|
||||
|
||||
CapabilitiesBuilder& SetSupportsFramebufferFetch(bool value);
|
||||
@@ -80,6 +84,7 @@ class CapabilitiesBuilder {
|
||||
bool has_threading_restrictions_ = false;
|
||||
bool supports_offscreen_msaa_ = false;
|
||||
bool supports_ssbo_ = false;
|
||||
bool supports_buffer_to_texture_blits_ = false;
|
||||
bool supports_texture_to_texture_blits_ = false;
|
||||
bool supports_framebuffer_fetch_ = false;
|
||||
bool supports_compute_ = false;
|
||||
|
||||
Reference in New Issue
Block a user