egdaniel | 9cb6340 | 2016-06-23 08:37:05 -0700 | [diff] [blame] | 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 | |
Greg Daniel | 2d41d0d | 2019-08-26 11:08:51 -0400 | [diff] [blame] | 8 | #include "src/gpu/GrOpsRenderPass.h" |
egdaniel | 9cb6340 | 2016-06-23 08:37:05 -0700 | [diff] [blame] | 9 | |
Mike Klein | c0bd9f9 | 2019-04-23 12:05:21 -0500 | [diff] [blame] | 10 | #include "include/core/SkRect.h" |
Mike Klein | c0bd9f9 | 2019-04-23 12:05:21 -0500 | [diff] [blame] | 11 | #include "src/gpu/GrCaps.h" |
Michael Ludwig | 1e63279 | 2020-05-21 12:45:31 -0400 | [diff] [blame] | 12 | #include "src/gpu/GrCpuBuffer.h" |
Chris Dalton | a6a3d05 | 2021-02-07 20:56:36 -0700 | [diff] [blame] | 13 | #include "src/gpu/GrDrawIndirectCommand.h" |
Robert Phillips | 787fd9d | 2021-03-22 14:48:09 -0400 | [diff] [blame] | 14 | #include "src/gpu/GrGeometryProcessor.h" |
Mike Klein | c0bd9f9 | 2019-04-23 12:05:21 -0500 | [diff] [blame] | 15 | #include "src/gpu/GrGpu.h" |
Robert Phillips | 901aff0 | 2019-10-08 12:32:56 -0400 | [diff] [blame] | 16 | #include "src/gpu/GrProgramInfo.h" |
Brian Salomon | 201cdbb | 2019-08-14 17:00:30 -0400 | [diff] [blame] | 17 | #include "src/gpu/GrRenderTarget.h" |
Michael Ludwig | 1e63279 | 2020-05-21 12:45:31 -0400 | [diff] [blame] | 18 | #include "src/gpu/GrScissorState.h" |
Chris Dalton | eb694b7 | 2020-03-16 09:25:50 -0600 | [diff] [blame] | 19 | #include "src/gpu/GrSimpleMesh.h" |
Brian Salomon | 4cfae3b | 2020-07-23 10:33:24 -0400 | [diff] [blame] | 20 | #include "src/gpu/GrTexture.h" |
egdaniel | 9cb6340 | 2016-06-23 08:37:05 -0700 | [diff] [blame] | 21 | |
Chris Dalton | 2c3e169 | 2020-03-20 12:32:55 -0600 | [diff] [blame] | 22 | void GrOpsRenderPass::begin() { |
| 23 | fDrawPipelineStatus = DrawPipelineStatus::kNotConfigured; |
| 24 | #ifdef SK_DEBUG |
| 25 | fScissorStatus = DynamicStateStatus::kDisabled; |
| 26 | fTextureBindingStatus = DynamicStateStatus::kDisabled; |
| 27 | fHasIndexBuffer = false; |
| 28 | fInstanceBufferStatus = DynamicStateStatus::kDisabled; |
| 29 | fVertexBufferStatus = DynamicStateStatus::kDisabled; |
| 30 | #endif |
| 31 | this->onBegin(); |
| 32 | } |
| 33 | |
| 34 | void GrOpsRenderPass::end() { |
| 35 | this->onEnd(); |
Chris Dalton | b60c8a2 | 2020-03-31 17:24:22 -0600 | [diff] [blame] | 36 | this->resetActiveBuffers(); |
Chris Dalton | 2c3e169 | 2020-03-20 12:32:55 -0600 | [diff] [blame] | 37 | } |
| 38 | |
Brian Salomon | 07bc9a2 | 2020-12-02 13:37:16 -0500 | [diff] [blame] | 39 | void GrOpsRenderPass::clear(const GrScissorState& scissor, std::array<float, 4> color) { |
Robert Phillips | 4912d90 | 2018-04-27 12:09:35 -0400 | [diff] [blame] | 40 | SkASSERT(fRenderTarget); |
Michael Ludwig | c39d0c8 | 2019-01-15 10:03:43 -0500 | [diff] [blame] | 41 | // A clear at this level will always be a true clear, so make sure clears were not supposed to |
| 42 | // be redirected to draws instead |
| 43 | SkASSERT(!this->gpu()->caps()->performColorClearsAsDraws()); |
Michael Ludwig | 1e63279 | 2020-05-21 12:45:31 -0400 | [diff] [blame] | 44 | SkASSERT(!scissor.enabled() || !this->gpu()->caps()->performPartialClearsAsDraws()); |
Chris Dalton | 4386ad1 | 2020-02-19 16:42:06 -0700 | [diff] [blame] | 45 | fDrawPipelineStatus = DrawPipelineStatus::kNotConfigured; |
Michael Ludwig | 1e63279 | 2020-05-21 12:45:31 -0400 | [diff] [blame] | 46 | this->onClear(scissor, color); |
egdaniel | 9cb6340 | 2016-06-23 08:37:05 -0700 | [diff] [blame] | 47 | } |
| 48 | |
Michael Ludwig | 1e63279 | 2020-05-21 12:45:31 -0400 | [diff] [blame] | 49 | void GrOpsRenderPass::clearStencilClip(const GrScissorState& scissor, bool insideStencilMask) { |
Michael Ludwig | c39d0c8 | 2019-01-15 10:03:43 -0500 | [diff] [blame] | 50 | // As above, make sure the stencil clear wasn't supposed to be a draw rect with stencil settings |
| 51 | SkASSERT(!this->gpu()->caps()->performStencilClearsAsDraws()); |
Michael Ludwig | 1e63279 | 2020-05-21 12:45:31 -0400 | [diff] [blame] | 52 | SkASSERT(!scissor.enabled() || !this->gpu()->caps()->performPartialClearsAsDraws()); |
Chris Dalton | 4386ad1 | 2020-02-19 16:42:06 -0700 | [diff] [blame] | 53 | fDrawPipelineStatus = DrawPipelineStatus::kNotConfigured; |
Michael Ludwig | 1e63279 | 2020-05-21 12:45:31 -0400 | [diff] [blame] | 54 | this->onClearStencilClip(scissor, insideStencilMask); |
egdaniel | 9cb6340 | 2016-06-23 08:37:05 -0700 | [diff] [blame] | 55 | } |
| 56 | |
Chris Dalton | 4386ad1 | 2020-02-19 16:42:06 -0700 | [diff] [blame] | 57 | void GrOpsRenderPass::executeDrawable(std::unique_ptr<SkDrawable::GpuDrawHandler> drawable) { |
| 58 | fDrawPipelineStatus = DrawPipelineStatus::kNotConfigured; |
| 59 | this->onExecuteDrawable(std::move(drawable)); |
| 60 | } |
Robert Phillips | 901aff0 | 2019-10-08 12:32:56 -0400 | [diff] [blame] | 61 | |
Chris Dalton | aa0e45c | 2020-03-16 10:05:11 -0600 | [diff] [blame] | 62 | void GrOpsRenderPass::bindPipeline(const GrProgramInfo& programInfo, const SkRect& drawBounds) { |
Chris Dalton | bca46e2 | 2017-05-15 11:03:26 -0600 | [diff] [blame] | 63 | #ifdef SK_DEBUG |
Chris Dalton | 56c09f0 | 2020-03-13 17:30:03 -0600 | [diff] [blame] | 64 | // Both the 'programInfo' and this renderPass have an origin. Since they come from the same |
| 65 | // place (i.e., the target renderTargetProxy) they had best agree. |
| 66 | SkASSERT(programInfo.origin() == fOrigin); |
Robert Phillips | 787fd9d | 2021-03-22 14:48:09 -0400 | [diff] [blame] | 67 | if (programInfo.geomProc().hasInstanceAttributes()) { |
Chris Dalton | a77cdee | 2020-04-03 14:50:43 -0600 | [diff] [blame] | 68 | SkASSERT(this->gpu()->caps()->drawInstancedSupport()); |
Chris Dalton | 4386ad1 | 2020-02-19 16:42:06 -0700 | [diff] [blame] | 69 | } |
| 70 | if (programInfo.pipeline().usesConservativeRaster()) { |
| 71 | SkASSERT(this->gpu()->caps()->conservativeRasterSupport()); |
Chris Dalton | 4386ad1 | 2020-02-19 16:42:06 -0700 | [diff] [blame] | 72 | } |
| 73 | if (programInfo.pipeline().isWireframe()) { |
| 74 | SkASSERT(this->gpu()->caps()->wireframeSupport()); |
| 75 | } |
Chris Dalton | 3d28b6a | 2020-04-13 11:12:28 -0600 | [diff] [blame] | 76 | if (this->gpu()->caps()->twoSidedStencilRefsAndMasksMustMatch() && |
Chris Dalton | 1b6a43c | 2020-09-25 12:21:18 -0600 | [diff] [blame] | 77 | programInfo.isStencilEnabled()) { |
| 78 | const GrUserStencilSettings* stencil = programInfo.userStencilSettings(); |
Chris Dalton | 3d28b6a | 2020-04-13 11:12:28 -0600 | [diff] [blame] | 79 | if (stencil->isTwoSided(programInfo.pipeline().hasStencilClip())) { |
| 80 | SkASSERT(stencil->fCCWFace.fRef == stencil->fCWFace.fRef); |
| 81 | SkASSERT(stencil->fCCWFace.fTestMask == stencil->fCWFace.fTestMask); |
| 82 | SkASSERT(stencil->fCCWFace.fWriteMask == stencil->fCWFace.fWriteMask); |
| 83 | } |
| 84 | } |
Chris Dalton | 4386ad1 | 2020-02-19 16:42:06 -0700 | [diff] [blame] | 85 | if (GrPrimitiveType::kPatches == programInfo.primitiveType()) { |
| 86 | SkASSERT(this->gpu()->caps()->shaderCaps()->tessellationSupport()); |
| 87 | } |
Robert Phillips | 2d8a95e | 2019-10-10 12:50:22 -0400 | [diff] [blame] | 88 | programInfo.checkAllInstantiated(); |
| 89 | programInfo.checkMSAAAndMIPSAreResolved(); |
Robert Phillips | 12c4629 | 2019-04-23 07:36:17 -0400 | [diff] [blame] | 90 | #endif |
Robert Phillips | a91e0b7 | 2017-05-01 13:12:20 -0400 | [diff] [blame] | 91 | |
Chris Dalton | b60c8a2 | 2020-03-31 17:24:22 -0600 | [diff] [blame] | 92 | this->resetActiveBuffers(); |
| 93 | |
Robert Phillips | 787fd9d | 2021-03-22 14:48:09 -0400 | [diff] [blame] | 94 | if (programInfo.geomProc().numVertexAttributes() > this->gpu()->caps()->maxVertexAttributes()) { |
Chris Dalton | 4386ad1 | 2020-02-19 16:42:06 -0700 | [diff] [blame] | 95 | fDrawPipelineStatus = DrawPipelineStatus::kFailedToBind; |
| 96 | return; |
egdaniel | 9cb6340 | 2016-06-23 08:37:05 -0700 | [diff] [blame] | 97 | } |
Chris Dalton | 4386ad1 | 2020-02-19 16:42:06 -0700 | [diff] [blame] | 98 | |
| 99 | if (!this->onBindPipeline(programInfo, drawBounds)) { |
| 100 | fDrawPipelineStatus = DrawPipelineStatus::kFailedToBind; |
| 101 | return; |
| 102 | } |
Robert Phillips | 901aff0 | 2019-10-08 12:32:56 -0400 | [diff] [blame] | 103 | |
Chris Dalton | 8c4cafd | 2019-04-15 19:14:36 -0600 | [diff] [blame] | 104 | #ifdef SK_DEBUG |
Chris Dalton | 2e7ed26 | 2020-02-21 15:17:59 -0700 | [diff] [blame] | 105 | fScissorStatus = (programInfo.pipeline().isScissorTestEnabled()) ? |
| 106 | DynamicStateStatus::kUninitialized : DynamicStateStatus::kDisabled; |
Robert Phillips | 787fd9d | 2021-03-22 14:48:09 -0400 | [diff] [blame] | 107 | bool hasTextures = (programInfo.geomProc().numTextureSamplers() > 0); |
Chris Dalton | 2e7ed26 | 2020-02-21 15:17:59 -0700 | [diff] [blame] | 108 | if (!hasTextures) { |
Brian Salomon | 7e67dca | 2020-07-21 09:27:25 -0400 | [diff] [blame] | 109 | programInfo.pipeline().visitProxies([&hasTextures](GrSurfaceProxy*, GrMipmapped) { |
Chris Dalton | 2e7ed26 | 2020-02-21 15:17:59 -0700 | [diff] [blame] | 110 | hasTextures = true; |
| 111 | }); |
| 112 | } |
| 113 | fTextureBindingStatus = (hasTextures) ? |
| 114 | DynamicStateStatus::kUninitialized : DynamicStateStatus::kDisabled; |
Chris Dalton | ded4370 | 2020-03-02 11:45:27 -0700 | [diff] [blame] | 115 | fHasIndexBuffer = false; |
Robert Phillips | 787fd9d | 2021-03-22 14:48:09 -0400 | [diff] [blame] | 116 | fInstanceBufferStatus = (programInfo.geomProc().hasInstanceAttributes()) ? |
Chris Dalton | ded4370 | 2020-03-02 11:45:27 -0700 | [diff] [blame] | 117 | DynamicStateStatus::kUninitialized : DynamicStateStatus::kDisabled; |
Robert Phillips | 787fd9d | 2021-03-22 14:48:09 -0400 | [diff] [blame] | 118 | fVertexBufferStatus = (programInfo.geomProc().hasVertexAttributes()) ? |
Chris Dalton | ded4370 | 2020-03-02 11:45:27 -0700 | [diff] [blame] | 119 | DynamicStateStatus::kUninitialized : DynamicStateStatus::kDisabled; |
Chris Dalton | 8c4cafd | 2019-04-15 19:14:36 -0600 | [diff] [blame] | 120 | #endif |
Chris Dalton | 4386ad1 | 2020-02-19 16:42:06 -0700 | [diff] [blame] | 121 | |
| 122 | fDrawPipelineStatus = DrawPipelineStatus::kOk; |
Greg Daniel | d358cbe | 2020-09-11 09:33:54 -0400 | [diff] [blame] | 123 | fXferBarrierType = programInfo.pipeline().xferBarrierType(*this->gpu()->caps()); |
Chris Dalton | 2e7ed26 | 2020-02-21 15:17:59 -0700 | [diff] [blame] | 124 | } |
| 125 | |
| 126 | void GrOpsRenderPass::setScissorRect(const SkIRect& scissor) { |
| 127 | if (DrawPipelineStatus::kOk != fDrawPipelineStatus) { |
| 128 | SkASSERT(DrawPipelineStatus::kNotConfigured != fDrawPipelineStatus); |
| 129 | return; |
| 130 | } |
| 131 | SkASSERT(DynamicStateStatus::kDisabled != fScissorStatus); |
| 132 | this->onSetScissorRect(scissor); |
| 133 | SkDEBUGCODE(fScissorStatus = DynamicStateStatus::kConfigured); |
| 134 | } |
| 135 | |
Robert Phillips | 787fd9d | 2021-03-22 14:48:09 -0400 | [diff] [blame] | 136 | void GrOpsRenderPass::bindTextures(const GrGeometryProcessor& geomProc, |
| 137 | const GrSurfaceProxy* const geomProcTextures[], |
Chris Dalton | db20afc | 2020-03-05 12:13:53 -0700 | [diff] [blame] | 138 | const GrPipeline& pipeline) { |
Chris Dalton | 1b1b0d5 | 2020-03-03 12:00:59 -0700 | [diff] [blame] | 139 | #ifdef SK_DEBUG |
Robert Phillips | 787fd9d | 2021-03-22 14:48:09 -0400 | [diff] [blame] | 140 | SkASSERT((geomProc.numTextureSamplers() > 0) == SkToBool(geomProcTextures)); |
| 141 | for (int i = 0; i < geomProc.numTextureSamplers(); ++i) { |
| 142 | const auto& sampler = geomProc.textureSampler(i); |
| 143 | const GrSurfaceProxy* proxy = geomProcTextures[i]; |
Chris Dalton | 3bf2f3a | 2020-03-17 11:48:23 -0600 | [diff] [blame] | 144 | SkASSERT(proxy); |
| 145 | SkASSERT(proxy->backendFormat() == sampler.backendFormat()); |
| 146 | SkASSERT(proxy->backendFormat().textureType() == sampler.backendFormat().textureType()); |
| 147 | |
| 148 | const GrTexture* tex = proxy->peekTexture(); |
| 149 | SkASSERT(tex); |
Brian Salomon | e69b9ef | 2020-07-22 11:18:06 -0400 | [diff] [blame] | 150 | if (sampler.samplerState().mipmapped() == GrMipmapped::kYes && |
Chris Dalton | 3bf2f3a | 2020-03-17 11:48:23 -0600 | [diff] [blame] | 151 | (tex->width() != 1 || tex->height() != 1)) { |
| 152 | // There are some cases where we might be given a non-mipmapped texture with a mipmap |
| 153 | // filter. See skbug.com/7094. |
Brian Salomon | 4cfae3b | 2020-07-23 10:33:24 -0400 | [diff] [blame] | 154 | SkASSERT(tex->mipmapped() != GrMipmapped::kYes || !tex->mipmapsAreDirty()); |
Chris Dalton | 3bf2f3a | 2020-03-17 11:48:23 -0600 | [diff] [blame] | 155 | } |
Chris Dalton | 1b1b0d5 | 2020-03-03 12:00:59 -0700 | [diff] [blame] | 156 | } |
| 157 | #endif |
| 158 | |
Chris Dalton | 2e7ed26 | 2020-02-21 15:17:59 -0700 | [diff] [blame] | 159 | if (DrawPipelineStatus::kOk != fDrawPipelineStatus) { |
| 160 | SkASSERT(DrawPipelineStatus::kNotConfigured != fDrawPipelineStatus); |
| 161 | return; |
| 162 | } |
Chris Dalton | 1b1b0d5 | 2020-03-03 12:00:59 -0700 | [diff] [blame] | 163 | |
Chris Dalton | 2e7ed26 | 2020-02-21 15:17:59 -0700 | [diff] [blame] | 164 | // Don't assert on fTextureBindingStatus. onBindTextures() just turns into a no-op when there |
| 165 | // aren't any textures, and it's hard to tell from the GrPipeline whether there are any. For |
| 166 | // many clients it is easier to just always call this method. |
Robert Phillips | 787fd9d | 2021-03-22 14:48:09 -0400 | [diff] [blame] | 167 | if (!this->onBindTextures(geomProc, geomProcTextures, pipeline)) { |
Chris Dalton | 2e7ed26 | 2020-02-21 15:17:59 -0700 | [diff] [blame] | 168 | fDrawPipelineStatus = DrawPipelineStatus::kFailedToBind; |
| 169 | return; |
| 170 | } |
Chris Dalton | 1b1b0d5 | 2020-03-03 12:00:59 -0700 | [diff] [blame] | 171 | |
Chris Dalton | 2e7ed26 | 2020-02-21 15:17:59 -0700 | [diff] [blame] | 172 | SkDEBUGCODE(fTextureBindingStatus = DynamicStateStatus::kConfigured); |
Chris Dalton | 4386ad1 | 2020-02-19 16:42:06 -0700 | [diff] [blame] | 173 | } |
| 174 | |
Greg Daniel | 426274b | 2020-07-20 11:37:38 -0400 | [diff] [blame] | 175 | void GrOpsRenderPass::bindBuffers(sk_sp<const GrBuffer> indexBuffer, |
| 176 | sk_sp<const GrBuffer> instanceBuffer, |
| 177 | sk_sp<const GrBuffer> vertexBuffer, |
| 178 | GrPrimitiveRestart primRestart) { |
Chris Dalton | ded4370 | 2020-03-02 11:45:27 -0700 | [diff] [blame] | 179 | if (DrawPipelineStatus::kOk != fDrawPipelineStatus) { |
| 180 | SkASSERT(DrawPipelineStatus::kNotConfigured != fDrawPipelineStatus); |
| 181 | return; |
| 182 | } |
| 183 | |
| 184 | #ifdef SK_DEBUG |
| 185 | if (indexBuffer) { |
| 186 | fHasIndexBuffer = true; |
| 187 | } |
| 188 | |
| 189 | SkASSERT((DynamicStateStatus::kDisabled == fInstanceBufferStatus) != SkToBool(instanceBuffer)); |
| 190 | if (instanceBuffer) { |
| 191 | fInstanceBufferStatus = DynamicStateStatus::kConfigured; |
| 192 | } |
| 193 | |
| 194 | SkASSERT((DynamicStateStatus::kDisabled == fVertexBufferStatus) != SkToBool(vertexBuffer)); |
| 195 | if (vertexBuffer) { |
| 196 | fVertexBufferStatus = DynamicStateStatus::kConfigured; |
| 197 | } |
| 198 | |
| 199 | if (GrPrimitiveRestart::kYes == primRestart) { |
| 200 | SkASSERT(this->gpu()->caps()->usePrimitiveRestart()); |
| 201 | } |
| 202 | #endif |
| 203 | |
Greg Daniel | 426274b | 2020-07-20 11:37:38 -0400 | [diff] [blame] | 204 | this->onBindBuffers(std::move(indexBuffer), std::move(instanceBuffer), std::move(vertexBuffer), |
| 205 | primRestart); |
Chris Dalton | ded4370 | 2020-03-02 11:45:27 -0700 | [diff] [blame] | 206 | } |
| 207 | |
Chris Dalton | 33db9fc | 2020-02-25 18:52:12 -0700 | [diff] [blame] | 208 | bool GrOpsRenderPass::prepareToDraw() { |
Chris Dalton | 4386ad1 | 2020-02-19 16:42:06 -0700 | [diff] [blame] | 209 | if (DrawPipelineStatus::kOk != fDrawPipelineStatus) { |
| 210 | SkASSERT(DrawPipelineStatus::kNotConfigured != fDrawPipelineStatus); |
| 211 | this->gpu()->stats()->incNumFailedDraws(); |
Chris Dalton | 33db9fc | 2020-02-25 18:52:12 -0700 | [diff] [blame] | 212 | return false; |
Chris Dalton | 4386ad1 | 2020-02-19 16:42:06 -0700 | [diff] [blame] | 213 | } |
Chris Dalton | 2e7ed26 | 2020-02-21 15:17:59 -0700 | [diff] [blame] | 214 | SkASSERT(DynamicStateStatus::kUninitialized != fScissorStatus); |
| 215 | SkASSERT(DynamicStateStatus::kUninitialized != fTextureBindingStatus); |
Chris Dalton | 4386ad1 | 2020-02-19 16:42:06 -0700 | [diff] [blame] | 216 | |
Chris Dalton | 2e7ed26 | 2020-02-21 15:17:59 -0700 | [diff] [blame] | 217 | if (kNone_GrXferBarrierType != fXferBarrierType) { |
| 218 | this->gpu()->xferBarrier(fRenderTarget, fXferBarrierType); |
Chris Dalton | 4386ad1 | 2020-02-19 16:42:06 -0700 | [diff] [blame] | 219 | } |
Chris Dalton | 33db9fc | 2020-02-25 18:52:12 -0700 | [diff] [blame] | 220 | return true; |
| 221 | } |
| 222 | |
Chris Dalton | ded4370 | 2020-03-02 11:45:27 -0700 | [diff] [blame] | 223 | void GrOpsRenderPass::draw(int vertexCount, int baseVertex) { |
Chris Dalton | 33db9fc | 2020-02-25 18:52:12 -0700 | [diff] [blame] | 224 | if (!this->prepareToDraw()) { |
| 225 | return; |
| 226 | } |
Chris Dalton | ded4370 | 2020-03-02 11:45:27 -0700 | [diff] [blame] | 227 | SkASSERT(!fHasIndexBuffer); |
| 228 | SkASSERT(DynamicStateStatus::kConfigured != fInstanceBufferStatus); |
| 229 | SkASSERT(DynamicStateStatus::kUninitialized != fVertexBufferStatus); |
| 230 | this->onDraw(vertexCount, baseVertex); |
Chris Dalton | 33db9fc | 2020-02-25 18:52:12 -0700 | [diff] [blame] | 231 | } |
| 232 | |
Chris Dalton | ded4370 | 2020-03-02 11:45:27 -0700 | [diff] [blame] | 233 | void GrOpsRenderPass::drawIndexed(int indexCount, int baseIndex, uint16_t minIndexValue, |
| 234 | uint16_t maxIndexValue, int baseVertex) { |
Chris Dalton | 33db9fc | 2020-02-25 18:52:12 -0700 | [diff] [blame] | 235 | if (!this->prepareToDraw()) { |
| 236 | return; |
| 237 | } |
Chris Dalton | ded4370 | 2020-03-02 11:45:27 -0700 | [diff] [blame] | 238 | SkASSERT(fHasIndexBuffer); |
| 239 | SkASSERT(DynamicStateStatus::kConfigured != fInstanceBufferStatus); |
| 240 | SkASSERT(DynamicStateStatus::kUninitialized != fVertexBufferStatus); |
| 241 | this->onDrawIndexed(indexCount, baseIndex, minIndexValue, maxIndexValue, baseVertex); |
Chris Dalton | 33db9fc | 2020-02-25 18:52:12 -0700 | [diff] [blame] | 242 | } |
| 243 | |
Chris Dalton | ded4370 | 2020-03-02 11:45:27 -0700 | [diff] [blame] | 244 | void GrOpsRenderPass::drawInstanced(int instanceCount, int baseInstance, int vertexCount, |
Chris Dalton | 33db9fc | 2020-02-25 18:52:12 -0700 | [diff] [blame] | 245 | int baseVertex) { |
Chris Dalton | a77cdee | 2020-04-03 14:50:43 -0600 | [diff] [blame] | 246 | SkASSERT(this->gpu()->caps()->drawInstancedSupport()); |
Chris Dalton | 33db9fc | 2020-02-25 18:52:12 -0700 | [diff] [blame] | 247 | if (!this->prepareToDraw()) { |
| 248 | return; |
| 249 | } |
Chris Dalton | ded4370 | 2020-03-02 11:45:27 -0700 | [diff] [blame] | 250 | SkASSERT(!fHasIndexBuffer); |
| 251 | SkASSERT(DynamicStateStatus::kUninitialized != fInstanceBufferStatus); |
| 252 | SkASSERT(DynamicStateStatus::kUninitialized != fVertexBufferStatus); |
| 253 | this->onDrawInstanced(instanceCount, baseInstance, vertexCount, baseVertex); |
Chris Dalton | 33db9fc | 2020-02-25 18:52:12 -0700 | [diff] [blame] | 254 | } |
| 255 | |
Chris Dalton | ded4370 | 2020-03-02 11:45:27 -0700 | [diff] [blame] | 256 | void GrOpsRenderPass::drawIndexedInstanced(int indexCount, int baseIndex, int instanceCount, |
| 257 | int baseInstance, int baseVertex) { |
Chris Dalton | a77cdee | 2020-04-03 14:50:43 -0600 | [diff] [blame] | 258 | SkASSERT(this->gpu()->caps()->drawInstancedSupport()); |
Chris Dalton | 33db9fc | 2020-02-25 18:52:12 -0700 | [diff] [blame] | 259 | if (!this->prepareToDraw()) { |
| 260 | return; |
| 261 | } |
Chris Dalton | ded4370 | 2020-03-02 11:45:27 -0700 | [diff] [blame] | 262 | SkASSERT(fHasIndexBuffer); |
| 263 | SkASSERT(DynamicStateStatus::kUninitialized != fInstanceBufferStatus); |
| 264 | SkASSERT(DynamicStateStatus::kUninitialized != fVertexBufferStatus); |
| 265 | this->onDrawIndexedInstanced(indexCount, baseIndex, instanceCount, baseInstance, baseVertex); |
egdaniel | 9cb6340 | 2016-06-23 08:37:05 -0700 | [diff] [blame] | 266 | } |
Chris Dalton | bb76842 | 2020-03-12 12:13:29 -0600 | [diff] [blame] | 267 | |
Chris Dalton | 03fdf6a | 2020-04-07 12:31:59 -0600 | [diff] [blame] | 268 | void GrOpsRenderPass::drawIndirect(const GrBuffer* drawIndirectBuffer, size_t bufferOffset, |
| 269 | int drawCount) { |
| 270 | SkASSERT(this->gpu()->caps()->drawInstancedSupport()); |
| 271 | SkASSERT(drawIndirectBuffer->isCpuBuffer() || |
| 272 | !static_cast<const GrGpuBuffer*>(drawIndirectBuffer)->isMapped()); |
| 273 | if (!this->prepareToDraw()) { |
| 274 | return; |
| 275 | } |
| 276 | SkASSERT(!fHasIndexBuffer); |
| 277 | SkASSERT(DynamicStateStatus::kUninitialized != fInstanceBufferStatus); |
| 278 | SkASSERT(DynamicStateStatus::kUninitialized != fVertexBufferStatus); |
| 279 | if (!this->gpu()->caps()->nativeDrawIndirectSupport()) { |
| 280 | // Polyfill indirect draws with looping instanced calls. |
| 281 | SkASSERT(drawIndirectBuffer->isCpuBuffer()); |
Chris Dalton | a6a3d05 | 2021-02-07 20:56:36 -0700 | [diff] [blame] | 282 | auto* cpuIndirectBuffer = static_cast<const GrCpuBuffer*>(drawIndirectBuffer); |
| 283 | auto* cmds = reinterpret_cast<const GrDrawIndirectCommand*>( |
Chris Dalton | 03fdf6a | 2020-04-07 12:31:59 -0600 | [diff] [blame] | 284 | cpuIndirectBuffer->data() + bufferOffset); |
Chris Dalton | a6a3d05 | 2021-02-07 20:56:36 -0700 | [diff] [blame] | 285 | for (int i = 0; i < drawCount; ++i) { |
Chris Dalton | a6a3d05 | 2021-02-07 20:56:36 -0700 | [diff] [blame] | 286 | auto [vertexCount, instanceCount, baseVertex, baseInstance] = cmds[i]; |
| 287 | this->onDrawInstanced(instanceCount, baseInstance, vertexCount, baseVertex); |
Chris Dalton | 03fdf6a | 2020-04-07 12:31:59 -0600 | [diff] [blame] | 288 | } |
| 289 | return; |
| 290 | } |
| 291 | this->onDrawIndirect(drawIndirectBuffer, bufferOffset, drawCount); |
| 292 | } |
| 293 | |
| 294 | void GrOpsRenderPass::drawIndexedIndirect(const GrBuffer* drawIndirectBuffer, size_t bufferOffset, |
| 295 | int drawCount) { |
| 296 | SkASSERT(this->gpu()->caps()->drawInstancedSupport()); |
| 297 | SkASSERT(drawIndirectBuffer->isCpuBuffer() || |
| 298 | !static_cast<const GrGpuBuffer*>(drawIndirectBuffer)->isMapped()); |
| 299 | if (!this->prepareToDraw()) { |
| 300 | return; |
| 301 | } |
| 302 | SkASSERT(fHasIndexBuffer); |
| 303 | SkASSERT(DynamicStateStatus::kUninitialized != fInstanceBufferStatus); |
| 304 | SkASSERT(DynamicStateStatus::kUninitialized != fVertexBufferStatus); |
| 305 | if (!this->gpu()->caps()->nativeDrawIndirectSupport() || |
| 306 | this->gpu()->caps()->nativeDrawIndexedIndirectIsBroken()) { |
| 307 | // Polyfill indexedIndirect draws with looping indexedInstanced calls. |
| 308 | SkASSERT(drawIndirectBuffer->isCpuBuffer()); |
Chris Dalton | a6a3d05 | 2021-02-07 20:56:36 -0700 | [diff] [blame] | 309 | auto* cpuIndirectBuffer = static_cast<const GrCpuBuffer*>(drawIndirectBuffer); |
| 310 | auto* cmds = reinterpret_cast<const GrDrawIndexedIndirectCommand*>( |
Chris Dalton | 03fdf6a | 2020-04-07 12:31:59 -0600 | [diff] [blame] | 311 | cpuIndirectBuffer->data() + bufferOffset); |
Chris Dalton | a6a3d05 | 2021-02-07 20:56:36 -0700 | [diff] [blame] | 312 | for (int i = 0; i < drawCount; ++i) { |
Chris Dalton | a6a3d05 | 2021-02-07 20:56:36 -0700 | [diff] [blame] | 313 | auto [indexCount, instanceCount, baseIndex, baseVertex, baseInstance] = cmds[i]; |
| 314 | this->onDrawIndexedInstanced(indexCount, baseIndex, instanceCount, baseInstance, |
| 315 | baseVertex); |
Chris Dalton | 03fdf6a | 2020-04-07 12:31:59 -0600 | [diff] [blame] | 316 | } |
| 317 | return; |
| 318 | } |
| 319 | this->onDrawIndexedIndirect(drawIndirectBuffer, bufferOffset, drawCount); |
| 320 | } |
| 321 | |
Chris Dalton | bb76842 | 2020-03-12 12:13:29 -0600 | [diff] [blame] | 322 | void GrOpsRenderPass::drawIndexPattern(int patternIndexCount, int patternRepeatCount, |
| 323 | int maxPatternRepetitionsInIndexBuffer, |
| 324 | int patternVertexCount, int baseVertex) { |
| 325 | int baseRepetition = 0; |
| 326 | while (baseRepetition < patternRepeatCount) { |
| 327 | int repeatCount = std::min(patternRepeatCount - baseRepetition, |
| 328 | maxPatternRepetitionsInIndexBuffer); |
| 329 | int drawIndexCount = repeatCount * patternIndexCount; |
| 330 | // A patterned index buffer must contain indices in the range [0..vertexCount]. |
| 331 | int minIndexValue = 0; |
| 332 | int maxIndexValue = patternVertexCount * repeatCount - 1; |
| 333 | this->drawIndexed(drawIndexCount, 0, minIndexValue, maxIndexValue, |
| 334 | patternVertexCount * baseRepetition + baseVertex); |
| 335 | baseRepetition += repeatCount; |
| 336 | } |
| 337 | } |