xref: /aosp_15_r20/external/skia/src/gpu/ganesh/GrOpsRenderPass.h (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1 /*
2 * Copyright 2016 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 GrOpsRenderPass_DEFINED
9 #define GrOpsRenderPass_DEFINED
10 
11 #include "include/core/SkDrawable.h"
12 #include "include/core/SkRefCnt.h"
13 #include "include/gpu/ganesh/GrTypes.h"
14 #include "include/private/base/SkAssert.h"
15 #include "include/private/base/SkDebug.h"
16 #include "include/private/gpu/ganesh/GrTypesPriv.h"
17 #include "src/gpu/ganesh/GrBuffer.h"
18 #include "src/gpu/ganesh/GrDeferredUpload.h"
19 #include "src/gpu/ganesh/GrXferProcessor.h"
20 
21 #include <array>
22 #include <cstddef>
23 #include <cstdint>
24 #include <memory>
25 
26 class GrGeometryProcessor;
27 class GrGpu;
28 class GrOpFlushState;
29 class GrPipeline;
30 class GrProgramInfo;
31 class GrRenderTarget;
32 class GrScissorState;
33 class GrSurfaceProxy;
34 struct SkIRect;
35 struct SkRect;
36 
37 /**
38  * The GrOpsRenderPass is a series of commands (draws, clears, and discards), which all target the
39  * same render target. It is possible that these commands execute immediately (GL), or get buffered
40  * up for later execution (Vulkan). GrOps execute into a GrOpsRenderPass.
41  */
42 class GrOpsRenderPass {
43 public:
~GrOpsRenderPass()44     virtual ~GrOpsRenderPass() {}
45 
46     struct LoadAndStoreInfo {
47         GrLoadOp             fLoadOp;
48         GrStoreOp            fStoreOp;
49         std::array<float, 4> fClearColor;
50     };
51 
52     // Load-time clears of the stencil buffer are always to 0 so we don't store
53     // an 'fStencilClearValue'
54     struct StencilLoadAndStoreInfo {
55         GrLoadOp  fLoadOp;
56         GrStoreOp fStoreOp;
57     };
58 
59     void begin();
60     // Signals the end of recording to the GrOpsRenderPass and that it can now be submitted.
61     void end();
62 
63     // Updates the internal pipeline state for drawing with the provided GrProgramInfo. Enters an
64     // internal "bad" state if the pipeline could not be set.
65     void bindPipeline(const GrProgramInfo&, const SkRect& drawBounds);
66 
67     // The scissor rect is always dynamic state and therefore not stored on GrPipeline. If scissor
68     // test is enabled on the current pipeline, then the client must call setScissorRect() before
69     // drawing. The scissor rect may also be updated between draws without having to bind a new
70     // pipeline.
71     void setScissorRect(const SkIRect&);
72 
73     // Binds textures for the primitive processor and any FP on the GrPipeline. Texture bindings are
74     // dynamic state and therefore not set during bindPipeline(). If the current program uses
75     // textures, then the client must call bindTextures() before drawing. The primitive processor
76     // textures may also be updated between draws by calling bindTextures() again with a different
77     // array for primProcTextures. (On subsequent calls, if the backend is capable of updating the
78     // primitive processor textures independently, then it will automatically skip re-binding
79     // FP textures from GrPipeline.)
80     //
81     // If the current program does not use textures, this is a no-op.
82     void bindTextures(const GrGeometryProcessor&,
83                       const GrSurfaceProxy* const geomProcTextures[],
84                       const GrPipeline&);
85 
86     void bindBuffers(sk_sp<const GrBuffer> indexBuffer, sk_sp<const GrBuffer> instanceBuffer,
87                      sk_sp<const GrBuffer> vertexBuffer, GrPrimitiveRestart = GrPrimitiveRestart::kNo);
88 
89     // The next several draw*() methods issue draws using the current pipeline state. Before
90     // drawing, the caller must configure the pipeline and dynamic state:
91     //
92     //   - Call bindPipeline()
93     //   - If the scissor test is enabled, call setScissorRect()
94     //   - If the current program uses textures, call bindTextures()
95     //   - Call bindBuffers() (even if all buffers are null)
96     void draw(int vertexCount, int baseVertex);
97     void drawIndexed(int indexCount, int baseIndex, uint16_t minIndexValue, uint16_t maxIndexValue,
98                      int baseVertex);
99 
100     // Requires caps.drawInstancedSupport().
101     void drawInstanced(int instanceCount, int baseInstance, int vertexCount, int baseVertex);
102 
103     // Requires caps.drawInstancedSupport().
104     void drawIndexedInstanced(int indexCount, int baseIndex, int instanceCount, int baseInstance,
105                               int baseVertex);
106 
107     // Executes multiple draws from an array of GrDrawIndirectCommand in the provided buffer.
108     //
109     // Requires caps.drawInstancedSupport().
110     //
111     // If caps.nativeDrawIndirectSupport() is unavailable, then 'drawIndirectBuffer' must be a
112     // GrCpuBuffer in order to polyfill. Performance may suffer in this scenario.
113     void drawIndirect(const GrBuffer* drawIndirectBuffer, size_t bufferOffset, int drawCount);
114 
115     // Executes multiple draws from an array of GrDrawIndexedIndirectCommand in the provided buffer.
116     //
117     // Requires caps.drawInstancedSupport().
118     //
119     // If caps.nativeDrawIndirectSupport() is unavailable, then 'drawIndirectBuffer' must be a
120     // GrCpuBuffer in order to polyfill. Performance may suffer in this scenario.
121     void drawIndexedIndirect(const GrBuffer* drawIndirectBuffer, size_t bufferOffset,
122                              int drawCount);
123 
124     // This is a helper method for drawing a repeating pattern of vertices. The bound index buffer
125     // is understood to contain 'maxPatternRepetitionsInIndexBuffer' repetitions of the pattern.
126     // If more repetitions are required, then we loop.
127     void drawIndexPattern(int patternIndexCount, int patternRepeatCount,
128                           int maxPatternRepetitionsInIndexBuffer, int patternVertexCount,
129                           int baseVertex);
130 
131     // Performs an upload of vertex data in the middle of a set of a set of draws
132     virtual void inlineUpload(GrOpFlushState*, GrDeferredTextureUploadFn&) = 0;
133 
134     /**
135      * Clear the owned render target. Clears the full target if 'scissor' is disabled, otherwise it
136      * is restricted to 'scissor'. Must check caps.performPartialClearsAsDraws() before using an
137      * enabled scissor test; must check caps.performColorClearsAsDraws() before using this at all.
138      */
139     void clear(const GrScissorState& scissor, std::array<float, 4> color);
140 
141     /**
142      * Same as clear() but modifies the stencil; check caps.performStencilClearsAsDraws() and
143      * caps.performPartialClearsAsDraws().
144      */
145     void clearStencilClip(const GrScissorState& scissor, bool insideStencilMask);
146 
147     /**
148      * Executes the SkDrawable object for the underlying backend.
149      */
150     void executeDrawable(std::unique_ptr<SkDrawable::GpuDrawHandler>);
151 
152 protected:
GrOpsRenderPass()153     GrOpsRenderPass() : fOrigin(kTopLeft_GrSurfaceOrigin), fRenderTarget(nullptr) {}
154 
GrOpsRenderPass(GrRenderTarget * rt,GrSurfaceOrigin origin)155     GrOpsRenderPass(GrRenderTarget* rt, GrSurfaceOrigin origin)
156             : fOrigin(origin)
157             , fRenderTarget(rt) {
158     }
159 
set(GrRenderTarget * rt,GrSurfaceOrigin origin)160     void set(GrRenderTarget* rt, GrSurfaceOrigin origin) {
161         SkASSERT(!fRenderTarget);
162 
163         fRenderTarget = rt;
164         fOrigin = origin;
165     }
166 
167     GrSurfaceOrigin fOrigin;
168     GrRenderTarget* fRenderTarget;
169 
170     // Backends may defer binding of certain buffers if their draw API requires a buffer, or if
171     // their bind methods don't support base values.
172     sk_sp<const GrBuffer> fActiveIndexBuffer;
173     sk_sp<const GrBuffer> fActiveVertexBuffer;
174     sk_sp<const GrBuffer> fActiveInstanceBuffer;
175 
176 private:
177     virtual GrGpu* gpu() = 0;
178 
resetActiveBuffers()179     void resetActiveBuffers() {
180         fActiveIndexBuffer.reset();
181         fActiveInstanceBuffer.reset();
182         fActiveVertexBuffer.reset();
183     }
184 
185     bool prepareToDraw();
186 
187     // overridden by backend-specific derived class to perform the rendering command.
onBegin()188     virtual void onBegin() {}
onEnd()189     virtual void onEnd() {}
190     virtual bool onBindPipeline(const GrProgramInfo&, const SkRect& drawBounds) = 0;
191     virtual void onSetScissorRect(const SkIRect&) = 0;
192     virtual bool onBindTextures(const GrGeometryProcessor&,
193                                 const GrSurfaceProxy* const geomProcTextures[],
194                                 const GrPipeline&) = 0;
195     virtual void onBindBuffers(sk_sp<const GrBuffer> indexBuffer, sk_sp<const GrBuffer> instanceBuffer,
196                                sk_sp<const GrBuffer> vertexBuffer, GrPrimitiveRestart) = 0;
197     virtual void onDraw(int vertexCount, int baseVertex) = 0;
198     virtual void onDrawIndexed(int indexCount, int baseIndex, uint16_t minIndexValue,
199                                uint16_t maxIndexValue, int baseVertex) = 0;
200     virtual void onDrawInstanced(int instanceCount, int baseInstance, int vertexCount,
201                                  int baseVertex) = 0;
202     virtual void onDrawIndexedInstanced(int indexCount, int baseIndex, int instanceCount,
203                                         int baseInstance, int baseVertex) = 0;
onDrawIndirect(const GrBuffer *,size_t offset,int drawCount)204     virtual void onDrawIndirect(const GrBuffer*, size_t offset, int drawCount) {
205         SK_ABORT("Not implemented.");  // Only called if caps.nativeDrawIndirectSupport().
206     }
onDrawIndexedIndirect(const GrBuffer *,size_t offset,int drawCount)207     virtual void onDrawIndexedIndirect(const GrBuffer*, size_t offset, int drawCount) {
208         SK_ABORT("Not implemented.");  // Only called if caps.nativeDrawIndirectSupport().
209     }
210     virtual void onClear(const GrScissorState&, std::array<float, 4> color) = 0;
211     virtual void onClearStencilClip(const GrScissorState&, bool insideStencilMask) = 0;
onExecuteDrawable(std::unique_ptr<SkDrawable::GpuDrawHandler>)212     virtual void onExecuteDrawable(std::unique_ptr<SkDrawable::GpuDrawHandler>) {}
213 
214     enum class DrawPipelineStatus {
215         kOk = 0,
216         kNotConfigured,
217         kFailedToBind
218     };
219 
220     DrawPipelineStatus fDrawPipelineStatus = DrawPipelineStatus::kNotConfigured;
221     GrXferBarrierType fXferBarrierType;
222 
223 #ifdef SK_DEBUG
224     enum class DynamicStateStatus {
225         kDisabled,
226         kUninitialized,
227         kConfigured
228     };
229 
230     DynamicStateStatus fScissorStatus;
231     DynamicStateStatus fTextureBindingStatus;
232     bool fHasIndexBuffer;
233     DynamicStateStatus fInstanceBufferStatus;
234     DynamicStateStatus fVertexBufferStatus;
235 #endif
236 
237     using INHERITED = GrOpsRenderPass;
238 };
239 
240 #endif
241