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