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