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, *)) { 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 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, *)) { 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 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)) { 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)) { 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)) { 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) SK_API_AVAILABLE(macos(10.11), ios(9.0)) { 191 [fCommandEncoder drawPrimitives:primitiveType 192 vertexStart:vertexStart 193 vertexCount:vertexCount 194 instanceCount:instanceCount 195 baseInstance:baseInstance]; 196 } drawPrimitives(MTLPrimitiveType primitiveType,id<MTLBuffer> indirectBuffer,NSUInteger indirectBufferOffset)197 void drawPrimitives(MTLPrimitiveType primitiveType, id<MTLBuffer> indirectBuffer, 198 NSUInteger indirectBufferOffset) SK_API_AVAILABLE(macos(10.11), ios(9.0)) { 199 [fCommandEncoder drawPrimitives:primitiveType 200 indirectBuffer:indirectBuffer 201 indirectBufferOffset:indirectBufferOffset]; 202 } 203 drawIndexedPrimitives(MTLPrimitiveType primitiveType,NSUInteger indexCount,MTLIndexType indexType,id<MTLBuffer> indexBuffer,NSUInteger indexBufferOffset)204 void drawIndexedPrimitives(MTLPrimitiveType primitiveType, NSUInteger indexCount, 205 MTLIndexType indexType, id<MTLBuffer> indexBuffer, 206 NSUInteger indexBufferOffset) { 207 [fCommandEncoder drawIndexedPrimitives:primitiveType 208 indexCount:indexCount 209 indexType:indexType 210 indexBuffer:indexBuffer 211 indexBufferOffset:indexBufferOffset]; 212 } drawIndexedPrimitives(MTLPrimitiveType primitiveType,NSUInteger indexCount,MTLIndexType indexType,id<MTLBuffer> indexBuffer,NSUInteger indexBufferOffset,NSUInteger instanceCount,NSInteger baseVertex,NSUInteger baseInstance)213 void drawIndexedPrimitives(MTLPrimitiveType primitiveType, NSUInteger indexCount, 214 MTLIndexType indexType, id<MTLBuffer> indexBuffer, 215 NSUInteger indexBufferOffset, 216 NSUInteger instanceCount, 217 NSInteger baseVertex, 218 NSUInteger baseInstance) SK_API_AVAILABLE(macos(10.11), ios(9.0)) { 219 [fCommandEncoder drawIndexedPrimitives:primitiveType 220 indexCount:indexCount 221 indexType:indexType 222 indexBuffer:indexBuffer 223 indexBufferOffset:indexBufferOffset 224 instanceCount:instanceCount 225 baseVertex:baseVertex 226 baseInstance:baseInstance]; 227 } drawIndexedPrimitives(MTLPrimitiveType primitiveType,MTLIndexType indexType,id<MTLBuffer> indexBuffer,NSUInteger indexBufferOffset,id<MTLBuffer> indirectBuffer,NSUInteger indirectBufferOffset)228 void drawIndexedPrimitives(MTLPrimitiveType primitiveType, 229 MTLIndexType indexType, id<MTLBuffer> indexBuffer, 230 NSUInteger indexBufferOffset, id<MTLBuffer> indirectBuffer, 231 NSUInteger indirectBufferOffset) 232 SK_API_AVAILABLE(macos(10.11), ios(9.0)) { 233 [fCommandEncoder drawIndexedPrimitives:primitiveType 234 indexType:indexType 235 indexBuffer:indexBuffer 236 indexBufferOffset:indexBufferOffset 237 indirectBuffer:indirectBuffer 238 indirectBufferOffset:indirectBufferOffset]; 239 } 240 endEncoding()241 void endEncoding() { 242 [fCommandEncoder endEncoding]; 243 } 244 245 private: GrMtlRenderCommandEncoder(id<MTLRenderCommandEncoder> encoder)246 GrMtlRenderCommandEncoder(id<MTLRenderCommandEncoder> encoder) 247 : fCommandEncoder(encoder) {} 248 249 id<MTLRenderCommandEncoder> fCommandEncoder = nil; 250 251 // As of 2022-03-09 All GPU families have the same value at: 252 // https://developer.apple.com/metal/Metal-Feature-Set-Tables.pdf 253 static const int kMaxSamplers = 16; 254 // This is a self-imposed limit and is less than any GPU family's value at 255 // https://developer.apple.com/metal/Metal-Feature-Set-Tables.pdf 256 // Our implementation uses a 1:1 correspondence between textures and samplers. 257 static const int kMaxTextures = kMaxSamplers; 258 259 __weak id<MTLRenderPipelineState> fCurrentRenderPipelineState = nil; 260 __weak id<MTLDepthStencilState> fCurrentDepthStencilState = nil; 261 __weak id<MTLBuffer> fCurrentVertexBuffer[2 + GrMtlUniformHandler::kUniformBindingCount]; 262 NSUInteger fCurrentVertexOffset[2 + GrMtlUniformHandler::kUniformBindingCount]; 263 __weak id<MTLBuffer> fCurrentFragmentBuffer[GrMtlUniformHandler::kUniformBindingCount]; 264 NSUInteger fCurrentFragmentOffset[2 + GrMtlUniformHandler::kUniformBindingCount]; 265 __weak id<MTLTexture> fCurrentTexture[kMaxTextures]; 266 GrMtlSampler* fCurrentSampler[kMaxSamplers] = {}; 267 MTLScissorRect fCurrentScissorRect = { 0, 0, 0, 0 }; 268 MTLTriangleFillMode fCurrentTriangleFillMode = (MTLTriangleFillMode)-1; 269 }; 270 271 GR_NORETAIN_END 272 273 #endif 274