diff --git a/impeller/aiks/BUILD.gn b/impeller/aiks/BUILD.gn index 06d643c7b9993..f1d7d8ef681ac 100644 --- a/impeller/aiks/BUILD.gn +++ b/impeller/aiks/BUILD.gn @@ -76,7 +76,6 @@ impeller_component("context_spy") { "testing/context_spy.h", ] deps = [ - "//flutter/impeller/entity:entity_test_helpers", "//flutter/impeller/renderer", "//flutter/testing:testing_lib", ] diff --git a/impeller/aiks/testing/context_spy.cc b/impeller/aiks/testing/context_spy.cc index 460013cc2808a..e831719cd3008 100644 --- a/impeller/aiks/testing/context_spy.cc +++ b/impeller/aiks/testing/context_spy.cc @@ -2,8 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include - #include "impeller/aiks/testing/context_spy.h" namespace impeller { @@ -66,17 +64,14 @@ std::shared_ptr ContextSpy::MakeContext( }); ON_CALL(*spy, OnCreateRenderPass) - .WillByDefault([real_buffer, shared_this, - real_context](const RenderTarget& render_target) { - std::shared_ptr result = - CommandBufferMock::ForwardOnCreateRenderPass( - real_buffer.get(), render_target); - std::shared_ptr recorder = - std::make_shared(result, real_context, - render_target); - shared_this->render_passes_.push_back(recorder); - return recorder; - }); + .WillByDefault( + [real_buffer, shared_this](const RenderTarget& render_target) { + std::shared_ptr result = + CommandBufferMock::ForwardOnCreateRenderPass( + real_buffer.get(), render_target); + shared_this->render_passes_.push_back(result); + return result; + }); ON_CALL(*spy, OnCreateBlitPass).WillByDefault([real_buffer]() { return CommandBufferMock::ForwardOnCreateBlitPass(real_buffer.get()); diff --git a/impeller/aiks/testing/context_spy.h b/impeller/aiks/testing/context_spy.h index fe251b89e5999..28a5ec3907ae4 100644 --- a/impeller/aiks/testing/context_spy.h +++ b/impeller/aiks/testing/context_spy.h @@ -6,9 +6,7 @@ #define FLUTTER_IMPELLER_AIKS_TESTING_CONTEXT_SPY_H_ #include - #include "impeller/aiks/testing/context_mock.h" -#include "impeller/entity/contents/test/recording_render_pass.h" namespace impeller { namespace testing { @@ -22,7 +20,7 @@ class ContextSpy : public std::enable_shared_from_this { std::shared_ptr MakeContext( const std::shared_ptr& real_context); - std::vector> render_passes_; + std::vector> render_passes_; private: ContextSpy() = default; diff --git a/impeller/compiler/code_gen_template.h b/impeller/compiler/code_gen_template.h index dbef3017c0e41..7927c71d2952c 100644 --- a/impeller/compiler/code_gen_template.h +++ b/impeller/compiler/code_gen_template.h @@ -161,7 +161,7 @@ struct {{camel_case(shader_name)}}{{camel_case(shader_stage)}}Shader { {% endfor %}) { return {{ proto.args.0.argument_name }}.BindResource({% for arg in proto.args %} {% if loop.is_first %} -{{to_shader_stage(shader_stage)}}, {{ proto.descriptor_type }}, kResource{{ proto.name }}, kMetadata{{ proto.name }}, {% else %} +{{to_shader_stage(shader_stage)}}, kResource{{ proto.name }}, kMetadata{{ proto.name }}, {% else %} std::move({{ arg.argument_name }}){% if not loop.is_last %}, {% endif %} {% endif %} {% endfor %}); diff --git a/impeller/compiler/reflector.cc b/impeller/compiler/reflector.cc index cafa894256f4d..e01755bccc38f 100644 --- a/impeller/compiler/reflector.cc +++ b/impeller/compiler/reflector.cc @@ -1308,7 +1308,6 @@ std::vector Reflector::ReflectBindPrototypes( auto& proto = prototypes.emplace_back(BindPrototype{}); proto.return_type = "bool"; proto.name = ToCamelCase(uniform_buffer.name); - proto.descriptor_type = "DescriptorType::kUniformBuffer"; { std::stringstream stream; stream << "Bind uniform buffer for resource named " << uniform_buffer.name @@ -1328,7 +1327,6 @@ std::vector Reflector::ReflectBindPrototypes( auto& proto = prototypes.emplace_back(BindPrototype{}); proto.return_type = "bool"; proto.name = ToCamelCase(storage_buffer.name); - proto.descriptor_type = "DescriptorType::kStorageBuffer"; { std::stringstream stream; stream << "Bind storage buffer for resource named " << storage_buffer.name @@ -1348,7 +1346,6 @@ std::vector Reflector::ReflectBindPrototypes( auto& proto = prototypes.emplace_back(BindPrototype{}); proto.return_type = "bool"; proto.name = ToCamelCase(sampled_image.name); - proto.descriptor_type = "DescriptorType::kSampledImage"; { std::stringstream stream; stream << "Bind combined image sampler for resource named " @@ -1372,7 +1369,6 @@ std::vector Reflector::ReflectBindPrototypes( auto& proto = prototypes.emplace_back(BindPrototype{}); proto.return_type = "bool"; proto.name = ToCamelCase(separate_image.name); - proto.descriptor_type = "DescriptorType::kImage"; { std::stringstream stream; stream << "Bind separate image for resource named " << separate_image.name @@ -1392,7 +1388,6 @@ std::vector Reflector::ReflectBindPrototypes( auto& proto = prototypes.emplace_back(BindPrototype{}); proto.return_type = "bool"; proto.name = ToCamelCase(separate_sampler.name); - proto.descriptor_type = "DescriptorType::kSampler"; { std::stringstream stream; stream << "Bind separate sampler for resource named " @@ -1421,7 +1416,6 @@ nlohmann::json::array_t Reflector::EmitBindPrototypes( item["return_type"] = res.return_type; item["name"] = res.name; item["docstring"] = res.docstring; - item["descriptor_type"] = res.descriptor_type; auto& args = item["args"] = nlohmann::json::array_t{}; for (const auto& arg : res.args) { auto& json_arg = args.emplace_back(nlohmann::json::object_t{}); diff --git a/impeller/compiler/reflector.h b/impeller/compiler/reflector.h index 1448e412d4738..3de086c00a553 100644 --- a/impeller/compiler/reflector.h +++ b/impeller/compiler/reflector.h @@ -187,7 +187,6 @@ class Reflector { std::string name; std::string return_type; std::string docstring; - std::string descriptor_type = ""; std::vector args; }; diff --git a/impeller/core/resource_binder.h b/impeller/core/resource_binder.h index bd2dfea50508e..6a6172710d700 100644 --- a/impeller/core/resource_binder.h +++ b/impeller/core/resource_binder.h @@ -24,13 +24,11 @@ struct ResourceBinder { virtual ~ResourceBinder() = default; virtual bool BindResource(ShaderStage stage, - DescriptorType type, const ShaderUniformSlot& slot, const ShaderMetadata& metadata, BufferView view) = 0; virtual bool BindResource(ShaderStage stage, - DescriptorType type, const SampledImageSlot& slot, const ShaderMetadata& metadata, std::shared_ptr texture, diff --git a/impeller/entity/BUILD.gn b/impeller/entity/BUILD.gn index 0f900cf0345ab..31852bf1350df 100644 --- a/impeller/entity/BUILD.gn +++ b/impeller/entity/BUILD.gn @@ -257,8 +257,6 @@ impeller_component("entity_test_helpers") { sources = [ "contents/test/contents_test_helpers.cc", "contents/test/contents_test_helpers.h", - "contents/test/recording_render_pass.cc", - "contents/test/recording_render_pass.h", ] deps = [ ":entity" ] diff --git a/impeller/entity/contents/checkerboard_contents_unittests.cc b/impeller/entity/contents/checkerboard_contents_unittests.cc index 97e1dae4276d5..63a2cbdd3aa07 100644 --- a/impeller/entity/contents/checkerboard_contents_unittests.cc +++ b/impeller/entity/contents/checkerboard_contents_unittests.cc @@ -9,7 +9,6 @@ #include "impeller/entity/contents/checkerboard_contents.h" #include "impeller/entity/contents/contents.h" -#include "impeller/entity/contents/test/recording_render_pass.h" #include "impeller/entity/entity.h" #include "impeller/entity/entity_playground.h" #include "impeller/renderer/render_target.h" @@ -39,14 +38,11 @@ TEST_P(EntityTest, RendersWithoutError) { *GetContentContext()->GetRenderTargetCache(), {100, 100}, /*mip_count=*/1); auto render_pass = buffer->CreateRenderPass(render_target); - auto recording_pass = std::make_shared( - render_pass, GetContext(), render_target); - Entity entity; - ASSERT_TRUE(recording_pass->GetCommands().empty()); - ASSERT_TRUE(contents->Render(*content_context, entity, *recording_pass)); - ASSERT_FALSE(recording_pass->GetCommands().empty()); + ASSERT_TRUE(render_pass->GetCommands().empty()); + ASSERT_TRUE(contents->Render(*content_context, entity, *render_pass)); + ASSERT_FALSE(render_pass->GetCommands().empty()); } #endif // IMPELLER_DEBUG diff --git a/impeller/entity/contents/runtime_effect_contents.cc b/impeller/entity/contents/runtime_effect_contents.cc index 7da74e4a56b0b..54170ffff091f 100644 --- a/impeller/entity/contents/runtime_effect_contents.cc +++ b/impeller/entity/contents/runtime_effect_contents.cc @@ -199,9 +199,8 @@ bool RuntimeEffectContents::Render(const ContentContext& renderer, ShaderUniformSlot uniform_slot; uniform_slot.name = uniform.name.c_str(); uniform_slot.ext_res_0 = uniform.location; - pass.BindResource(ShaderStage::kFragment, - DescriptorType::kUniformBuffer, uniform_slot, - metadata, buffer_view); + pass.BindResource(ShaderStage::kFragment, uniform_slot, metadata, + buffer_view); buffer_index++; buffer_offset += uniform.GetSize(); break; @@ -238,8 +237,7 @@ bool RuntimeEffectContents::Render(const ContentContext& renderer, auto buffer_view = renderer.GetTransientsBuffer().Emplace( reinterpret_cast(uniform_buffer.data()), sizeof(float) * uniform_buffer.size(), alignment); - pass.BindResource(ShaderStage::kFragment, - DescriptorType::kUniformBuffer, uniform_slot, + pass.BindResource(ShaderStage::kFragment, uniform_slot, ShaderMetadata{}, buffer_view); } } @@ -273,8 +271,8 @@ bool RuntimeEffectContents::Render(const ContentContext& renderer, image_slot.binding = sampler_binding_location; image_slot.texture_index = uniform.location - minimum_sampler_index; - pass.BindResource(ShaderStage::kFragment, DescriptorType::kSampledImage, - image_slot, *metadata, input.texture, sampler); + pass.BindResource(ShaderStage::kFragment, image_slot, *metadata, + input.texture, sampler); sampler_index++; break; diff --git a/impeller/entity/contents/test/recording_render_pass.cc b/impeller/entity/contents/test/recording_render_pass.cc deleted file mode 100644 index ef22d86d69ed6..0000000000000 --- a/impeller/entity/contents/test/recording_render_pass.cc +++ /dev/null @@ -1,116 +0,0 @@ -// Copyright 2013 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "impeller/entity/contents/test/recording_render_pass.h" - -#include - -namespace impeller { - -RecordingRenderPass::RecordingRenderPass( - std::shared_ptr delegate, - const std::shared_ptr& context, - const RenderTarget& render_target) - : RenderPass(context, render_target), delegate_(std::move(delegate)) {} - -// |RenderPass| -void RecordingRenderPass::SetPipeline( - const std::shared_ptr>& pipeline) { - pending_.pipeline = pipeline; - delegate_->SetPipeline(pipeline); -} - -void RecordingRenderPass::SetCommandLabel(std::string_view label) { -#ifdef IMPELLER_DEBUG - pending_.label = std::string(label); -#endif // IMPELLER_DEBUG - delegate_->SetCommandLabel(label); -} - -// |RenderPass| -void RecordingRenderPass::SetStencilReference(uint32_t value) { - pending_.stencil_reference = value; - delegate_->SetStencilReference(value); -} - -// |RenderPass| -void RecordingRenderPass::SetBaseVertex(uint64_t value) { - pending_.base_vertex = value; - delegate_->SetBaseVertex(value); -} - -// |RenderPass| -void RecordingRenderPass::SetViewport(Viewport viewport) { - pending_.viewport = viewport; - delegate_->SetViewport(viewport); -} - -// |RenderPass| -void RecordingRenderPass::SetScissor(IRect scissor) { - pending_.scissor = scissor; - delegate_->SetScissor(scissor); -} - -// |RenderPass| -void RecordingRenderPass::SetInstanceCount(size_t count) { - pending_.instance_count = count; - delegate_->SetInstanceCount(count); -} - -// |RenderPass| -bool RecordingRenderPass::SetVertexBuffer(VertexBuffer buffer) { - pending_.vertex_buffer = buffer; - return delegate_->SetVertexBuffer(buffer); -} - -// |RenderPass| -fml::Status RecordingRenderPass::Draw() { - commands_.emplace_back(std::move(pending_)); - pending_ = {}; - return delegate_->Draw(); -} - -// |RenderPass| -void RecordingRenderPass::OnSetLabel(std::string label) { - return; -} - -// |RenderPass| -bool RecordingRenderPass::OnEncodeCommands(const Context& context) const { - return true; -} - -// |RenderPass| -bool RecordingRenderPass::BindResource(ShaderStage stage, - DescriptorType type, - const ShaderUniformSlot& slot, - const ShaderMetadata& metadata, - BufferView view) { - pending_.BindResource(stage, type, slot, metadata, view); - return delegate_->BindResource(stage, type, slot, metadata, view); -} - -// |RenderPass| -bool RecordingRenderPass::BindResource( - ShaderStage stage, - DescriptorType type, - const ShaderUniformSlot& slot, - const std::shared_ptr& metadata, - BufferView view) { - pending_.BindResource(stage, type, slot, metadata, view); - return delegate_->BindResource(stage, type, slot, metadata, view); -} - -// |RenderPass| -bool RecordingRenderPass::BindResource(ShaderStage stage, - DescriptorType type, - const SampledImageSlot& slot, - const ShaderMetadata& metadata, - std::shared_ptr texture, - std::shared_ptr sampler) { - pending_.BindResource(stage, type, slot, metadata, texture, sampler); - return delegate_->BindResource(stage, type, slot, metadata, texture, sampler); -} - -} // namespace impeller diff --git a/impeller/entity/contents/test/recording_render_pass.h b/impeller/entity/contents/test/recording_render_pass.h deleted file mode 100644 index eb585c27767eb..0000000000000 --- a/impeller/entity/contents/test/recording_render_pass.h +++ /dev/null @@ -1,87 +0,0 @@ -// Copyright 2013 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef FLUTTER_IMPELLER_ENTITY_CONTENTS_TEST_RECORDING_RENDER_PASS_H_ -#define FLUTTER_IMPELLER_ENTITY_CONTENTS_TEST_RECORDING_RENDER_PASS_H_ - -#include "impeller/renderer/render_pass.h" - -namespace impeller { - -class RecordingRenderPass : public RenderPass { - public: - explicit RecordingRenderPass(std::shared_ptr delegate, - const std::shared_ptr& context, - const RenderTarget& render_target); - - ~RecordingRenderPass() = default; - - const std::vector& GetCommands() const override { return commands_; } - - // |RenderPass| - void SetPipeline( - const std::shared_ptr>& pipeline) override; - - void SetCommandLabel(std::string_view label) override; - - // |RenderPass| - void SetStencilReference(uint32_t value) override; - - // |RenderPass| - void SetBaseVertex(uint64_t value) override; - - // |RenderPass| - void SetViewport(Viewport viewport) override; - - // |RenderPass| - void SetScissor(IRect scissor) override; - - // |RenderPass| - void SetInstanceCount(size_t count) override; - - // |RenderPass| - bool SetVertexBuffer(VertexBuffer buffer) override; - - // |RenderPass| - fml::Status Draw() override; - - // |RenderPass| - bool BindResource(ShaderStage stage, - DescriptorType type, - const ShaderUniformSlot& slot, - const ShaderMetadata& metadata, - BufferView view) override; - - // |RenderPass| - bool BindResource(ShaderStage stage, - DescriptorType type, - const ShaderUniformSlot& slot, - const std::shared_ptr& metadata, - BufferView view) override; - - // |RenderPass| - bool BindResource(ShaderStage stage, - DescriptorType type, - const SampledImageSlot& slot, - const ShaderMetadata& metadata, - std::shared_ptr texture, - std::shared_ptr sampler) override; - - // |RenderPass| - void OnSetLabel(std::string label) override; - - // |RenderPass| - bool OnEncodeCommands(const Context& context) const override; - - bool IsValid() const override { return true; } - - private: - Command pending_; - std::shared_ptr delegate_; - std::vector commands_; -}; - -} // namespace impeller - -#endif // FLUTTER_IMPELLER_ENTITY_CONTENTS_TEST_RECORDING_RENDER_PASS_H_ diff --git a/impeller/entity/contents/tiled_texture_contents_unittests.cc b/impeller/entity/contents/tiled_texture_contents_unittests.cc index ddaedc3efc1f1..4715eaad79133 100644 --- a/impeller/entity/contents/tiled_texture_contents_unittests.cc +++ b/impeller/entity/contents/tiled_texture_contents_unittests.cc @@ -6,7 +6,6 @@ #include "impeller/core/formats.h" #include "impeller/core/texture_descriptor.h" -#include "impeller/entity/contents/test/recording_render_pass.h" #include "impeller/entity/contents/tiled_texture_contents.h" #include "impeller/entity/entity_playground.h" #include "impeller/playground/playground_test.h" @@ -37,11 +36,9 @@ TEST_P(EntityTest, TiledTextureContentsRendersWithCorrectPipeline) { *GetContentContext()->GetRenderTargetCache(), {100, 100}, /*mip_count=*/1); auto render_pass = buffer->CreateRenderPass(render_target); - auto recording_pass = std::make_shared( - render_pass, GetContext(), render_target); - ASSERT_TRUE(contents.Render(*GetContentContext(), {}, *recording_pass)); - const std::vector& commands = recording_pass->GetCommands(); + ASSERT_TRUE(contents.Render(*GetContentContext(), {}, *render_pass)); + const std::vector& commands = render_pass->GetCommands(); ASSERT_EQ(commands.size(), 1u); ASSERT_STREQ(commands[0].pipeline->GetDescriptor().GetLabel().c_str(), diff --git a/impeller/entity/contents/vertices_contents_unittests.cc b/impeller/entity/contents/vertices_contents_unittests.cc index 4f1e778986070..17fac72d722dc 100644 --- a/impeller/entity/contents/vertices_contents_unittests.cc +++ b/impeller/entity/contents/vertices_contents_unittests.cc @@ -10,7 +10,6 @@ #include "impeller/entity/contents/contents.h" #include "impeller/entity/contents/solid_color_contents.h" #include "impeller/entity/contents/test/contents_test_helpers.h" -#include "impeller/entity/contents/test/recording_render_pass.h" #include "impeller/entity/contents/vertices_contents.h" #include "impeller/entity/entity.h" #include "impeller/entity/entity_playground.h" @@ -65,15 +64,12 @@ TEST_P(EntityTest, RendersDstPerColorWithAlpha) { *GetContentContext()->GetRenderTargetCache(), {100, 100}, /*mip_count=*/1); auto render_pass = buffer->CreateRenderPass(render_target); - auto recording_pass = std::make_shared( - render_pass, GetContext(), render_target); Entity entity; - ASSERT_TRUE(recording_pass->GetCommands().empty()); - ASSERT_TRUE(contents->Render(*content_context, entity, *recording_pass)); + ASSERT_TRUE(render_pass->GetCommands().empty()); + ASSERT_TRUE(contents->Render(*content_context, entity, *render_pass)); - ASSERT_TRUE(recording_pass->GetCommands().size() > 0); - const auto& cmd = recording_pass->GetCommands()[0]; + const auto& cmd = render_pass->GetCommands()[0]; auto* frag_uniforms = GetFragInfo(cmd); ASSERT_TRUE(frag_uniforms); diff --git a/impeller/playground/imgui/imgui_impl_impeller.cc b/impeller/playground/imgui/imgui_impl_impeller.cc index 279c94e51189c..ada717b742ea8 100644 --- a/impeller/playground/imgui/imgui_impl_impeller.cc +++ b/impeller/playground/imgui/imgui_impl_impeller.cc @@ -126,7 +126,7 @@ void ImGui_ImplImpeller_RenderDrawData(ImDrawData* draw_data, return; // Nothing to render. } auto host_buffer = impeller::HostBuffer::Create( - render_pass.GetContext()->GetResourceAllocator()); + render_pass.GetContext().lock()->GetResourceAllocator()); using VS = impeller::ImguiRasterVertexShader; using FS = impeller::ImguiRasterFragmentShader; diff --git a/impeller/renderer/backend/gles/command_buffer_gles.cc b/impeller/renderer/backend/gles/command_buffer_gles.cc index ea6a651d0189a..737984d3ae1a8 100644 --- a/impeller/renderer/backend/gles/command_buffer_gles.cc +++ b/impeller/renderer/backend/gles/command_buffer_gles.cc @@ -49,12 +49,8 @@ std::shared_ptr CommandBufferGLES::OnCreateRenderPass( if (!IsValid()) { return nullptr; } - auto context = context_.lock(); - if (!context) { - return nullptr; - } auto pass = std::shared_ptr( - new RenderPassGLES(context, target, reactor_)); + new RenderPassGLES(context_, target, reactor_)); if (!pass->IsValid()) { return nullptr; } diff --git a/impeller/renderer/backend/gles/render_pass_gles.cc b/impeller/renderer/backend/gles/render_pass_gles.cc index 6cff519a41270..20b6fd4bea71b 100644 --- a/impeller/renderer/backend/gles/render_pass_gles.cc +++ b/impeller/renderer/backend/gles/render_pass_gles.cc @@ -20,7 +20,7 @@ namespace impeller { -RenderPassGLES::RenderPassGLES(std::shared_ptr context, +RenderPassGLES::RenderPassGLES(std::weak_ptr context, const RenderTarget& target, ReactorGLES::Ref reactor) : RenderPass(std::move(context), target), diff --git a/impeller/renderer/backend/gles/render_pass_gles.h b/impeller/renderer/backend/gles/render_pass_gles.h index 9d4f986108d57..e7e408306336c 100644 --- a/impeller/renderer/backend/gles/render_pass_gles.h +++ b/impeller/renderer/backend/gles/render_pass_gles.h @@ -26,7 +26,7 @@ class RenderPassGLES final std::string label_; bool is_valid_ = false; - RenderPassGLES(std::shared_ptr context, + RenderPassGLES(std::weak_ptr context, const RenderTarget& target, ReactorGLES::Ref reactor); diff --git a/impeller/renderer/backend/metal/command_buffer_mtl.mm b/impeller/renderer/backend/metal/command_buffer_mtl.mm index c7899d48982f3..7adb44a189225 100644 --- a/impeller/renderer/backend/metal/command_buffer_mtl.mm +++ b/impeller/renderer/backend/metal/command_buffer_mtl.mm @@ -275,12 +275,8 @@ static bool LogMTLCommandBufferErrorIfPresent(id buffer) { return nullptr; } - auto context = context_.lock(); - if (!context) { - return nullptr; - } auto pass = std::shared_ptr( - new RenderPassMTL(context, target, buffer_)); + new RenderPassMTL(context_, target, buffer_)); if (!pass->IsValid()) { return nullptr; } diff --git a/impeller/renderer/backend/metal/render_pass_mtl.h b/impeller/renderer/backend/metal/render_pass_mtl.h index 00240d45249d3..69c78573e8add 100644 --- a/impeller/renderer/backend/metal/render_pass_mtl.h +++ b/impeller/renderer/backend/metal/render_pass_mtl.h @@ -26,7 +26,7 @@ class RenderPassMTL final : public RenderPass { std::string label_; bool is_valid_ = false; - RenderPassMTL(std::shared_ptr context, + RenderPassMTL(std::weak_ptr context, const RenderTarget& target, id buffer); diff --git a/impeller/renderer/backend/metal/render_pass_mtl.mm b/impeller/renderer/backend/metal/render_pass_mtl.mm index 396127d598733..83918f71fce84 100644 --- a/impeller/renderer/backend/metal/render_pass_mtl.mm +++ b/impeller/renderer/backend/metal/render_pass_mtl.mm @@ -134,7 +134,7 @@ static bool ConfigureStencilAttachment( return result; } -RenderPassMTL::RenderPassMTL(std::shared_ptr context, +RenderPassMTL::RenderPassMTL(std::weak_ptr context, const RenderTarget& target, id buffer) : RenderPass(std::move(context), target), diff --git a/impeller/renderer/backend/vulkan/binding_helpers_vk.cc b/impeller/renderer/backend/vulkan/binding_helpers_vk.cc index 92b30313f5f3a..3bc11ba252784 100644 --- a/impeller/renderer/backend/vulkan/binding_helpers_vk.cc +++ b/impeller/renderer/backend/vulkan/binding_helpers_vk.cc @@ -20,6 +20,11 @@ namespace impeller { +// Warning: if any of the constant values or layouts are changed in the +// framebuffer fetch shader, then this input binding may need to be +// manually changed. +static constexpr size_t kMagicSubpassInputBinding = 64; + static bool BindImages( const Bindings& bindings, Allocator& allocator, @@ -120,6 +125,67 @@ static bool BindBuffers( return true; } +fml::StatusOr AllocateAndBindDescriptorSets( + const ContextVK& context, + const std::shared_ptr& encoder, + Allocator& allocator, + const Command& command, + const TextureVK& input_attachment, + std::array& image_workspace, + std::array& buffer_workspace, + std::array& + write_workspace) { + auto descriptor_result = encoder->AllocateDescriptorSets( + PipelineVK::Cast(*command.pipeline).GetDescriptorSetLayout(), context); + if (!descriptor_result.ok()) { + return descriptor_result.status(); + } + vk::DescriptorSet descriptor_set = descriptor_result.value(); + + size_t buffer_offset = 0u; + size_t image_offset = 0u; + size_t write_offset = 0u; + + auto& pipeline_descriptor = command.pipeline->GetDescriptor(); + auto& desc_set = + pipeline_descriptor.GetVertexDescriptor()->GetDescriptorSetLayouts(); + + if (!BindBuffers(command.vertex_bindings, allocator, encoder, descriptor_set, + desc_set, buffer_workspace, buffer_offset, write_workspace, + write_offset) || + !BindBuffers(command.fragment_bindings, allocator, encoder, + descriptor_set, desc_set, buffer_workspace, buffer_offset, + write_workspace, write_offset) || + !BindImages(command.fragment_bindings, allocator, encoder, descriptor_set, + image_workspace, image_offset, write_workspace, + write_offset)) { + return fml::Status(fml::StatusCode::kUnknown, + "Failed to bind texture or buffer."); + } + + if (pipeline_descriptor.UsesSubpassInput()) { + vk::DescriptorImageInfo image_info; + image_info.imageLayout = vk::ImageLayout::eGeneral; + image_info.sampler = VK_NULL_HANDLE; + image_info.imageView = input_attachment.GetImageView(); + image_workspace[image_offset++] = image_info; + + vk::WriteDescriptorSet write_set; + write_set.dstSet = descriptor_set; + write_set.dstBinding = kMagicSubpassInputBinding; + write_set.descriptorCount = 1u; + write_set.descriptorType = vk::DescriptorType::eInputAttachment; + write_set.pImageInfo = &image_workspace[image_offset - 1]; + + write_workspace[write_offset++] = write_set; + } + + context.GetDevice().updateDescriptorSets(write_offset, write_workspace.data(), + 0u, {}); + + return descriptor_set; +} + fml::StatusOr AllocateAndBindDescriptorSets( const ContextVK& context, const std::shared_ptr& encoder, diff --git a/impeller/renderer/backend/vulkan/binding_helpers_vk.h b/impeller/renderer/backend/vulkan/binding_helpers_vk.h index be35567a77e3b..1dc7f32d2a4b6 100644 --- a/impeller/renderer/backend/vulkan/binding_helpers_vk.h +++ b/impeller/renderer/backend/vulkan/binding_helpers_vk.h @@ -17,6 +17,17 @@ namespace impeller { // backend to avoid dynamic heap allocations. static constexpr size_t kMaxBindings = 32; +fml::StatusOr AllocateAndBindDescriptorSets( + const ContextVK& context, + const std::shared_ptr& encoder, + Allocator& allocator, + const Command& command, + const TextureVK& input_attachment, + std::array& image_workspace, + std::array& buffer_workspace, + std::array& + write_workspace); + fml::StatusOr AllocateAndBindDescriptorSets( const ContextVK& context, const std::shared_ptr& encoder, diff --git a/impeller/renderer/backend/vulkan/command_buffer_vk.cc b/impeller/renderer/backend/vulkan/command_buffer_vk.cc index 6b7b14f243fdb..78eb547847082 100644 --- a/impeller/renderer/backend/vulkan/command_buffer_vk.cc +++ b/impeller/renderer/backend/vulkan/command_buffer_vk.cc @@ -7,10 +7,13 @@ #include #include +#include "flutter/fml/logging.h" +#include "impeller/base/validation.h" #include "impeller/renderer/backend/vulkan/blit_pass_vk.h" #include "impeller/renderer/backend/vulkan/command_encoder_vk.h" #include "impeller/renderer/backend/vulkan/compute_pass_vk.h" #include "impeller/renderer/backend/vulkan/context_vk.h" +#include "impeller/renderer/backend/vulkan/formats_vk.h" #include "impeller/renderer/backend/vulkan/render_pass_vk.h" #include "impeller/renderer/command_buffer.h" #include "impeller/renderer/render_target.h" @@ -70,9 +73,9 @@ std::shared_ptr CommandBufferVK::OnCreateRenderPass( return nullptr; } auto pass = - std::shared_ptr(new RenderPassVK(context, // - target, // - shared_from_this() // + std::shared_ptr(new RenderPassVK(context, // + target, // + weak_from_this() // )); if (!pass->IsValid()) { return nullptr; diff --git a/impeller/renderer/backend/vulkan/command_buffer_vk.h b/impeller/renderer/backend/vulkan/command_buffer_vk.h index d85ce290082a8..b1ede05b724f0 100644 --- a/impeller/renderer/backend/vulkan/command_buffer_vk.h +++ b/impeller/renderer/backend/vulkan/command_buffer_vk.h @@ -5,6 +5,7 @@ #ifndef FLUTTER_IMPELLER_RENDERER_BACKEND_VULKAN_COMMAND_BUFFER_VK_H_ #define FLUTTER_IMPELLER_RENDERER_BACKEND_VULKAN_COMMAND_BUFFER_VK_H_ +#include "flutter/fml/macros.h" #include "impeller/base/backend_cast.h" #include "impeller/renderer/backend/vulkan/vk.h" #include "impeller/renderer/command_buffer.h" diff --git a/impeller/renderer/backend/vulkan/gpu_tracer_vk.cc b/impeller/renderer/backend/vulkan/gpu_tracer_vk.cc index 4867c9626c941..921677408697c 100644 --- a/impeller/renderer/backend/vulkan/gpu_tracer_vk.cc +++ b/impeller/renderer/backend/vulkan/gpu_tracer_vk.cc @@ -8,7 +8,6 @@ #include #include #include - #include "fml/logging.h" #include "fml/trace_event.h" #include "impeller/base/validation.h" @@ -31,7 +30,7 @@ GPUTracerVK::GPUTracerVK(const std::shared_ptr& device_holder) // Disable tracing in release mode. #ifdef IMPELLER_DEBUG enabled_ = true; -#endif // IMPELLER_DEBUG +#endif } bool GPUTracerVK::IsEnabled() const { @@ -106,14 +105,16 @@ void GPUTracerVK::RecordCmdBufferStart(const vk::CommandBuffer& buffer, trace_states_[current_state_].query_pool.get(), state.current_index); state.current_index += 1; - probe.index_ = current_state_; - state.pending_buffers += 1; + if (!probe.index_.has_value()) { + state.pending_buffers += 1; + probe.index_ = current_state_; + } } void GPUTracerVK::RecordCmdBufferEnd(const vk::CommandBuffer& buffer, GPUProbe& probe) { if (!enabled_ || std::this_thread::get_id() != raster_thread_id_ || - !in_frame_ || !probe.index_.has_value()) { + !in_frame_) { return; } Lock lock(trace_state_mutex_); @@ -127,6 +128,10 @@ void GPUTracerVK::RecordCmdBufferEnd(const vk::CommandBuffer& buffer, state.query_pool.get(), state.current_index); state.current_index += 1; + if (!probe.index_.has_value()) { + state.pending_buffers += 1; + probe.index_ = current_state_; + } } void GPUTracerVK::OnFenceComplete(size_t frame_index) { diff --git a/impeller/renderer/backend/vulkan/render_pass_vk.cc b/impeller/renderer/backend/vulkan/render_pass_vk.cc index dc40fc6b70b67..ef2fbff69ecfc 100644 --- a/impeller/renderer/backend/vulkan/render_pass_vk.cc +++ b/impeller/renderer/backend/vulkan/render_pass_vk.cc @@ -8,11 +8,10 @@ #include #include -#include "fml/status.h" +#include "flutter/fml/trace_event.h" #include "impeller/base/validation.h" #include "impeller/core/device_buffer.h" #include "impeller/core/formats.h" -#include "impeller/core/texture.h" #include "impeller/renderer/backend/vulkan/barrier_vk.h" #include "impeller/renderer/backend/vulkan/binding_helpers_vk.h" #include "impeller/renderer/backend/vulkan/command_buffer_vk.h" @@ -21,63 +20,15 @@ #include "impeller/renderer/backend/vulkan/device_buffer_vk.h" #include "impeller/renderer/backend/vulkan/formats_vk.h" #include "impeller/renderer/backend/vulkan/pipeline_vk.h" -#include "impeller/renderer/backend/vulkan/sampler_vk.h" #include "impeller/renderer/backend/vulkan/shared_object_vk.h" #include "impeller/renderer/backend/vulkan/texture_vk.h" - +#include "impeller/renderer/command.h" #include "vulkan/vulkan_enums.hpp" #include "vulkan/vulkan_handles.hpp" #include "vulkan/vulkan_to_string.hpp" namespace impeller { -// Warning: if any of the constant values or layouts are changed in the -// framebuffer fetch shader, then this input binding may need to be -// manually changed. -static constexpr size_t kMagicSubpassInputBinding = 64; - -static vk::ClearColorValue VKClearValueFromColor(Color color) { - vk::ClearColorValue value; - value.setFloat32( - std::array{color.red, color.green, color.blue, color.alpha}); - return value; -} - -static vk::ClearDepthStencilValue VKClearValueFromDepthStencil(uint32_t stencil, - Scalar depth) { - vk::ClearDepthStencilValue value; - value.depth = depth; - value.stencil = stencil; - return value; -} - -static std::vector GetVKClearValues( - const RenderTarget& target) { - std::vector clears; - - for (const auto& [_, color] : target.GetColorAttachments()) { - clears.emplace_back(VKClearValueFromColor(color.clear_color)); - if (color.resolve_texture) { - clears.emplace_back(VKClearValueFromColor(color.clear_color)); - } - } - - const auto& depth = target.GetDepthAttachment(); - const auto& stencil = target.GetStencilAttachment(); - - if (depth.has_value()) { - clears.emplace_back(VKClearValueFromDepthStencil( - stencil ? stencil->clear_stencil : 0u, depth->clear_depth)); - } - - if (stencil.has_value()) { - clears.emplace_back(VKClearValueFromDepthStencil( - stencil->clear_stencil, depth ? depth->clear_depth : 0.0f)); - } - - return clears; -} - static vk::AttachmentDescription CreateAttachmentDescription( const Attachment& attachment, const std::shared_ptr Attachment::*texture_ptr, @@ -248,76 +199,8 @@ SharedHandleVK RenderPassVK::CreateVKRenderPass( RenderPassVK::RenderPassVK(const std::shared_ptr& context, const RenderTarget& target, - std::shared_ptr command_buffer) + std::weak_ptr command_buffer) : RenderPass(context, target), command_buffer_(std::move(command_buffer)) { - const auto& vk_context = ContextVK::Cast(*context); - const std::shared_ptr& encoder = - command_buffer_->GetEncoder(); - command_buffer_vk_ = encoder->GetCommandBuffer(); - render_target_.IterateAllAttachments( - [&encoder](const auto& attachment) -> bool { - encoder->Track(attachment.texture); - encoder->Track(attachment.resolve_texture); - return true; - }); - - const auto& target_size = render_target_.GetRenderTargetSize(); - - SharedHandleVK render_pass = CreateVKRenderPass( - vk_context, command_buffer_, - vk_context.GetCapabilities()->SupportsFramebufferFetch()); - if (!render_pass) { - VALIDATION_LOG << "Could not create renderpass."; - is_valid_ = false; - return; - } - - auto framebuffer = CreateVKFramebuffer(vk_context, *render_pass); - if (!framebuffer) { - VALIDATION_LOG << "Could not create framebuffer."; - is_valid_ = false; - return; - } - - if (!encoder->Track(framebuffer) || !encoder->Track(render_pass)) { - is_valid_ = false; - return; - } - - auto clear_values = GetVKClearValues(render_target_); - - vk::RenderPassBeginInfo pass_info; - pass_info.renderPass = *render_pass; - pass_info.framebuffer = *framebuffer; - pass_info.renderArea.extent.width = static_cast(target_size.width); - pass_info.renderArea.extent.height = - static_cast(target_size.height); - pass_info.setClearValues(clear_values); - - command_buffer_vk_.beginRenderPass(pass_info, vk::SubpassContents::eInline); - - // Set the initial viewport and scissors. - const auto vp = Viewport{.rect = Rect::MakeSize(target_size)}; - vk::Viewport viewport = vk::Viewport() - .setWidth(vp.rect.GetWidth()) - .setHeight(-vp.rect.GetHeight()) - .setY(vp.rect.GetHeight()) - .setMinDepth(0.0f) - .setMaxDepth(1.0f); - command_buffer_vk_.setViewport(0, 1, &viewport); - - // Set the initial scissor rect. - const auto sc = IRect::MakeSize(target_size); - vk::Rect2D scissor = - vk::Rect2D() - .setOffset(vk::Offset2D(sc.GetX(), sc.GetY())) - .setExtent(vk::Extent2D(sc.GetWidth(), sc.GetHeight())); - command_buffer_vk_.setScissor(0, 1, &scissor); - - color_image_vk_ = - render_target_.GetColorAttachments().find(0u)->second.texture; - resolve_image_vk_ = - render_target_.GetColorAttachments().find(0u)->second.resolve_texture; is_valid_ = true; } @@ -331,6 +214,48 @@ void RenderPassVK::OnSetLabel(std::string label) { debug_label_ = std::move(label); } +static vk::ClearColorValue VKClearValueFromColor(Color color) { + vk::ClearColorValue value; + value.setFloat32( + std::array{color.red, color.green, color.blue, color.alpha}); + return value; +} + +static vk::ClearDepthStencilValue VKClearValueFromDepthStencil(uint32_t stencil, + Scalar depth) { + vk::ClearDepthStencilValue value; + value.depth = depth; + value.stencil = stencil; + return value; +} + +static std::vector GetVKClearValues( + const RenderTarget& target) { + std::vector clears; + + for (const auto& [_, color] : target.GetColorAttachments()) { + clears.emplace_back(VKClearValueFromColor(color.clear_color)); + if (color.resolve_texture) { + clears.emplace_back(VKClearValueFromColor(color.clear_color)); + } + } + + const auto& depth = target.GetDepthAttachment(); + const auto& stencil = target.GetStencilAttachment(); + + if (depth.has_value()) { + clears.emplace_back(VKClearValueFromDepthStencil( + stencil ? stencil->clear_stencil : 0u, depth->clear_depth)); + } + + if (stencil.has_value()) { + clears.emplace_back(VKClearValueFromDepthStencil( + stencil->clear_stencil, depth ? depth->clear_depth : 0.0f)); + } + + return clears; +} + SharedHandleVK RenderPassVK::CreateVKFramebuffer( const ContextVK& context, const vk::RenderPass& pass) const { @@ -377,114 +302,134 @@ SharedHandleVK RenderPassVK::CreateVKFramebuffer( return MakeSharedVK(std::move(framebuffer)); } -// |RenderPass| -void RenderPassVK::SetPipeline( - const std::shared_ptr>& pipeline) { - PipelineVK& pipeline_vk = PipelineVK::Cast(*pipeline); - - auto descriptor_result = - command_buffer_->GetEncoder()->AllocateDescriptorSets( - pipeline_vk.GetDescriptorSetLayout(), ContextVK::Cast(*context_)); - if (!descriptor_result.ok()) { - return; +static bool UpdateBindingLayouts(const Bindings& bindings, + const vk::CommandBuffer& buffer) { + // All previous writes via a render or blit pass must be done before another + // shader attempts to read the resource. + BarrierVK barrier; + barrier.cmd_buffer = buffer; + barrier.src_access = vk::AccessFlagBits::eColorAttachmentWrite | + vk::AccessFlagBits::eTransferWrite; + barrier.src_stage = vk::PipelineStageFlagBits::eColorAttachmentOutput | + vk::PipelineStageFlagBits::eTransfer; + barrier.dst_access = vk::AccessFlagBits::eShaderRead; + barrier.dst_stage = vk::PipelineStageFlagBits::eFragmentShader; + + barrier.new_layout = vk::ImageLayout::eShaderReadOnlyOptimal; + + for (const TextureAndSampler& data : bindings.sampled_images) { + if (!TextureVK::Cast(*data.texture.resource).SetLayout(barrier)) { + return false; + } } - pipeline_valid_ = true; - descriptor_set_ = descriptor_result.value(); - pipeline_layout_ = pipeline_vk.GetPipelineLayout(); - command_buffer_vk_.bindPipeline(vk::PipelineBindPoint::eGraphics, - pipeline_vk.GetPipeline()); + return true; +} - if (pipeline->GetDescriptor().UsesSubpassInput()) { - if (bound_image_offset_ >= kMaxBindings) { - pipeline_valid_ = false; - return; - } +static bool UpdateBindingLayouts(const Command& command, + const vk::CommandBuffer& buffer) { + return UpdateBindingLayouts(command.vertex_bindings, buffer) && + UpdateBindingLayouts(command.fragment_bindings, buffer); +} - vk::DescriptorImageInfo image_info; - image_info.imageLayout = vk::ImageLayout::eGeneral; - image_info.sampler = VK_NULL_HANDLE; - image_info.imageView = TextureVK::Cast(*color_image_vk_).GetImageView(); - image_workspace_[bound_image_offset_++] = image_info; +static bool UpdateBindingLayouts(const std::vector& commands, + const vk::CommandBuffer& buffer) { + for (const Command& command : commands) { + if (!UpdateBindingLayouts(command, buffer)) { + return false; + } + } + return true; +} - vk::WriteDescriptorSet write_set; - write_set.dstBinding = kMagicSubpassInputBinding; - write_set.descriptorCount = 1u; - write_set.descriptorType = vk::DescriptorType::eInputAttachment; - write_set.pImageInfo = &image_workspace_[bound_image_offset_ - 1]; +static void SetViewportAndScissor(const Command& command, + const vk::CommandBuffer& cmd_buffer, + PassBindingsCache& cmd_buffer_cache, + const ISize& target_size) { + // Set the viewport. + const auto& vp = command.viewport.value_or( + {.rect = Rect::MakeSize(target_size)}); + vk::Viewport viewport = vk::Viewport() + .setWidth(vp.rect.GetWidth()) + .setHeight(-vp.rect.GetHeight()) + .setY(vp.rect.GetHeight()) + .setMinDepth(0.0f) + .setMaxDepth(1.0f); + cmd_buffer_cache.SetViewport(cmd_buffer, 0, 1, &viewport); - write_workspace_[descriptor_write_offset_++] = write_set; - } + // Set the scissor rect. + const auto& sc = command.scissor.value_or(IRect::MakeSize(target_size)); + vk::Rect2D scissor = + vk::Rect2D() + .setOffset(vk::Offset2D(sc.GetX(), sc.GetY())) + .setExtent(vk::Extent2D(sc.GetWidth(), sc.GetHeight())); + cmd_buffer_cache.SetScissor(cmd_buffer, 0, 1, &scissor); } -// |RenderPass| -void RenderPassVK::SetCommandLabel(std::string_view label) { +static bool EncodeCommand(const Context& context, + const Command& command, + CommandEncoderVK& encoder, + PassBindingsCache& command_buffer_cache, + const ISize& target_size, + const vk::DescriptorSet vk_desc_set, + const vk::CommandBuffer& cmd_buffer) { #ifdef IMPELLER_DEBUG - std::string label_copy(label); - command_buffer_->GetEncoder()->PushDebugGroup(label_copy.c_str()); - has_label_ = true; + fml::ScopedCleanupClosure pop_marker( + [&encoder]() { encoder.PopDebugGroup(); }); + if (!command.label.empty()) { + encoder.PushDebugGroup(command.label.c_str()); + } else { + pop_marker.Release(); + } #endif // IMPELLER_DEBUG -} -// |RenderPass| -void RenderPassVK::SetStencilReference(uint32_t value) { - command_buffer_vk_.setStencilReference( - vk::StencilFaceFlagBits::eVkStencilFrontAndBack, value); -} + const PipelineVK& pipeline_vk = PipelineVK::Cast(*command.pipeline); -// |RenderPass| -void RenderPassVK::SetBaseVertex(uint64_t value) { - base_vertex_ = value; -} + cmd_buffer.bindDescriptorSets(vk::PipelineBindPoint::eGraphics, // bind point + pipeline_vk.GetPipelineLayout(), // layout + 0, // first set + 1, // set count + &vk_desc_set, // sets + 0, // offset count + nullptr // offsets + ); -// |RenderPass| -void RenderPassVK::SetViewport(Viewport viewport) { - vk::Viewport viewport_vk = vk::Viewport() - .setWidth(viewport.rect.GetWidth()) - .setHeight(-viewport.rect.GetHeight()) - .setY(viewport.rect.GetHeight()) - .setMinDepth(0.0f) - .setMaxDepth(1.0f); - command_buffer_vk_.setViewport(0, 1, &viewport_vk); -} + command_buffer_cache.BindPipeline( + cmd_buffer, vk::PipelineBindPoint::eGraphics, pipeline_vk.GetPipeline()); -// |RenderPass| -void RenderPassVK::SetScissor(IRect scissor) { - vk::Rect2D scissor_vk = - vk::Rect2D() - .setOffset(vk::Offset2D(scissor.GetX(), scissor.GetY())) - .setExtent(vk::Extent2D(scissor.GetWidth(), scissor.GetHeight())); - command_buffer_vk_.setScissor(0, 1, &scissor_vk); -} + // Set the viewport and scissors. + SetViewportAndScissor(command, cmd_buffer, command_buffer_cache, target_size); -// |RenderPass| -void RenderPassVK::SetInstanceCount(size_t count) { - instance_count_ = count; -} + // Set the stencil reference. + command_buffer_cache.SetStencilReference( + cmd_buffer, vk::StencilFaceFlagBits::eVkStencilFrontAndBack, + command.stencil_reference); -// |RenderPass| -bool RenderPassVK::SetVertexBuffer(VertexBuffer buffer) { - vertex_count_ = buffer.vertex_count; - if (buffer.index_type == IndexType::kUnknown) { + // Configure vertex and index and buffers for binding. + if (!command.vertex_buffer.vertex_buffer) { + VALIDATION_LOG << "Failed to acquire device buffer" + << " for vertex buffer view"; return false; } - if (!command_buffer_->GetEncoder()->Track(buffer.vertex_buffer.buffer)) { + auto& allocator = *context.GetResourceAllocator(); + const std::shared_ptr& vertex_buffer = + command.vertex_buffer.vertex_buffer.buffer; + + if (!encoder.Track(vertex_buffer)) { return false; } // Bind the vertex buffer. vk::Buffer vertex_buffer_handle = - DeviceBufferVK::Cast(*buffer.vertex_buffer.buffer).GetBuffer(); + DeviceBufferVK::Cast(*vertex_buffer).GetBuffer(); vk::Buffer vertex_buffers[] = {vertex_buffer_handle}; - vk::DeviceSize vertex_buffer_offsets[] = {buffer.vertex_buffer.range.offset}; + vk::DeviceSize vertex_buffer_offsets[] = { + command.vertex_buffer.vertex_buffer.range.offset}; + cmd_buffer.bindVertexBuffers(0u, 1u, vertex_buffers, vertex_buffer_offsets); - command_buffer_vk_.bindVertexBuffers(0u, 1u, vertex_buffers, - vertex_buffer_offsets); - - // Bind the index buffer. - if (buffer.index_type != IndexType::kNone) { - has_index_buffer_ = true; - const BufferView& index_buffer_view = buffer.index_buffer; + if (command.vertex_buffer.index_type != IndexType::kNone) { + // Bind the index buffer. + const BufferView& index_buffer_view = command.vertex_buffer.index_buffer; if (!index_buffer_view) { return false; } @@ -497,187 +442,128 @@ bool RenderPassVK::SetVertexBuffer(VertexBuffer buffer) { return false; } - if (!command_buffer_->GetEncoder()->Track(index_buffer)) { + if (!encoder.Track(index_buffer)) { return false; } vk::Buffer index_buffer_handle = DeviceBufferVK::Cast(*index_buffer).GetBuffer(); - command_buffer_vk_.bindIndexBuffer(index_buffer_handle, - index_buffer_view.range.offset, - ToVKIndexType(buffer.index_type)); + cmd_buffer.bindIndexBuffer(index_buffer_handle, + index_buffer_view.range.offset, + ToVKIndexType(command.vertex_buffer.index_type)); + + // Engage! + cmd_buffer.drawIndexed(command.vertex_buffer.vertex_count, // index count + command.instance_count, // instance count + 0u, // first index + command.base_vertex, // vertex offset + 0u // first instance + ); } else { - has_index_buffer_ = false; + cmd_buffer.draw(command.vertex_buffer.vertex_count, // vertex count + command.instance_count, // instance count + command.base_vertex, // vertex offset + 0u // first instance + ); } return true; } -// |RenderPass| -fml::Status RenderPassVK::Draw() { - if (!pipeline_valid_) { - return fml::Status(fml::StatusCode::kCancelled, - "No valid pipeline is bound to the RenderPass."); - } - - const ContextVK& context_vk = ContextVK::Cast(*context_); - for (auto i = 0u; i < descriptor_write_offset_; i++) { - write_workspace_[i].dstSet = descriptor_set_; +bool RenderPassVK::OnEncodeCommands(const Context& context) const { + TRACE_EVENT0("impeller", "RenderPassVK::OnEncodeCommands"); + if (!IsValid()) { + return false; } - context_vk.GetDevice().updateDescriptorSets(descriptor_write_offset_, - write_workspace_.data(), 0u, {}); - - command_buffer_vk_.bindDescriptorSets( - vk::PipelineBindPoint::eGraphics, // bind point - pipeline_layout_, // layout - 0, // first set - 1, // set count - &descriptor_set_, // sets - 0, // offset count - nullptr // offsets - ); + const auto& vk_context = ContextVK::Cast(context); - if (has_index_buffer_) { - command_buffer_vk_.drawIndexed(vertex_count_, // index count - instance_count_, // instance count - 0u, // first index - base_vertex_, // vertex offset - 0u // first instance - ); - } else { - command_buffer_vk_.draw(vertex_count_, // vertex count - instance_count_, // instance count - base_vertex_, // vertex offset - 0u // first instance - ); + std::shared_ptr command_buffer = command_buffer_.lock(); + if (!command_buffer) { + VALIDATION_LOG << "Command buffer died before commands could be encoded."; + return false; + } + const std::shared_ptr& encoder = + command_buffer->GetEncoder(); + if (!encoder) { + return false; } #ifdef IMPELLER_DEBUG - if (has_label_) { - command_buffer_->GetEncoder()->PopDebugGroup(); + fml::ScopedCleanupClosure pop_marker( + [&encoder]() { encoder->PopDebugGroup(); }); + if (!debug_label_.empty()) { + encoder->PushDebugGroup(debug_label_.c_str()); + } else { + pop_marker.Release(); } #endif // IMPELLER_DEBUG - has_label_ = false; - has_index_buffer_ = false; - bound_image_offset_ = 0u; - bound_buffer_offset_ = 0u; - descriptor_write_offset_ = 0u; - instance_count_ = 1u; - base_vertex_ = 0u; - vertex_count_ = 0u; - pipeline_valid_ = false; - return fml::Status(); -} -// The RenderPassVK binding methods only need the binding, set, and buffer type -// information. -bool RenderPassVK::BindResource(ShaderStage stage, - DescriptorType type, - const ShaderUniformSlot& slot, - const ShaderMetadata& metadata, - BufferView view) { - return BindResource(slot.binding, type, view); -} + vk::CommandBuffer cmd_buffer = encoder->GetCommandBuffer(); -bool RenderPassVK::BindResource( - ShaderStage stage, - DescriptorType type, - const ShaderUniformSlot& slot, - const std::shared_ptr& metadata, - BufferView view) { - return BindResource(slot.binding, type, view); -} - -bool RenderPassVK::BindResource(size_t binding, - DescriptorType type, - const BufferView& view) { - if (bound_buffer_offset_ >= kMaxBindings) { + if (!UpdateBindingLayouts(commands_, cmd_buffer)) { return false; } - const std::shared_ptr& device_buffer = view.buffer; - auto buffer = DeviceBufferVK::Cast(*device_buffer).GetBuffer(); - if (!buffer) { - return false; - } + render_target_.IterateAllAttachments( + [&encoder](const auto& attachment) -> bool { + encoder->Track(attachment.texture); + encoder->Track(attachment.resolve_texture); + return true; + }); + + const auto& target_size = render_target_.GetRenderTargetSize(); - if (!command_buffer_->GetEncoder()->Track(device_buffer)) { + SharedHandleVK render_pass = CreateVKRenderPass( + vk_context, command_buffer, + vk_context.GetCapabilities()->SupportsFramebufferFetch()); + if (!render_pass) { + VALIDATION_LOG << "Could not create renderpass."; return false; } - uint32_t offset = view.range.offset; - - vk::DescriptorBufferInfo buffer_info; - buffer_info.buffer = buffer; - buffer_info.offset = offset; - buffer_info.range = view.range.length; - buffer_workspace_[bound_buffer_offset_++] = buffer_info; - - vk::WriteDescriptorSet write_set; - write_set.dstBinding = binding; - write_set.descriptorCount = 1u; - write_set.descriptorType = ToVKDescriptorType(type); - write_set.pBufferInfo = &buffer_workspace_[bound_buffer_offset_ - 1]; - - write_workspace_[descriptor_write_offset_++] = write_set; - return true; -} - -bool RenderPassVK::BindResource(ShaderStage stage, - DescriptorType type, - const SampledImageSlot& slot, - const ShaderMetadata& metadata, - std::shared_ptr texture, - std::shared_ptr sampler) { - if (bound_buffer_offset_ >= kMaxBindings) { + auto framebuffer = CreateVKFramebuffer(vk_context, *render_pass); + if (!framebuffer) { + VALIDATION_LOG << "Could not create framebuffer."; return false; } - const TextureVK& texture_vk = TextureVK::Cast(*texture); - const SamplerVK& sampler_vk = SamplerVK::Cast(*sampler); - if (!command_buffer_->GetEncoder()->Track(texture) || - !command_buffer_->GetEncoder()->Track(sampler_vk.GetSharedSampler())) { + if (!encoder->Track(framebuffer) || !encoder->Track(render_pass)) { return false; } - vk::DescriptorImageInfo image_info; - image_info.imageLayout = vk::ImageLayout::eShaderReadOnlyOptimal; - image_info.sampler = sampler_vk.GetSampler(); - image_info.imageView = texture_vk.GetImageView(); - image_workspace_[bound_image_offset_++] = image_info; - - vk::WriteDescriptorSet write_set; - write_set.dstBinding = slot.binding; - write_set.descriptorCount = 1u; - write_set.descriptorType = vk::DescriptorType::eCombinedImageSampler; - write_set.pImageInfo = &image_workspace_[bound_image_offset_ - 1]; - - write_workspace_[descriptor_write_offset_++] = write_set; - return true; -} - -bool RenderPassVK::OnEncodeCommands(const Context& context) const { - command_buffer_->GetEncoder()->GetCommandBuffer().endRenderPass(); - - // If this render target will be consumed by a subsequent render pass, - // perform a layout transition to a shader read state. - const std::shared_ptr& result_texture = - resolve_image_vk_ ? resolve_image_vk_ : color_image_vk_; - if (result_texture->GetTextureDescriptor().usage & - static_cast(TextureUsage::kShaderRead)) { - BarrierVK barrier; - barrier.cmd_buffer = command_buffer_vk_; - barrier.src_access = vk::AccessFlagBits::eColorAttachmentWrite | - vk::AccessFlagBits::eTransferWrite; - barrier.src_stage = vk::PipelineStageFlagBits::eColorAttachmentOutput | - vk::PipelineStageFlagBits::eTransfer; - barrier.dst_access = vk::AccessFlagBits::eShaderRead; - barrier.dst_stage = vk::PipelineStageFlagBits::eFragmentShader; + auto clear_values = GetVKClearValues(render_target_); - barrier.new_layout = vk::ImageLayout::eShaderReadOnlyOptimal; + vk::RenderPassBeginInfo pass_info; + pass_info.renderPass = *render_pass; + pass_info.framebuffer = *framebuffer; + pass_info.renderArea.extent.width = static_cast(target_size.width); + pass_info.renderArea.extent.height = + static_cast(target_size.height); + pass_info.setClearValues(clear_values); - if (!TextureVK::Cast(*result_texture).SetLayout(barrier)) { - return false; + const TextureVK& color_image_vk = TextureVK::Cast( + *render_target_.GetColorAttachments().find(0u)->second.texture); + Allocator& allocator = *context.GetResourceAllocator(); + + { + TRACE_EVENT0("impeller", "EncodeRenderPassCommands"); + cmd_buffer.beginRenderPass(pass_info, vk::SubpassContents::eInline); + + fml::ScopedCleanupClosure end_render_pass( + [cmd_buffer]() { cmd_buffer.endRenderPass(); }); + + for (const auto& command : commands_) { + fml::StatusOr desc_set_result = + AllocateAndBindDescriptorSets(vk_context, encoder, allocator, command, + color_image_vk, image_workspace_, + buffer_workspace_, write_workspace_); + if (!desc_set_result.ok()) { + return false; + } + if (!EncodeCommand(context, command, *encoder, pass_bindings_cache_, + target_size, desc_set_result.value(), cmd_buffer)) { + return false; + } } } diff --git a/impeller/renderer/backend/vulkan/render_pass_vk.h b/impeller/renderer/backend/vulkan/render_pass_vk.h index 26c635c41c6fe..2d31abd4019f6 100644 --- a/impeller/renderer/backend/vulkan/render_pass_vk.h +++ b/impeller/renderer/backend/vulkan/render_pass_vk.h @@ -5,10 +5,10 @@ #ifndef FLUTTER_IMPELLER_RENDERER_BACKEND_VULKAN_RENDER_PASS_VK_H_ #define FLUTTER_IMPELLER_RENDERER_BACKEND_VULKAN_RENDER_PASS_VK_H_ -#include "impeller/core/buffer_view.h" +#include "flutter/fml/macros.h" #include "impeller/renderer/backend/vulkan/binding_helpers_vk.h" #include "impeller/renderer/backend/vulkan/context_vk.h" -#include "impeller/renderer/backend/vulkan/pipeline_vk.h" +#include "impeller/renderer/backend/vulkan/pass_bindings_cache.h" #include "impeller/renderer/backend/vulkan/shared_object_vk.h" #include "impeller/renderer/render_pass.h" #include "impeller/renderer/render_target.h" @@ -25,92 +25,20 @@ class RenderPassVK final : public RenderPass { private: friend class CommandBufferVK; - std::shared_ptr command_buffer_; + std::weak_ptr command_buffer_; std::string debug_label_; bool is_valid_ = false; - vk::CommandBuffer command_buffer_vk_; - std::shared_ptr color_image_vk_; - std::shared_ptr resolve_image_vk_; - - // Per-command state. - std::array image_workspace_; - std::array buffer_workspace_; - std::array + mutable std::array image_workspace_; + mutable std::array buffer_workspace_; + mutable std::array write_workspace_; - size_t bound_image_offset_ = 0u; - size_t bound_buffer_offset_ = 0u; - size_t descriptor_write_offset_ = 0u; - size_t instance_count_ = 1u; - size_t base_vertex_ = 0u; - size_t vertex_count_ = 0u; - bool has_index_buffer_ = false; - bool has_label_ = false; - bool pipeline_valid_ = false; - vk::Pipeline last_pipeline_; - vk::DescriptorSet descriptor_set_ = {}; - vk::PipelineLayout pipeline_layout_ = {}; + + mutable PassBindingsCache pass_bindings_cache_; RenderPassVK(const std::shared_ptr& context, const RenderTarget& target, - std::shared_ptr command_buffer); - - // |RenderPass| - void SetPipeline( - const std::shared_ptr>& pipeline) override; - - // |RenderPass| - void SetCommandLabel(std::string_view label) override; - - // |RenderPass| - void SetStencilReference(uint32_t value) override; - - // |RenderPass| - void SetBaseVertex(uint64_t value) override; - - // |RenderPass| - void SetViewport(Viewport viewport) override; - - // |RenderPass| - void SetScissor(IRect scissor) override; - - // |RenderPass| - void SetInstanceCount(size_t count) override; - - // |RenderPass| - bool SetVertexBuffer(VertexBuffer buffer) override; - - // |RenderPass| - fml::Status Draw() override; - - // |RenderPass| - void ReserveCommands(size_t command_count) override {} - - // |ResourceBinder| - bool BindResource(ShaderStage stage, - DescriptorType type, - const ShaderUniformSlot& slot, - const ShaderMetadata& metadata, - BufferView view) override; - - // |RenderPass| - bool BindResource(ShaderStage stage, - DescriptorType type, - const ShaderUniformSlot& slot, - const std::shared_ptr& metadata, - BufferView view) override; - - // |ResourceBinder| - bool BindResource(ShaderStage stage, - DescriptorType type, - const SampledImageSlot& slot, - const ShaderMetadata& metadata, - std::shared_ptr texture, - std::shared_ptr sampler) override; - - bool BindResource(size_t binding, - DescriptorType type, - const BufferView& view); + std::weak_ptr command_buffer); // |RenderPass| bool IsValid() const override; diff --git a/impeller/renderer/backend/vulkan/texture_vk.cc b/impeller/renderer/backend/vulkan/texture_vk.cc index 36f5d3878fe91..cbe525400c303 100644 --- a/impeller/renderer/backend/vulkan/texture_vk.cc +++ b/impeller/renderer/backend/vulkan/texture_vk.cc @@ -107,24 +107,6 @@ bool TextureVK::OnSetContents(const uint8_t* contents, © // regions ); - // Transition to shader-read. - { - BarrierVK barrier; - barrier.cmd_buffer = vk_cmd_buffer; - barrier.src_access = vk::AccessFlagBits::eColorAttachmentWrite | - vk::AccessFlagBits::eTransferWrite; - barrier.src_stage = vk::PipelineStageFlagBits::eColorAttachmentOutput | - vk::PipelineStageFlagBits::eTransfer; - barrier.dst_access = vk::AccessFlagBits::eShaderRead; - barrier.dst_stage = vk::PipelineStageFlagBits::eFragmentShader; - - barrier.new_layout = vk::ImageLayout::eShaderReadOnlyOptimal; - - if (!SetLayout(barrier)) { - return false; - } - } - return cmd_buffer->SubmitCommands(); } diff --git a/impeller/renderer/command.cc b/impeller/renderer/command.cc index 6507c81d565c0..40dfd8c09d518 100644 --- a/impeller/renderer/command.cc +++ b/impeller/renderer/command.cc @@ -23,7 +23,6 @@ bool Command::BindVertices(VertexBuffer buffer) { } bool Command::BindResource(ShaderStage stage, - DescriptorType type, const ShaderUniformSlot& slot, const ShaderMetadata& metadata, BufferView view) { @@ -32,7 +31,6 @@ bool Command::BindResource(ShaderStage stage, bool Command::BindResource( ShaderStage stage, - DescriptorType type, const ShaderUniformSlot& slot, const std::shared_ptr& metadata, BufferView view) { @@ -68,7 +66,6 @@ bool Command::DoBindResource(ShaderStage stage, } bool Command::BindResource(ShaderStage stage, - DescriptorType type, const SampledImageSlot& slot, const ShaderMetadata& metadata, std::shared_ptr texture, diff --git a/impeller/renderer/command.h b/impeller/renderer/command.h index 0df30895b7959..0e27d74750a71 100644 --- a/impeller/renderer/command.h +++ b/impeller/renderer/command.h @@ -162,20 +162,17 @@ struct Command : public ResourceBinder { // |ResourceBinder| bool BindResource(ShaderStage stage, - DescriptorType type, const ShaderUniformSlot& slot, const ShaderMetadata& metadata, BufferView view) override; bool BindResource(ShaderStage stage, - DescriptorType type, const ShaderUniformSlot& slot, const std::shared_ptr& metadata, BufferView view); // |ResourceBinder| bool BindResource(ShaderStage stage, - DescriptorType type, const SampledImageSlot& slot, const ShaderMetadata& metadata, std::shared_ptr texture, diff --git a/impeller/renderer/command_buffer.cc b/impeller/renderer/command_buffer.cc index b25ab3af000ff..98b23204604b1 100644 --- a/impeller/renderer/command_buffer.cc +++ b/impeller/renderer/command_buffer.cc @@ -38,6 +38,7 @@ void CommandBuffer::WaitUntilScheduled() { bool CommandBuffer::EncodeAndSubmit( const std::shared_ptr& render_pass) { + TRACE_EVENT0("impeller", "CommandBuffer::EncodeAndSubmit"); if (!render_pass->IsValid() || !IsValid()) { return false; } @@ -51,6 +52,7 @@ bool CommandBuffer::EncodeAndSubmit( bool CommandBuffer::EncodeAndSubmit( const std::shared_ptr& blit_pass, const std::shared_ptr& allocator) { + TRACE_EVENT0("impeller", "CommandBuffer::EncodeAndSubmit"); if (!blit_pass->IsValid() || !IsValid()) { return false; } diff --git a/impeller/renderer/compute_command.cc b/impeller/renderer/compute_command.cc index e1a06015fa611..fbbfe3b58666f 100644 --- a/impeller/renderer/compute_command.cc +++ b/impeller/renderer/compute_command.cc @@ -8,12 +8,10 @@ #include "impeller/base/validation.h" #include "impeller/core/formats.h" -#include "impeller/core/shader_types.h" namespace impeller { bool ComputeCommand::BindResource(ShaderStage stage, - DescriptorType type, const ShaderUniformSlot& slot, const ShaderMetadata& metadata, BufferView view) { @@ -31,7 +29,6 @@ bool ComputeCommand::BindResource(ShaderStage stage, } bool ComputeCommand::BindResource(ShaderStage stage, - DescriptorType type, const SampledImageSlot& slot, const ShaderMetadata& metadata, std::shared_ptr texture, diff --git a/impeller/renderer/compute_command.h b/impeller/renderer/compute_command.h index c0c56e9f698f6..fb2639df664e8 100644 --- a/impeller/renderer/compute_command.h +++ b/impeller/renderer/compute_command.h @@ -53,14 +53,12 @@ struct ComputeCommand : public ResourceBinder { // |ResourceBinder| bool BindResource(ShaderStage stage, - DescriptorType type, const ShaderUniformSlot& slot, const ShaderMetadata& metadata, BufferView view) override; // |ResourceBinder| bool BindResource(ShaderStage stage, - DescriptorType type, const SampledImageSlot& slot, const ShaderMetadata& metadata, std::shared_ptr texture, diff --git a/impeller/renderer/render_pass.cc b/impeller/renderer/render_pass.cc index 8c3998d8720af..10c5a16556117 100644 --- a/impeller/renderer/render_pass.cc +++ b/impeller/renderer/render_pass.cc @@ -7,7 +7,7 @@ namespace impeller { -RenderPass::RenderPass(std::shared_ptr context, +RenderPass::RenderPass(std::weak_ptr context, const RenderTarget& target) : context_(std::move(context)), sample_count_(target.GetSampleCount()), @@ -77,10 +77,15 @@ bool RenderPass::AddCommand(Command&& command) { } bool RenderPass::EncodeCommands() const { - return OnEncodeCommands(*context_); + auto context = context_.lock(); + // The context could have been collected in the meantime. + if (!context) { + return false; + } + return OnEncodeCommands(*context); } -const std::shared_ptr& RenderPass::GetContext() const { +const std::weak_ptr& RenderPass::GetContext() const { return context_; } @@ -131,30 +136,27 @@ fml::Status RenderPass::Draw() { // |ResourceBinder| bool RenderPass::BindResource(ShaderStage stage, - DescriptorType type, const ShaderUniformSlot& slot, const ShaderMetadata& metadata, BufferView view) { - return pending_.BindResource(stage, type, slot, metadata, view); + return pending_.BindResource(stage, slot, metadata, view); } bool RenderPass::BindResource( ShaderStage stage, - DescriptorType type, const ShaderUniformSlot& slot, const std::shared_ptr& metadata, BufferView view) { - return pending_.BindResource(stage, type, slot, metadata, std::move(view)); + return pending_.BindResource(stage, slot, metadata, std::move(view)); } // |ResourceBinder| bool RenderPass::BindResource(ShaderStage stage, - DescriptorType type, const SampledImageSlot& slot, const ShaderMetadata& metadata, std::shared_ptr texture, std::shared_ptr sampler) { - return pending_.BindResource(stage, type, slot, metadata, std::move(texture), + return pending_.BindResource(stage, slot, metadata, std::move(texture), std::move(sampler)); } diff --git a/impeller/renderer/render_pass.h b/impeller/renderer/render_pass.h index cae0fe3046f7d..c2bd755c58f9b 100644 --- a/impeller/renderer/render_pass.h +++ b/impeller/renderer/render_pass.h @@ -34,7 +34,7 @@ class RenderPass : public ResourceBinder { public: virtual ~RenderPass(); - const std::shared_ptr& GetContext() const; + const std::weak_ptr& GetContext() const; const RenderTarget& GetRenderTarget() const; @@ -46,18 +46,21 @@ class RenderPass : public ResourceBinder { void SetLabel(std::string label); - virtual void ReserveCommands(size_t command_count) { + /// @brief Reserve [command_count] commands in the HAL command buffer. + /// + /// Note: this is not the native command buffer. + void ReserveCommands(size_t command_count) { commands_.reserve(command_count); } //---------------------------------------------------------------------------- /// The pipeline to use for this command. - virtual void SetPipeline( + void SetPipeline( const std::shared_ptr>& pipeline); //---------------------------------------------------------------------------- /// The debugging label to use for the command. - virtual void SetCommandLabel(std::string_view label); + void SetCommandLabel(std::string_view label); //---------------------------------------------------------------------------- /// The reference value to use in stenciling operations. Stencil configuration @@ -66,9 +69,9 @@ class RenderPass : public ResourceBinder { /// @see `Pipeline` /// @see `PipelineDescriptor` /// - virtual void SetStencilReference(uint32_t value); + void SetStencilReference(uint32_t value); - virtual void SetBaseVertex(uint64_t value); + void SetBaseVertex(uint64_t value); //---------------------------------------------------------------------------- /// The viewport coordinates that the rasterizer linearly maps normalized @@ -76,14 +79,14 @@ class RenderPass : public ResourceBinder { /// If unset, the viewport is the size of the render target with a zero /// origin, znear=0, and zfar=1. /// - virtual void SetViewport(Viewport viewport); + void SetViewport(Viewport viewport); //---------------------------------------------------------------------------- /// The scissor rect to use for clipping writes to the render target. The /// scissor rect must lie entirely within the render target. /// If unset, no scissor is applied. /// - virtual void SetScissor(IRect scissor); + void SetScissor(IRect scissor); //---------------------------------------------------------------------------- /// The number of instances of the given set of vertices to render. Not all @@ -92,7 +95,7 @@ class RenderPass : public ResourceBinder { /// @warning Setting this to more than one will limit the availability of /// backends to use with this command. /// - virtual void SetInstanceCount(size_t count); + void SetInstanceCount(size_t count); //---------------------------------------------------------------------------- /// @brief Specify the vertex and index buffer to use for this command. @@ -102,32 +105,28 @@ class RenderPass : public ResourceBinder { /// /// @return returns if the binding was updated. /// - virtual bool SetVertexBuffer(VertexBuffer buffer); + bool SetVertexBuffer(VertexBuffer buffer); /// Record the currently pending command. - virtual fml::Status Draw(); + fml::Status Draw(); // |ResourceBinder| - virtual bool BindResource(ShaderStage stage, - DescriptorType type, - const ShaderUniformSlot& slot, - const ShaderMetadata& metadata, - BufferView view) override; - - virtual bool BindResource( - ShaderStage stage, - DescriptorType type, - const ShaderUniformSlot& slot, - const std::shared_ptr& metadata, - BufferView view); + bool BindResource(ShaderStage stage, + const ShaderUniformSlot& slot, + const ShaderMetadata& metadata, + BufferView view) override; + + bool BindResource(ShaderStage stage, + const ShaderUniformSlot& slot, + const std::shared_ptr& metadata, + BufferView view); // |ResourceBinder| - virtual bool BindResource(ShaderStage stage, - DescriptorType type, - const SampledImageSlot& slot, - const ShaderMetadata& metadata, - std::shared_ptr texture, - std::shared_ptr sampler) override; + bool BindResource(ShaderStage stage, + const SampledImageSlot& slot, + const ShaderMetadata& metadata, + std::shared_ptr texture, + std::shared_ptr sampler) override; //---------------------------------------------------------------------------- /// @brief Encode the recorded commands to the underlying command buffer. @@ -142,7 +141,7 @@ class RenderPass : public ResourceBinder { /// /// @details Visible for testing. /// - virtual const std::vector& GetCommands() const { return commands_; } + const std::vector& GetCommands() const { return commands_; } //---------------------------------------------------------------------------- /// @brief The sample count of the attached render target. @@ -157,7 +156,7 @@ class RenderPass : public ResourceBinder { bool HasStencilAttachment() const; protected: - const std::shared_ptr context_; + const std::weak_ptr context_; // The following properties: sample_count, pixel_format, // has_stencil_attachment, and render_target_size are cached on the // RenderTarget to speed up numerous lookups during rendering. This is safe as @@ -182,8 +181,7 @@ class RenderPass : public ResourceBinder { /// bool AddCommand(Command&& command); - RenderPass(std::shared_ptr context, - const RenderTarget& target); + RenderPass(std::weak_ptr context, const RenderTarget& target); virtual void OnSetLabel(std::string label) = 0; diff --git a/impeller/renderer/renderer_unittests.cc b/impeller/renderer/renderer_unittests.cc index b01f8ed328c2d..0881fd6c4bd15 100644 --- a/impeller/renderer/renderer_unittests.cc +++ b/impeller/renderer/renderer_unittests.cc @@ -1255,6 +1255,21 @@ TEST_P(RendererTest, StencilMask) { OpenPlaygroundHere(callback); } +TEST_P(RendererTest, CanPreAllocateCommands) { + auto context = GetContext(); + auto cmd_buffer = context->CreateCommandBuffer(); + auto render_target_cache = std::make_shared( + GetContext()->GetResourceAllocator()); + + auto render_target = RenderTarget::CreateOffscreen( + *context, *render_target_cache, {100, 100}, /*mip_count=*/1); + auto render_pass = cmd_buffer->CreateRenderPass(render_target); + + render_pass->ReserveCommands(100u); + + EXPECT_EQ(render_pass->GetCommands().capacity(), 100u); +} + TEST_P(RendererTest, CanLookupRenderTargetProperties) { auto context = GetContext(); auto cmd_buffer = context->CreateCommandBuffer(); diff --git a/impeller/renderer/testing/mocks.h b/impeller/renderer/testing/mocks.h index 2c3b096bda6f7..4960a57ef78fd 100644 --- a/impeller/renderer/testing/mocks.h +++ b/impeller/renderer/testing/mocks.h @@ -92,7 +92,7 @@ class MockBlitPass : public BlitPass { class MockRenderPass : public RenderPass { public: - MockRenderPass(std::shared_ptr context, + MockRenderPass(std::weak_ptr context, const RenderTarget& target) : RenderPass(std::move(context), target) {} MOCK_METHOD(bool, IsValid, (), (const, override)); diff --git a/lib/gpu/render_pass.cc b/lib/gpu/render_pass.cc index 206da54bde4ac..35a43793fb637 100644 --- a/lib/gpu/render_pass.cc +++ b/lib/gpu/render_pass.cc @@ -28,7 +28,7 @@ RenderPass::RenderPass() RenderPass::~RenderPass() = default; -const std::shared_ptr& RenderPass::GetContext() const { +const std::weak_ptr& RenderPass::GetContext() const { return render_pass_->GetContext(); } @@ -115,7 +115,7 @@ RenderPass::GetOrCreatePipeline() { } } - auto& context = *GetContext(); + auto& context = *GetContext().lock(); render_pipeline_->BindToPipelineDescriptor(*context.GetShaderLibrary(), pipeline_desc); @@ -151,27 +151,23 @@ bool RenderPass::Draw() { } render_pass_->SetVertexBuffer(result.vertex_buffer); for (const auto& buffer : result.vertex_bindings.buffers) { - render_pass_->BindResource(impeller::ShaderStage::kVertex, - impeller::DescriptorType::kUniformBuffer, - buffer.slot, *buffer.view.GetMetadata(), + render_pass_->BindResource(impeller::ShaderStage::kVertex, buffer.slot, + *buffer.view.GetMetadata(), buffer.view.resource); } for (const auto& texture : result.vertex_bindings.sampled_images) { - render_pass_->BindResource(impeller::ShaderStage::kVertex, - impeller::DescriptorType::kSampledImage, - texture.slot, *texture.texture.GetMetadata(), + render_pass_->BindResource(impeller::ShaderStage::kVertex, texture.slot, + *texture.texture.GetMetadata(), texture.texture.resource, texture.sampler); } for (const auto& buffer : result.fragment_bindings.buffers) { - render_pass_->BindResource(impeller::ShaderStage::kFragment, - impeller::DescriptorType::kUniformBuffer, - buffer.slot, *buffer.view.GetMetadata(), + render_pass_->BindResource(impeller::ShaderStage::kFragment, buffer.slot, + *buffer.view.GetMetadata(), buffer.view.resource); } for (const auto& texture : result.fragment_bindings.sampled_images) { - render_pass_->BindResource(impeller::ShaderStage::kFragment, - impeller::DescriptorType::kSampledImage, - texture.slot, *texture.texture.GetMetadata(), + render_pass_->BindResource(impeller::ShaderStage::kFragment, texture.slot, + *texture.texture.GetMetadata(), texture.texture.resource, texture.sampler); } return render_pass_->Draw().ok(); @@ -381,8 +377,7 @@ static bool BindUniform(flutter::gpu::RenderPass* wrapper, } return command.BindResource( - shader->GetShaderStage(), impeller::DescriptorType::kUniformBuffer, - uniform_struct->slot, uniform_struct->metadata, + shader->GetShaderStage(), uniform_struct->slot, uniform_struct->metadata, impeller::BufferView{ .buffer = buffer, .range = impeller::Range(offset_in_bytes, length_in_bytes), @@ -448,12 +443,12 @@ bool InternalFlutterGpu_RenderPass_BindTexture( flutter::gpu::ToImpellerSamplerAddressMode(width_address_mode); sampler_desc.height_address_mode = flutter::gpu::ToImpellerSamplerAddressMode(height_address_mode); - auto sampler = - wrapper->GetContext()->GetSamplerLibrary()->GetSampler(sampler_desc); + auto sampler = wrapper->GetContext().lock()->GetSamplerLibrary()->GetSampler( + sampler_desc); - return command.BindResource( - shader->GetShaderStage(), impeller::DescriptorType::kSampledImage, - *image_slot, impeller::ShaderMetadata{}, texture->GetTexture(), sampler); + return command.BindResource(shader->GetShaderStage(), *image_slot, + impeller::ShaderMetadata{}, texture->GetTexture(), + sampler); } void InternalFlutterGpu_RenderPass_ClearBindings( diff --git a/lib/gpu/render_pass.h b/lib/gpu/render_pass.h index 94b7d5faebcca..1581ac1597ead 100644 --- a/lib/gpu/render_pass.h +++ b/lib/gpu/render_pass.h @@ -33,7 +33,7 @@ class RenderPass : public RefCountedDartWrappable { ~RenderPass() override; - const std::shared_ptr& GetContext() const; + const std::weak_ptr& GetContext() const; impeller::Command& GetCommand(); const impeller::Command& GetCommand() const;