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