diff --git a/impeller/entity/contents/text_contents.cc b/impeller/entity/contents/text_contents.cc index ab2130f039bc2..12c1e6ac488f7 100644 --- a/impeller/entity/contents/text_contents.cc +++ b/impeller/entity/contents/text_contents.cc @@ -256,8 +256,9 @@ bool TextContents::Render(const ContentContext& renderer, } }); - pass.SetVertexBuffer(std::move(buffer_view), vertex_count); + pass.SetVertexBuffer(std::move(buffer_view)); pass.SetIndexBuffer({}, IndexType::kNone); + pass.SetElementCount(vertex_count); return pass.Draw().ok(); } diff --git a/impeller/renderer/backend/gles/buffer_bindings_gles.cc b/impeller/renderer/backend/gles/buffer_bindings_gles.cc index 15da48591b646..c893833b460fd 100644 --- a/impeller/renderer/backend/gles/buffer_bindings_gles.cc +++ b/impeller/renderer/backend/gles/buffer_bindings_gles.cc @@ -415,7 +415,7 @@ std::optional BufferBindingsGLES::BindTextures( /// If there is a sampler for the texture at the same index, configure the /// bound texture using that sampler. /// - const auto& sampler_gles = SamplerGLES::Cast(*data.sampler); + const auto& sampler_gles = SamplerGLES::Cast(**data.sampler); if (!sampler_gles.ConfigureBoundTexture(texture_gles, gl)) { return std::nullopt; } diff --git a/impeller/renderer/backend/gles/render_pass_gles.cc b/impeller/renderer/backend/gles/render_pass_gles.cc index 54d8441d3653b..c6ab8d53fbd74 100644 --- a/impeller/renderer/backend/gles/render_pass_gles.cc +++ b/impeller/renderer/backend/gles/render_pass_gles.cc @@ -455,7 +455,7 @@ static bool BindVertexBuffer(const ProcTableGLES& gl, /// Finally! Invoke the draw call. /// if (command.index_type == IndexType::kNone) { - gl.DrawArrays(mode, command.base_vertex, command.vertex_count); + gl.DrawArrays(mode, command.base_vertex, command.element_count); } else { // Bind the index buffer if necessary. auto index_buffer_view = command.index_buffer; @@ -466,7 +466,7 @@ static bool BindVertexBuffer(const ProcTableGLES& gl, return false; } gl.DrawElements(mode, // mode - command.vertex_count, // count + command.element_count, // count ToIndexType(command.index_type), // type reinterpret_cast(static_cast( index_buffer_view.range.offset)) // indices diff --git a/impeller/renderer/backend/metal/render_pass_mtl.h b/impeller/renderer/backend/metal/render_pass_mtl.h index 60cfe52eb67ea..16302efc048fd 100644 --- a/impeller/renderer/backend/metal/render_pass_mtl.h +++ b/impeller/renderer/backend/metal/render_pass_mtl.h @@ -79,13 +79,15 @@ class RenderPassMTL final : public RenderPass { // |RenderPass| void SetScissor(IRect scissor) override; + // |RenderPass| + void SetElementCount(size_t count) override; + // |RenderPass| void SetInstanceCount(size_t count) override; // |RenderPass| bool SetVertexBuffer(BufferView vertex_buffers[], - size_t vertex_buffer_count, - size_t vertex_count) override; + size_t vertex_buffer_count) override; // |RenderPass| bool SetIndexBuffer(BufferView index_buffer, IndexType index_type) override; diff --git a/impeller/renderer/backend/metal/render_pass_mtl.mm b/impeller/renderer/backend/metal/render_pass_mtl.mm index 3c9fda401092b..58b41334ed1f2 100644 --- a/impeller/renderer/backend/metal/render_pass_mtl.mm +++ b/impeller/renderer/backend/metal/render_pass_mtl.mm @@ -283,6 +283,11 @@ static bool Bind(PassBindingsCacheMTL& pass, pass_bindings_.SetScissor(scissor); } +// |RenderPass| +void RenderPassMTL::SetElementCount(size_t count) { + vertex_count_ = count; +} + // |RenderPass| void RenderPassMTL::SetInstanceCount(size_t count) { instance_count_ = count; @@ -290,8 +295,7 @@ static bool Bind(PassBindingsCacheMTL& pass, // |RenderPass| bool RenderPassMTL::SetVertexBuffer(BufferView vertex_buffers[], - size_t vertex_buffer_count, - size_t vertex_count) { + size_t vertex_buffer_count) { if (!ValidateVertexBuffers(vertex_buffers, vertex_buffer_count)) { return false; } @@ -304,8 +308,6 @@ static bool Bind(PassBindingsCacheMTL& pass, } } - vertex_count_ = vertex_count; - return true; } diff --git a/impeller/renderer/backend/vulkan/render_pass_vk.cc b/impeller/renderer/backend/vulkan/render_pass_vk.cc index df6d27d37610c..4ad3d09478cad 100644 --- a/impeller/renderer/backend/vulkan/render_pass_vk.cc +++ b/impeller/renderer/backend/vulkan/render_pass_vk.cc @@ -365,6 +365,11 @@ void RenderPassVK::SetScissor(IRect scissor) { command_buffer_vk_.setScissor(0, 1, &scissor_vk); } +// |RenderPass| +void RenderPassVK::SetElementCount(size_t count) { + element_count_ = count; +} + // |RenderPass| void RenderPassVK::SetInstanceCount(size_t count) { instance_count_ = count; @@ -372,8 +377,7 @@ void RenderPassVK::SetInstanceCount(size_t count) { // |RenderPass| bool RenderPassVK::SetVertexBuffer(BufferView vertex_buffers[], - size_t vertex_buffer_count, - size_t vertex_count) { + size_t vertex_buffer_count) { if (!ValidateVertexBuffers(vertex_buffers, vertex_buffer_count)) { return false; } @@ -390,8 +394,6 @@ bool RenderPassVK::SetVertexBuffer(BufferView vertex_buffers[], command_buffer_vk_.bindVertexBuffers(0u, vertex_buffer_count, buffers, vertex_buffer_offsets); - vertex_count_ = vertex_count; - return true; } @@ -507,14 +509,14 @@ fml::Status RenderPassVK::Draw() { } if (has_index_buffer_) { - command_buffer_vk_.drawIndexed(vertex_count_, // index count + command_buffer_vk_.drawIndexed(element_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 + command_buffer_vk_.draw(element_count_, // vertex count instance_count_, // instance count base_vertex_, // vertex offset 0u // first instance @@ -533,7 +535,7 @@ fml::Status RenderPassVK::Draw() { descriptor_write_offset_ = 0u; instance_count_ = 1u; base_vertex_ = 0u; - vertex_count_ = 0u; + element_count_ = 0u; pipeline_ = nullptr; pipeline_uses_input_attachments_ = false; immutable_sampler_ = nullptr; diff --git a/impeller/renderer/backend/vulkan/render_pass_vk.h b/impeller/renderer/backend/vulkan/render_pass_vk.h index fa59713a652c8..bf5b09235d206 100644 --- a/impeller/renderer/backend/vulkan/render_pass_vk.h +++ b/impeller/renderer/backend/vulkan/render_pass_vk.h @@ -46,7 +46,7 @@ class RenderPassVK final : public RenderPass { size_t descriptor_write_offset_ = 0u; size_t instance_count_ = 1u; size_t base_vertex_ = 0u; - size_t vertex_count_ = 0u; + size_t element_count_ = 0u; bool has_index_buffer_ = false; bool has_label_ = false; const Pipeline* pipeline_; @@ -76,13 +76,15 @@ class RenderPassVK final : public RenderPass { // |RenderPass| void SetScissor(IRect scissor) override; + // |RenderPass| + void SetElementCount(size_t count) override; + // |RenderPass| void SetInstanceCount(size_t count) override; // |RenderPass| bool SetVertexBuffer(BufferView vertex_buffers[], - size_t vertex_buffer_count, - size_t vertex_count) override; + size_t vertex_buffer_count) override; // |RenderPass| bool SetIndexBuffer(BufferView index_buffer, IndexType index_type) override; diff --git a/impeller/renderer/command.cc b/impeller/renderer/command.cc index fca3e2c089ded..b95d93cb06952 100644 --- a/impeller/renderer/command.cc +++ b/impeller/renderer/command.cc @@ -20,7 +20,7 @@ bool Command::BindVertices(const VertexBuffer& buffer) { vertex_buffers = {buffer.vertex_buffer}; vertex_buffer_count = 1u; - vertex_count = buffer.vertex_count; + element_count = buffer.vertex_count; index_buffer = buffer.index_buffer; index_type = buffer.index_type; return true; @@ -89,14 +89,14 @@ bool Command::BindResource(ShaderStage stage, vertex_bindings.sampled_images.emplace_back(TextureAndSampler{ .slot = slot, .texture = {&metadata, std::move(texture)}, - .sampler = sampler, + .sampler = &sampler, }); return true; case ShaderStage::kFragment: fragment_bindings.sampled_images.emplace_back(TextureAndSampler{ .slot = slot, .texture = {&metadata, std::move(texture)}, - .sampler = sampler, + .sampler = &sampler, }); return true; case ShaderStage::kCompute: diff --git a/impeller/renderer/command.h b/impeller/renderer/command.h index bcd7b0865a0d3..fee137d669f66 100644 --- a/impeller/renderer/command.h +++ b/impeller/renderer/command.h @@ -61,7 +61,7 @@ using TextureResource = Resource>; struct TextureAndSampler { SampledImageSlot slot; TextureResource texture; - const std::unique_ptr& sampler; + const std::unique_ptr* sampler; }; /// @brief combines the buffer resource and its uniform slot information. @@ -160,14 +160,13 @@ struct Command : public ResourceBinder { BufferView index_buffer; //---------------------------------------------------------------------------- - /// The total count of vertices, either in the vertex_buffer if the - /// index_type is IndexType::kNone or in the index_buffer otherwise. - size_t vertex_count = 0u; + /// The number of elements to draw. When only a vertex buffer is set, this is + /// the vertex count. When an index buffer is set, this is the index count. + size_t element_count = 0u; //---------------------------------------------------------------------------- /// The type of indices in the index buffer. The indices must be tightly /// packed in the index buffer. - /// IndexType index_type = IndexType::kUnknown; //---------------------------------------------------------------------------- diff --git a/impeller/renderer/render_pass.cc b/impeller/renderer/render_pass.cc index df68c499c2490..4960acf948dbe 100644 --- a/impeller/renderer/render_pass.cc +++ b/impeller/renderer/render_pass.cc @@ -72,7 +72,7 @@ bool RenderPass::AddCommand(Command&& command) { } } - if (command.vertex_count == 0u || command.instance_count == 0u) { + if (command.element_count == 0u || command.instance_count == 0u) { // Essentially a no-op. Don't record the command but this is not necessary // an error either. return true; @@ -117,40 +117,40 @@ void RenderPass::SetScissor(IRect scissor) { pending_.scissor = scissor; } +void RenderPass::SetElementCount(size_t count) { + pending_.element_count = count; +} + void RenderPass::SetInstanceCount(size_t count) { pending_.instance_count = count; } bool RenderPass::SetVertexBuffer(VertexBuffer buffer) { - if (!SetVertexBuffer(&buffer.vertex_buffer, 1u, buffer.vertex_count)) { + if (!SetVertexBuffer(&buffer.vertex_buffer, 1u)) { return false; } if (!SetIndexBuffer(buffer.index_buffer, buffer.index_type)) { return false; } + SetElementCount(buffer.vertex_count); return true; } -bool RenderPass::SetVertexBuffer(BufferView vertex_buffer, - size_t vertex_count) { - return SetVertexBuffer(&vertex_buffer, 1, vertex_count); +bool RenderPass::SetVertexBuffer(BufferView vertex_buffer) { + return SetVertexBuffer(&vertex_buffer, 1); } -bool RenderPass::SetVertexBuffer(std::vector vertex_buffers, - size_t vertex_count) { - return SetVertexBuffer(vertex_buffers.data(), vertex_buffers.size(), - vertex_count); +bool RenderPass::SetVertexBuffer(std::vector vertex_buffers) { + return SetVertexBuffer(vertex_buffers.data(), vertex_buffers.size()); } bool RenderPass::SetVertexBuffer(BufferView vertex_buffers[], - size_t vertex_buffer_count, - size_t vertex_count) { + size_t vertex_buffer_count) { if (!ValidateVertexBuffers(vertex_buffers, vertex_buffer_count)) { return false; } - pending_.vertex_count = vertex_count; pending_.vertex_buffer_count = vertex_buffer_count; for (size_t i = 0; i < vertex_buffer_count; i++) { pending_.vertex_buffers[i] = std::move(vertex_buffers[i]); diff --git a/impeller/renderer/render_pass.h b/impeller/renderer/render_pass.h index c0e9b73c802bb..f4a8bd2dcc603 100644 --- a/impeller/renderer/render_pass.h +++ b/impeller/renderer/render_pass.h @@ -89,6 +89,12 @@ class RenderPass : public ResourceBinder { /// virtual void SetScissor(IRect scissor); + //---------------------------------------------------------------------------- + /// The number of elements to draw. When only a vertex buffer is set, this is + /// the vertex count. When an index buffer is set, this is the index count. + /// + virtual void SetElementCount(size_t count); + //---------------------------------------------------------------------------- /// The number of instances of the given set of vertices to render. Not all /// backends support rendering more than one instance at a time. @@ -115,11 +121,9 @@ class RenderPass : public ResourceBinder { /// /// @param[in] vertex_buffer The buffer view to use for sourcing vertices. /// - /// @param[in] vertex_count The number of vertices to draw. - /// /// @return Returns false if the given buffer view is invalid. /// - bool SetVertexBuffer(BufferView vertex_buffer, size_t vertex_count); + bool SetVertexBuffer(BufferView vertex_buffer); //---------------------------------------------------------------------------- /// @brief Specify a set of vertex buffers to use for this command. @@ -131,12 +135,9 @@ class RenderPass : public ResourceBinder { /// @param[in] vertex_buffers The array of vertex buffer views to use. /// The maximum number of vertex buffers is 16. /// - /// @param[in] vertex_count The number of vertices to draw. - /// /// @return Returns false if any of the given buffer views are invalid. /// - bool SetVertexBuffer(std::vector vertex_buffers, - size_t vertex_count); + bool SetVertexBuffer(std::vector vertex_buffers); //---------------------------------------------------------------------------- /// @brief Specify a set of vertex buffers to use for this command. @@ -152,22 +153,20 @@ class RenderPass : public ResourceBinder { /// @param[in] vertex_buffer_count The number of vertex buffers to copy from /// the array (max 16). /// - /// @param[in] vertex_count The number of vertices to draw. - /// /// @return Returns false if any of the given buffer views are invalid. /// virtual bool SetVertexBuffer(BufferView vertex_buffers[], - size_t vertex_buffer_count, - size_t vertex_count); + size_t vertex_buffer_count); //---------------------------------------------------------------------------- /// @brief Specify an index buffer to use for this command. /// To unset the index buffer, pass IndexType::kNone to /// index_type. /// - /// @param[in] index_buffer The buffer view to use for sourcing indices. The - /// total number of indices is inferred from the - /// buffer view size and index type. + /// @param[in] index_buffer The buffer view to use for sourcing indices. + /// When an index buffer is bound, the + /// `vertex_count` set via `SetVertexBuffer` is used + /// as the number of indices to draw. /// /// @param[in] index_type The size of each index in the index buffer. Pass /// IndexType::kNone to unset the index buffer. diff --git a/impeller/renderer/renderer_unittests.cc b/impeller/renderer/renderer_unittests.cc index 30214a94f9636..ab4520ed6348c 100644 --- a/impeller/renderer/renderer_unittests.cc +++ b/impeller/renderer/renderer_unittests.cc @@ -266,7 +266,8 @@ TEST_P(RendererTest, CanRenderPerspectiveCube) { BufferView index_buffer = { .buffer = device_buffer, .range = Range(offsetof(Cube, indices), sizeof(Cube::indices))}; - pass.SetVertexBuffer(vertex_buffers.data(), vertex_buffers.size(), 36); + pass.SetVertexBuffer(vertex_buffers.data(), vertex_buffers.size()); + pass.SetElementCount(36); pass.SetIndexBuffer(index_buffer, IndexType::k16bit); VS::UniformBuffer uniforms; diff --git a/lib/gpu/render_pass.cc b/lib/gpu/render_pass.cc index 24f43bc43cfac..70d68d0e78081 100644 --- a/lib/gpu/render_pass.cc +++ b/lib/gpu/render_pass.cc @@ -15,8 +15,8 @@ #include "impeller/core/formats.h" #include "impeller/core/sampler_descriptor.h" #include "impeller/core/shader_types.h" -#include "impeller/core/vertex_buffer.h" #include "impeller/geometry/color.h" +#include "impeller/renderer/command.h" #include "impeller/renderer/pipeline.h" #include "impeller/renderer/pipeline_descriptor.h" #include "impeller/renderer/pipeline_library.h" @@ -28,9 +28,7 @@ namespace gpu { IMPLEMENT_WRAPPERTYPEINFO(flutter_gpu, RenderPass); -RenderPass::RenderPass() - : vertex_buffer_( - impeller::VertexBuffer{.index_type = impeller::IndexType::kNone}){}; +RenderPass::RenderPass() = default; RenderPass::~RenderPass() = default; @@ -38,14 +36,6 @@ const std::shared_ptr& RenderPass::GetContext() const { return render_pass_->GetContext(); } -impeller::Command& RenderPass::GetCommand() { - return command_; -} - -const impeller::Command& RenderPass::GetCommand() const { - return command_; -} - impeller::RenderTarget& RenderPass::GetRenderTarget() { return render_target_; } @@ -78,10 +68,6 @@ RenderPass::GetStencilBackAttachmentDescriptor() { return stencil_back_desc_; } -impeller::VertexBuffer& RenderPass::GetVertexBuffer() { - return vertex_buffer_; -} - impeller::PipelineDescriptor& RenderPass::GetPipelineDescriptor() { return pipeline_descriptor_; } @@ -100,6 +86,17 @@ void RenderPass::SetPipeline(fml::RefPtr pipeline) { render_pipeline_ = std::move(pipeline); } +void RenderPass::ClearBindings() { + vertex_uniform_bindings.clear(); + vertex_texture_bindings.clear(); + fragment_uniform_bindings.clear(); + fragment_texture_bindings.clear(); + vertex_buffer = {}; + index_buffer = {}; + index_buffer_type = impeller::IndexType::kNone; + element_count = 0; +} + std::shared_ptr> RenderPass::GetOrCreatePipeline() { // Infer the pipeline layout based on the shape of the RenderTarget. @@ -172,54 +169,43 @@ RenderPass::GetOrCreatePipeline() { return pipeline; } -impeller::Command RenderPass::ProvisionRasterCommand() { - impeller::Command result = command_; - - result.pipeline = GetOrCreatePipeline(); - - return result; -} - bool RenderPass::Draw() { - impeller::Command result = ProvisionRasterCommand(); -#ifdef IMPELLER_DEBUG - render_pass_->SetCommandLabel(result.label); -#endif // IMPELLER_DEBUG - render_pass_->SetPipeline(result.pipeline); - render_pass_->SetStencilReference(result.stencil_reference); - render_pass_->SetBaseVertex(result.base_vertex); - if (result.viewport.has_value()) { - render_pass_->SetViewport(result.viewport.value()); - } - if (result.scissor.has_value()) { - render_pass_->SetScissor(result.scissor.value()); - } - render_pass_->SetVertexBuffer(GetVertexBuffer()); - for (const auto& buffer : result.vertex_bindings.buffers) { + render_pass_->SetPipeline(GetOrCreatePipeline()); + + for (const auto& [_, buffer] : vertex_uniform_bindings) { render_pass_->BindResource(impeller::ShaderStage::kVertex, impeller::DescriptorType::kUniformBuffer, buffer.slot, *buffer.view.GetMetadata(), buffer.view.resource); } - for (const auto& texture : result.vertex_bindings.sampled_images) { + for (const auto& [_, texture] : vertex_texture_bindings) { render_pass_->BindResource(impeller::ShaderStage::kVertex, impeller::DescriptorType::kSampledImage, texture.slot, *texture.texture.GetMetadata(), - texture.texture.resource, texture.sampler); + texture.texture.resource, *texture.sampler); } - for (const auto& buffer : result.fragment_bindings.buffers) { + for (const auto& [_, buffer] : fragment_uniform_bindings) { render_pass_->BindResource(impeller::ShaderStage::kFragment, impeller::DescriptorType::kUniformBuffer, buffer.slot, *buffer.view.GetMetadata(), buffer.view.resource); } - for (const auto& texture : result.fragment_bindings.sampled_images) { + for (const auto& [_, texture] : fragment_texture_bindings) { render_pass_->BindResource(impeller::ShaderStage::kFragment, impeller::DescriptorType::kSampledImage, texture.slot, *texture.texture.GetMetadata(), - texture.texture.resource, texture.sampler); + texture.texture.resource, *texture.sampler); } - return render_pass_->Draw().ok(); + + render_pass_->SetVertexBuffer(vertex_buffer); + render_pass_->SetIndexBuffer(index_buffer, index_buffer_type); + render_pass_->SetElementCount(element_count); + + render_pass_->SetStencilReference(stencil_reference); + + bool result = render_pass_->Draw().ok(); + + return result; } } // namespace gpu @@ -307,14 +293,13 @@ void InternalFlutterGpu_RenderPass_BindPipeline( wrapper->SetPipeline(std::move(ref)); } -template -static void BindVertexBuffer(flutter::gpu::RenderPass* wrapper, - TBuffer buffer, - int offset_in_bytes, - int length_in_bytes, - int vertex_count) { - auto& vertex_buffer = wrapper->GetVertexBuffer(); - vertex_buffer.vertex_buffer = impeller::BufferView{ +static void BindVertexBuffer( + flutter::gpu::RenderPass* wrapper, + const std::shared_ptr& buffer, + int offset_in_bytes, + int length_in_bytes, + int vertex_count) { + wrapper->vertex_buffer = impeller::BufferView{ .buffer = buffer, .range = impeller::Range(offset_in_bytes, length_in_bytes), }; @@ -327,8 +312,8 @@ static void BindVertexBuffer(flutter::gpu::RenderPass* wrapper, // but overall it would be a bit more explicit and we wouldn't // have to document this behavior where the presence of the index // buffer always takes precedent. - if (vertex_buffer.index_type == impeller::IndexType::kNone) { - vertex_buffer.vertex_count = vertex_count; + if (!wrapper->has_index_buffer) { + wrapper->element_count = vertex_count; } } @@ -360,20 +345,25 @@ void InternalFlutterGpu_RenderPass_BindVertexBufferHost( view->range.length, vertex_count); } -template -static void BindIndexBuffer(flutter::gpu::RenderPass* wrapper, - TBuffer buffer, - int offset_in_bytes, - int length_in_bytes, - int index_type, - int index_count) { - auto& vertex_buffer = wrapper->GetVertexBuffer(); - vertex_buffer.index_buffer = impeller::BufferView{ +static void BindIndexBuffer( + flutter::gpu::RenderPass* wrapper, + const std::shared_ptr& buffer, + int offset_in_bytes, + int length_in_bytes, + int index_type, + int index_count) { + impeller::IndexType type = flutter::gpu::ToImpellerIndexType(index_type); + wrapper->index_buffer = impeller::BufferView{ .buffer = buffer, .range = impeller::Range(offset_in_bytes, length_in_bytes), }; - vertex_buffer.index_type = flutter::gpu::ToImpellerIndexType(index_type); - vertex_buffer.vertex_count = index_count; + wrapper->index_buffer_type = type; + + bool setting_index_buffer = type != impeller::IndexType::kNone; + if (setting_index_buffer) { + wrapper->element_count = index_count; + } + wrapper->has_index_buffer = setting_index_buffer; } void InternalFlutterGpu_RenderPass_BindIndexBufferDevice( @@ -405,15 +395,13 @@ void InternalFlutterGpu_RenderPass_BindIndexBufferHost( index_type, index_count); } -template -static bool BindUniform(flutter::gpu::RenderPass* wrapper, - flutter::gpu::Shader* shader, - Dart_Handle uniform_name_handle, - TBuffer buffer, - int offset_in_bytes, - int length_in_bytes) { - auto& command = wrapper->GetCommand(); - +static bool BindUniform( + flutter::gpu::RenderPass* wrapper, + flutter::gpu::Shader* shader, + Dart_Handle uniform_name_handle, + const std::shared_ptr& buffer, + int offset_in_bytes, + int length_in_bytes) { auto uniform_name = tonic::StdStringFromDart(uniform_name_handle); const flutter::gpu::Shader::UniformBinding* uniform_struct = shader->GetUniformStruct(uniform_name); @@ -423,13 +411,36 @@ static bool BindUniform(flutter::gpu::RenderPass* wrapper, return false; } - return command.BindResource( - shader->GetShaderStage(), impeller::DescriptorType::kUniformBuffer, - uniform_struct->slot, uniform_struct->metadata, - impeller::BufferView{ - .buffer = buffer, - .range = impeller::Range(offset_in_bytes, length_in_bytes), - }); + flutter::gpu::RenderPass::BufferUniformMap* uniform_map = nullptr; + switch (shader->GetShaderStage()) { + case impeller::ShaderStage::kVertex: + uniform_map = &wrapper->vertex_uniform_bindings; + break; + case impeller::ShaderStage::kFragment: + uniform_map = &wrapper->fragment_uniform_bindings; + break; + case impeller::ShaderStage::kUnknown: + case impeller::ShaderStage::kCompute: + return false; + } + + if (!buffer || static_cast(offset_in_bytes + length_in_bytes) >= + buffer->GetDeviceBufferDescriptor().size) { + return false; + } + + uniform_map->insert_or_assign( + uniform_struct, + impeller::BufferAndUniformSlot{ + .slot = uniform_struct->slot, + .view = impeller::BufferResource{ + &uniform_struct->metadata, + impeller::BufferView{ + .buffer = buffer, + .range = impeller::Range(offset_in_bytes, length_in_bytes), + }, + }}); + return true; } bool InternalFlutterGpu_RenderPass_BindUniformDevice( @@ -472,8 +483,6 @@ bool InternalFlutterGpu_RenderPass_BindTexture( int mip_filter, int width_address_mode, int height_address_mode) { - auto& command = wrapper->GetCommand(); - auto uniform_name = tonic::StdStringFromDart(uniform_name_handle); const flutter::gpu::Shader::TextureBinding* texture_binding = shader->GetUniformTexture(uniform_name); @@ -493,17 +502,32 @@ bool InternalFlutterGpu_RenderPass_BindTexture( flutter::gpu::ToImpellerSamplerAddressMode(height_address_mode); const std::unique_ptr& sampler = wrapper->GetContext()->GetSamplerLibrary()->GetSampler(sampler_desc); - return command.BindResource(shader->GetShaderStage(), - impeller::DescriptorType::kSampledImage, - texture_binding->slot, texture_binding->metadata, - texture->GetTexture(), sampler); + + flutter::gpu::RenderPass::TextureUniformMap* uniform_map = nullptr; + switch (shader->GetShaderStage()) { + case impeller::ShaderStage::kVertex: + uniform_map = &wrapper->vertex_texture_bindings; + break; + case impeller::ShaderStage::kFragment: + uniform_map = &wrapper->fragment_texture_bindings; + break; + case impeller::ShaderStage::kUnknown: + case impeller::ShaderStage::kCompute: + return false; + } + uniform_map->insert_or_assign( + texture_binding, + impeller::TextureAndSampler{ + .slot = texture_binding->slot, + .texture = {&texture_binding->metadata, texture->GetTexture()}, + .sampler = &sampler, + }); + return true; } void InternalFlutterGpu_RenderPass_ClearBindings( flutter::gpu::RenderPass* wrapper) { - auto& command = wrapper->GetCommand(); - command.vertex_bindings = {}; - command.fragment_bindings = {}; + wrapper->ClearBindings(); } void InternalFlutterGpu_RenderPass_SetColorBlendEnable( @@ -556,8 +580,7 @@ void InternalFlutterGpu_RenderPass_SetDepthCompareOperation( void InternalFlutterGpu_RenderPass_SetStencilReference( flutter::gpu::RenderPass* wrapper, int stencil_reference) { - auto& command = wrapper->GetCommand(); - command.stencil_reference = static_cast(stencil_reference); + wrapper->stencil_reference = static_cast(stencil_reference); } void InternalFlutterGpu_RenderPass_SetStencilConfig( diff --git a/lib/gpu/render_pass.h b/lib/gpu/render_pass.h index cf572641fb86d..da9840d62699f 100644 --- a/lib/gpu/render_pass.h +++ b/lib/gpu/render_pass.h @@ -5,6 +5,7 @@ #ifndef FLUTTER_LIB_GPU_RENDER_PASS_H_ #define FLUTTER_LIB_GPU_RENDER_PASS_H_ +#include #include #include #include "flutter/lib/gpu/command_buffer.h" @@ -12,7 +13,6 @@ #include "flutter/lib/ui/dart_wrapper.h" #include "fml/memory/ref_ptr.h" #include "impeller/core/formats.h" -#include "impeller/core/vertex_buffer.h" #include "impeller/renderer/command.h" #include "impeller/renderer/render_pass.h" #include "impeller/renderer/render_target.h" @@ -35,9 +35,6 @@ class RenderPass : public RefCountedDartWrappable { const std::shared_ptr& GetContext() const; - impeller::Command& GetCommand(); - const impeller::Command& GetCommand() const; - impeller::RenderTarget& GetRenderTarget(); const impeller::RenderTarget& GetRenderTarget() const; @@ -50,42 +47,59 @@ class RenderPass : public RefCountedDartWrappable { impeller::StencilAttachmentDescriptor& GetStencilBackAttachmentDescriptor(); - impeller::VertexBuffer& GetVertexBuffer(); - impeller::PipelineDescriptor& GetPipelineDescriptor(); bool Begin(flutter::gpu::CommandBuffer& command_buffer); void SetPipeline(fml::RefPtr pipeline); + void ClearBindings(); + + bool Draw(); + + using BufferUniformMap = + std::unordered_map; + using TextureUniformMap = + std::unordered_map; + + BufferUniformMap vertex_uniform_bindings; + TextureUniformMap vertex_texture_bindings; + BufferUniformMap fragment_uniform_bindings; + TextureUniformMap fragment_texture_bindings; + + impeller::BufferView vertex_buffer; + impeller::BufferView index_buffer; + impeller::IndexType index_buffer_type = impeller::IndexType::kNone; + size_t element_count = 0; + + uint32_t stencil_reference = 0; + + // Helper flag to determine whether the vertex_count should override the + // element count. The index count takes precedent. + bool has_index_buffer = false; + + private: /// Lookup an Impeller pipeline by building a descriptor based on the current /// command state. std::shared_ptr> GetOrCreatePipeline(); - impeller::Command ProvisionRasterCommand(); - - bool Draw(); - - private: impeller::RenderTarget render_target_; std::shared_ptr render_pass_; // Command encoding state. - impeller::Command command_; fml::RefPtr render_pipeline_; impeller::PipelineDescriptor pipeline_descriptor_; - // Pipeline descriptor layout state. We always keep track of this state, but - // we'll only apply it as necessary to match the RenderTarget. + // Pipeline descriptor layout state. We always keep track of this state, + // but we'll only apply it as necessary to match the RenderTarget. std::map color_descriptors_; impeller::StencilAttachmentDescriptor stencil_front_desc_; impeller::StencilAttachmentDescriptor stencil_back_desc_; impeller::DepthAttachmentDescriptor depth_desc_; - // Command state. - impeller::VertexBuffer vertex_buffer_; - FML_DISALLOW_COPY_AND_ASSIGN(RenderPass); }; diff --git a/testing/dart/gpu_test.dart b/testing/dart/gpu_test.dart index a26bab37b9c87..508e7e08d9e6f 100644 --- a/testing/dart/gpu_test.dart +++ b/testing/dart/gpu_test.dart @@ -472,11 +472,6 @@ void main() async { // the API. state.renderPass.setStencilConfig( gpu.StencilConfig(compareFunction: gpu.CompareFunction.equal)); - // TODO(bdero): https://github.com/flutter/flutter/issues/155335 - // Re-binding the same uniform with `bindUniform` does not - // replace the previous binding. We shouldn't need to clear the - // command bindings to work around this. - state.renderPass.clearBindings(); state.renderPass.bindUniform(vertInfo, outerGreenVertInfo); state.renderPass.draw(); @@ -511,9 +506,6 @@ void main() async { final gpu.UniformSlot vertInfo = pipeline.vertexShader.getUniformSlot('VertInfo'); - // TODO(bdero): Overwrite bindings with the same slot so we don't need to clear. - // https://github.com/flutter/flutter/issues/155335 - state.renderPass.clearBindings(); state.renderPass.bindVertexBuffer(vertices, 3); state.renderPass.bindUniform(vertInfo, vertInfoUboFront); state.renderPass.draw();