7 #include "flutter/fml/closure.h"
8 #include "flutter/fml/logging.h"
9 #include "flutter/fml/make_copyable.h"
10 #include "fml/status.h"
29 MTLRenderPassAttachmentDescriptor* attachment) {
35 VALIDATION_LOG <<
"Resolve store action specified on attachment but no "
36 "resolve texture was specified.";
41 VALIDATION_LOG <<
"A resolve texture was specified even though the store "
42 "action doesn't require it.";
50 attachment.resolveTexture =
57 MTLRenderPassAttachmentDescriptor* attachment) {
75 MTLRenderPassColorAttachmentDescriptor* attachment) {
85 MTLRenderPassDepthAttachmentDescriptor* attachment) {
95 MTLRenderPassStencilAttachmentDescriptor* attachment) {
105 auto result = [MTLRenderPassDescriptor renderPassDescriptor];
110 result.colorAttachments[index]);
113 if (!configured_attachment) {
120 if (depth.has_value() &&
128 if (stencil.has_value() &&
137 RenderPassMTL::RenderPassMTL(std::shared_ptr<const Context> context,
138 const RenderTarget& target,
139 id<MTLCommandBuffer> buffer)
140 : RenderPass(
std::move(context), target),
143 if (!buffer_ || !
desc_ || !render_target_.IsValid()) {
146 encoder_ = [buffer_ renderCommandEncoderWithDescriptor:
desc_];
151 #ifdef IMPELLER_DEBUG
152 is_metal_trace_active_ =
153 [[MTLCaptureManager sharedCaptureManager] isCapturing];
155 pass_bindings_.SetEncoder(encoder_);
156 pass_bindings_.SetViewport(
162 RenderPassMTL::~RenderPassMTL() {
163 if (!did_finish_encoding_) {
164 [encoder_ endEncoding];
165 did_finish_encoding_ =
true;
169 bool RenderPassMTL::IsValid()
const {
173 void RenderPassMTL::OnSetLabel(std::string_view label) {
174 #ifdef IMPELLER_DEBUG
178 encoder_.label = @(std::string(label).c_str());
182 bool RenderPassMTL::OnEncodeCommands(
const Context& context)
const {
183 did_finish_encoding_ =
true;
184 [encoder_ endEncoding];
197 if (!device_buffer) {
201 auto buffer = DeviceBufferMTL::Cast(*device_buffer).GetMTLBuffer();
215 if (!sampler || !texture.
IsValid()) {
223 <<
"Texture at binding index " << bind_index
224 <<
" has a mip count > 1, but the mipmap has not been generated.";
230 TextureMTL::Cast(texture).GetMTLTexture()) &&
232 SamplerMTL::Cast(*sampler).GetMTLSamplerState());
236 void RenderPassMTL::SetPipeline(
PipelineRef pipeline) {
237 const PipelineDescriptor& pipeline_desc = pipeline->GetDescriptor();
238 primitive_type_ = pipeline_desc.GetPrimitiveType();
239 pass_bindings_.SetRenderPipelineState(
240 PipelineMTL::Cast(*pipeline).GetMTLRenderPipelineState());
241 pass_bindings_.SetDepthStencilState(
242 PipelineMTL::Cast(*pipeline).GetMTLDepthStencilState());
244 [encoder_ setFrontFacingWinding:pipeline_desc.GetWindingOrder() ==
245 WindingOrder::kClockwise
246 ? MTLWindingClockwise
247 : MTLWindingCounterClockwise];
248 [encoder_ setCullMode:
ToMTLCullMode(pipeline_desc.GetCullMode())];
250 pipeline_desc.GetPolygonMode())];
251 has_valid_pipeline_ =
true;
255 void RenderPassMTL::SetCommandLabel(std::string_view label) {
256 #ifdef IMPELLER_DEBUG
257 if (is_metal_trace_active_) {
259 std::string label_copy(label);
260 [encoder_ pushDebugGroup:@(label_copy.c_str())];
266 void RenderPassMTL::SetStencilReference(uint32_t
value) {
267 pass_bindings_.SetStencilRef(
value);
271 void RenderPassMTL::SetBaseVertex(uint64_t
value) {
272 base_vertex_ =
value;
276 void RenderPassMTL::SetViewport(Viewport viewport) {
277 pass_bindings_.SetViewport(viewport);
281 void RenderPassMTL::SetScissor(
IRect scissor) {
282 pass_bindings_.SetScissor(scissor);
286 void RenderPassMTL::SetElementCount(
size_t count) {
287 vertex_count_ = count;
291 void RenderPassMTL::SetInstanceCount(
size_t count) {
292 instance_count_ = count;
296 bool RenderPassMTL::SetVertexBuffer(BufferView vertex_buffers[],
297 size_t vertex_buffer_count) {
298 if (!ValidateVertexBuffers(vertex_buffers, vertex_buffer_count)) {
302 for (
size_t i = 0; i < vertex_buffer_count; i++) {
303 if (!
Bind(pass_bindings_, ShaderStage::kVertex,
304 VertexDescriptor::kReservedVertexBufferIndex - i,
305 vertex_buffers[i])) {
314 bool RenderPassMTL::SetIndexBuffer(BufferView index_buffer,
316 if (!ValidateIndexBuffer(index_buffer, index_type)) {
320 if (index_type != IndexType::kNone) {
322 index_buffer_ = std::move(index_buffer);
329 fml::Status RenderPassMTL::Draw() {
330 if (!has_valid_pipeline_) {
331 return fml::Status(fml::StatusCode::kCancelled,
"Invalid pipeline.");
334 if (!index_buffer_) {
335 if (instance_count_ != 1u) {
337 vertexStart:base_vertex_
338 vertexCount:vertex_count_
339 instanceCount:instance_count_
343 vertexStart:base_vertex_
344 vertexCount:vertex_count_];
347 id<MTLBuffer> mtl_index_buffer =
348 DeviceBufferMTL::Cast(*index_buffer_.GetBuffer()).GetMTLBuffer();
349 if (instance_count_ != 1u) {
351 indexCount:vertex_count_
352 indexType:index_type_
353 indexBuffer:mtl_index_buffer
354 indexBufferOffset:index_buffer_.GetRange().offset
355 instanceCount:instance_count_
356 baseVertex:base_vertex_
360 indexCount:vertex_count_
361 indexType:index_type_
362 indexBuffer:mtl_index_buffer
363 indexBufferOffset:index_buffer_.GetRange().offset];
367 #ifdef IMPELLER_DEBUG
369 [encoder_ popDebugGroup];
375 instance_count_ = 1u;
377 has_valid_pipeline_ =
false;
380 return fml::Status();
384 bool RenderPassMTL::BindResource(
ShaderStage stage,
386 const ShaderUniformSlot& slot,
387 const ShaderMetadata* metadata,
389 return Bind(pass_bindings_, stage, slot.ext_res_0, view);
393 bool RenderPassMTL::BindDynamicResource(
396 const ShaderUniformSlot& slot,
397 std::unique_ptr<ShaderMetadata> metadata,
399 return Bind(pass_bindings_, stage, slot.ext_res_0, view);
403 bool RenderPassMTL::BindResource(
ShaderStage stage,
405 const SampledImageSlot& slot,
406 const ShaderMetadata* metadata,
407 std::shared_ptr<const Texture> texture,
408 raw_ptr<const Sampler> sampler) {
412 return Bind(pass_bindings_, stage, slot.texture_index, sampler, *texture);
415 bool RenderPassMTL::BindDynamicResource(
418 const SampledImageSlot& slot,
419 std::unique_ptr<ShaderMetadata> metadata,
420 std::shared_ptr<const Texture> texture,
421 raw_ptr<const Sampler> sampler) {
425 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)