2 * Copyright 2021 Google Inc.
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
8 #ifndef GrMtlRenderCommandEncoder_DEFINED
9 #define GrMtlRenderCommandEncoder_DEFINED
13 #include "include/private/SkColorData.h"
14 #include "src/gpu/ganesh/GrSamplerState.h"
15 #include "src/gpu/ganesh/mtl/GrMtlSampler.h"
16 #include "src/gpu/ganesh/mtl/GrMtlUniformHandler.h"
17 #include "src/gpu/ganesh/mtl/GrMtlUtil.h"
21 #import <Metal/Metal.h>
26 * Wraps a MTLRenderCommandEncoder object and associated tracked state
28 class GrMtlRenderCommandEncoder {
30 static std::unique_ptr<GrMtlRenderCommandEncoder> Make(id<MTLRenderCommandEncoder> encoder) {
31 return std::unique_ptr<GrMtlRenderCommandEncoder>(new GrMtlRenderCommandEncoder(encoder));
34 void setLabel(NSString* label) {
35 [fCommandEncoder setLabel:label];
38 void pushDebugGroup(NSString* string) {
39 [fCommandEncoder pushDebugGroup:string];
41 void popDebugGroup() {
42 [fCommandEncoder popDebugGroup];
44 void insertDebugSignpost(NSString* string) {
45 [fCommandEncoder insertDebugSignpost:string];
48 void setRenderPipelineState(id<MTLRenderPipelineState> pso) {
49 if (fCurrentRenderPipelineState != pso) {
50 [fCommandEncoder setRenderPipelineState:pso];
51 fCurrentRenderPipelineState = pso;
55 void setTriangleFillMode(MTLTriangleFillMode fillMode) {
56 if (fCurrentTriangleFillMode != fillMode) {
57 [fCommandEncoder setTriangleFillMode:fillMode];
58 fCurrentTriangleFillMode = fillMode;
62 void setFrontFacingWinding(MTLWinding winding) {
63 [fCommandEncoder setFrontFacingWinding:winding];
66 void setViewport(const MTLViewport& viewport) {
67 [fCommandEncoder setViewport:viewport];
70 void setVertexBuffer(id<MTLBuffer> buffer, NSUInteger offset, NSUInteger index) {
71 if (@available(macOS 10.11, iOS 8.3, *)) {
72 if (fCurrentVertexBuffer[index] == buffer) {
73 this->setVertexBufferOffset(offset, index);
77 if (fCurrentVertexBuffer[index] != buffer || fCurrentVertexOffset[index] != offset) {
78 [fCommandEncoder setVertexBuffer:buffer
81 fCurrentVertexBuffer[index] = buffer;
82 fCurrentVertexOffset[index] = offset;
85 void setVertexBufferOffset(NSUInteger offset, NSUInteger index)
86 SK_API_AVAILABLE(macos(10.11), ios(8.3)) {
87 if (fCurrentVertexOffset[index] != offset) {
88 [fCommandEncoder setVertexBufferOffset:offset
90 fCurrentVertexOffset[index] = offset;
94 void setFragmentBuffer(id<MTLBuffer> buffer, NSUInteger offset, NSUInteger index) {
95 if (@available(macOS 10.11, iOS 8.3, *)) {
96 if (fCurrentFragmentBuffer[index] == buffer) {
97 this->setFragmentBufferOffset(offset, index);
101 if (fCurrentFragmentBuffer[index] != buffer || fCurrentFragmentOffset[index] != offset) {
102 [fCommandEncoder setFragmentBuffer:buffer
105 fCurrentFragmentBuffer[index] = buffer;
106 fCurrentFragmentOffset[index] = offset;
109 void setFragmentBufferOffset(NSUInteger offset, NSUInteger index)
110 SK_API_AVAILABLE(macos(10.11), ios(8.3)) {
111 if (fCurrentFragmentOffset[index] != offset) {
112 [fCommandEncoder setFragmentBufferOffset:offset
114 fCurrentFragmentOffset[index] = offset;
118 void setVertexBytes(const void* bytes, NSUInteger length, NSUInteger index)
119 SK_API_AVAILABLE(macos(10.11), ios(8.3)) {
120 [fCommandEncoder setVertexBytes:bytes
124 void setFragmentBytes(const void* bytes, NSUInteger length, NSUInteger index)
125 SK_API_AVAILABLE(macos(10.11), ios(8.3)) {
126 [fCommandEncoder setFragmentBytes:bytes
131 void setFragmentTexture(id<MTLTexture> texture, NSUInteger index) {
132 SkASSERT(index < kMaxTextures);
133 if (fCurrentTexture[index] != texture) {
134 [fCommandEncoder setFragmentTexture:texture
136 fCurrentTexture[index] = texture;
139 void setFragmentSamplerState(GrMtlSampler* sampler, NSUInteger index) {
140 SkASSERT(index < kMaxSamplers);
141 if (fCurrentSampler[index] != sampler) {
142 [fCommandEncoder setFragmentSamplerState: sampler->mtlSampler()
144 fCurrentSampler[index] = sampler;
148 void setBlendColor(SkPMColor4f blendConst) {
149 [fCommandEncoder setBlendColorRed: blendConst.fR
152 alpha: blendConst.fA];
155 void setStencilFrontBackReferenceValues(uint32_t frontReferenceValue,
156 uint32_t backReferenceValue)
157 SK_API_AVAILABLE(macos(10.11), ios(9.0)) {
159 setStencilFrontReferenceValue:frontReferenceValue
160 backReferenceValue:backReferenceValue];
162 void setStencilReferenceValue(uint32_t referenceValue) {
163 [fCommandEncoder setStencilReferenceValue:referenceValue];
165 void setDepthStencilState(id<MTLDepthStencilState> depthStencilState) {
166 if (depthStencilState != fCurrentDepthStencilState) {
167 [fCommandEncoder setDepthStencilState:depthStencilState];
168 fCurrentDepthStencilState = depthStencilState;
172 void setScissorRect(const MTLScissorRect& scissorRect) {
173 if (fCurrentScissorRect.x != scissorRect.x ||
174 fCurrentScissorRect.y != scissorRect.y ||
175 fCurrentScissorRect.width != scissorRect.width ||
176 fCurrentScissorRect.height != scissorRect.height) {
177 [fCommandEncoder setScissorRect:scissorRect];
178 fCurrentScissorRect = scissorRect;
182 void drawPrimitives(MTLPrimitiveType primitiveType, NSUInteger vertexStart,
183 NSUInteger vertexCount) {
184 [fCommandEncoder drawPrimitives:primitiveType
185 vertexStart:vertexStart
186 vertexCount:vertexCount];
188 void drawPrimitives(MTLPrimitiveType primitiveType, NSUInteger vertexStart,
189 NSUInteger vertexCount, NSUInteger instanceCount,
190 NSUInteger baseInstance) SK_API_AVAILABLE(macos(10.11), ios(9.0)) {
191 [fCommandEncoder drawPrimitives:primitiveType
192 vertexStart:vertexStart
193 vertexCount:vertexCount
194 instanceCount:instanceCount
195 baseInstance:baseInstance];
197 void drawPrimitives(MTLPrimitiveType primitiveType, id<MTLBuffer> indirectBuffer,
198 NSUInteger indirectBufferOffset) SK_API_AVAILABLE(macos(10.11), ios(9.0)) {
199 [fCommandEncoder drawPrimitives:primitiveType
200 indirectBuffer:indirectBuffer
201 indirectBufferOffset:indirectBufferOffset];
204 void drawIndexedPrimitives(MTLPrimitiveType primitiveType, NSUInteger indexCount,
205 MTLIndexType indexType, id<MTLBuffer> indexBuffer,
206 NSUInteger indexBufferOffset) {
207 [fCommandEncoder drawIndexedPrimitives:primitiveType
208 indexCount:indexCount
210 indexBuffer:indexBuffer
211 indexBufferOffset:indexBufferOffset];
213 void drawIndexedPrimitives(MTLPrimitiveType primitiveType, NSUInteger indexCount,
214 MTLIndexType indexType, id<MTLBuffer> indexBuffer,
215 NSUInteger indexBufferOffset,
216 NSUInteger instanceCount,
217 NSInteger baseVertex,
218 NSUInteger baseInstance) SK_API_AVAILABLE(macos(10.11), ios(9.0)) {
219 [fCommandEncoder drawIndexedPrimitives:primitiveType
220 indexCount:indexCount
222 indexBuffer:indexBuffer
223 indexBufferOffset:indexBufferOffset
224 instanceCount:instanceCount
225 baseVertex:baseVertex
226 baseInstance:baseInstance];
228 void drawIndexedPrimitives(MTLPrimitiveType primitiveType,
229 MTLIndexType indexType, id<MTLBuffer> indexBuffer,
230 NSUInteger indexBufferOffset, id<MTLBuffer> indirectBuffer,
231 NSUInteger indirectBufferOffset)
232 SK_API_AVAILABLE(macos(10.11), ios(9.0)) {
233 [fCommandEncoder drawIndexedPrimitives:primitiveType
235 indexBuffer:indexBuffer
236 indexBufferOffset:indexBufferOffset
237 indirectBuffer:indirectBuffer
238 indirectBufferOffset:indirectBufferOffset];
242 [fCommandEncoder endEncoding];
246 GrMtlRenderCommandEncoder(id<MTLRenderCommandEncoder> encoder)
247 : fCommandEncoder(encoder) {}
249 id<MTLRenderCommandEncoder> fCommandEncoder = nil;
251 // As of 2022-03-09 All GPU families have the same value at:
252 // https://developer.apple.com/metal/Metal-Feature-Set-Tables.pdf
253 static const int kMaxSamplers = 16;
254 // This is a self-imposed limit and is less than any GPU family's value at
255 // https://developer.apple.com/metal/Metal-Feature-Set-Tables.pdf
256 // Our implementation uses a 1:1 correspondence between textures and samplers.
257 static const int kMaxTextures = kMaxSamplers;
259 __weak id<MTLRenderPipelineState> fCurrentRenderPipelineState = nil;
260 __weak id<MTLDepthStencilState> fCurrentDepthStencilState = nil;
261 __weak id<MTLBuffer> fCurrentVertexBuffer[2 + GrMtlUniformHandler::kUniformBindingCount];
262 NSUInteger fCurrentVertexOffset[2 + GrMtlUniformHandler::kUniformBindingCount];
263 __weak id<MTLBuffer> fCurrentFragmentBuffer[GrMtlUniformHandler::kUniformBindingCount];
264 NSUInteger fCurrentFragmentOffset[2 + GrMtlUniformHandler::kUniformBindingCount];
265 __weak id<MTLTexture> fCurrentTexture[kMaxTextures];
266 GrMtlSampler* fCurrentSampler[kMaxSamplers] = {};
267 MTLScissorRect fCurrentScissorRect = { 0, 0, 0, 0 };
268 MTLTriangleFillMode fCurrentTriangleFillMode = (MTLTriangleFillMode)-1;