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