blob: bf7cefb581cca924162515259a43cdc5b677fc0d [file] [log] [blame]
egdaniel9cb63402016-06-23 08:37:05 -07001/*
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 Daniel2d41d0d2019-08-26 11:08:51 -04008#include "src/gpu/GrOpsRenderPass.h"
egdaniel9cb63402016-06-23 08:37:05 -07009
Mike Kleinc0bd9f92019-04-23 12:05:21 -050010#include "include/core/SkRect.h"
11#include "include/gpu/GrContext.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050012#include "src/gpu/GrCaps.h"
13#include "src/gpu/GrContextPriv.h"
14#include "src/gpu/GrFixedClip.h"
15#include "src/gpu/GrGpu.h"
16#include "src/gpu/GrMesh.h"
17#include "src/gpu/GrPrimitiveProcessor.h"
Robert Phillips901aff02019-10-08 12:32:56 -040018#include "src/gpu/GrProgramInfo.h"
Brian Salomon201cdbb2019-08-14 17:00:30 -040019#include "src/gpu/GrRenderTarget.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050020#include "src/gpu/GrRenderTargetPriv.h"
Chris Dalton4ece96d2019-08-30 11:26:39 -060021#include "src/gpu/GrTexturePriv.h"
egdaniel9cb63402016-06-23 08:37:05 -070022
Greg Daniel2d41d0d2019-08-26 11:08:51 -040023void GrOpsRenderPass::clear(const GrFixedClip& clip, const SkPMColor4f& color) {
Robert Phillips4912d902018-04-27 12:09:35 -040024 SkASSERT(fRenderTarget);
Michael Ludwigc39d0c82019-01-15 10:03:43 -050025 // A clear at this level will always be a true clear, so make sure clears were not supposed to
26 // be redirected to draws instead
27 SkASSERT(!this->gpu()->caps()->performColorClearsAsDraws());
28 SkASSERT(!clip.scissorEnabled() || !this->gpu()->caps()->performPartialClearsAsDraws());
Chris Dalton4386ad12020-02-19 16:42:06 -070029 fDrawPipelineStatus = DrawPipelineStatus::kNotConfigured;
Robert Phillips19e51dc2017-08-09 09:30:51 -040030 this->onClear(clip, color);
egdaniel9cb63402016-06-23 08:37:05 -070031}
32
Greg Daniel2d41d0d2019-08-26 11:08:51 -040033void GrOpsRenderPass::clearStencilClip(const GrFixedClip& clip, bool insideStencilMask) {
Michael Ludwigc39d0c82019-01-15 10:03:43 -050034 // As above, make sure the stencil clear wasn't supposed to be a draw rect with stencil settings
35 SkASSERT(!this->gpu()->caps()->performStencilClearsAsDraws());
Chris Dalton4386ad12020-02-19 16:42:06 -070036 fDrawPipelineStatus = DrawPipelineStatus::kNotConfigured;
Robert Phillips19e51dc2017-08-09 09:30:51 -040037 this->onClearStencilClip(clip, insideStencilMask);
egdaniel9cb63402016-06-23 08:37:05 -070038}
39
Chris Dalton4386ad12020-02-19 16:42:06 -070040void GrOpsRenderPass::executeDrawable(std::unique_ptr<SkDrawable::GpuDrawHandler> drawable) {
41 fDrawPipelineStatus = DrawPipelineStatus::kNotConfigured;
42 this->onExecuteDrawable(std::move(drawable));
43}
Robert Phillips901aff02019-10-08 12:32:56 -040044
Chris Dalton012f8492020-03-05 11:49:15 -070045void GrOpsRenderPass::bindPipeline(const GrProgramInfo& programInfo, const SkRect& drawBounds,
46 const SkIRect* optionalScissorRect) {
Chris Daltonbca46e22017-05-15 11:03:26 -060047#ifdef SK_DEBUG
Chris Dalton4386ad12020-02-19 16:42:06 -070048 if (programInfo.primProc().hasInstanceAttributes()) {
49 SkASSERT(this->gpu()->caps()->instanceAttribSupport());
50 }
51 if (programInfo.pipeline().usesConservativeRaster()) {
52 SkASSERT(this->gpu()->caps()->conservativeRasterSupport());
53 // Conservative raster, by default, only supports triangles. Implementations can
54 // optionally indicate that they also support points and lines, but we don't currently
55 // query or track that info.
56 SkASSERT(GrIsPrimTypeTris(programInfo.primitiveType()));
57 }
58 if (programInfo.pipeline().isWireframe()) {
59 SkASSERT(this->gpu()->caps()->wireframeSupport());
60 }
61 if (GrPrimitiveType::kPatches == programInfo.primitiveType()) {
62 SkASSERT(this->gpu()->caps()->shaderCaps()->tessellationSupport());
63 }
Robert Phillips2d8a95e2019-10-10 12:50:22 -040064 programInfo.checkAllInstantiated();
65 programInfo.checkMSAAAndMIPSAreResolved();
Robert Phillips12c46292019-04-23 07:36:17 -040066#endif
Robert Phillipsa91e0b72017-05-01 13:12:20 -040067
Robert Phillips901aff02019-10-08 12:32:56 -040068 if (programInfo.primProc().numVertexAttributes() > this->gpu()->caps()->maxVertexAttributes()) {
Chris Dalton4386ad12020-02-19 16:42:06 -070069 fDrawPipelineStatus = DrawPipelineStatus::kFailedToBind;
70 return;
egdaniel9cb63402016-06-23 08:37:05 -070071 }
Chris Dalton4386ad12020-02-19 16:42:06 -070072
73 if (!this->onBindPipeline(programInfo, drawBounds)) {
74 fDrawPipelineStatus = DrawPipelineStatus::kFailedToBind;
75 return;
76 }
Robert Phillips901aff02019-10-08 12:32:56 -040077
Chris Dalton8c4cafd2019-04-15 19:14:36 -060078#ifdef SK_DEBUG
Robert Phillips901aff02019-10-08 12:32:56 -040079 GrProcessor::CustomFeatures processorFeatures = programInfo.requestedFeatures();
Chris Dalton8c4cafd2019-04-15 19:14:36 -060080 if (GrProcessor::CustomFeatures::kSampleLocations & processorFeatures) {
81 // Verify we always have the same sample pattern key, regardless of graphics state.
82 SkASSERT(this->gpu()->findOrAssignSamplePatternKey(fRenderTarget)
83 == fRenderTarget->renderTargetPriv().getSamplePatternKey());
84 }
Chris Dalton2e7ed262020-02-21 15:17:59 -070085 fScissorStatus = (programInfo.pipeline().isScissorTestEnabled()) ?
86 DynamicStateStatus::kUninitialized : DynamicStateStatus::kDisabled;
87 bool hasTextures = (programInfo.primProc().numTextureSamplers() > 0);
88 if (!hasTextures) {
89 programInfo.pipeline().visitProxies([&hasTextures](GrSurfaceProxy*, GrMipMapped) {
90 hasTextures = true;
91 });
92 }
93 fTextureBindingStatus = (hasTextures) ?
94 DynamicStateStatus::kUninitialized : DynamicStateStatus::kDisabled;
Chris Daltonded43702020-03-02 11:45:27 -070095 fHasIndexBuffer = false;
96 fInstanceBufferStatus = (programInfo.primProc().hasInstanceAttributes()) ?
97 DynamicStateStatus::kUninitialized : DynamicStateStatus::kDisabled;
98 fVertexBufferStatus = (programInfo.primProc().hasVertexAttributes()) ?
99 DynamicStateStatus::kUninitialized : DynamicStateStatus::kDisabled;
Chris Dalton8c4cafd2019-04-15 19:14:36 -0600100#endif
Chris Dalton4386ad12020-02-19 16:42:06 -0700101
102 fDrawPipelineStatus = DrawPipelineStatus::kOk;
Chris Dalton2e7ed262020-02-21 15:17:59 -0700103 fXferBarrierType = programInfo.pipeline().xferBarrierType(fRenderTarget->asTexture(),
104 *this->gpu()->caps());
Chris Dalton012f8492020-03-05 11:49:15 -0700105
106 if (optionalScissorRect) {
107 SkASSERT(programInfo.pipeline().isScissorTestEnabled());
108 this->setScissorRect(*optionalScissorRect);
109 }
Chris Dalton2e7ed262020-02-21 15:17:59 -0700110}
111
112void GrOpsRenderPass::setScissorRect(const SkIRect& scissor) {
113 if (DrawPipelineStatus::kOk != fDrawPipelineStatus) {
114 SkASSERT(DrawPipelineStatus::kNotConfigured != fDrawPipelineStatus);
115 return;
116 }
117 SkASSERT(DynamicStateStatus::kDisabled != fScissorStatus);
118 this->onSetScissorRect(scissor);
119 SkDEBUGCODE(fScissorStatus = DynamicStateStatus::kConfigured);
120}
121
Chris Daltondb20afc2020-03-05 12:13:53 -0700122void GrOpsRenderPass::bindTextures(const GrPrimitiveProcessor& primProc,
123 const GrSurfaceProxy* const primProcTextures[],
124 const GrPipeline& pipeline) {
Chris Dalton1b1b0d52020-03-03 12:00:59 -0700125#ifdef SK_DEBUG
126 SkASSERT((primProc.numTextureSamplers() > 0) == SkToBool(primProcTextures));
127 for (int i = 0; i < primProc.numTextureSamplers(); ++i) {
128 SkASSERT(primProcTextures[i]->backendFormat() ==
129 primProc.textureSampler(i).backendFormat());
130 }
131#endif
132
Chris Dalton2e7ed262020-02-21 15:17:59 -0700133 if (DrawPipelineStatus::kOk != fDrawPipelineStatus) {
134 SkASSERT(DrawPipelineStatus::kNotConfigured != fDrawPipelineStatus);
135 return;
136 }
Chris Dalton1b1b0d52020-03-03 12:00:59 -0700137
Chris Dalton2e7ed262020-02-21 15:17:59 -0700138 // Don't assert on fTextureBindingStatus. onBindTextures() just turns into a no-op when there
139 // aren't any textures, and it's hard to tell from the GrPipeline whether there are any. For
140 // many clients it is easier to just always call this method.
Chris Daltondb20afc2020-03-05 12:13:53 -0700141 if (!this->onBindTextures(primProc, primProcTextures, pipeline)) {
Chris Dalton2e7ed262020-02-21 15:17:59 -0700142 fDrawPipelineStatus = DrawPipelineStatus::kFailedToBind;
143 return;
144 }
Chris Dalton1b1b0d52020-03-03 12:00:59 -0700145
Chris Dalton2e7ed262020-02-21 15:17:59 -0700146 SkDEBUGCODE(fTextureBindingStatus = DynamicStateStatus::kConfigured);
Chris Dalton4386ad12020-02-19 16:42:06 -0700147}
148
Chris Dalton012f8492020-03-05 11:49:15 -0700149void GrOpsRenderPass::bindTextures(const GrPrimitiveProcessor& primProc,
150 const GrSurfaceProxy& singlePrimProcTexture,
151 const GrPipeline& pipeline) {
152 SkASSERT(primProc.numTextureSamplers() == 1);
153 const GrSurfaceProxy* ptr = &singlePrimProcTexture;
154 this->bindTextures(primProc, &ptr, pipeline);
155}
156
Chris Dalton4386ad12020-02-19 16:42:06 -0700157void GrOpsRenderPass::drawMeshes(const GrProgramInfo& programInfo, const GrMesh meshes[],
158 int meshCount) {
Chris Dalton2e7ed262020-02-21 15:17:59 -0700159 if (programInfo.hasFixedScissor()) {
160 this->setScissorRect(programInfo.fixedScissor());
161 }
162 if (!programInfo.hasDynamicPrimProcTextures()) {
163 auto primProcTextures = (programInfo.hasFixedPrimProcTextures()) ?
164 programInfo.fixedPrimProcTextures() : nullptr;
Chris Daltondb20afc2020-03-05 12:13:53 -0700165 this->bindTextures(programInfo.primProc(), primProcTextures, programInfo.pipeline());
Chris Dalton2e7ed262020-02-21 15:17:59 -0700166 }
167 for (int i = 0; i < meshCount; ++i) {
168 if (programInfo.hasDynamicScissors()) {
169 this->setScissorRect(programInfo.dynamicScissor(i));
170 }
171 if (programInfo.hasDynamicPrimProcTextures()) {
Chris Daltondb20afc2020-03-05 12:13:53 -0700172 this->bindTextures(programInfo.primProc(), programInfo.dynamicPrimProcTextures(i),
173 programInfo.pipeline());
Chris Dalton2e7ed262020-02-21 15:17:59 -0700174 }
Chris Dalton33db9fc2020-02-25 18:52:12 -0700175 meshes[i].draw(this);
Chris Dalton2e7ed262020-02-21 15:17:59 -0700176 }
177}
178
Chris Daltonded43702020-03-02 11:45:27 -0700179void GrOpsRenderPass::bindBuffers(const GrBuffer* indexBuffer, const GrBuffer* instanceBuffer,
180 const GrBuffer* vertexBuffer, GrPrimitiveRestart primRestart) {
181 if (DrawPipelineStatus::kOk != fDrawPipelineStatus) {
182 SkASSERT(DrawPipelineStatus::kNotConfigured != fDrawPipelineStatus);
183 return;
184 }
185
186#ifdef SK_DEBUG
187 if (indexBuffer) {
188 fHasIndexBuffer = true;
189 }
190
191 SkASSERT((DynamicStateStatus::kDisabled == fInstanceBufferStatus) != SkToBool(instanceBuffer));
192 if (instanceBuffer) {
193 fInstanceBufferStatus = DynamicStateStatus::kConfigured;
194 }
195
196 SkASSERT((DynamicStateStatus::kDisabled == fVertexBufferStatus) != SkToBool(vertexBuffer));
197 if (vertexBuffer) {
198 fVertexBufferStatus = DynamicStateStatus::kConfigured;
199 }
200
201 if (GrPrimitiveRestart::kYes == primRestart) {
202 SkASSERT(this->gpu()->caps()->usePrimitiveRestart());
203 }
204#endif
205
206 this->onBindBuffers(indexBuffer, instanceBuffer, vertexBuffer, primRestart);
207}
208
Chris Dalton33db9fc2020-02-25 18:52:12 -0700209bool GrOpsRenderPass::prepareToDraw() {
Chris Dalton4386ad12020-02-19 16:42:06 -0700210 if (DrawPipelineStatus::kOk != fDrawPipelineStatus) {
211 SkASSERT(DrawPipelineStatus::kNotConfigured != fDrawPipelineStatus);
212 this->gpu()->stats()->incNumFailedDraws();
Chris Dalton33db9fc2020-02-25 18:52:12 -0700213 return false;
Chris Dalton4386ad12020-02-19 16:42:06 -0700214 }
Chris Dalton2e7ed262020-02-21 15:17:59 -0700215 SkASSERT(DynamicStateStatus::kUninitialized != fScissorStatus);
216 SkASSERT(DynamicStateStatus::kUninitialized != fTextureBindingStatus);
Chris Dalton4386ad12020-02-19 16:42:06 -0700217
Chris Dalton2e7ed262020-02-21 15:17:59 -0700218 if (kNone_GrXferBarrierType != fXferBarrierType) {
219 this->gpu()->xferBarrier(fRenderTarget, fXferBarrierType);
Chris Dalton4386ad12020-02-19 16:42:06 -0700220 }
Chris Dalton33db9fc2020-02-25 18:52:12 -0700221 return true;
222}
223
Chris Daltonded43702020-03-02 11:45:27 -0700224void GrOpsRenderPass::draw(int vertexCount, int baseVertex) {
Chris Dalton33db9fc2020-02-25 18:52:12 -0700225 if (!this->prepareToDraw()) {
226 return;
227 }
Chris Daltonded43702020-03-02 11:45:27 -0700228 SkASSERT(!fHasIndexBuffer);
229 SkASSERT(DynamicStateStatus::kConfigured != fInstanceBufferStatus);
230 SkASSERT(DynamicStateStatus::kUninitialized != fVertexBufferStatus);
231 this->onDraw(vertexCount, baseVertex);
Chris Dalton33db9fc2020-02-25 18:52:12 -0700232}
233
Chris Daltonded43702020-03-02 11:45:27 -0700234void GrOpsRenderPass::drawIndexed(int indexCount, int baseIndex, uint16_t minIndexValue,
235 uint16_t maxIndexValue, int baseVertex) {
Chris Dalton33db9fc2020-02-25 18:52:12 -0700236 if (!this->prepareToDraw()) {
237 return;
238 }
Chris Daltonded43702020-03-02 11:45:27 -0700239 SkASSERT(fHasIndexBuffer);
240 SkASSERT(DynamicStateStatus::kConfigured != fInstanceBufferStatus);
241 SkASSERT(DynamicStateStatus::kUninitialized != fVertexBufferStatus);
242 this->onDrawIndexed(indexCount, baseIndex, minIndexValue, maxIndexValue, baseVertex);
Chris Dalton33db9fc2020-02-25 18:52:12 -0700243}
244
Chris Daltonded43702020-03-02 11:45:27 -0700245void GrOpsRenderPass::drawInstanced(int instanceCount, int baseInstance, int vertexCount,
Chris Dalton33db9fc2020-02-25 18:52:12 -0700246 int baseVertex) {
247 if (!this->prepareToDraw()) {
248 return;
249 }
Chris Daltonded43702020-03-02 11:45:27 -0700250 SkASSERT(!fHasIndexBuffer);
251 SkASSERT(DynamicStateStatus::kUninitialized != fInstanceBufferStatus);
252 SkASSERT(DynamicStateStatus::kUninitialized != fVertexBufferStatus);
253 this->onDrawInstanced(instanceCount, baseInstance, vertexCount, baseVertex);
Chris Dalton33db9fc2020-02-25 18:52:12 -0700254}
255
Chris Daltonded43702020-03-02 11:45:27 -0700256void GrOpsRenderPass::drawIndexedInstanced(int indexCount, int baseIndex, int instanceCount,
257 int baseInstance, int baseVertex) {
Chris Dalton33db9fc2020-02-25 18:52:12 -0700258 if (!this->prepareToDraw()) {
259 return;
260 }
Chris Daltonded43702020-03-02 11:45:27 -0700261 SkASSERT(fHasIndexBuffer);
262 SkASSERT(DynamicStateStatus::kUninitialized != fInstanceBufferStatus);
263 SkASSERT(DynamicStateStatus::kUninitialized != fVertexBufferStatus);
264 this->onDrawIndexedInstanced(indexCount, baseIndex, instanceCount, baseInstance, baseVertex);
egdaniel9cb63402016-06-23 08:37:05 -0700265}
Chris Daltonbb768422020-03-12 12:13:29 -0600266
267void GrOpsRenderPass::drawIndexPattern(int patternIndexCount, int patternRepeatCount,
268 int maxPatternRepetitionsInIndexBuffer,
269 int patternVertexCount, int baseVertex) {
270 int baseRepetition = 0;
271 while (baseRepetition < patternRepeatCount) {
272 int repeatCount = std::min(patternRepeatCount - baseRepetition,
273 maxPatternRepetitionsInIndexBuffer);
274 int drawIndexCount = repeatCount * patternIndexCount;
275 // A patterned index buffer must contain indices in the range [0..vertexCount].
276 int minIndexValue = 0;
277 int maxIndexValue = patternVertexCount * repeatCount - 1;
278 this->drawIndexed(drawIndexCount, 0, minIndexValue, maxIndexValue,
279 patternVertexCount * baseRepetition + baseVertex);
280 baseRepetition += repeatCount;
281 }
282}