Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
MtlRenderCommandEncoder.h
Go to the documentation of this file.
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
14
15#import <Metal/Metal.h>
16
17namespace skgpu::graphite {
18
19/**
20 * Wraps a MTLRenderCommandEncoder object and associated tracked state
21 */
23public:
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]);
34 std::move(encoder)));
35 }
36 }
37
38 const char* getResourceType() const override { return "Metal Render Command Encoder"; }
39
40 void setLabel(NSString* label) {
41 [(*fCommandEncoder) setLabel:label];
42 }
43
44 void pushDebugGroup(NSString* string) {
45 [(*fCommandEncoder) pushDebugGroup:string];
46 }
48 [(*fCommandEncoder) popDebugGroup];
49 }
50 void insertDebugSignpost(NSString* string) {
51 [(*fCommandEncoder) insertDebugSignpost:string];
52 }
53
54 void setRenderPipelineState(id<MTLRenderPipelineState> pso) {
55 if (fCurrentRenderPipelineState != pso) {
56 [(*fCommandEncoder) setRenderPipelineState:pso];
57 fCurrentRenderPipelineState = pso;
58 }
59 }
60
61 void setTriangleFillMode(MTLTriangleFillMode fillMode) {
62 if (fCurrentTriangleFillMode != fillMode) {
63 [(*fCommandEncoder) setTriangleFillMode:fillMode];
64 fCurrentTriangleFillMode = fillMode;
65 }
66 }
67
68 void setFrontFacingWinding(MTLWinding winding) {
69 [(*fCommandEncoder) setFrontFacingWinding:winding];
70 }
71
72 void setViewport(const MTLViewport& viewport) {
73 [(*fCommandEncoder) setViewport:viewport];
74 }
75
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
88 atIndex:index];
89 fCurrentVertexBuffer[index] = buffer;
90 fCurrentVertexOffset[index] = offset;
91 }
92 }
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
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
115 atIndex:index];
116 fCurrentFragmentBuffer[index] = buffer;
117 fCurrentFragmentOffset[index] = offset;
118 }
119 }
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
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
134 atIndex:index];
135 }
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
140 atIndex:index];
141 }
142
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 }
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
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
167 void setStencilReferenceValue(uint32_t referenceValue) {
168 if (referenceValue != fCurrentStencilReferenceValue) {
169 [(*fCommandEncoder) setStencilReferenceValue:referenceValue];
170 fCurrentStencilReferenceValue = referenceValue;
171 }
172 }
173 void setDepthStencilState(id<MTLDepthStencilState> depthStencilState) {
174 if (depthStencilState != fCurrentDepthStencilState) {
175 [(*fCommandEncoder) setDepthStencilState:depthStencilState];
176 fCurrentDepthStencilState = depthStencilState;
177 }
178 }
179
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
190 void drawPrimitives(MTLPrimitiveType primitiveType, NSUInteger vertexStart,
191 NSUInteger vertexCount) {
192 [(*fCommandEncoder) drawPrimitives:primitiveType
193 vertexStart:vertexStart
194 vertexCount:vertexCount];
195 }
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 }
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
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 }
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 }
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
252 void endEncoding() {
253 [(*fCommandEncoder) endEncoding];
254 }
255
256private:
257 inline static constexpr int kMaxExpectedBuffers = 5;
258 inline static constexpr int kMaxExpectedTextures = 16;
259
261 sk_cfp<id<MTLRenderCommandEncoder>> encoder)
265 /*gpuMemorySize=*/0,
266 /*label=*/"MtlRenderCommandEncoder")
267 , fCommandEncoder(std::move(encoder)) {
268 for (int i = 0; i < kMaxExpectedBuffers; i++) {
269 fCurrentVertexBuffer[i] = nil;
270 fCurrentFragmentBuffer[i] = nil;
271 // We don't initialize fCurrentVertexOffset or fCurrentFragmentOffset because neither
272 // of those should ever be read unless we've already confirmed the current buffer
273 // matches the new one. That would mean we would have initialized the offset when we
274 // set the current buffer.
275 }
276
277 for (int i = 0; i < kMaxExpectedTextures; i++) {
278 fCurrentTexture[i] = nil;
279 fCurrentSampler[i] = nil;
280 }
281 }
282
283 void freeGpuData() override {
284 fCommandEncoder.reset();
285 }
286
287 sk_cfp<id<MTLRenderCommandEncoder>> fCommandEncoder;
288
289 id<MTLRenderPipelineState> fCurrentRenderPipelineState = nil;
290 id<MTLDepthStencilState> fCurrentDepthStencilState = nil;
291 uint32_t fCurrentStencilReferenceValue = 0; // Metal default value
292
293 id<MTLBuffer> fCurrentVertexBuffer[kMaxExpectedBuffers];
294 NSUInteger fCurrentVertexOffset[kMaxExpectedBuffers];
295 id<MTLBuffer> fCurrentFragmentBuffer[kMaxExpectedBuffers];
296 NSUInteger fCurrentFragmentOffset[kMaxExpectedBuffers];
297
298 id<MTLTexture> fCurrentTexture[kMaxExpectedTextures];
299 id<MTLSamplerState> fCurrentSampler[kMaxExpectedTextures];
300
301 MTLScissorRect fCurrentScissorRect = { 0, 0, 0, 0 };
302 MTLTriangleFillMode fCurrentTriangleFillMode = (MTLTriangleFillMode)-1;
303};
304
305} // namespace skgpu::graphite
306
307#endif // skgpu_graphite_MtlRenderCommandEncoder_DEFINED
#define SK_API_AVAILABLE(...)
Definition SkAPI.h:49
#define SkASSERT(cond)
Definition SkAssert.h:116
@ kYes
Do pre-clip the geometry before applying the (perspective) matrix.
void setScissorRect(const MTLScissorRect &scissorRect)
void drawIndexedPrimitives(MTLPrimitiveType primitiveType, MTLIndexType indexType, id< MTLBuffer > indexBuffer, NSUInteger indexBufferOffset, id< MTLBuffer > indirectBuffer, NSUInteger indirectBufferOffset) SK_API_AVAILABLE(macos(10.11)
void drawIndexedPrimitives(MTLPrimitiveType primitiveType, NSUInteger indexCount, MTLIndexType indexType, id< MTLBuffer > indexBuffer, NSUInteger indexBufferOffset)
void setVertexBuffer(id< MTLBuffer > buffer, NSUInteger offset, NSUInteger index)
void drawIndexedPrimitives(MTLPrimitiveType primitiveType, NSUInteger indexCount, MTLIndexType indexType, id< MTLBuffer > indexBuffer, NSUInteger indexBufferOffset, NSUInteger instanceCount, NSInteger baseVertex, NSUInteger baseInstance) SK_API_AVAILABLE(macos(10.11)
void setStencilReferenceValue(uint32_t referenceValue)
void setFragmentSamplerState(id< MTLSamplerState > sampler, NSUInteger index)
void setTriangleFillMode(MTLTriangleFillMode fillMode)
static sk_sp< MtlRenderCommandEncoder > Make(const SharedContext *sharedContext, id< MTLCommandBuffer > commandBuffer, MTLRenderPassDescriptor *descriptor)
void drawPrimitives(MTLPrimitiveType primitiveType, NSUInteger vertexStart, NSUInteger vertexCount)
void setViewport(const MTLViewport &viewport)
void setRenderPipelineState(id< MTLRenderPipelineState > pso)
void setFragmentBufferOffset(NSUInteger offset, NSUInteger index) SK_API_AVAILABLE(macos(10.11)
void drawPrimitives(MTLPrimitiveType primitiveType, id< MTLBuffer > indirectBuffer, NSUInteger indirectBufferOffset) SK_API_AVAILABLE(macos(10.11)
void setFragmentBytes(const void *bytes, NSUInteger length, NSUInteger index) SK_API_AVAILABLE(macos(10.11)
void setFragmentBuffer(id< MTLBuffer > buffer, NSUInteger offset, NSUInteger index)
void setFragmentTexture(id< MTLTexture > texture, NSUInteger index)
void setVertexBytes(const void *bytes, NSUInteger length, NSUInteger index) SK_API_AVAILABLE(macos(10.11)
void setVertexBufferOffset(NSUInteger offset, NSUInteger index) SK_API_AVAILABLE(macos(10.11)
void drawPrimitives(MTLPrimitiveType primitiveType, NSUInteger vertexStart, NSUInteger vertexCount, NSUInteger instanceCount, NSUInteger baseInstance) SK_API_AVAILABLE(macos(10.11)
void setDepthStencilState(id< MTLDepthStencilState > depthStencilState)
const SharedContext * sharedContext() const
Definition Resource.h:187
static const uint8_t buffer[]
size_t length
FlTexture * texture
Budgeted
Definition GpuTypes.h:35
Definition ref_ptr.h:256
Point offset