diff --git a/impeller/renderer/backend/gles/blit_pass_gles.cc b/impeller/renderer/backend/gles/blit_pass_gles.cc index 8685d86aa4a29..4819670db49fb 100644 --- a/impeller/renderer/backend/gles/blit_pass_gles.cc +++ b/impeller/renderer/backend/gles/blit_pass_gles.cc @@ -130,6 +130,11 @@ bool BlitPassGLES::OnCopyTextureToBufferCommand( return true; } +bool BlitPassGLES::OnOptimizeForGPUAccess(std::shared_ptr texture, + std::string label) { + return true; +} + // |BlitPass| bool BlitPassGLES::OnGenerateMipmapCommand(std::shared_ptr texture, std::string label) { diff --git a/impeller/renderer/backend/gles/blit_pass_gles.h b/impeller/renderer/backend/gles/blit_pass_gles.h index deaf1a41835f4..146aedf953a1b 100644 --- a/impeller/renderer/backend/gles/blit_pass_gles.h +++ b/impeller/renderer/backend/gles/blit_pass_gles.h @@ -50,6 +50,10 @@ class BlitPassGLES final : public BlitPass { size_t destination_offset, std::string label) override; + // |BlitPass| + bool OnOptimizeForGPUAccess(std::shared_ptr texture, + std::string label) override; + // |BlitPass| bool OnGenerateMipmapCommand(std::shared_ptr texture, std::string label) override; diff --git a/impeller/renderer/backend/metal/blit_command_mtl.h b/impeller/renderer/backend/metal/blit_command_mtl.h index ffdd450f16c9b..b1411ce8c8063 100644 --- a/impeller/renderer/backend/metal/blit_command_mtl.h +++ b/impeller/renderer/backend/metal/blit_command_mtl.h @@ -50,4 +50,13 @@ struct BlitGenerateMipmapCommandMTL : public BlitGenerateMipmapCommand, [[nodiscard]] bool Encode(id encoder) const override; }; +struct BlitOptimizeGPUAccessCommandMTL : public BlitGenerateMipmapCommand, + public BlitEncodeMTL { + ~BlitOptimizeGPUAccessCommandMTL() override; + + std::string GetLabel() const override; + + [[nodiscard]] bool Encode(id encoder) const override; +}; + } // namespace impeller diff --git a/impeller/renderer/backend/metal/blit_command_mtl.mm b/impeller/renderer/backend/metal/blit_command_mtl.mm index 7f589b4f54175..2981faef692c8 100644 --- a/impeller/renderer/backend/metal/blit_command_mtl.mm +++ b/impeller/renderer/backend/metal/blit_command_mtl.mm @@ -112,4 +112,23 @@ return true; }; +BlitOptimizeGPUAccessCommandMTL::~BlitOptimizeGPUAccessCommandMTL() = default; + +std::string BlitOptimizeGPUAccessCommandMTL::GetLabel() const { + return label; +} + +bool BlitOptimizeGPUAccessCommandMTL::Encode( + id encoder) const { + if (@available(macOS 10.14, iOS 12, tvOS 12, *)) { + auto texture_mtl = TextureMTL::Cast(*texture).GetMTLTexture(); + if (!texture_mtl) { + return false; + } + + [encoder optimizeContentsForGPUAccess:texture_mtl]; + } + return true; +} + } // namespace impeller diff --git a/impeller/renderer/backend/metal/blit_pass_mtl.h b/impeller/renderer/backend/metal/blit_pass_mtl.h index 108d320d98bf0..836273819da28 100644 --- a/impeller/renderer/backend/metal/blit_pass_mtl.h +++ b/impeller/renderer/backend/metal/blit_pass_mtl.h @@ -57,6 +57,10 @@ class BlitPassMTL final : public BlitPass { bool OnGenerateMipmapCommand(std::shared_ptr texture, std::string label) override; + // |BlitPass| + bool OnOptimizeForGPUAccess(std::shared_ptr texture, + std::string label) override; + FML_DISALLOW_COPY_AND_ASSIGN(BlitPassMTL); }; diff --git a/impeller/renderer/backend/metal/blit_pass_mtl.mm b/impeller/renderer/backend/metal/blit_pass_mtl.mm index 74df114143655..9b084eb5f043b 100644 --- a/impeller/renderer/backend/metal/blit_pass_mtl.mm +++ b/impeller/renderer/backend/metal/blit_pass_mtl.mm @@ -134,4 +134,15 @@ return true; } +// |BlitPass| +bool BlitPassMTL::OnOptimizeForGPUAccess(std::shared_ptr texture, + std::string label) { + auto command = std::make_unique(); + command->label = label; + command->texture = std::move(texture); + + commands_.emplace_back(std::move(command)); + return true; +} + } // namespace impeller diff --git a/impeller/renderer/backend/vulkan/blit_pass_vk.cc b/impeller/renderer/backend/vulkan/blit_pass_vk.cc index f563681af3455..e649a73d51b20 100644 --- a/impeller/renderer/backend/vulkan/blit_pass_vk.cc +++ b/impeller/renderer/backend/vulkan/blit_pass_vk.cc @@ -87,6 +87,12 @@ bool BlitPassVK::OnCopyTextureToBufferCommand( return true; } +// |BlitPass| +bool BlitPassVK::OnOptimizeForGPUAccess(std::shared_ptr texture, + std::string label) { + return true; +} + // |BlitPass| bool BlitPassVK::OnGenerateMipmapCommand(std::shared_ptr texture, std::string label) { diff --git a/impeller/renderer/backend/vulkan/blit_pass_vk.h b/impeller/renderer/backend/vulkan/blit_pass_vk.h index 62e52c15477bc..72f8b40ea01e2 100644 --- a/impeller/renderer/backend/vulkan/blit_pass_vk.h +++ b/impeller/renderer/backend/vulkan/blit_pass_vk.h @@ -51,6 +51,9 @@ class BlitPassVK final : public BlitPass { std::string label) override; // |BlitPass| + bool OnOptimizeForGPUAccess(std::shared_ptr texture, + std::string label) override; + // |BlitPass| bool OnGenerateMipmapCommand(std::shared_ptr texture, std::string label) override; diff --git a/impeller/renderer/blit_pass.cc b/impeller/renderer/blit_pass.cc index dd53e125645b5..14760889e14aa 100644 --- a/impeller/renderer/blit_pass.cc +++ b/impeller/renderer/blit_pass.cc @@ -116,6 +116,11 @@ bool BlitPass::AddCopy(std::shared_ptr source, std::move(label)); } +bool BlitPass::OptimizeForGPUAccess(std::shared_ptr texture, + std::string label) { + return OnOptimizeForGPUAccess(std::move(texture), std::move(label)); +} + bool BlitPass::GenerateMipmap(std::shared_ptr texture, std::string label) { if (!texture) { diff --git a/impeller/renderer/blit_pass.h b/impeller/renderer/blit_pass.h index 7ac7b820e5972..5341c20f62de5 100644 --- a/impeller/renderer/blit_pass.h +++ b/impeller/renderer/blit_pass.h @@ -95,6 +95,19 @@ class BlitPass { /// bool GenerateMipmap(std::shared_ptr texture, std::string label = ""); + //---------------------------------------------------------------------------- + /// @brief Optimize the provided texture for GPU access. + /// This will no-op on platforms where this functionality is + /// unsupported. + /// + /// @param[in] texture The texture to generate mipmaps for. + /// @param[in] label The optional debug label to give the command. + /// + /// @return If the command was valid for subsequent commitment. + /// + bool OptimizeForGPUAccess(std::shared_ptr texture, + std::string label = ""); + //---------------------------------------------------------------------------- /// @brief Encode the recorded commands to the underlying command buffer. /// @@ -127,6 +140,9 @@ class BlitPass { size_t destination_offset, std::string label) = 0; + virtual bool OnOptimizeForGPUAccess(std::shared_ptr texture, + std::string label) = 0; + virtual bool OnGenerateMipmapCommand(std::shared_ptr texture, std::string label) = 0; diff --git a/impeller/renderer/testing/mocks.h b/impeller/renderer/testing/mocks.h index 1f387ee58e05a..29f4faa01e37b 100644 --- a/impeller/renderer/testing/mocks.h +++ b/impeller/renderer/testing/mocks.h @@ -62,6 +62,9 @@ class MockBlitPass : public BlitPass { size_t destination_offset, std::string label)); + MOCK_METHOD2(OnOptimizeForGPUAccess, + bool(std::shared_ptr texture, std::string label)); + MOCK_METHOD2(OnGenerateMipmapCommand, bool(std::shared_ptr texture, std::string label)); }; diff --git a/lib/ui/painting/image_decoder_impeller.cc b/lib/ui/painting/image_decoder_impeller.cc index a6a130b3932c0..3c6ba866e0da7 100644 --- a/lib/ui/painting/image_decoder_impeller.cc +++ b/lib/ui/painting/image_decoder_impeller.cc @@ -286,6 +286,7 @@ sk_sp ImageDecoderImpeller::UploadTexture( } blit_pass->SetLabel("Mipmap Blit Pass"); blit_pass->GenerateMipmap(texture); + blit_pass->OptimizeForGPUAccess(texture); blit_pass->EncodeCommands(context->GetResourceAllocator()); if (!command_buffer->SubmitCommands()) {