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 GrMtlRenderCommandEncoder_DEFINED 9 #define GrMtlRenderCommandEncoder_DEFINED 10 11 #include <memory> 12 13 #include "include/private/SkColorData.h" 14 #include "src/gpu/ganesh/GrSamplerState.h" 15 #include "src/gpu/ganesh/mtl/GrMtlSampler.h" 16 #include "src/gpu/ganesh/mtl/GrMtlUniformHandler.h" 17 #include "src/gpu/ganesh/mtl/GrMtlUtil.h" 18 19 class GrMtlSampler; 20 21 #import <Metal/Metal.h> 22 23 GR_NORETAIN_BEGIN 24 25 /** 26 * Wraps a MTLRenderCommandEncoder object and associated tracked state 27 */ 28 class GrMtlRenderCommandEncoder { 29 public: Make(id<MTLRenderCommandEncoder> encoder)30 static std::unique_ptr<GrMtlRenderCommandEncoder> Make(id<MTLRenderCommandEncoder> encoder) { 31 return std::unique_ptr<GrMtlRenderCommandEncoder>(new GrMtlRenderCommandEncoder(encoder)); 32 } 33 setLabel(NSString * label)34 void setLabel(NSString* label) { 35 [fCommandEncoder setLabel:label]; 36 } 37 pushDebugGroup(NSString * string)38 void pushDebugGroup(NSString* string) { 39 [fCommandEncoder pushDebugGroup:string]; 40 } popDebugGroup()41 void popDebugGroup() { 42 [fCommandEncoder popDebugGroup]; 43 } insertDebugSignpost(NSString * string)44 void insertDebugSignpost(NSString* string) { 45 [fCommandEncoder insertDebugSignpost:string]; 46 } 47 setRenderPipelineState(id<MTLRenderPipelineState> pso)48 void setRenderPipelineState(id<MTLRenderPipelineState> pso) { 49 if (fCurrentRenderPipelineState != pso) { 50 [fCommandEncoder setRenderPipelineState:pso]; 51 fCurrentRenderPipelineState = pso; 52 } 53 } 54 setTriangleFillMode(MTLTriangleFillMode fillMode)55 void setTriangleFillMode(MTLTriangleFillMode fillMode) { 56 if (fCurrentTriangleFillMode != fillMode) { 57 [fCommandEncoder setTriangleFillMode:fillMode]; 58 fCurrentTriangleFillMode = fillMode; 59 } 60 } 61 setFrontFacingWinding(MTLWinding winding)62 void setFrontFacingWinding(MTLWinding winding) { 63 [fCommandEncoder setFrontFacingWinding:winding]; 64 } 65 setViewport(const MTLViewport & viewport)66 void setViewport(const MTLViewport& viewport) { 67 [fCommandEncoder setViewport:viewport]; 68 } 69 setVertexBuffer(id<MTLBuffer> buffer,NSUInteger offset,NSUInteger index)70 void setVertexBuffer(id<MTLBuffer> buffer, NSUInteger offset, NSUInteger index) { 71 if (@available(macOS 10.11, iOS 8.3, tvOS 9.0, *)) { 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), tvos(9.0)) { 87 if (fCurrentVertexOffset[index] != offset) { 88 [fCommandEncoder setVertexBufferOffset:offset 89 atIndex:index]; 90 fCurrentVertexOffset[index] = offset; 91 } 92 } 93 setFragmentBuffer(id<MTLBuffer> buffer,NSUInteger offset,NSUInteger index)94 void setFragmentBuffer(id<MTLBuffer> buffer, NSUInteger offset, NSUInteger index) { 95 if (@available(macOS 10.11, iOS 8.3, tvOS 9.0, *)) { 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), tvos(9.0)) { 111 if (fCurrentFragmentOffset[index] != offset) { 112 [fCommandEncoder setFragmentBufferOffset:offset 113 atIndex:index]; 114 fCurrentFragmentOffset[index] = offset; 115 } 116 } 117 setVertexBytes(const void * bytes,NSUInteger length,NSUInteger index)118 void setVertexBytes(const void* bytes, NSUInteger length, NSUInteger index) 119 SK_API_AVAILABLE(macos(10.11), ios(8.3), tvos(9.0)) { 120 [fCommandEncoder setVertexBytes:bytes 121 length:length 122 atIndex:index]; 123 } setFragmentBytes(const void * bytes,NSUInteger length,NSUInteger index)124 void setFragmentBytes(const void* bytes, NSUInteger length, NSUInteger index) 125 SK_API_AVAILABLE(macos(10.11), ios(8.3), tvos(9.0)) { 126 [fCommandEncoder setFragmentBytes:bytes 127 length:length 128 atIndex:index]; 129 } 130 setFragmentTexture(id<MTLTexture> texture,NSUInteger index)131 void setFragmentTexture(id<MTLTexture> texture, NSUInteger index) { 132 SkASSERT(index < kMaxTextures); 133 if (fCurrentTexture[index] != texture) { 134 [fCommandEncoder setFragmentTexture:texture 135 atIndex:index]; 136 fCurrentTexture[index] = texture; 137 } 138 } setFragmentSamplerState(GrMtlSampler * sampler,NSUInteger index)139 void setFragmentSamplerState(GrMtlSampler* sampler, NSUInteger index) { 140 SkASSERT(index < kMaxSamplers); 141 if (fCurrentSampler[index] != sampler) { 142 [fCommandEncoder setFragmentSamplerState: sampler->mtlSampler() 143 atIndex: index]; 144 fCurrentSampler[index] = sampler; 145 } 146 } 147 setBlendColor(SkPMColor4f blendConst)148 void setBlendColor(SkPMColor4f blendConst) { 149 [fCommandEncoder setBlendColorRed: blendConst.fR 150 green: blendConst.fG 151 blue: blendConst.fB 152 alpha: blendConst.fA]; 153 } 154 setStencilFrontBackReferenceValues(uint32_t frontReferenceValue,uint32_t backReferenceValue)155 void setStencilFrontBackReferenceValues(uint32_t frontReferenceValue, 156 uint32_t backReferenceValue) 157 SK_API_AVAILABLE(macos(10.11), ios(9.0), tvos(9.0)) { 158 [fCommandEncoder 159 setStencilFrontReferenceValue:frontReferenceValue 160 backReferenceValue:backReferenceValue]; 161 } setStencilReferenceValue(uint32_t referenceValue)162 void setStencilReferenceValue(uint32_t referenceValue) { 163 [fCommandEncoder setStencilReferenceValue:referenceValue]; 164 } setDepthStencilState(id<MTLDepthStencilState> depthStencilState)165 void setDepthStencilState(id<MTLDepthStencilState> depthStencilState) { 166 if (depthStencilState != fCurrentDepthStencilState) { 167 [fCommandEncoder setDepthStencilState:depthStencilState]; 168 fCurrentDepthStencilState = depthStencilState; 169 } 170 } 171 setScissorRect(const MTLScissorRect & scissorRect)172 void setScissorRect(const MTLScissorRect& scissorRect) { 173 if (fCurrentScissorRect.x != scissorRect.x || 174 fCurrentScissorRect.y != scissorRect.y || 175 fCurrentScissorRect.width != scissorRect.width || 176 fCurrentScissorRect.height != scissorRect.height) { 177 [fCommandEncoder setScissorRect:scissorRect]; 178 fCurrentScissorRect = scissorRect; 179 } 180 } 181 drawPrimitives(MTLPrimitiveType primitiveType,NSUInteger vertexStart,NSUInteger vertexCount)182 void drawPrimitives(MTLPrimitiveType primitiveType, NSUInteger vertexStart, 183 NSUInteger vertexCount) { 184 [fCommandEncoder drawPrimitives:primitiveType 185 vertexStart:vertexStart 186 vertexCount:vertexCount]; 187 } drawPrimitives(MTLPrimitiveType primitiveType,NSUInteger vertexStart,NSUInteger vertexCount,NSUInteger instanceCount,NSUInteger baseInstance)188 void drawPrimitives(MTLPrimitiveType primitiveType, NSUInteger vertexStart, 189 NSUInteger vertexCount, NSUInteger instanceCount, 190 NSUInteger baseInstance) 191 SK_API_AVAILABLE(macos(10.11), ios(9.0), tvos(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) 200 SK_API_AVAILABLE(macos(10.11), ios(9.0), tvos(9.0)) { 201 [fCommandEncoder drawPrimitives:primitiveType 202 indirectBuffer:indirectBuffer 203 indirectBufferOffset:indirectBufferOffset]; 204 } 205 drawIndexedPrimitives(MTLPrimitiveType primitiveType,NSUInteger indexCount,MTLIndexType indexType,id<MTLBuffer> indexBuffer,NSUInteger indexBufferOffset)206 void drawIndexedPrimitives(MTLPrimitiveType primitiveType, NSUInteger indexCount, 207 MTLIndexType indexType, id<MTLBuffer> indexBuffer, 208 NSUInteger indexBufferOffset) { 209 [fCommandEncoder drawIndexedPrimitives:primitiveType 210 indexCount:indexCount 211 indexType:indexType 212 indexBuffer:indexBuffer 213 indexBufferOffset:indexBufferOffset]; 214 } drawIndexedPrimitives(MTLPrimitiveType primitiveType,NSUInteger indexCount,MTLIndexType indexType,id<MTLBuffer> indexBuffer,NSUInteger indexBufferOffset,NSUInteger instanceCount,NSInteger baseVertex,NSUInteger baseInstance)215 void drawIndexedPrimitives(MTLPrimitiveType primitiveType, NSUInteger indexCount, 216 MTLIndexType indexType, id<MTLBuffer> indexBuffer, 217 NSUInteger indexBufferOffset, 218 NSUInteger instanceCount, 219 NSInteger baseVertex, 220 NSUInteger baseInstance) 221 SK_API_AVAILABLE(macos(10.11), ios(9.0), tvos(9.0)) { 222 [fCommandEncoder drawIndexedPrimitives:primitiveType 223 indexCount:indexCount 224 indexType:indexType 225 indexBuffer:indexBuffer 226 indexBufferOffset:indexBufferOffset 227 instanceCount:instanceCount 228 baseVertex:baseVertex 229 baseInstance:baseInstance]; 230 } drawIndexedPrimitives(MTLPrimitiveType primitiveType,MTLIndexType indexType,id<MTLBuffer> indexBuffer,NSUInteger indexBufferOffset,id<MTLBuffer> indirectBuffer,NSUInteger indirectBufferOffset)231 void drawIndexedPrimitives(MTLPrimitiveType primitiveType, 232 MTLIndexType indexType, id<MTLBuffer> indexBuffer, 233 NSUInteger indexBufferOffset, id<MTLBuffer> indirectBuffer, 234 NSUInteger indirectBufferOffset) 235 SK_API_AVAILABLE(macos(10.11), ios(9.0), tvos(9.0)) { 236 [fCommandEncoder drawIndexedPrimitives:primitiveType 237 indexType:indexType 238 indexBuffer:indexBuffer 239 indexBufferOffset:indexBufferOffset 240 indirectBuffer:indirectBuffer 241 indirectBufferOffset:indirectBufferOffset]; 242 } 243 endEncoding()244 void endEncoding() { 245 [fCommandEncoder endEncoding]; 246 } 247 248 private: GrMtlRenderCommandEncoder(id<MTLRenderCommandEncoder> encoder)249 GrMtlRenderCommandEncoder(id<MTLRenderCommandEncoder> encoder) 250 : fCommandEncoder(encoder) {} 251 252 id<MTLRenderCommandEncoder> fCommandEncoder = nil; 253 254 // As of 2022-03-09 All GPU families have the same value at: 255 // https://developer.apple.com/metal/Metal-Feature-Set-Tables.pdf 256 static const int kMaxSamplers = 16; 257 // This is a self-imposed limit and is less than any GPU family's value at 258 // https://developer.apple.com/metal/Metal-Feature-Set-Tables.pdf 259 // Our implementation uses a 1:1 correspondence between textures and samplers. 260 static const int kMaxTextures = kMaxSamplers; 261 262 __weak id<MTLRenderPipelineState> fCurrentRenderPipelineState = nil; 263 __weak id<MTLDepthStencilState> fCurrentDepthStencilState = nil; 264 __weak id<MTLBuffer> fCurrentVertexBuffer[2 + GrMtlUniformHandler::kUniformBindingCount]; 265 NSUInteger fCurrentVertexOffset[2 + GrMtlUniformHandler::kUniformBindingCount]; 266 __weak id<MTLBuffer> fCurrentFragmentBuffer[GrMtlUniformHandler::kUniformBindingCount]; 267 NSUInteger fCurrentFragmentOffset[2 + GrMtlUniformHandler::kUniformBindingCount]; 268 __weak id<MTLTexture> fCurrentTexture[kMaxTextures]; 269 GrMtlSampler* fCurrentSampler[kMaxSamplers] = {}; 270 MTLScissorRect fCurrentScissorRect = { 0, 0, 0, 0 }; 271 MTLTriangleFillMode fCurrentTriangleFillMode = (MTLTriangleFillMode)-1; 272 }; 273 274 GR_NORETAIN_END 275 276 #endif 277