xref: /aosp_15_r20/external/skia/src/gpu/graphite/mtl/MtlRenderCommandEncoder.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 skgpu_graphite_MtlRenderCommandEncoder_DEFINED
9 #define skgpu_graphite_MtlRenderCommandEncoder_DEFINED
10 
11 #include "include/core/SkRefCnt.h"
12 #include "include/ports/SkCFObject.h"
13 #include "src/gpu/graphite/Resource.h"
14 
15 #import <Metal/Metal.h>
16 
17 namespace skgpu::graphite {
18 
19 /**
20  * Wraps a MTLRenderCommandEncoder object and associated tracked state
21  */
22 class MtlRenderCommandEncoder : public Resource {
23 public:
Make(const SharedContext * sharedContext,id<MTLCommandBuffer> commandBuffer,MTLRenderPassDescriptor * descriptor)24     static sk_sp<MtlRenderCommandEncoder> Make(const SharedContext* sharedContext,
25                                                id<MTLCommandBuffer> commandBuffer,
26                                                MTLRenderPassDescriptor* descriptor) {
27         // Inserting a pool here so the autorelease occurs when we return and the
28         // only remaining ref is the retain below.
29         @autoreleasepool {
30             // Adding a retain here to keep our own ref separate from the autorelease pool
31             sk_cfp<id<MTLRenderCommandEncoder>> encoder =
32                     sk_ret_cfp([commandBuffer renderCommandEncoderWithDescriptor:descriptor]);
33             return sk_sp<MtlRenderCommandEncoder>(new MtlRenderCommandEncoder(sharedContext,
34                                                                               std::move(encoder)));
35         }
36     }
37 
getResourceType()38     const char* getResourceType() const override { return "Metal Render Command Encoder"; }
39 
setLabel(NSString * label)40     void setLabel(NSString* label) {
41         [(*fCommandEncoder) setLabel:label];
42     }
43 
pushDebugGroup(NSString * string)44     void pushDebugGroup(NSString* string) {
45         [(*fCommandEncoder) pushDebugGroup:string];
46     }
popDebugGroup()47     void popDebugGroup() {
48         [(*fCommandEncoder) popDebugGroup];
49     }
insertDebugSignpost(NSString * string)50     void insertDebugSignpost(NSString* string) {
51         [(*fCommandEncoder) insertDebugSignpost:string];
52     }
53 
setRenderPipelineState(id<MTLRenderPipelineState> pso)54     void setRenderPipelineState(id<MTLRenderPipelineState> pso) {
55         if (fCurrentRenderPipelineState != pso) {
56             [(*fCommandEncoder) setRenderPipelineState:pso];
57             fCurrentRenderPipelineState = pso;
58         }
59     }
60 
setTriangleFillMode(MTLTriangleFillMode fillMode)61     void setTriangleFillMode(MTLTriangleFillMode fillMode) {
62         if (fCurrentTriangleFillMode != fillMode) {
63             [(*fCommandEncoder) setTriangleFillMode:fillMode];
64             fCurrentTriangleFillMode = fillMode;
65         }
66     }
67 
setFrontFacingWinding(MTLWinding winding)68     void setFrontFacingWinding(MTLWinding winding) {
69         [(*fCommandEncoder) setFrontFacingWinding:winding];
70     }
71 
setViewport(const MTLViewport & viewport)72     void setViewport(const MTLViewport& viewport) {
73         [(*fCommandEncoder) setViewport:viewport];
74     }
75 
setVertexBuffer(id<MTLBuffer> buffer,NSUInteger offset,NSUInteger index)76     void setVertexBuffer(id<MTLBuffer> buffer, NSUInteger offset, NSUInteger index) {
77         SkASSERT(buffer != nil);
78         SkASSERT(index < kMaxExpectedBuffers);
79         if (@available(macOS 10.11, iOS 8.3, tvOS 9.0, *)) {
80             if (fCurrentVertexBuffer[index] == buffer) {
81                 this->setVertexBufferOffset(offset, index);
82                 return;
83             }
84         }
85         if (fCurrentVertexBuffer[index] != buffer || fCurrentVertexOffset[index] != offset) {
86             [(*fCommandEncoder) setVertexBuffer:buffer
87                                          offset:offset
88                                         atIndex:index];
89             fCurrentVertexBuffer[index] = buffer;
90             fCurrentVertexOffset[index] = offset;
91         }
92     }
setVertexBufferOffset(NSUInteger offset,NSUInteger index)93     void setVertexBufferOffset(NSUInteger offset, NSUInteger index)
94             SK_API_AVAILABLE(macos(10.11), ios(8.3), tvos(9.0)) {
95         SkASSERT(index < kMaxExpectedBuffers);
96         if (fCurrentVertexOffset[index] != offset) {
97             [(*fCommandEncoder) setVertexBufferOffset:offset
98                                               atIndex:index];
99             fCurrentVertexOffset[index] = offset;
100         }
101     }
102 
setFragmentBuffer(id<MTLBuffer> buffer,NSUInteger offset,NSUInteger index)103     void setFragmentBuffer(id<MTLBuffer> buffer, NSUInteger offset, NSUInteger index) {
104         SkASSERT(buffer != nil);
105         SkASSERT(index < kMaxExpectedBuffers);
106         if (@available(macOS 10.11, iOS 8.3, tvOS 9.0, *)) {
107             if (fCurrentFragmentBuffer[index] == buffer) {
108                 this->setFragmentBufferOffset(offset, index);
109                 return;
110             }
111         }
112         if (fCurrentFragmentBuffer[index] != buffer || fCurrentFragmentOffset[index] != offset) {
113             [(*fCommandEncoder) setFragmentBuffer:buffer
114                                            offset:offset
115                                           atIndex:index];
116             fCurrentFragmentBuffer[index] = buffer;
117             fCurrentFragmentOffset[index] = offset;
118         }
119     }
setFragmentBufferOffset(NSUInteger offset,NSUInteger index)120     void setFragmentBufferOffset(NSUInteger offset, NSUInteger index)
121             SK_API_AVAILABLE(macos(10.11), ios(8.3), tvos(9.0)) {
122         SkASSERT(index < kMaxExpectedBuffers);
123         if (fCurrentFragmentOffset[index] != offset) {
124             [(*fCommandEncoder) setFragmentBufferOffset:offset
125                                                 atIndex:index];
126             fCurrentFragmentOffset[index] = offset;
127         }
128     }
129 
setVertexBytes(const void * bytes,NSUInteger length,NSUInteger index)130     void setVertexBytes(const void* bytes, NSUInteger length, NSUInteger index)
131             SK_API_AVAILABLE(macos(10.11), ios(8.3), tvos(9.0)) {
132         [(*fCommandEncoder) setVertexBytes:bytes
133                                     length:length
134                                    atIndex:index];
135     }
setFragmentBytes(const void * bytes,NSUInteger length,NSUInteger index)136     void setFragmentBytes(const void* bytes, NSUInteger length, NSUInteger index)
137             SK_API_AVAILABLE(macos(10.11), ios(8.3), tvos(9.0)) {
138         [(*fCommandEncoder) setFragmentBytes:bytes
139                                       length:length
140                                      atIndex:index];
141     }
142 
setFragmentTexture(id<MTLTexture> texture,NSUInteger index)143     void setFragmentTexture(id<MTLTexture> texture, NSUInteger index) {
144         SkASSERT(index < kMaxExpectedTextures);
145         if (fCurrentTexture[index] != texture) {
146             [(*fCommandEncoder) setFragmentTexture:texture
147                                            atIndex:index];
148             fCurrentTexture[index] = texture;
149         }
150     }
setFragmentSamplerState(id<MTLSamplerState> sampler,NSUInteger index)151     void setFragmentSamplerState(id<MTLSamplerState> sampler, NSUInteger index) {
152         SkASSERT(index < kMaxExpectedTextures);
153         if (fCurrentSampler[index] != sampler) {
154             [(*fCommandEncoder) setFragmentSamplerState: sampler
155                                                 atIndex: index];
156             fCurrentSampler[index] = sampler;
157         }
158     }
159 
setBlendColor(float blendConst[4])160     void setBlendColor(float blendConst[4]) {
161         [(*fCommandEncoder) setBlendColorRed: blendConst[0]
162                                        green: blendConst[1]
163                                         blue: blendConst[2]
164                                        alpha: blendConst[3]];
165     }
166 
setStencilReferenceValue(uint32_t referenceValue)167     void setStencilReferenceValue(uint32_t referenceValue) {
168         if (referenceValue != fCurrentStencilReferenceValue) {
169             [(*fCommandEncoder) setStencilReferenceValue:referenceValue];
170             fCurrentStencilReferenceValue = referenceValue;
171         }
172     }
setDepthStencilState(id<MTLDepthStencilState> depthStencilState)173     void setDepthStencilState(id<MTLDepthStencilState> depthStencilState) {
174         if (depthStencilState != fCurrentDepthStencilState) {
175             [(*fCommandEncoder) setDepthStencilState:depthStencilState];
176             fCurrentDepthStencilState = depthStencilState;
177         }
178     }
179 
setScissorRect(const MTLScissorRect & scissorRect)180     void setScissorRect(const MTLScissorRect& scissorRect) {
181         if (fCurrentScissorRect.x != scissorRect.x ||
182             fCurrentScissorRect.y != scissorRect.y ||
183             fCurrentScissorRect.width != scissorRect.width ||
184             fCurrentScissorRect.height != scissorRect.height) {
185             [(*fCommandEncoder) setScissorRect:scissorRect];
186             fCurrentScissorRect = scissorRect;
187         }
188     }
189 
drawPrimitives(MTLPrimitiveType primitiveType,NSUInteger vertexStart,NSUInteger vertexCount)190     void drawPrimitives(MTLPrimitiveType primitiveType, NSUInteger vertexStart,
191                         NSUInteger vertexCount) {
192         [(*fCommandEncoder) drawPrimitives:primitiveType
193                                vertexStart:vertexStart
194                                vertexCount:vertexCount];
195     }
drawPrimitives(MTLPrimitiveType primitiveType,NSUInteger vertexStart,NSUInteger vertexCount,NSUInteger instanceCount,NSUInteger baseInstance)196     void drawPrimitives(MTLPrimitiveType primitiveType, NSUInteger vertexStart,
197                         NSUInteger vertexCount, NSUInteger instanceCount,
198                         NSUInteger baseInstance)
199             SK_API_AVAILABLE(macos(10.11), ios(9.0), tvos(9.0)) {
200         [(*fCommandEncoder) drawPrimitives:primitiveType
201                             vertexStart:vertexStart
202                             vertexCount:vertexCount
203                           instanceCount:instanceCount
204                            baseInstance:baseInstance];
205     }
drawPrimitives(MTLPrimitiveType primitiveType,id<MTLBuffer> indirectBuffer,NSUInteger indirectBufferOffset)206     void drawPrimitives(MTLPrimitiveType primitiveType, id<MTLBuffer> indirectBuffer,
207                         NSUInteger indirectBufferOffset)
208             SK_API_AVAILABLE(macos(10.11), ios(9.0), tvos(9.0)) {
209         [(*fCommandEncoder) drawPrimitives:primitiveType
210                             indirectBuffer:indirectBuffer
211                       indirectBufferOffset:indirectBufferOffset];
212     }
213 
drawIndexedPrimitives(MTLPrimitiveType primitiveType,NSUInteger indexCount,MTLIndexType indexType,id<MTLBuffer> indexBuffer,NSUInteger indexBufferOffset)214     void drawIndexedPrimitives(MTLPrimitiveType primitiveType, NSUInteger indexCount,
215                                MTLIndexType indexType, id<MTLBuffer> indexBuffer,
216                                NSUInteger indexBufferOffset) {
217         [(*fCommandEncoder) drawIndexedPrimitives:primitiveType
218                                     indexCount:indexCount
219                                      indexType:indexType
220                                    indexBuffer:indexBuffer
221                              indexBufferOffset:indexBufferOffset];
222     }
drawIndexedPrimitives(MTLPrimitiveType primitiveType,NSUInteger indexCount,MTLIndexType indexType,id<MTLBuffer> indexBuffer,NSUInteger indexBufferOffset,NSUInteger instanceCount,NSInteger baseVertex,NSUInteger baseInstance)223     void drawIndexedPrimitives(MTLPrimitiveType primitiveType, NSUInteger indexCount,
224                                MTLIndexType indexType, id<MTLBuffer> indexBuffer,
225                                NSUInteger indexBufferOffset,
226                                NSUInteger instanceCount,
227                                NSInteger baseVertex,
228                                NSUInteger baseInstance)
229             SK_API_AVAILABLE(macos(10.11), ios(9.0), tvos(9.0)) {
230         [(*fCommandEncoder) drawIndexedPrimitives:primitiveType
231                                     indexCount:indexCount
232                                      indexType:indexType
233                                    indexBuffer:indexBuffer
234                              indexBufferOffset:indexBufferOffset
235                                  instanceCount:instanceCount
236                                     baseVertex:baseVertex
237                                   baseInstance:baseInstance];
238     }
drawIndexedPrimitives(MTLPrimitiveType primitiveType,MTLIndexType indexType,id<MTLBuffer> indexBuffer,NSUInteger indexBufferOffset,id<MTLBuffer> indirectBuffer,NSUInteger indirectBufferOffset)239     void drawIndexedPrimitives(MTLPrimitiveType primitiveType,
240                                MTLIndexType indexType, id<MTLBuffer> indexBuffer,
241                                NSUInteger indexBufferOffset, id<MTLBuffer> indirectBuffer,
242                                NSUInteger indirectBufferOffset)
243             SK_API_AVAILABLE(macos(10.11), ios(9.0), tvos(9.0)) {
244         [(*fCommandEncoder) drawIndexedPrimitives:primitiveType
245                                         indexType:indexType
246                                       indexBuffer:indexBuffer
247                                 indexBufferOffset:indexBufferOffset
248                                    indirectBuffer:indirectBuffer
249                              indirectBufferOffset:indirectBufferOffset];
250     }
251 
endEncoding()252     void endEncoding() {
253         [(*fCommandEncoder) endEncoding];
254     }
255 
256 private:
257     inline static constexpr int kMaxExpectedBuffers = 6;
258     inline static constexpr int kMaxExpectedTextures = 16;
259 
MtlRenderCommandEncoder(const SharedContext * sharedContext,sk_cfp<id<MTLRenderCommandEncoder>> encoder)260     MtlRenderCommandEncoder(const SharedContext* sharedContext,
261                             sk_cfp<id<MTLRenderCommandEncoder>> encoder)
262             : Resource(sharedContext,
263                        Ownership::kOwned,
264                        skgpu::Budgeted::kYes,
265                        /*gpuMemorySize=*/0)
266             , fCommandEncoder(std::move(encoder)) {
267         for (int i = 0; i < kMaxExpectedBuffers; i++) {
268             fCurrentVertexBuffer[i] = nil;
269             fCurrentFragmentBuffer[i] = nil;
270             // We don't initialize fCurrentVertexOffset or fCurrentFragmentOffset because neither
271             // of those should ever be read unless we've already confirmed the current buffer
272             // matches the new one. That would mean we would have initialized the offset when we
273             // set the current buffer.
274         }
275 
276         for (int i = 0; i < kMaxExpectedTextures; i++) {
277             fCurrentTexture[i] = nil;
278             fCurrentSampler[i] = nil;
279         }
280     }
281 
freeGpuData()282     void freeGpuData() override {
283         fCommandEncoder.reset();
284     }
285 
286     sk_cfp<id<MTLRenderCommandEncoder>> fCommandEncoder;
287 
288     id<MTLRenderPipelineState> fCurrentRenderPipelineState = nil;
289     id<MTLDepthStencilState> fCurrentDepthStencilState = nil;
290     uint32_t fCurrentStencilReferenceValue = 0; // Metal default value
291 
292     id<MTLBuffer> fCurrentVertexBuffer[kMaxExpectedBuffers];
293     NSUInteger fCurrentVertexOffset[kMaxExpectedBuffers];
294     id<MTLBuffer> fCurrentFragmentBuffer[kMaxExpectedBuffers];
295     NSUInteger fCurrentFragmentOffset[kMaxExpectedBuffers];
296 
297     id<MTLTexture> fCurrentTexture[kMaxExpectedTextures];
298     id<MTLSamplerState> fCurrentSampler[kMaxExpectedTextures];
299 
300     MTLScissorRect fCurrentScissorRect = { 0, 0, 0, 0 };
301     MTLTriangleFillMode fCurrentTriangleFillMode = (MTLTriangleFillMode)-1;
302 };
303 
304 } // namespace skgpu::graphite
305 
306 #endif // skgpu_graphite_MtlRenderCommandEncoder_DEFINED
307