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