diff --git a/engine/src/flutter/impeller/compositor/pipeline_descriptor.h b/engine/src/flutter/impeller/compositor/pipeline_descriptor.h index 1d6a1d2e015..f81da73fe1d 100644 --- a/engine/src/flutter/impeller/compositor/pipeline_descriptor.h +++ b/engine/src/flutter/impeller/compositor/pipeline_descriptor.h @@ -44,6 +44,9 @@ class PipelineDescriptor final : public Comparable { size_t index, ColorAttachmentDescriptor desc); + const ColorAttachmentDescriptor* GetColorAttachmentDescriptor( + size_t index) const; + PipelineDescriptor& SetDepthStencilAttachmentDescriptor( DepthAttachmentDescriptor desc); diff --git a/engine/src/flutter/impeller/compositor/pipeline_descriptor.mm b/engine/src/flutter/impeller/compositor/pipeline_descriptor.mm index 1aa9d5e781c..b7439487446 100644 --- a/engine/src/flutter/impeller/compositor/pipeline_descriptor.mm +++ b/engine/src/flutter/impeller/compositor/pipeline_descriptor.mm @@ -94,6 +94,13 @@ PipelineDescriptor& PipelineDescriptor::SetColorAttachmentDescriptor( return *this; } +const ColorAttachmentDescriptor* +PipelineDescriptor::GetColorAttachmentDescriptor(size_t index) const { + auto found = color_attachment_descriptors_.find(index); + return found == color_attachment_descriptors_.end() ? nullptr + : &found->second; +} + PipelineDescriptor& PipelineDescriptor::SetDepthPixelFormat( PixelFormat format) { depth_pixel_format_ = format; diff --git a/engine/src/flutter/impeller/compositor/render_pass.h b/engine/src/flutter/impeller/compositor/render_pass.h index 70688bc3548..67d405ab7ce 100644 --- a/engine/src/flutter/impeller/compositor/render_pass.h +++ b/engine/src/flutter/impeller/compositor/render_pass.h @@ -80,7 +80,17 @@ class RenderPass { [[nodiscard]] bool RecordCommand(Command command); - [[nodiscard]] bool FinishEncoding(Allocator& transients_allocator) const; + //---------------------------------------------------------------------------- + /// @brief Commit the recorded commands to the underlying command buffer. + /// Any completion handlers must on the underlying command buffer + /// must have already been added by this point. + /// + /// @param transients_allocator The transients allocator. + /// + /// @return If the commands were committed to the underlying command + /// buffer. + /// + [[nodiscard]] bool Commit(Allocator& transients_allocator) const; private: friend class CommandBuffer; diff --git a/engine/src/flutter/impeller/compositor/render_pass.mm b/engine/src/flutter/impeller/compositor/render_pass.mm index f390d0cacf7..d835c2ad72c 100644 --- a/engine/src/flutter/impeller/compositor/render_pass.mm +++ b/engine/src/flutter/impeller/compositor/render_pass.mm @@ -158,7 +158,7 @@ void RenderPass::SetLabel(std::string label) { transients_buffer_->SetLabel(SPrintF("%s Transients", label_.c_str())); } -bool RenderPass::FinishEncoding(Allocator& transients_allocator) const { +bool RenderPass::Commit(Allocator& transients_allocator) const { if (!IsValid()) { return false; } diff --git a/engine/src/flutter/impeller/compositor/renderer.mm b/engine/src/flutter/impeller/compositor/renderer.mm index 8b55e4b7c8a..ed13c1ce89e 100644 --- a/engine/src/flutter/impeller/compositor/renderer.mm +++ b/engine/src/flutter/impeller/compositor/renderer.mm @@ -54,7 +54,7 @@ bool Renderer::Render(const Surface& surface, return false; } - if (!render_pass->FinishEncoding(*GetContext()->GetTransientsAllocator())) { + if (!render_pass->Commit(*GetContext()->GetTransientsAllocator())) { return false; } diff --git a/engine/src/flutter/impeller/primitives/primitives_unittests.mm b/engine/src/flutter/impeller/primitives/primitives_unittests.mm index 3cb8fbc0d28..6a55d5c0d08 100644 --- a/engine/src/flutter/impeller/primitives/primitives_unittests.mm +++ b/engine/src/flutter/impeller/primitives/primitives_unittests.mm @@ -5,6 +5,7 @@ #include "flutter/fml/time/time_point.h" #include "flutter/testing/testing.h" #include "impeller/compositor/command.h" +#include "impeller/compositor/command_buffer.h" #include "impeller/compositor/pipeline_builder.h" #include "impeller/compositor/renderer.h" #include "impeller/compositor/sampler_descriptor.h" @@ -153,7 +154,98 @@ TEST_F(PrimitivesTest, CanRenderMultiplePrimitives) { return true; }; - OpenPlaygroundHere(callback); + // OpenPlaygroundHere(callback); +} + +TEST_F(PrimitivesTest, CanRenderToTexture) { + using VS = BoxFadeVertexShader; + using FS = BoxFadeFragmentShader; + auto context = GetContext(); + ASSERT_TRUE(context); + using BoxPipelineBuilder = PipelineBuilder; + auto pipeline_desc = + BoxPipelineBuilder::MakeDefaultPipelineDescriptor(*context); + auto box_pipeline = context->GetPipelineLibrary() + ->GetRenderPipeline(std::move(pipeline_desc)) + .get(); + ASSERT_TRUE(box_pipeline); + + VertexBufferBuilder vertex_builder; + vertex_builder.SetLabel("Box"); + vertex_builder.AddVertices({ + {{100, 100, 0.0}, {0.0, 0.0}}, // 1 + {{800, 100, 0.0}, {1.0, 0.0}}, // 2 + {{800, 800, 0.0}, {1.0, 1.0}}, // 3 + {{100, 100, 0.0}, {0.0, 0.0}}, // 1 + {{800, 800, 0.0}, {1.0, 1.0}}, // 3 + {{100, 800, 0.0}, {0.0, 1.0}}, // 4 + }); + auto vertex_buffer = + vertex_builder.CreateVertexBuffer(*context->GetPermanentsAllocator()); + ASSERT_TRUE(vertex_buffer); + + auto bridge = CreateTextureForFixture("bay_bridge.jpg"); + auto boston = CreateTextureForFixture("boston.jpg"); + ASSERT_TRUE(bridge && boston); + auto sampler = context->GetSamplerLibrary()->GetSampler({}); + ASSERT_TRUE(sampler); + + std::shared_ptr r2t_pass; + + { + ColorRenderPassAttachment color0; + color0.load_action = LoadAction::kClear; + color0.store_action = StoreAction::kStore; + + TextureDescriptor texture_descriptor; + ASSERT_NE(pipeline_desc->GetColorAttachmentDescriptor(0u), nullptr); + texture_descriptor.format = + pipeline_desc->GetColorAttachmentDescriptor(0u)->format; + texture_descriptor.size = {400, 400}; + texture_descriptor.mip_count = 1u; + texture_descriptor.usage = + static_cast(TextureUsage::kRenderTarget); + + color0.texture = context->GetPermanentsAllocator()->CreateTexture( + StorageMode::kHostVisible, texture_descriptor); + + ASSERT_TRUE(color0); + + color0.texture->SetLabel("r2t_target"); + + RenderPassDescriptor r2t_desc; + r2t_desc.SetColorAttachment(color0, 0u); + auto cmd_buffer = context->CreateRenderCommandBuffer(); + r2t_pass = cmd_buffer->CreateRenderPass(r2t_desc); + ASSERT_TRUE(r2t_pass && r2t_pass->IsValid()); + } + + Command cmd; + cmd.label = "Box"; + cmd.pipeline = box_pipeline; + + cmd.BindVertices(vertex_buffer); + + FS::FrameInfo frame_info; + frame_info.current_time = fml::TimePoint::Now().ToEpochDelta().ToSecondsF(); + frame_info.cursor_position = GetCursorPosition(); + frame_info.window_size.x = GetWindowSize().width; + frame_info.window_size.y = GetWindowSize().height; + + FS::BindFrameInfo(cmd, + r2t_pass->GetTransientsBuffer().EmplaceUniform(frame_info)); + FS::BindContents1(cmd, boston, sampler); + FS::BindContents2(cmd, bridge, sampler); + + cmd.primitive_type = PrimitiveType::kTriangle; + + VS::UniformBuffer uniforms; + uniforms.mvp = Matrix::MakeOrthographic(ISize{1024, 768}) * + Matrix::MakeTranslation({50.0f, 50.0f, 0.0f}); + VS::BindUniformBuffer( + cmd, r2t_pass->GetTransientsBuffer().EmplaceUniform(uniforms)); + ASSERT_TRUE(r2t_pass->RecordCommand(std::move(cmd))); + ASSERT_TRUE(r2t_pass->Commit(*context->GetTransientsAllocator())); } } // namespace testing