xref: /aosp_15_r20/external/skia/src/gpu/ganesh/mtl/GrMtlRenderCommandEncoder.h (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1 /*
2  * Copyright 2021 Google Inc.
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 #ifndef GrMtlRenderCommandEncoder_DEFINED
9 #define GrMtlRenderCommandEncoder_DEFINED
10 
11 #include <memory>
12 
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"
18 
19 class GrMtlSampler;
20 
21 #import <Metal/Metal.h>
22 
23 GR_NORETAIN_BEGIN
24 
25 /**
26  * Wraps a MTLRenderCommandEncoder object and associated tracked state
27  */
28 class GrMtlRenderCommandEncoder {
29 public:
Make(id<MTLRenderCommandEncoder> encoder)30     static std::unique_ptr<GrMtlRenderCommandEncoder> Make(id<MTLRenderCommandEncoder> encoder) {
31         return std::unique_ptr<GrMtlRenderCommandEncoder>(new GrMtlRenderCommandEncoder(encoder));
32     }
33 
setLabel(NSString * label)34     void setLabel(NSString* label) {
35         [fCommandEncoder setLabel:label];
36     }
37 
pushDebugGroup(NSString * string)38     void pushDebugGroup(NSString* string) {
39         [fCommandEncoder pushDebugGroup:string];
40     }
popDebugGroup()41     void popDebugGroup() {
42         [fCommandEncoder popDebugGroup];
43     }
insertDebugSignpost(NSString * string)44     void insertDebugSignpost(NSString* string) {
45         [fCommandEncoder insertDebugSignpost:string];
46     }
47 
setRenderPipelineState(id<MTLRenderPipelineState> pso)48     void setRenderPipelineState(id<MTLRenderPipelineState> pso) {
49         if (fCurrentRenderPipelineState != pso) {
50             [fCommandEncoder setRenderPipelineState:pso];
51             fCurrentRenderPipelineState = pso;
52         }
53     }
54 
setTriangleFillMode(MTLTriangleFillMode fillMode)55     void setTriangleFillMode(MTLTriangleFillMode fillMode) {
56         if (fCurrentTriangleFillMode != fillMode) {
57             [fCommandEncoder setTriangleFillMode:fillMode];
58             fCurrentTriangleFillMode = fillMode;
59         }
60     }
61 
setFrontFacingWinding(MTLWinding winding)62     void setFrontFacingWinding(MTLWinding winding) {
63         [fCommandEncoder setFrontFacingWinding:winding];
64     }
65 
setViewport(const MTLViewport & viewport)66     void setViewport(const MTLViewport& viewport) {
67         [fCommandEncoder setViewport:viewport];
68     }
69 
setVertexBuffer(id<MTLBuffer> buffer,NSUInteger offset,NSUInteger index)70     void setVertexBuffer(id<MTLBuffer> buffer, NSUInteger offset, NSUInteger index) {
71         if (@available(macOS 10.11, iOS 8.3, tvOS 9.0, *)) {
72             if (fCurrentVertexBuffer[index] == buffer) {
73                 this->setVertexBufferOffset(offset, index);
74                 return;
75             }
76         }
77         if (fCurrentVertexBuffer[index] != buffer || fCurrentVertexOffset[index] != offset) {
78             [fCommandEncoder setVertexBuffer:buffer
79                                       offset:offset
80                                      atIndex:index];
81             fCurrentVertexBuffer[index] = buffer;
82             fCurrentVertexOffset[index] = offset;
83         }
84     }
setVertexBufferOffset(NSUInteger offset,NSUInteger index)85     void setVertexBufferOffset(NSUInteger offset, NSUInteger index)
86             SK_API_AVAILABLE(macos(10.11), ios(8.3), tvos(9.0)) {
87         if (fCurrentVertexOffset[index] != offset) {
88             [fCommandEncoder setVertexBufferOffset:offset
89                                            atIndex:index];
90             fCurrentVertexOffset[index] = offset;
91         }
92     }
93 
setFragmentBuffer(id<MTLBuffer> buffer,NSUInteger offset,NSUInteger index)94     void setFragmentBuffer(id<MTLBuffer> buffer, NSUInteger offset, NSUInteger index) {
95         if (@available(macOS 10.11, iOS 8.3, tvOS 9.0, *)) {
96             if (fCurrentFragmentBuffer[index] == buffer) {
97                 this->setFragmentBufferOffset(offset, index);
98                 return;
99             }
100         }
101         if (fCurrentFragmentBuffer[index] != buffer || fCurrentFragmentOffset[index] != offset) {
102             [fCommandEncoder setFragmentBuffer:buffer
103                                         offset:offset
104                                        atIndex:index];
105             fCurrentFragmentBuffer[index] = buffer;
106             fCurrentFragmentOffset[index] = offset;
107         }
108     }
setFragmentBufferOffset(NSUInteger offset,NSUInteger index)109     void setFragmentBufferOffset(NSUInteger offset, NSUInteger index)
110             SK_API_AVAILABLE(macos(10.11), ios(8.3), tvos(9.0)) {
111         if (fCurrentFragmentOffset[index] != offset) {
112             [fCommandEncoder setFragmentBufferOffset:offset
113                                              atIndex:index];
114             fCurrentFragmentOffset[index] = offset;
115         }
116     }
117 
setVertexBytes(const void * bytes,NSUInteger length,NSUInteger index)118     void setVertexBytes(const void* bytes, NSUInteger length, NSUInteger index)
119             SK_API_AVAILABLE(macos(10.11), ios(8.3), tvos(9.0)) {
120         [fCommandEncoder setVertexBytes:bytes
121                                  length:length
122                                 atIndex:index];
123     }
setFragmentBytes(const void * bytes,NSUInteger length,NSUInteger index)124     void setFragmentBytes(const void* bytes, NSUInteger length, NSUInteger index)
125             SK_API_AVAILABLE(macos(10.11), ios(8.3), tvos(9.0)) {
126         [fCommandEncoder setFragmentBytes:bytes
127                                    length:length
128                                   atIndex:index];
129     }
130 
setFragmentTexture(id<MTLTexture> texture,NSUInteger index)131     void setFragmentTexture(id<MTLTexture> texture, NSUInteger index) {
132         SkASSERT(index < kMaxTextures);
133         if (fCurrentTexture[index] != texture) {
134             [fCommandEncoder setFragmentTexture:texture
135                                          atIndex:index];
136             fCurrentTexture[index] = texture;
137         }
138     }
setFragmentSamplerState(GrMtlSampler * sampler,NSUInteger index)139     void setFragmentSamplerState(GrMtlSampler* sampler, NSUInteger index) {
140         SkASSERT(index < kMaxSamplers);
141         if (fCurrentSampler[index] != sampler) {
142             [fCommandEncoder setFragmentSamplerState: sampler->mtlSampler()
143                                          atIndex: index];
144             fCurrentSampler[index] = sampler;
145         }
146     }
147 
setBlendColor(SkPMColor4f blendConst)148     void setBlendColor(SkPMColor4f blendConst) {
149         [fCommandEncoder setBlendColorRed: blendConst.fR
150                                     green: blendConst.fG
151                                      blue: blendConst.fB
152                                     alpha: blendConst.fA];
153     }
154 
setStencilFrontBackReferenceValues(uint32_t frontReferenceValue,uint32_t backReferenceValue)155     void setStencilFrontBackReferenceValues(uint32_t frontReferenceValue,
156                                             uint32_t backReferenceValue)
157             SK_API_AVAILABLE(macos(10.11), ios(9.0), tvos(9.0)) {
158         [fCommandEncoder
159                 setStencilFrontReferenceValue:frontReferenceValue
160                            backReferenceValue:backReferenceValue];
161     }
setStencilReferenceValue(uint32_t referenceValue)162     void setStencilReferenceValue(uint32_t referenceValue) {
163         [fCommandEncoder setStencilReferenceValue:referenceValue];
164     }
setDepthStencilState(id<MTLDepthStencilState> depthStencilState)165     void setDepthStencilState(id<MTLDepthStencilState> depthStencilState) {
166         if (depthStencilState != fCurrentDepthStencilState) {
167             [fCommandEncoder setDepthStencilState:depthStencilState];
168             fCurrentDepthStencilState = depthStencilState;
169         }
170     }
171 
setScissorRect(const MTLScissorRect & scissorRect)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;
179         }
180     }
181 
drawPrimitives(MTLPrimitiveType primitiveType,NSUInteger vertexStart,NSUInteger vertexCount)182     void drawPrimitives(MTLPrimitiveType primitiveType, NSUInteger vertexStart,
183                         NSUInteger vertexCount) {
184         [fCommandEncoder drawPrimitives:primitiveType
185                             vertexStart:vertexStart
186                             vertexCount:vertexCount];
187     }
drawPrimitives(MTLPrimitiveType primitiveType,NSUInteger vertexStart,NSUInteger vertexCount,NSUInteger instanceCount,NSUInteger baseInstance)188     void drawPrimitives(MTLPrimitiveType primitiveType, NSUInteger vertexStart,
189                         NSUInteger vertexCount, NSUInteger instanceCount,
190                         NSUInteger baseInstance)
191             SK_API_AVAILABLE(macos(10.11), ios(9.0), tvos(9.0)) {
192         [fCommandEncoder drawPrimitives:primitiveType
193                             vertexStart:vertexStart
194                             vertexCount:vertexCount
195                           instanceCount:instanceCount
196                            baseInstance:baseInstance];
197     }
drawPrimitives(MTLPrimitiveType primitiveType,id<MTLBuffer> indirectBuffer,NSUInteger indirectBufferOffset)198     void drawPrimitives(MTLPrimitiveType primitiveType, id<MTLBuffer> indirectBuffer,
199                         NSUInteger indirectBufferOffset)
200             SK_API_AVAILABLE(macos(10.11), ios(9.0), tvos(9.0)) {
201         [fCommandEncoder drawPrimitives:primitiveType
202                          indirectBuffer:indirectBuffer
203                    indirectBufferOffset:indirectBufferOffset];
204     }
205 
drawIndexedPrimitives(MTLPrimitiveType primitiveType,NSUInteger indexCount,MTLIndexType indexType,id<MTLBuffer> indexBuffer,NSUInteger indexBufferOffset)206     void drawIndexedPrimitives(MTLPrimitiveType primitiveType, NSUInteger indexCount,
207                                MTLIndexType indexType, id<MTLBuffer> indexBuffer,
208                                NSUInteger indexBufferOffset) {
209         [fCommandEncoder drawIndexedPrimitives:primitiveType
210                                     indexCount:indexCount
211                                      indexType:indexType
212                                    indexBuffer:indexBuffer
213                              indexBufferOffset:indexBufferOffset];
214     }
drawIndexedPrimitives(MTLPrimitiveType primitiveType,NSUInteger indexCount,MTLIndexType indexType,id<MTLBuffer> indexBuffer,NSUInteger indexBufferOffset,NSUInteger instanceCount,NSInteger baseVertex,NSUInteger baseInstance)215     void drawIndexedPrimitives(MTLPrimitiveType primitiveType, NSUInteger indexCount,
216                                MTLIndexType indexType, id<MTLBuffer> indexBuffer,
217                                NSUInteger indexBufferOffset,
218                                NSUInteger instanceCount,
219                                NSInteger baseVertex,
220                                NSUInteger baseInstance)
221             SK_API_AVAILABLE(macos(10.11), ios(9.0), tvos(9.0)) {
222         [fCommandEncoder drawIndexedPrimitives:primitiveType
223                                     indexCount:indexCount
224                                      indexType:indexType
225                                    indexBuffer:indexBuffer
226                              indexBufferOffset:indexBufferOffset
227                                  instanceCount:instanceCount
228                                     baseVertex:baseVertex
229                                   baseInstance:baseInstance];
230     }
drawIndexedPrimitives(MTLPrimitiveType primitiveType,MTLIndexType indexType,id<MTLBuffer> indexBuffer,NSUInteger indexBufferOffset,id<MTLBuffer> indirectBuffer,NSUInteger indirectBufferOffset)231     void drawIndexedPrimitives(MTLPrimitiveType primitiveType,
232                                MTLIndexType indexType, id<MTLBuffer> indexBuffer,
233                                NSUInteger indexBufferOffset, id<MTLBuffer> indirectBuffer,
234                                NSUInteger indirectBufferOffset)
235             SK_API_AVAILABLE(macos(10.11), ios(9.0), tvos(9.0)) {
236         [fCommandEncoder drawIndexedPrimitives:primitiveType
237                                      indexType:indexType
238                                    indexBuffer:indexBuffer
239                              indexBufferOffset:indexBufferOffset
240                                 indirectBuffer:indirectBuffer
241                           indirectBufferOffset:indirectBufferOffset];
242     }
243 
endEncoding()244     void endEncoding() {
245         [fCommandEncoder endEncoding];
246     }
247 
248 private:
GrMtlRenderCommandEncoder(id<MTLRenderCommandEncoder> encoder)249     GrMtlRenderCommandEncoder(id<MTLRenderCommandEncoder> encoder)
250         : fCommandEncoder(encoder) {}
251 
252     id<MTLRenderCommandEncoder> fCommandEncoder = nil;
253 
254     // As of 2022-03-09 All GPU families have the same value at:
255     // https://developer.apple.com/metal/Metal-Feature-Set-Tables.pdf
256     static const int kMaxSamplers = 16;
257     // This is a self-imposed limit and is less than any GPU family's value at
258     // https://developer.apple.com/metal/Metal-Feature-Set-Tables.pdf
259     // Our implementation uses a 1:1 correspondence between textures and samplers.
260     static const int kMaxTextures = kMaxSamplers;
261 
262     __weak id<MTLRenderPipelineState> fCurrentRenderPipelineState = nil;
263     __weak id<MTLDepthStencilState> fCurrentDepthStencilState = nil;
264     __weak id<MTLBuffer> fCurrentVertexBuffer[2 + GrMtlUniformHandler::kUniformBindingCount];
265     NSUInteger fCurrentVertexOffset[2 + GrMtlUniformHandler::kUniformBindingCount];
266     __weak id<MTLBuffer> fCurrentFragmentBuffer[GrMtlUniformHandler::kUniformBindingCount];
267     NSUInteger fCurrentFragmentOffset[2 + GrMtlUniformHandler::kUniformBindingCount];
268     __weak id<MTLTexture> fCurrentTexture[kMaxTextures];
269     GrMtlSampler* fCurrentSampler[kMaxSamplers] = {};
270     MTLScissorRect fCurrentScissorRect = { 0, 0, 0, 0 };
271     MTLTriangleFillMode fCurrentTriangleFillMode = (MTLTriangleFillMode)-1;
272 };
273 
274 GR_NORETAIN_END
275 
276 #endif
277