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