// 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/renderer/render_pass.h" #include "fml/status.h" namespace impeller { RenderPass::RenderPass(std::shared_ptr context, const RenderTarget& target) : context_(std::move(context)), sample_count_(target.GetSampleCount()), pixel_format_(target.GetRenderTargetPixelFormat()), has_depth_attachment_(target.GetDepthAttachment().has_value()), has_stencil_attachment_(target.GetStencilAttachment().has_value()), render_target_size_(target.GetRenderTargetSize()), render_target_(target), orthographic_(Matrix::MakeOrthographic(render_target_size_)) {} RenderPass::~RenderPass() {} SampleCount RenderPass::GetSampleCount() const { return sample_count_; } PixelFormat RenderPass::GetRenderTargetPixelFormat() const { return pixel_format_; } bool RenderPass::HasDepthAttachment() const { return has_depth_attachment_; } bool RenderPass::HasStencilAttachment() const { return has_stencil_attachment_; } const RenderTarget& RenderPass::GetRenderTarget() const { return render_target_; } ISize RenderPass::GetRenderTargetSize() const { return render_target_size_; } const Matrix& RenderPass::GetOrthographicTransform() const { return orthographic_; } void RenderPass::SetLabel(std::string label) { if (label.empty()) { return; } OnSetLabel(std::move(label)); } bool RenderPass::AddCommand(Command&& command) { if (!command.IsValid()) { VALIDATION_LOG << "Attempted to add an invalid command to the render pass."; return false; } if (command.scissor.has_value()) { auto target_rect = IRect::MakeSize(render_target_.GetRenderTargetSize()); if (!target_rect.Contains(command.scissor.value())) { VALIDATION_LOG << "Cannot apply a scissor that lies outside the bounds " "of the render target."; return false; } } if (command.vertex_buffer.vertex_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; } commands_.emplace_back(std::move(command)); return true; } bool RenderPass::EncodeCommands() const { return OnEncodeCommands(*context_); } const std::shared_ptr& RenderPass::GetContext() const { return context_; } void RenderPass::SetPipeline( const std::shared_ptr>& pipeline) { pending_.pipeline = pipeline; } void RenderPass::SetCommandLabel(std::string_view label) { #ifdef IMPELLER_DEBUG pending_.label = std::string(label); #endif // IMPELLER_DEBUG } void RenderPass::SetStencilReference(uint32_t value) { pending_.stencil_reference = value; } void RenderPass::SetBaseVertex(uint64_t value) { pending_.base_vertex = value; } void RenderPass::SetViewport(Viewport viewport) { pending_.viewport = viewport; } void RenderPass::SetScissor(IRect scissor) { pending_.scissor = scissor; } void RenderPass::SetInstanceCount(size_t count) { pending_.instance_count = count; } bool RenderPass::SetVertexBuffer(VertexBuffer buffer) { return pending_.BindVertices(std::move(buffer)); } fml::Status RenderPass::Draw() { auto result = AddCommand(std::move(pending_)); pending_ = Command{}; if (result) { return fml::Status(); } return fml::Status(fml::StatusCode::kInvalidArgument, "Failed to encode command"); } // |ResourceBinder| bool RenderPass::BindResource(ShaderStage stage, DescriptorType type, const ShaderUniformSlot& slot, const ShaderMetadata& metadata, BufferView view) { return pending_.BindResource(stage, type, 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)); } // |ResourceBinder| bool RenderPass::BindResource(ShaderStage stage, DescriptorType type, const SampledImageSlot& slot, const ShaderMetadata& metadata, std::shared_ptr texture, const std::unique_ptr& sampler) { return pending_.BindResource(stage, type, slot, metadata, std::move(texture), sampler); } } // namespace impeller