Flutter Engine
The Flutter Engine
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 = 6;
258 inline static constexpr int kMaxExpectedTextures = 16;
259
261 sk_cfp<id<MTLRenderCommandEncoder>> encoder)
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
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
#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)
const char * getResourceType() const override
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:189
size_t length
FlTexture * texture
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not defaults to or::depending on whether ipv6 is specified vm service A custom Dart VM Service port The default is to pick a randomly available open port disable vm Disable the Dart VM Service The Dart VM Service is never available in release mode disable vm service Disable mDNS Dart VM Service publication Bind to the IPv6 localhost address for the Dart VM Service Ignored if vm service host is set endless trace buffer
Definition: switches.h:126
Definition: GpuTools.h:21
Budgeted
Definition: GpuTypes.h:35
Definition: ref_ptr.h:256
SeparatedVector2 offset