blob: 9ce11a0e0736a255d1b1df0f815633490cbd5d22 [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 Dalton4386ad12020-02-19 16:42:06 -070045void GrOpsRenderPass::bindPipeline(const GrProgramInfo& programInfo, const SkRect& drawBounds) {
Chris Daltonbca46e22017-05-15 11:03:26 -060046#ifdef SK_DEBUG
Chris Dalton4386ad12020-02-19 16:42:06 -070047 if (programInfo.primProc().hasInstanceAttributes()) {
48 SkASSERT(this->gpu()->caps()->instanceAttribSupport());
49 }
50 if (programInfo.pipeline().usesConservativeRaster()) {
51 SkASSERT(this->gpu()->caps()->conservativeRasterSupport());
52 // Conservative raster, by default, only supports triangles. Implementations can
53 // optionally indicate that they also support points and lines, but we don't currently
54 // query or track that info.
55 SkASSERT(GrIsPrimTypeTris(programInfo.primitiveType()));
56 }
57 if (programInfo.pipeline().isWireframe()) {
58 SkASSERT(this->gpu()->caps()->wireframeSupport());
59 }
60 if (GrPrimitiveType::kPatches == programInfo.primitiveType()) {
61 SkASSERT(this->gpu()->caps()->shaderCaps()->tessellationSupport());
62 }
Robert Phillips2d8a95e2019-10-10 12:50:22 -040063 programInfo.checkAllInstantiated();
64 programInfo.checkMSAAAndMIPSAreResolved();
Robert Phillips12c46292019-04-23 07:36:17 -040065#endif
Robert Phillipsa91e0b72017-05-01 13:12:20 -040066
Robert Phillips901aff02019-10-08 12:32:56 -040067 if (programInfo.primProc().numVertexAttributes() > this->gpu()->caps()->maxVertexAttributes()) {
Chris Dalton4386ad12020-02-19 16:42:06 -070068 fDrawPipelineStatus = DrawPipelineStatus::kFailedToBind;
69 return;
egdaniel9cb63402016-06-23 08:37:05 -070070 }
Chris Dalton4386ad12020-02-19 16:42:06 -070071
72 if (!this->onBindPipeline(programInfo, drawBounds)) {
73 fDrawPipelineStatus = DrawPipelineStatus::kFailedToBind;
74 return;
75 }
Robert Phillips901aff02019-10-08 12:32:56 -040076
Chris Dalton8c4cafd2019-04-15 19:14:36 -060077#ifdef SK_DEBUG
Robert Phillips901aff02019-10-08 12:32:56 -040078 GrProcessor::CustomFeatures processorFeatures = programInfo.requestedFeatures();
Chris Dalton8c4cafd2019-04-15 19:14:36 -060079 if (GrProcessor::CustomFeatures::kSampleLocations & processorFeatures) {
80 // Verify we always have the same sample pattern key, regardless of graphics state.
81 SkASSERT(this->gpu()->findOrAssignSamplePatternKey(fRenderTarget)
82 == fRenderTarget->renderTargetPriv().getSamplePatternKey());
83 }
Chris Dalton2e7ed262020-02-21 15:17:59 -070084 fScissorStatus = (programInfo.pipeline().isScissorTestEnabled()) ?
85 DynamicStateStatus::kUninitialized : DynamicStateStatus::kDisabled;
86 bool hasTextures = (programInfo.primProc().numTextureSamplers() > 0);
87 if (!hasTextures) {
88 programInfo.pipeline().visitProxies([&hasTextures](GrSurfaceProxy*, GrMipMapped) {
89 hasTextures = true;
90 });
91 }
92 fTextureBindingStatus = (hasTextures) ?
93 DynamicStateStatus::kUninitialized : DynamicStateStatus::kDisabled;
Chris Daltonded43702020-03-02 11:45:27 -070094 fHasIndexBuffer = false;
95 fInstanceBufferStatus = (programInfo.primProc().hasInstanceAttributes()) ?
96 DynamicStateStatus::kUninitialized : DynamicStateStatus::kDisabled;
97 fVertexBufferStatus = (programInfo.primProc().hasVertexAttributes()) ?
98 DynamicStateStatus::kUninitialized : DynamicStateStatus::kDisabled;
Chris Dalton8c4cafd2019-04-15 19:14:36 -060099#endif
Chris Dalton4386ad12020-02-19 16:42:06 -0700100
101 fDrawPipelineStatus = DrawPipelineStatus::kOk;
Chris Dalton2e7ed262020-02-21 15:17:59 -0700102 fXferBarrierType = programInfo.pipeline().xferBarrierType(fRenderTarget->asTexture(),
103 *this->gpu()->caps());
104}
105
106void GrOpsRenderPass::setScissorRect(const SkIRect& scissor) {
107 if (DrawPipelineStatus::kOk != fDrawPipelineStatus) {
108 SkASSERT(DrawPipelineStatus::kNotConfigured != fDrawPipelineStatus);
109 return;
110 }
111 SkASSERT(DynamicStateStatus::kDisabled != fScissorStatus);
112 this->onSetScissorRect(scissor);
113 SkDEBUGCODE(fScissorStatus = DynamicStateStatus::kConfigured);
114}
115
116void GrOpsRenderPass::bindTextures(const GrPrimitiveProcessor& primProc, const GrPipeline& pipeline,
117 const GrSurfaceProxy* const primProcTextures[]) {
118 if (DrawPipelineStatus::kOk != fDrawPipelineStatus) {
119 SkASSERT(DrawPipelineStatus::kNotConfigured != fDrawPipelineStatus);
120 return;
121 }
122 SkASSERT((primProc.numTextureSamplers() > 0) == SkToBool(primProcTextures));
123 // Don't assert on fTextureBindingStatus. onBindTextures() just turns into a no-op when there
124 // aren't any textures, and it's hard to tell from the GrPipeline whether there are any. For
125 // many clients it is easier to just always call this method.
126 if (!this->onBindTextures(primProc, pipeline, primProcTextures)) {
127 fDrawPipelineStatus = DrawPipelineStatus::kFailedToBind;
128 return;
129 }
130 SkDEBUGCODE(fTextureBindingStatus = DynamicStateStatus::kConfigured);
Chris Dalton4386ad12020-02-19 16:42:06 -0700131}
132
133void GrOpsRenderPass::drawMeshes(const GrProgramInfo& programInfo, const GrMesh meshes[],
134 int meshCount) {
Chris Dalton2e7ed262020-02-21 15:17:59 -0700135 if (programInfo.hasFixedScissor()) {
136 this->setScissorRect(programInfo.fixedScissor());
137 }
138 if (!programInfo.hasDynamicPrimProcTextures()) {
139 auto primProcTextures = (programInfo.hasFixedPrimProcTextures()) ?
140 programInfo.fixedPrimProcTextures() : nullptr;
141 this->bindTextures(programInfo.primProc(), programInfo.pipeline(), primProcTextures);
142 }
143 for (int i = 0; i < meshCount; ++i) {
144 if (programInfo.hasDynamicScissors()) {
145 this->setScissorRect(programInfo.dynamicScissor(i));
146 }
147 if (programInfo.hasDynamicPrimProcTextures()) {
148 this->bindTextures(programInfo.primProc(), programInfo.pipeline(),
149 programInfo.dynamicPrimProcTextures(i));
150 }
Chris Dalton33db9fc2020-02-25 18:52:12 -0700151 meshes[i].draw(this);
Chris Dalton2e7ed262020-02-21 15:17:59 -0700152 }
153}
154
Chris Daltonded43702020-03-02 11:45:27 -0700155void GrOpsRenderPass::bindBuffers(const GrBuffer* indexBuffer, const GrBuffer* instanceBuffer,
156 const GrBuffer* vertexBuffer, GrPrimitiveRestart primRestart) {
157 if (DrawPipelineStatus::kOk != fDrawPipelineStatus) {
158 SkASSERT(DrawPipelineStatus::kNotConfigured != fDrawPipelineStatus);
159 return;
160 }
161
162#ifdef SK_DEBUG
163 if (indexBuffer) {
164 fHasIndexBuffer = true;
165 }
166
167 SkASSERT((DynamicStateStatus::kDisabled == fInstanceBufferStatus) != SkToBool(instanceBuffer));
168 if (instanceBuffer) {
169 fInstanceBufferStatus = DynamicStateStatus::kConfigured;
170 }
171
172 SkASSERT((DynamicStateStatus::kDisabled == fVertexBufferStatus) != SkToBool(vertexBuffer));
173 if (vertexBuffer) {
174 fVertexBufferStatus = DynamicStateStatus::kConfigured;
175 }
176
177 if (GrPrimitiveRestart::kYes == primRestart) {
178 SkASSERT(this->gpu()->caps()->usePrimitiveRestart());
179 }
180#endif
181
182 this->onBindBuffers(indexBuffer, instanceBuffer, vertexBuffer, primRestart);
183}
184
Chris Dalton33db9fc2020-02-25 18:52:12 -0700185bool GrOpsRenderPass::prepareToDraw() {
Chris Dalton4386ad12020-02-19 16:42:06 -0700186 if (DrawPipelineStatus::kOk != fDrawPipelineStatus) {
187 SkASSERT(DrawPipelineStatus::kNotConfigured != fDrawPipelineStatus);
188 this->gpu()->stats()->incNumFailedDraws();
Chris Dalton33db9fc2020-02-25 18:52:12 -0700189 return false;
Chris Dalton4386ad12020-02-19 16:42:06 -0700190 }
Chris Dalton2e7ed262020-02-21 15:17:59 -0700191 SkASSERT(DynamicStateStatus::kUninitialized != fScissorStatus);
192 SkASSERT(DynamicStateStatus::kUninitialized != fTextureBindingStatus);
Chris Dalton4386ad12020-02-19 16:42:06 -0700193
Chris Dalton2e7ed262020-02-21 15:17:59 -0700194 if (kNone_GrXferBarrierType != fXferBarrierType) {
195 this->gpu()->xferBarrier(fRenderTarget, fXferBarrierType);
Chris Dalton4386ad12020-02-19 16:42:06 -0700196 }
Chris Dalton33db9fc2020-02-25 18:52:12 -0700197 return true;
198}
199
Chris Daltonded43702020-03-02 11:45:27 -0700200void GrOpsRenderPass::draw(int vertexCount, int baseVertex) {
Chris Dalton33db9fc2020-02-25 18:52:12 -0700201 if (!this->prepareToDraw()) {
202 return;
203 }
Chris Daltonded43702020-03-02 11:45:27 -0700204 SkASSERT(!fHasIndexBuffer);
205 SkASSERT(DynamicStateStatus::kConfigured != fInstanceBufferStatus);
206 SkASSERT(DynamicStateStatus::kUninitialized != fVertexBufferStatus);
207 this->onDraw(vertexCount, baseVertex);
Chris Dalton33db9fc2020-02-25 18:52:12 -0700208}
209
Chris Daltonded43702020-03-02 11:45:27 -0700210void GrOpsRenderPass::drawIndexed(int indexCount, int baseIndex, uint16_t minIndexValue,
211 uint16_t maxIndexValue, int baseVertex) {
Chris Dalton33db9fc2020-02-25 18:52:12 -0700212 if (!this->prepareToDraw()) {
213 return;
214 }
Chris Daltonded43702020-03-02 11:45:27 -0700215 SkASSERT(fHasIndexBuffer);
216 SkASSERT(DynamicStateStatus::kConfigured != fInstanceBufferStatus);
217 SkASSERT(DynamicStateStatus::kUninitialized != fVertexBufferStatus);
218 this->onDrawIndexed(indexCount, baseIndex, minIndexValue, maxIndexValue, baseVertex);
Chris Dalton33db9fc2020-02-25 18:52:12 -0700219}
220
Chris Daltonded43702020-03-02 11:45:27 -0700221void GrOpsRenderPass::drawInstanced(int instanceCount, int baseInstance, int vertexCount,
Chris Dalton33db9fc2020-02-25 18:52:12 -0700222 int baseVertex) {
223 if (!this->prepareToDraw()) {
224 return;
225 }
Chris Daltonded43702020-03-02 11:45:27 -0700226 SkASSERT(!fHasIndexBuffer);
227 SkASSERT(DynamicStateStatus::kUninitialized != fInstanceBufferStatus);
228 SkASSERT(DynamicStateStatus::kUninitialized != fVertexBufferStatus);
229 this->onDrawInstanced(instanceCount, baseInstance, vertexCount, baseVertex);
Chris Dalton33db9fc2020-02-25 18:52:12 -0700230}
231
Chris Daltonded43702020-03-02 11:45:27 -0700232void GrOpsRenderPass::drawIndexedInstanced(int indexCount, int baseIndex, int instanceCount,
233 int baseInstance, int baseVertex) {
Chris Dalton33db9fc2020-02-25 18:52:12 -0700234 if (!this->prepareToDraw()) {
235 return;
236 }
Chris Daltonded43702020-03-02 11:45:27 -0700237 SkASSERT(fHasIndexBuffer);
238 SkASSERT(DynamicStateStatus::kUninitialized != fInstanceBufferStatus);
239 SkASSERT(DynamicStateStatus::kUninitialized != fVertexBufferStatus);
240 this->onDrawIndexedInstanced(indexCount, baseIndex, instanceCount, baseInstance, baseVertex);
egdaniel9cb63402016-06-23 08:37:05 -0700241}