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