| // 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/pipeline_descriptor.h" |
| |
| #include "impeller/core/formats.h" |
| #include "impeller/renderer/shader_function.h" |
| #include "impeller/renderer/shader_library.h" |
| #include "impeller/renderer/vertex_descriptor.h" |
| |
| namespace impeller { |
| |
| PipelineDescriptor::PipelineDescriptor() = default; |
| |
| PipelineDescriptor::~PipelineDescriptor() = default; |
| |
| // Comparable<PipelineDescriptor> |
| std::size_t PipelineDescriptor::GetHash() const { |
| auto seed = fml::HashCombine(); |
| fml::HashCombineSeed(seed, label_); |
| fml::HashCombineSeed(seed, sample_count_); |
| for (const auto& entry : entrypoints_) { |
| fml::HashCombineSeed(seed, entry.first); |
| if (auto second = entry.second) { |
| fml::HashCombineSeed(seed, second->GetHash()); |
| } |
| } |
| for (const auto& des : color_attachment_descriptors_) { |
| fml::HashCombineSeed(seed, des.first); |
| fml::HashCombineSeed(seed, des.second.Hash()); |
| } |
| if (vertex_descriptor_) { |
| fml::HashCombineSeed(seed, vertex_descriptor_->GetHash()); |
| } |
| fml::HashCombineSeed(seed, depth_pixel_format_); |
| fml::HashCombineSeed(seed, stencil_pixel_format_); |
| fml::HashCombineSeed(seed, depth_attachment_descriptor_); |
| fml::HashCombineSeed(seed, front_stencil_attachment_descriptor_); |
| fml::HashCombineSeed(seed, back_stencil_attachment_descriptor_); |
| fml::HashCombineSeed(seed, winding_order_); |
| fml::HashCombineSeed(seed, cull_mode_); |
| fml::HashCombineSeed(seed, primitive_type_); |
| fml::HashCombineSeed(seed, polygon_mode_); |
| return seed; |
| } |
| |
| // Comparable<PipelineDescriptor> |
| bool PipelineDescriptor::IsEqual(const PipelineDescriptor& other) const { |
| return label_ == other.label_ && sample_count_ == other.sample_count_ && |
| DeepCompareMap(entrypoints_, other.entrypoints_) && |
| color_attachment_descriptors_ == other.color_attachment_descriptors_ && |
| DeepComparePointer(vertex_descriptor_, other.vertex_descriptor_) && |
| stencil_pixel_format_ == other.stencil_pixel_format_ && |
| depth_pixel_format_ == other.depth_pixel_format_ && |
| depth_attachment_descriptor_ == other.depth_attachment_descriptor_ && |
| front_stencil_attachment_descriptor_ == |
| other.front_stencil_attachment_descriptor_ && |
| back_stencil_attachment_descriptor_ == |
| other.back_stencil_attachment_descriptor_ && |
| winding_order_ == other.winding_order_ && |
| cull_mode_ == other.cull_mode_ && |
| primitive_type_ == other.primitive_type_ && |
| polygon_mode_ == other.polygon_mode_; |
| } |
| |
| PipelineDescriptor& PipelineDescriptor::SetLabel(std::string label) { |
| label_ = std::move(label); |
| return *this; |
| } |
| |
| PipelineDescriptor& PipelineDescriptor::SetSampleCount(SampleCount samples) { |
| sample_count_ = samples; |
| return *this; |
| } |
| |
| PipelineDescriptor& PipelineDescriptor::AddStageEntrypoint( |
| std::shared_ptr<const ShaderFunction> function) { |
| if (!function) { |
| return *this; |
| } |
| |
| if (function->GetStage() == ShaderStage::kUnknown) { |
| return *this; |
| } |
| |
| entrypoints_[function->GetStage()] = std::move(function); |
| |
| return *this; |
| } |
| |
| PipelineDescriptor& PipelineDescriptor::SetVertexDescriptor( |
| std::shared_ptr<VertexDescriptor> vertex_descriptor) { |
| vertex_descriptor_ = std::move(vertex_descriptor); |
| return *this; |
| } |
| |
| size_t PipelineDescriptor::GetMaxColorAttacmentBindIndex() const { |
| size_t max = 0; |
| for (const auto& color : color_attachment_descriptors_) { |
| max = std::max(color.first, max); |
| } |
| return max; |
| } |
| |
| PipelineDescriptor& PipelineDescriptor::SetColorAttachmentDescriptor( |
| size_t index, |
| ColorAttachmentDescriptor desc) { |
| color_attachment_descriptors_[index] = desc; |
| return *this; |
| } |
| |
| PipelineDescriptor& PipelineDescriptor::SetColorAttachmentDescriptors( |
| std::map<size_t /* index */, ColorAttachmentDescriptor> descriptors) { |
| color_attachment_descriptors_ = std::move(descriptors); |
| return *this; |
| } |
| |
| const ColorAttachmentDescriptor* |
| PipelineDescriptor::GetColorAttachmentDescriptor(size_t index) const { |
| auto found = color_attachment_descriptors_.find(index); |
| return found == color_attachment_descriptors_.end() ? nullptr |
| : &found->second; |
| } |
| |
| const ColorAttachmentDescriptor* |
| PipelineDescriptor::GetLegacyCompatibleColorAttachment() const { |
| // Legacy renderers may only render to a single color attachment at index 0u. |
| if (color_attachment_descriptors_.size() != 1u) { |
| return nullptr; |
| } |
| return GetColorAttachmentDescriptor(0u); |
| } |
| |
| PipelineDescriptor& PipelineDescriptor::SetDepthPixelFormat( |
| PixelFormat format) { |
| depth_pixel_format_ = format; |
| return *this; |
| } |
| |
| PipelineDescriptor& PipelineDescriptor::SetStencilPixelFormat( |
| PixelFormat format) { |
| stencil_pixel_format_ = format; |
| return *this; |
| } |
| |
| PipelineDescriptor& PipelineDescriptor::SetDepthStencilAttachmentDescriptor( |
| std::optional<DepthAttachmentDescriptor> desc) { |
| depth_attachment_descriptor_ = desc; |
| return *this; |
| } |
| |
| PipelineDescriptor& PipelineDescriptor::SetStencilAttachmentDescriptors( |
| std::optional<StencilAttachmentDescriptor> front_and_back) { |
| return SetStencilAttachmentDescriptors(front_and_back, front_and_back); |
| } |
| |
| PipelineDescriptor& PipelineDescriptor::SetStencilAttachmentDescriptors( |
| std::optional<StencilAttachmentDescriptor> front, |
| std::optional<StencilAttachmentDescriptor> back) { |
| front_stencil_attachment_descriptor_ = front; |
| back_stencil_attachment_descriptor_ = back; |
| return *this; |
| } |
| |
| void PipelineDescriptor::ClearStencilAttachments() { |
| back_stencil_attachment_descriptor_.reset(); |
| front_stencil_attachment_descriptor_.reset(); |
| SetStencilPixelFormat(impeller::PixelFormat::kUnknown); |
| } |
| |
| void PipelineDescriptor::ClearDepthAttachment() { |
| depth_attachment_descriptor_.reset(); |
| SetDepthPixelFormat(impeller::PixelFormat::kUnknown); |
| } |
| |
| void PipelineDescriptor::ClearColorAttachment(size_t index) { |
| if (color_attachment_descriptors_.find(index) == |
| color_attachment_descriptors_.end()) { |
| return; |
| } |
| |
| color_attachment_descriptors_.erase(index); |
| } |
| |
| void PipelineDescriptor::ResetAttachments() { |
| color_attachment_descriptors_.clear(); |
| depth_attachment_descriptor_.reset(); |
| front_stencil_attachment_descriptor_.reset(); |
| back_stencil_attachment_descriptor_.reset(); |
| } |
| |
| PixelFormat PipelineDescriptor::GetStencilPixelFormat() const { |
| return stencil_pixel_format_; |
| } |
| |
| std::optional<StencilAttachmentDescriptor> |
| PipelineDescriptor::GetFrontStencilAttachmentDescriptor() const { |
| return front_stencil_attachment_descriptor_; |
| } |
| |
| std::optional<DepthAttachmentDescriptor> |
| PipelineDescriptor::GetDepthStencilAttachmentDescriptor() const { |
| return depth_attachment_descriptor_; |
| } |
| |
| const std::map<size_t /* index */, ColorAttachmentDescriptor>& |
| PipelineDescriptor::GetColorAttachmentDescriptors() const { |
| return color_attachment_descriptors_; |
| } |
| |
| const std::shared_ptr<VertexDescriptor>& |
| PipelineDescriptor::GetVertexDescriptor() const { |
| return vertex_descriptor_; |
| } |
| |
| const std::map<ShaderStage, std::shared_ptr<const ShaderFunction>>& |
| PipelineDescriptor::GetStageEntrypoints() const { |
| return entrypoints_; |
| } |
| |
| std::shared_ptr<const ShaderFunction> PipelineDescriptor::GetEntrypointForStage( |
| ShaderStage stage) const { |
| if (auto found = entrypoints_.find(stage); found != entrypoints_.end()) { |
| return found->second; |
| } |
| return nullptr; |
| } |
| |
| const std::string& PipelineDescriptor::GetLabel() const { |
| return label_; |
| } |
| |
| PixelFormat PipelineDescriptor::GetDepthPixelFormat() const { |
| return depth_pixel_format_; |
| } |
| |
| std::optional<StencilAttachmentDescriptor> |
| PipelineDescriptor::GetBackStencilAttachmentDescriptor() const { |
| return back_stencil_attachment_descriptor_; |
| } |
| |
| bool PipelineDescriptor::HasStencilAttachmentDescriptors() const { |
| return front_stencil_attachment_descriptor_.has_value() || |
| back_stencil_attachment_descriptor_.has_value(); |
| } |
| |
| void PipelineDescriptor::SetCullMode(CullMode mode) { |
| cull_mode_ = mode; |
| } |
| |
| CullMode PipelineDescriptor::GetCullMode() const { |
| return cull_mode_; |
| } |
| |
| void PipelineDescriptor::SetWindingOrder(WindingOrder order) { |
| winding_order_ = order; |
| } |
| |
| WindingOrder PipelineDescriptor::GetWindingOrder() const { |
| return winding_order_; |
| } |
| |
| void PipelineDescriptor::SetPrimitiveType(PrimitiveType type) { |
| primitive_type_ = type; |
| } |
| |
| PrimitiveType PipelineDescriptor::GetPrimitiveType() const { |
| return primitive_type_; |
| } |
| |
| void PipelineDescriptor::SetPolygonMode(PolygonMode mode) { |
| polygon_mode_ = mode; |
| } |
| |
| PolygonMode PipelineDescriptor::GetPolygonMode() const { |
| return polygon_mode_; |
| } |
| |
| } // namespace impeller |