7 #include "flutter/fml/closure.h"
8 #include "flutter/fml/logging.h"
9 #include "flutter/fml/make_copyable.h"
10 #include "fml/status.h"
31 MTLRenderPassAttachmentDescriptor* attachment) {
37 VALIDATION_LOG <<
"Resolve store action specified on attachment but no "
38 "resolve texture was specified.";
43 VALIDATION_LOG <<
"A resolve texture was specified even though the store "
44 "action doesn't require it.";
52 attachment.resolveTexture =
59 MTLRenderPassAttachmentDescriptor* attachment) {
77 MTLRenderPassColorAttachmentDescriptor* attachment) {
87 MTLRenderPassDepthAttachmentDescriptor* attachment) {
97 MTLRenderPassStencilAttachmentDescriptor* attachment) {
107 auto result = [MTLRenderPassDescriptor renderPassDescriptor];
112 result.colorAttachments[index]);
115 if (!configured_attachment) {
122 if (depth.has_value() &&
130 if (stencil.has_value() &&
139 RenderPassMTL::RenderPassMTL(std::shared_ptr<const Context> context,
140 const RenderTarget& target,
141 id<MTLCommandBuffer> buffer)
142 : RenderPass(
std::move(context), target),
145 if (!buffer_ || !
desc_ || !render_target_.IsValid()) {
148 encoder_ = [buffer_ renderCommandEncoderWithDescriptor:
desc_];
153 #ifdef IMPELLER_DEBUG
154 is_metal_trace_active_ =
155 [[MTLCaptureManager sharedCaptureManager] isCapturing];
157 pass_bindings_.SetEncoder(encoder_);
158 pass_bindings_.SetViewport(
164 RenderPassMTL::~RenderPassMTL() {
165 if (!did_finish_encoding_) {
166 [encoder_ endEncoding];
167 did_finish_encoding_ =
true;
171 bool RenderPassMTL::IsValid()
const {
175 void RenderPassMTL::OnSetLabel(std::string_view label) {
176 #ifdef IMPELLER_DEBUG
180 encoder_.label = @(std::string(label).c_str());
184 bool RenderPassMTL::OnEncodeCommands(
const Context& context)
const {
185 did_finish_encoding_ =
true;
186 [encoder_ endEncoding];
199 if (!device_buffer) {
203 auto buffer = DeviceBufferMTL::Cast(*device_buffer).GetMTLBuffer();
217 if (!sampler || !texture.
IsValid()) {
225 <<
"Texture at binding index " << bind_index
226 <<
" has a mip count > 1, but the mipmap has not been generated.";
232 TextureMTL::Cast(texture).GetMTLTexture()) &&
234 SamplerMTL::Cast(*sampler).GetMTLSamplerState());
238 void RenderPassMTL::SetPipeline(
PipelineRef pipeline) {
239 const PipelineDescriptor& pipeline_desc = pipeline->GetDescriptor();
240 context_->GetPipelineLibrary()->LogPipelineUsage(pipeline_desc);
241 primitive_type_ = pipeline_desc.GetPrimitiveType();
242 pass_bindings_.SetRenderPipelineState(
243 PipelineMTL::Cast(*pipeline).GetMTLRenderPipelineState());
244 pass_bindings_.SetDepthStencilState(
245 PipelineMTL::Cast(*pipeline).GetMTLDepthStencilState());
247 [encoder_ setFrontFacingWinding:pipeline_desc.GetWindingOrder() ==
248 WindingOrder::kClockwise
249 ? MTLWindingClockwise
250 : MTLWindingCounterClockwise];
251 [encoder_ setCullMode:
ToMTLCullMode(pipeline_desc.GetCullMode())];
253 pipeline_desc.GetPolygonMode())];
254 has_valid_pipeline_ =
true;
258 void RenderPassMTL::SetCommandLabel(std::string_view label) {
259 #ifdef IMPELLER_DEBUG
260 if (is_metal_trace_active_) {
262 std::string label_copy(label);
263 [encoder_ pushDebugGroup:@(label_copy.c_str())];
269 void RenderPassMTL::SetStencilReference(uint32_t
value) {
270 pass_bindings_.SetStencilRef(
value);
274 void RenderPassMTL::SetBaseVertex(uint64_t
value) {
275 base_vertex_ =
value;
279 void RenderPassMTL::SetViewport(Viewport viewport) {
280 pass_bindings_.SetViewport(viewport);
284 void RenderPassMTL::SetScissor(
IRect32 scissor) {
285 pass_bindings_.SetScissor(scissor);
289 void RenderPassMTL::SetElementCount(
size_t count) {
290 vertex_count_ = count;
294 void RenderPassMTL::SetInstanceCount(
size_t count) {
295 instance_count_ = count;
299 bool RenderPassMTL::SetVertexBuffer(BufferView vertex_buffers[],
300 size_t vertex_buffer_count) {
301 if (!ValidateVertexBuffers(vertex_buffers, vertex_buffer_count)) {
305 for (
size_t i = 0; i < vertex_buffer_count; i++) {
306 if (!
Bind(pass_bindings_, ShaderStage::kVertex,
307 VertexDescriptor::kReservedVertexBufferIndex - i,
308 vertex_buffers[i])) {
317 bool RenderPassMTL::SetIndexBuffer(BufferView index_buffer,
319 if (!ValidateIndexBuffer(index_buffer, index_type)) {
323 if (index_type != IndexType::kNone) {
325 index_buffer_ = std::move(index_buffer);
332 fml::Status RenderPassMTL::Draw() {
333 if (!has_valid_pipeline_) {
334 return fml::Status(fml::StatusCode::kCancelled,
"Invalid pipeline.");
337 if (!index_buffer_) {
338 if (instance_count_ != 1u) {
340 vertexStart:base_vertex_
341 vertexCount:vertex_count_
342 instanceCount:instance_count_
346 vertexStart:base_vertex_
347 vertexCount:vertex_count_];
350 id<MTLBuffer> mtl_index_buffer =
351 DeviceBufferMTL::Cast(*index_buffer_.GetBuffer()).GetMTLBuffer();
352 if (instance_count_ != 1u) {
354 indexCount:vertex_count_
355 indexType:index_type_
356 indexBuffer:mtl_index_buffer
357 indexBufferOffset:index_buffer_.GetRange().offset
358 instanceCount:instance_count_
359 baseVertex:base_vertex_
363 indexCount:vertex_count_
364 indexType:index_type_
365 indexBuffer:mtl_index_buffer
366 indexBufferOffset:index_buffer_.GetRange().offset];
370 #ifdef IMPELLER_DEBUG
372 [encoder_ popDebugGroup];
378 instance_count_ = 1u;
380 has_valid_pipeline_ =
false;
383 return fml::Status();
387 bool RenderPassMTL::BindResource(
ShaderStage stage,
389 const ShaderUniformSlot& slot,
390 const ShaderMetadata* metadata,
392 return Bind(pass_bindings_, stage, slot.ext_res_0, view);
396 bool RenderPassMTL::BindDynamicResource(
399 const ShaderUniformSlot& slot,
400 std::unique_ptr<ShaderMetadata> metadata,
402 return Bind(pass_bindings_, stage, slot.ext_res_0, view);
406 bool RenderPassMTL::BindResource(
ShaderStage stage,
408 const SampledImageSlot& slot,
409 const ShaderMetadata* metadata,
410 std::shared_ptr<const Texture> texture,
411 raw_ptr<const Sampler> sampler) {
415 return Bind(pass_bindings_, stage, slot.texture_index, sampler, *texture);
418 bool RenderPassMTL::BindDynamicResource(
421 const SampledImageSlot& slot,
422 std::unique_ptr<ShaderMetadata> metadata,
423 std::shared_ptr<const Texture> texture,
424 raw_ptr<const Sampler> sampler) {
428 return Bind(pass_bindings_, stage, slot.texture_index, sampler, *texture);
static TextureMTL & Cast(Texture &base)
bool IterateAllColorAttachments(const std::function< bool(size_t index, const ColorAttachment &attachment)> &iterator) const
const std::optional< DepthAttachment > & GetDepthAttachment() const
const std::optional< StencilAttachment > & GetStencilAttachment() const
bool NeedsMipmapGeneration() const
virtual bool IsValid() const =0
id< MTLTexture > GetMTLTexture() const
A wrapper around a raw ptr that adds additional unopt mode only checks.
std::optional< PipelineDescriptor > desc_
static bool ConfigureColorAttachment(const ColorAttachment &desc, MTLRenderPassColorAttachmentDescriptor *attachment)
static bool ConfigureDepthAttachment(const DepthAttachment &desc, MTLRenderPassDepthAttachmentDescriptor *attachment)
raw_ptr< Pipeline< PipelineDescriptor > > PipelineRef
A raw ptr to a pipeline object.
static MTLRenderPassDescriptor * ToMTLRenderPassDescriptor(const RenderTarget &desc)
constexpr MTLLoadAction ToMTLLoadAction(LoadAction action)
static bool Bind(PassBindingsCacheMTL &pass, ShaderStage stage, size_t bind_index, raw_ptr< const Sampler > sampler, const Texture &texture)
@ kStoreAndMultisampleResolve
static bool ConfigureResolveTextureAttachment(const Attachment &desc, MTLRenderPassAttachmentDescriptor *attachment)
constexpr MTLPrimitiveType ToMTLPrimitiveType(PrimitiveType type)
static bool ConfigureStencilAttachment(const StencilAttachment &desc, MTLRenderPassStencilAttachmentDescriptor *attachment)
constexpr MTLTriangleFillMode ToMTLTriangleFillMode(PolygonMode mode)
constexpr MTLIndexType ToMTLIndexType(IndexType type)
constexpr MTLStoreAction ToMTLStoreAction(StoreAction action)
MTLClearColor ToMTLClearColor(const Color &color)
static bool ConfigureAttachment(const Attachment &desc, MTLRenderPassAttachmentDescriptor *attachment)
constexpr MTLCullMode ToMTLCullMode(CullMode mode)
std::shared_ptr< Texture > resolve_texture
std::shared_ptr< Texture > texture
const DeviceBuffer * GetBuffer() const
Ensures that bindings on the pass are not redundantly set or updated. Avoids making the driver do add...
bool SetSampler(ShaderStage stage, uint64_t index, id< MTLSamplerState > sampler)
Set the sampler for the given stage and binding.
bool SetBuffer(ShaderStage stage, uint64_t index, uint64_t offset, id< MTLBuffer > buffer)
Set the buffer for the given shader stage, binding, and offset.
bool SetTexture(ShaderStage stage, uint64_t index, id< MTLTexture > texture)
Set the texture for the given stage and binding.
constexpr static TRect MakeSize(const TSize< U > &size)