• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_MtlRenderCommandEncoder_DEFINED
9 #define skgpu_MtlRenderCommandEncoder_DEFINED
10 
11 #include "include/core/SkRefCnt.h"
12 #include "include/ports/SkCFObject.h"
13 
14 #import <Metal/Metal.h>
15 
16 namespace skgpu::mtl {
17 
18 /**
19  * Wraps a MTLRenderCommandEncoder object and associated tracked state
20  */
21 class RenderCommandEncoder : public SkRefCnt {
22 public:
Make(id<MTLCommandBuffer> commandBuffer,MTLRenderPassDescriptor * descriptor)23     static sk_sp<RenderCommandEncoder> Make(id<MTLCommandBuffer> commandBuffer,
24                                             MTLRenderPassDescriptor* descriptor) {
25         // Adding a retain here to keep our own ref separate from the autorelease pool
26         sk_cfp<id<MTLRenderCommandEncoder>> encoder =
27                  sk_ret_cfp([commandBuffer renderCommandEncoderWithDescriptor:descriptor]);
28         return sk_sp<RenderCommandEncoder>(new RenderCommandEncoder(std::move(encoder)));
29     }
30 
setLabel(NSString * label)31     void setLabel(NSString* label) {
32         [(*fCommandEncoder) setLabel:label];
33     }
34 
pushDebugGroup(NSString * string)35     void pushDebugGroup(NSString* string) {
36         [(*fCommandEncoder) pushDebugGroup:string];
37     }
popDebugGroup()38     void popDebugGroup() {
39         [(*fCommandEncoder) popDebugGroup];
40     }
insertDebugSignpost(NSString * string)41     void insertDebugSignpost(NSString* string) {
42         [(*fCommandEncoder) insertDebugSignpost:string];
43     }
44 
setRenderPipelineState(id<MTLRenderPipelineState> pso)45     void setRenderPipelineState(id<MTLRenderPipelineState> pso) {
46         if (fCurrentRenderPipelineState != pso) {
47             [(*fCommandEncoder) setRenderPipelineState:pso];
48             fCurrentRenderPipelineState = pso;
49         }
50     }
51 
setTriangleFillMode(MTLTriangleFillMode fillMode)52     void setTriangleFillMode(MTLTriangleFillMode fillMode) {
53         if (fCurrentTriangleFillMode != fillMode) {
54             [(*fCommandEncoder) setTriangleFillMode:fillMode];
55             fCurrentTriangleFillMode = fillMode;
56         }
57     }
58 
setFrontFacingWinding(MTLWinding winding)59     void setFrontFacingWinding(MTLWinding winding) {
60         [(*fCommandEncoder) setFrontFacingWinding:winding];
61     }
62 
setViewport(const MTLViewport & viewport)63     void setViewport(const MTLViewport& viewport) {
64         [(*fCommandEncoder) setViewport:viewport];
65     }
66 
setVertexBuffer(id<MTLBuffer> buffer,NSUInteger offset,NSUInteger index)67     void setVertexBuffer(id<MTLBuffer> buffer, NSUInteger offset, NSUInteger index) {
68         SkASSERT(index < kMaxExpectedBuffers);
69         if (@available(macOS 10.11, iOS 8.3, *)) {
70             if (fCurrentVertexBuffer[index] == buffer) {
71                 this->setVertexBufferOffset(offset, index);
72                 return;
73             }
74         }
75         if (fCurrentVertexBuffer[index] != buffer || fCurrentVertexOffset[index] != offset) {
76             [(*fCommandEncoder) setVertexBuffer:buffer
77                                          offset:offset
78                                         atIndex:index];
79             fCurrentVertexBuffer[index] = buffer;
80             fCurrentVertexOffset[index] = offset;
81         }
82     }
setVertexBufferOffset(NSUInteger offset,NSUInteger index)83     void setVertexBufferOffset(NSUInteger offset, NSUInteger index)
84             SK_API_AVAILABLE(macos(10.11), ios(8.3)) {
85         SkASSERT(index < kMaxExpectedBuffers);
86         if (fCurrentVertexOffset[index] != offset) {
87             [(*fCommandEncoder) setVertexBufferOffset:offset
88                                               atIndex:index];
89             fCurrentVertexOffset[index] = offset;
90         }
91     }
92 
setFragmentBuffer(id<MTLBuffer> buffer,NSUInteger offset,NSUInteger index)93     void setFragmentBuffer(id<MTLBuffer> buffer, NSUInteger offset, NSUInteger index) {
94         SkASSERT(index < kMaxExpectedBuffers);
95         if (@available(macOS 10.11, iOS 8.3, *)) {
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)) {
111         SkASSERT(index < kMaxExpectedBuffers);
112         if (fCurrentFragmentOffset[index] != offset) {
113             [(*fCommandEncoder) setFragmentBufferOffset:offset
114                                                 atIndex:index];
115             fCurrentFragmentOffset[index] = offset;
116         }
117     }
118 
setVertexBytes(const void * bytes,NSUInteger length,NSUInteger index)119     void setVertexBytes(const void* bytes, NSUInteger length, NSUInteger index)
120             SK_API_AVAILABLE(macos(10.11), ios(8.3)) {
121         [(*fCommandEncoder) setVertexBytes:bytes
122                                     length:length
123                                    atIndex:index];
124     }
setFragmentBytes(const void * bytes,NSUInteger length,NSUInteger index)125     void setFragmentBytes(const void* bytes, NSUInteger length, NSUInteger index)
126             SK_API_AVAILABLE(macos(10.11), ios(8.3)) {
127         [(*fCommandEncoder) setFragmentBytes:bytes
128                                       length:length
129                                      atIndex:index];
130     }
131 
setFragmentTexture(id<MTLTexture> texture,NSUInteger index)132     void setFragmentTexture(id<MTLTexture> texture, NSUInteger index) {
133         SkASSERT(index < kMaxExpectedTextures);
134         if (fCurrentTexture[index] != texture) {
135             [(*fCommandEncoder) setFragmentTexture:texture
136                                            atIndex:index];
137             fCurrentTexture[index] = texture;
138         }
139     }
setFragmentSamplerState(id<MTLSamplerState> sampler,NSUInteger index)140     void setFragmentSamplerState(id<MTLSamplerState> sampler, NSUInteger index) {
141         SkASSERT(index < kMaxExpectedTextures);
142         if (fCurrentSampler[index] != sampler) {
143             [(*fCommandEncoder) setFragmentSamplerState: sampler
144                                                 atIndex: index];
145             fCurrentSampler[index] = sampler;
146         }
147     }
148 
setBlendColor(float blendConst[4])149     void setBlendColor(float blendConst[4]) {
150         [(*fCommandEncoder) setBlendColorRed: blendConst[0]
151                                        green: blendConst[1]
152                                         blue: blendConst[2]
153                                        alpha: blendConst[3]];
154     }
155 
setStencilFrontBackReferenceValues(uint32_t frontReferenceValue,uint32_t backReferenceValue)156     void setStencilFrontBackReferenceValues(uint32_t frontReferenceValue,
157                                             uint32_t backReferenceValue)
158             SK_API_AVAILABLE(macos(10.11), ios(9.0)) {
159         [(*fCommandEncoder)
160                 setStencilFrontReferenceValue:frontReferenceValue
161                            backReferenceValue:backReferenceValue];
162     }
setStencilReferenceValue(uint32_t referenceValue)163     void setStencilReferenceValue(uint32_t referenceValue) {
164         [(*fCommandEncoder) setStencilReferenceValue:referenceValue];
165     }
setDepthStencilState(id<MTLDepthStencilState> depthStencilState)166     void setDepthStencilState(id<MTLDepthStencilState> depthStencilState) {
167         if (depthStencilState != fCurrentDepthStencilState) {
168             [(*fCommandEncoder) setDepthStencilState:depthStencilState];
169             fCurrentDepthStencilState = depthStencilState;
170         }
171     }
172 
setScissorRect(const MTLScissorRect & scissorRect)173     void setScissorRect(const MTLScissorRect& scissorRect) {
174         if (fCurrentScissorRect.x != scissorRect.x ||
175             fCurrentScissorRect.y != scissorRect.y ||
176             fCurrentScissorRect.width != scissorRect.width ||
177             fCurrentScissorRect.height != scissorRect.height) {
178             [(*fCommandEncoder) setScissorRect:scissorRect];
179             fCurrentScissorRect = scissorRect;
180         }
181     }
182 
drawPrimitives(MTLPrimitiveType primitiveType,NSUInteger vertexStart,NSUInteger vertexCount)183     void drawPrimitives(MTLPrimitiveType primitiveType, NSUInteger vertexStart,
184                         NSUInteger vertexCount) {
185         [(*fCommandEncoder) drawPrimitives:primitiveType
186                                vertexStart:vertexStart
187                                vertexCount:vertexCount];
188     }
drawPrimitives(MTLPrimitiveType primitiveType,NSUInteger vertexStart,NSUInteger vertexCount,NSUInteger instanceCount,NSUInteger baseInstance)189     void drawPrimitives(MTLPrimitiveType primitiveType, NSUInteger vertexStart,
190                         NSUInteger vertexCount, NSUInteger instanceCount,
191                         NSUInteger baseInstance) SK_API_AVAILABLE(macos(10.11), ios(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) SK_API_AVAILABLE(macos(10.11), ios(9.0)) {
200         [(*fCommandEncoder) drawPrimitives:primitiveType
201                             indirectBuffer:indirectBuffer
202                       indirectBufferOffset:indirectBufferOffset];
203     }
204 
drawIndexedPrimitives(MTLPrimitiveType primitiveType,NSUInteger indexCount,MTLIndexType indexType,id<MTLBuffer> indexBuffer,NSUInteger indexBufferOffset)205     void drawIndexedPrimitives(MTLPrimitiveType primitiveType, NSUInteger indexCount,
206                                MTLIndexType indexType, id<MTLBuffer> indexBuffer,
207                                NSUInteger indexBufferOffset) {
208         [(*fCommandEncoder) drawIndexedPrimitives:primitiveType
209                                     indexCount:indexCount
210                                      indexType:indexType
211                                    indexBuffer:indexBuffer
212                              indexBufferOffset:indexBufferOffset];
213     }
drawIndexedPrimitives(MTLPrimitiveType primitiveType,NSUInteger indexCount,MTLIndexType indexType,id<MTLBuffer> indexBuffer,NSUInteger indexBufferOffset,NSUInteger instanceCount,NSInteger baseVertex,NSUInteger baseInstance)214     void drawIndexedPrimitives(MTLPrimitiveType primitiveType, NSUInteger indexCount,
215                                MTLIndexType indexType, id<MTLBuffer> indexBuffer,
216                                NSUInteger indexBufferOffset,
217                                NSUInteger instanceCount,
218                                NSInteger baseVertex,
219                                NSUInteger baseInstance) SK_API_AVAILABLE(macos(10.11), ios(9.0)) {
220         [(*fCommandEncoder) drawIndexedPrimitives:primitiveType
221                                     indexCount:indexCount
222                                      indexType:indexType
223                                    indexBuffer:indexBuffer
224                              indexBufferOffset:indexBufferOffset
225                                  instanceCount:instanceCount
226                                     baseVertex:baseVertex
227                                   baseInstance:baseInstance];
228     }
drawIndexedPrimitives(MTLPrimitiveType primitiveType,MTLIndexType indexType,id<MTLBuffer> indexBuffer,NSUInteger indexBufferOffset,id<MTLBuffer> indirectBuffer,NSUInteger indirectBufferOffset)229     void drawIndexedPrimitives(MTLPrimitiveType primitiveType,
230                                MTLIndexType indexType, id<MTLBuffer> indexBuffer,
231                                NSUInteger indexBufferOffset, id<MTLBuffer> indirectBuffer,
232                                NSUInteger indirectBufferOffset)
233             SK_API_AVAILABLE(macos(10.11), ios(9.0)) {
234         [(*fCommandEncoder) drawIndexedPrimitives:primitiveType
235                                         indexType:indexType
236                                       indexBuffer:indexBuffer
237                                 indexBufferOffset:indexBufferOffset
238                                    indirectBuffer:indirectBuffer
239                              indirectBufferOffset:indirectBufferOffset];
240     }
241 
endEncoding()242     void endEncoding() {
243         [(*fCommandEncoder) endEncoding];
244     }
245 
246 private:
RenderCommandEncoder(sk_cfp<id<MTLRenderCommandEncoder>> encoder)247     RenderCommandEncoder(sk_cfp<id<MTLRenderCommandEncoder>> encoder)
248         : fCommandEncoder(std::move(encoder)) {}
249 
250     sk_cfp<id<MTLRenderCommandEncoder>> fCommandEncoder;
251 
252     id<MTLRenderPipelineState> fCurrentRenderPipelineState = nil;
253     id<MTLDepthStencilState> fCurrentDepthStencilState = nil;
254 
255     inline static constexpr int kMaxExpectedBuffers = 4;
256     id<MTLBuffer> fCurrentVertexBuffer[kMaxExpectedBuffers];
257     NSUInteger fCurrentVertexOffset[kMaxExpectedBuffers];
258     id<MTLBuffer> fCurrentFragmentBuffer[kMaxExpectedBuffers];
259     NSUInteger fCurrentFragmentOffset[kMaxExpectedBuffers];
260 
261     inline static constexpr int kMaxExpectedTextures = 16;
262     id<MTLTexture> fCurrentTexture[kMaxExpectedTextures];
263     id<MTLSamplerState> fCurrentSampler[kMaxExpectedTextures];
264 
265     MTLScissorRect fCurrentScissorRect = { 0, 0, 0, 0 };
266     MTLTriangleFillMode fCurrentTriangleFillMode = (MTLTriangleFillMode)-1;
267 };
268 
269 } // namespace skgpu::mtl
270 
271 #endif // skgpu_MtlRenderCommandEncoder_DEFINED
272