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) {
70 attachment.slice = desc.
slice;
81 MTLRenderPassColorAttachmentDescriptor* attachment) {
91 MTLRenderPassDepthAttachmentDescriptor* attachment) {
101 MTLRenderPassStencilAttachmentDescriptor* attachment) {
111 auto result = [MTLRenderPassDescriptor renderPassDescriptor];
116 result.colorAttachments[index]);
119 if (!configured_attachment) {
126 if (depth.has_value() &&
134 if (stencil.has_value() &&
143 RenderPassMTL::RenderPassMTL(std::shared_ptr<const Context>
context,
144 const RenderTarget& target,
145 id<MTLCommandBuffer> buffer)
149 if (!buffer_ || !
desc_ || !render_target_.IsValid()) {
152 encoder_ = [buffer_ renderCommandEncoderWithDescriptor:
desc_];
157 #ifdef IMPELLER_DEBUG
158 is_metal_trace_active_ =
159 [[MTLCaptureManager sharedCaptureManager] isCapturing];
161 pass_bindings_.SetEncoder(encoder_);
162 pass_bindings_.SetViewport(
168 RenderPassMTL::~RenderPassMTL() {
169 if (!did_finish_encoding_) {
170 [encoder_ endEncoding];
171 did_finish_encoding_ =
true;
175 bool RenderPassMTL::IsValid()
const {
179 void RenderPassMTL::OnSetLabel(std::string_view label) {
180 #ifdef IMPELLER_DEBUG
184 encoder_.label = @(std::string(label).c_str());
188 bool RenderPassMTL::OnEncodeCommands(
const Context&
context)
const {
189 did_finish_encoding_ =
true;
190 [encoder_ endEncoding];
203 if (!device_buffer) {
207 auto buffer = DeviceBufferMTL::Cast(*device_buffer).GetMTLBuffer();
221 if (!sampler || !texture.
IsValid()) {
226 TextureMTL::Cast(texture).GetMTLTexture()) &&
228 SamplerMTL::Cast(*sampler).GetMTLSamplerState());
233 const PipelineDescriptor& pipeline_desc =
pipeline->GetDescriptor();
234 context_->GetPipelineLibrary()->LogPipelineUsage(pipeline_desc);
235 primitive_type_ = pipeline_desc.GetPrimitiveType();
236 pass_bindings_.SetRenderPipelineState(
237 PipelineMTL::Cast(*pipeline).GetMTLRenderPipelineState());
238 pass_bindings_.SetDepthStencilState(
239 PipelineMTL::Cast(*pipeline).GetMTLDepthStencilState());
241 [encoder_ setFrontFacingWinding:pipeline_desc.GetWindingOrder() ==
242 WindingOrder::kClockwise
243 ? MTLWindingClockwise
244 : MTLWindingCounterClockwise];
245 [encoder_ setCullMode:
ToMTLCullMode(pipeline_desc.GetCullMode())];
247 pipeline_desc.GetPolygonMode())];
248 has_valid_pipeline_ =
true;
252 void RenderPassMTL::SetCommandLabel(std::string_view label) {
253 #ifdef IMPELLER_DEBUG
254 if (is_metal_trace_active_) {
256 std::string label_copy(label);
257 [encoder_ pushDebugGroup:@(label_copy.c_str())];
263 void RenderPassMTL::SetStencilReference(uint32_t
value) {
264 pass_bindings_.SetStencilRef(
value);
268 void RenderPassMTL::SetBaseVertex(uint64_t
value) {
269 base_vertex_ =
value;
273 void RenderPassMTL::SetViewport(Viewport viewport) {
274 pass_bindings_.SetViewport(viewport);
278 void RenderPassMTL::SetScissor(
IRect32 scissor) {
279 pass_bindings_.SetScissor(scissor);
283 void RenderPassMTL::SetElementCount(
size_t count) {
284 vertex_count_ = count;
288 void RenderPassMTL::SetInstanceCount(
size_t count) {
289 instance_count_ = count;
293 bool RenderPassMTL::SetVertexBuffer(BufferView vertex_buffers[],
294 size_t vertex_buffer_count) {
295 if (!ValidateVertexBuffers(vertex_buffers, vertex_buffer_count)) {
299 for (
size_t i = 0; i < vertex_buffer_count; i++) {
300 if (!
Bind(pass_bindings_, ShaderStage::kVertex,
301 VertexDescriptor::kReservedVertexBufferIndex - i,
302 vertex_buffers[i])) {
311 bool RenderPassMTL::SetIndexBuffer(BufferView index_buffer,
313 if (!ValidateIndexBuffer(index_buffer, index_type)) {
317 if (index_type != IndexType::kNone) {
319 index_buffer_ = std::move(index_buffer);
326 fml::Status RenderPassMTL::Draw() {
327 if (!has_valid_pipeline_) {
328 return fml::Status(fml::StatusCode::kCancelled,
"Invalid pipeline.");
331 if (!index_buffer_) {
332 if (instance_count_ != 1u) {
334 vertexStart:base_vertex_
335 vertexCount:vertex_count_
336 instanceCount:instance_count_
340 vertexStart:base_vertex_
341 vertexCount:vertex_count_];
344 id<MTLBuffer> mtl_index_buffer =
345 DeviceBufferMTL::Cast(*index_buffer_.GetBuffer()).GetMTLBuffer();
346 if (instance_count_ != 1u) {
348 indexCount:vertex_count_
349 indexType:index_type_
350 indexBuffer:mtl_index_buffer
351 indexBufferOffset:index_buffer_.GetRange().offset
352 instanceCount:instance_count_
353 baseVertex:base_vertex_
357 indexCount:vertex_count_
358 indexType:index_type_
359 indexBuffer:mtl_index_buffer
360 indexBufferOffset:index_buffer_.GetRange().offset];
364 #ifdef IMPELLER_DEBUG
366 [encoder_ popDebugGroup];
372 instance_count_ = 1u;
374 has_valid_pipeline_ =
false;
377 return fml::Status();
381 bool RenderPassMTL::BindResource(
ShaderStage stage,
383 const ShaderUniformSlot& slot,
384 const ShaderMetadata* metadata,
386 return Bind(pass_bindings_, stage, slot.ext_res_0, view);
390 bool RenderPassMTL::BindDynamicResource(
393 const ShaderUniformSlot& slot,
394 std::unique_ptr<ShaderMetadata> metadata,
396 return Bind(pass_bindings_, stage, slot.ext_res_0, view);
400 bool RenderPassMTL::BindResource(
ShaderStage stage,
402 const SampledImageSlot& slot,
403 const ShaderMetadata* metadata,
404 std::shared_ptr<const Texture> texture,
405 raw_ptr<const Sampler> sampler) {
409 return Bind(pass_bindings_, stage, slot.texture_index, sampler, *texture);
412 bool RenderPassMTL::BindDynamicResource(
415 const SampledImageSlot& slot,
416 std::unique_ptr<ShaderMetadata> metadata,
417 std::shared_ptr<const Texture> texture,
418 raw_ptr<const Sampler> sampler) {
422 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
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< ContextGLES > context
std::shared_ptr< PipelineGLES > pipeline
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)