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