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