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() &&
137RenderPassMTL::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_];
152 is_metal_trace_active_ =
153 [[MTLCaptureManager sharedCaptureManager] isCapturing];
155 pass_bindings_.SetEncoder(encoder_);
156 pass_bindings_.SetViewport(
162RenderPassMTL::~RenderPassMTL() {
163 if (!did_finish_encoding_) {
164 [encoder_ endEncoding];
165 did_finish_encoding_ =
true;
169bool RenderPassMTL::IsValid()
const {
173void RenderPassMTL::OnSetLabel(std::string_view label) {
178 encoder_.label = @(std::string(label).c_str());
182bool RenderPassMTL::OnEncodeCommands(
const Context& context)
const {
183 did_finish_encoding_ =
true;
184 [encoder_ endEncoding];
192 if (!
view.GetBuffer()) {
197 if (!device_buffer) {
201 auto buffer = DeviceBufferMTL::Cast(*device_buffer).GetMTLBuffer();
207 return pass.
SetBuffer(stage, bind_index,
view.GetRange().offset, buffer);
215 if (!sampler || !
texture.IsValid()) {
219 if (
texture.NeedsMipmapGeneration()) {
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());
236void 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())];
249 [encoder_ setTriangleFillMode:ToMTLTriangleFillMode(
250 pipeline_desc.GetPolygonMode())];
251 has_valid_pipeline_ =
true;
255void RenderPassMTL::SetCommandLabel(std::string_view label) {
257 if (is_metal_trace_active_) {
259 std::string label_copy(label);
260 [encoder_ pushDebugGroup:@(label_copy.c_str())];
266void RenderPassMTL::SetStencilReference(uint32_t value) {
267 pass_bindings_.SetStencilRef(value);
271void RenderPassMTL::SetBaseVertex(uint64_t value) {
272 base_vertex_ =
value;
276void RenderPassMTL::SetViewport(Viewport viewport) {
277 pass_bindings_.SetViewport(viewport);
281void RenderPassMTL::SetScissor(IRect32 scissor) {
282 pass_bindings_.SetScissor(scissor);
286void RenderPassMTL::SetElementCount(
size_t count) {
287 vertex_count_ = count;
291void RenderPassMTL::SetInstanceCount(
size_t count) {
292 instance_count_ = count;
296bool 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])) {
314bool RenderPassMTL::SetIndexBuffer(BufferView index_buffer,
315 IndexType index_type) {
316 if (!ValidateIndexBuffer(index_buffer, index_type)) {
320 if (index_type != IndexType::kNone) {
322 index_buffer_ = std::move(index_buffer);
330 if (!has_valid_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];
369 [encoder_ popDebugGroup];
375 instance_count_ = 1u;
377 has_valid_pipeline_ =
false;
384bool RenderPassMTL::BindResource(ShaderStage stage,
386 const ShaderUniformSlot& slot,
387 const ShaderMetadata* metadata,
389 return Bind(pass_bindings_, stage, slot.ext_res_0,
view);
393bool RenderPassMTL::BindDynamicResource(
396 const ShaderUniformSlot& slot,
397 std::unique_ptr<ShaderMetadata> metadata,
399 return Bind(pass_bindings_, stage, slot.ext_res_0,
view);
403bool 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);
415bool 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
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)
constexpr MTLLoadAction ToMTLLoadAction(LoadAction action)
@ kStoreAndMultisampleResolve
static MTLRenderPassDescriptor * ToMTLRenderPassDescriptor(const RenderTarget &desc)
static bool ConfigureResolveTextureAttachment(const Attachment &desc, MTLRenderPassAttachmentDescriptor *attachment)
constexpr MTLPrimitiveType ToMTLPrimitiveType(PrimitiveType type)
static bool ConfigureStencilAttachment(const StencilAttachment &desc, MTLRenderPassStencilAttachmentDescriptor *attachment)
static bool Bind(PassBindingsCacheMTL &pass, ShaderStage stage, size_t bind_index, const BufferView &view)
constexpr MTLIndexType ToMTLIndexType(IndexType type)
constexpr MTLStoreAction ToMTLStoreAction(StoreAction action)
MTLClearColor ToMTLClearColor(const Color &color)
static bool ConfigureAttachment(const Attachment &desc, MTLRenderPassAttachmentDescriptor *attachment)
std::shared_ptr< Texture > resolve_texture
std::shared_ptr< Texture > texture
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.
static constexpr TRect MakeSize(const TSize< U > &size)