blob: 9d790e0c40d167e5b51087a270f4498065d83029 [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"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050016#include "src/gpu/GrPrimitiveProcessor.h"
Robert Phillips901aff02019-10-08 12:32:56 -040017#include "src/gpu/GrProgramInfo.h"
Brian Salomon201cdbb2019-08-14 17:00:30 -040018#include "src/gpu/GrRenderTarget.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050019#include "src/gpu/GrRenderTargetPriv.h"
Chris Daltoneb694b72020-03-16 09:25:50 -060020#include "src/gpu/GrSimpleMesh.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 Daltonaa0e45c2020-03-16 10:05:11 -060045void GrOpsRenderPass::bindPipeline(const GrProgramInfo& programInfo, const SkRect& drawBounds) {
Chris Daltonbca46e22017-05-15 11:03:26 -060046#ifdef SK_DEBUG
Chris Dalton56c09f02020-03-13 17:30:03 -060047 // Both the 'programInfo' and this renderPass have an origin. Since they come from the same
48 // place (i.e., the target renderTargetProxy) they had best agree.
49 SkASSERT(programInfo.origin() == fOrigin);
Chris Dalton4386ad12020-02-19 16:42:06 -070050 if (programInfo.primProc().hasInstanceAttributes()) {
51 SkASSERT(this->gpu()->caps()->instanceAttribSupport());
52 }
53 if (programInfo.pipeline().usesConservativeRaster()) {
54 SkASSERT(this->gpu()->caps()->conservativeRasterSupport());
55 // Conservative raster, by default, only supports triangles. Implementations can
56 // optionally indicate that they also support points and lines, but we don't currently
57 // query or track that info.
58 SkASSERT(GrIsPrimTypeTris(programInfo.primitiveType()));
59 }
60 if (programInfo.pipeline().isWireframe()) {
61 SkASSERT(this->gpu()->caps()->wireframeSupport());
62 }
63 if (GrPrimitiveType::kPatches == programInfo.primitiveType()) {
64 SkASSERT(this->gpu()->caps()->shaderCaps()->tessellationSupport());
65 }
Robert Phillips2d8a95e2019-10-10 12:50:22 -040066 programInfo.checkAllInstantiated();
67 programInfo.checkMSAAAndMIPSAreResolved();
Robert Phillips12c46292019-04-23 07:36:17 -040068#endif
Robert Phillipsa91e0b72017-05-01 13:12:20 -040069
Robert Phillips901aff02019-10-08 12:32:56 -040070 if (programInfo.primProc().numVertexAttributes() > this->gpu()->caps()->maxVertexAttributes()) {
Chris Dalton4386ad12020-02-19 16:42:06 -070071 fDrawPipelineStatus = DrawPipelineStatus::kFailedToBind;
72 return;
egdaniel9cb63402016-06-23 08:37:05 -070073 }
Chris Dalton4386ad12020-02-19 16:42:06 -070074
75 if (!this->onBindPipeline(programInfo, drawBounds)) {
76 fDrawPipelineStatus = DrawPipelineStatus::kFailedToBind;
77 return;
78 }
Robert Phillips901aff02019-10-08 12:32:56 -040079
Chris Dalton8c4cafd2019-04-15 19:14:36 -060080#ifdef SK_DEBUG
Robert Phillips901aff02019-10-08 12:32:56 -040081 GrProcessor::CustomFeatures processorFeatures = programInfo.requestedFeatures();
Chris Dalton8c4cafd2019-04-15 19:14:36 -060082 if (GrProcessor::CustomFeatures::kSampleLocations & processorFeatures) {
83 // Verify we always have the same sample pattern key, regardless of graphics state.
84 SkASSERT(this->gpu()->findOrAssignSamplePatternKey(fRenderTarget)
85 == fRenderTarget->renderTargetPriv().getSamplePatternKey());
86 }
Chris Dalton2e7ed262020-02-21 15:17:59 -070087 fScissorStatus = (programInfo.pipeline().isScissorTestEnabled()) ?
88 DynamicStateStatus::kUninitialized : DynamicStateStatus::kDisabled;
89 bool hasTextures = (programInfo.primProc().numTextureSamplers() > 0);
90 if (!hasTextures) {
91 programInfo.pipeline().visitProxies([&hasTextures](GrSurfaceProxy*, GrMipMapped) {
92 hasTextures = true;
93 });
94 }
95 fTextureBindingStatus = (hasTextures) ?
96 DynamicStateStatus::kUninitialized : DynamicStateStatus::kDisabled;
Chris Daltonded43702020-03-02 11:45:27 -070097 fHasIndexBuffer = false;
98 fInstanceBufferStatus = (programInfo.primProc().hasInstanceAttributes()) ?
99 DynamicStateStatus::kUninitialized : DynamicStateStatus::kDisabled;
100 fVertexBufferStatus = (programInfo.primProc().hasVertexAttributes()) ?
101 DynamicStateStatus::kUninitialized : DynamicStateStatus::kDisabled;
Chris Dalton8c4cafd2019-04-15 19:14:36 -0600102#endif
Chris Dalton4386ad12020-02-19 16:42:06 -0700103
104 fDrawPipelineStatus = DrawPipelineStatus::kOk;
Chris Dalton2e7ed262020-02-21 15:17:59 -0700105 fXferBarrierType = programInfo.pipeline().xferBarrierType(fRenderTarget->asTexture(),
106 *this->gpu()->caps());
107}
108
109void GrOpsRenderPass::setScissorRect(const SkIRect& scissor) {
110 if (DrawPipelineStatus::kOk != fDrawPipelineStatus) {
111 SkASSERT(DrawPipelineStatus::kNotConfigured != fDrawPipelineStatus);
112 return;
113 }
114 SkASSERT(DynamicStateStatus::kDisabled != fScissorStatus);
115 this->onSetScissorRect(scissor);
116 SkDEBUGCODE(fScissorStatus = DynamicStateStatus::kConfigured);
117}
118
Chris Daltondb20afc2020-03-05 12:13:53 -0700119void GrOpsRenderPass::bindTextures(const GrPrimitiveProcessor& primProc,
120 const GrSurfaceProxy* const primProcTextures[],
121 const GrPipeline& pipeline) {
Chris Dalton1b1b0d52020-03-03 12:00:59 -0700122#ifdef SK_DEBUG
123 SkASSERT((primProc.numTextureSamplers() > 0) == SkToBool(primProcTextures));
124 for (int i = 0; i < primProc.numTextureSamplers(); ++i) {
Chris Dalton3bf2f3a2020-03-17 11:48:23 -0600125 const auto& sampler = primProc.textureSampler(i);
126 const GrSurfaceProxy* proxy = primProcTextures[i];
127 SkASSERT(proxy);
128 SkASSERT(proxy->backendFormat() == sampler.backendFormat());
129 SkASSERT(proxy->backendFormat().textureType() == sampler.backendFormat().textureType());
130
131 const GrTexture* tex = proxy->peekTexture();
132 SkASSERT(tex);
133 if (GrSamplerState::Filter::kMipMap == sampler.samplerState().filter() &&
134 (tex->width() != 1 || tex->height() != 1)) {
135 // There are some cases where we might be given a non-mipmapped texture with a mipmap
136 // filter. See skbug.com/7094.
137 SkASSERT(tex->texturePriv().mipMapped() != GrMipMapped::kYes ||
138 !tex->texturePriv().mipMapsAreDirty());
139 }
Chris Dalton1b1b0d52020-03-03 12:00:59 -0700140 }
141#endif
142
Chris Dalton2e7ed262020-02-21 15:17:59 -0700143 if (DrawPipelineStatus::kOk != fDrawPipelineStatus) {
144 SkASSERT(DrawPipelineStatus::kNotConfigured != fDrawPipelineStatus);
145 return;
146 }
Chris Dalton1b1b0d52020-03-03 12:00:59 -0700147
Chris Dalton2e7ed262020-02-21 15:17:59 -0700148 // Don't assert on fTextureBindingStatus. onBindTextures() just turns into a no-op when there
149 // aren't any textures, and it's hard to tell from the GrPipeline whether there are any. For
150 // many clients it is easier to just always call this method.
Chris Daltondb20afc2020-03-05 12:13:53 -0700151 if (!this->onBindTextures(primProc, primProcTextures, pipeline)) {
Chris Dalton2e7ed262020-02-21 15:17:59 -0700152 fDrawPipelineStatus = DrawPipelineStatus::kFailedToBind;
153 return;
154 }
Chris Dalton1b1b0d52020-03-03 12:00:59 -0700155
Chris Dalton2e7ed262020-02-21 15:17:59 -0700156 SkDEBUGCODE(fTextureBindingStatus = DynamicStateStatus::kConfigured);
Chris Dalton4386ad12020-02-19 16:42:06 -0700157}
158
Chris Daltonded43702020-03-02 11:45:27 -0700159void GrOpsRenderPass::bindBuffers(const GrBuffer* indexBuffer, const GrBuffer* instanceBuffer,
160 const GrBuffer* vertexBuffer, GrPrimitiveRestart primRestart) {
161 if (DrawPipelineStatus::kOk != fDrawPipelineStatus) {
162 SkASSERT(DrawPipelineStatus::kNotConfigured != fDrawPipelineStatus);
163 return;
164 }
165
166#ifdef SK_DEBUG
167 if (indexBuffer) {
168 fHasIndexBuffer = true;
169 }
170
171 SkASSERT((DynamicStateStatus::kDisabled == fInstanceBufferStatus) != SkToBool(instanceBuffer));
172 if (instanceBuffer) {
173 fInstanceBufferStatus = DynamicStateStatus::kConfigured;
174 }
175
176 SkASSERT((DynamicStateStatus::kDisabled == fVertexBufferStatus) != SkToBool(vertexBuffer));
177 if (vertexBuffer) {
178 fVertexBufferStatus = DynamicStateStatus::kConfigured;
179 }
180
181 if (GrPrimitiveRestart::kYes == primRestart) {
182 SkASSERT(this->gpu()->caps()->usePrimitiveRestart());
183 }
184#endif
185
186 this->onBindBuffers(indexBuffer, instanceBuffer, vertexBuffer, primRestart);
187}
188
Chris Dalton33db9fc2020-02-25 18:52:12 -0700189bool GrOpsRenderPass::prepareToDraw() {
Chris Dalton4386ad12020-02-19 16:42:06 -0700190 if (DrawPipelineStatus::kOk != fDrawPipelineStatus) {
191 SkASSERT(DrawPipelineStatus::kNotConfigured != fDrawPipelineStatus);
192 this->gpu()->stats()->incNumFailedDraws();
Chris Dalton33db9fc2020-02-25 18:52:12 -0700193 return false;
Chris Dalton4386ad12020-02-19 16:42:06 -0700194 }
Chris Dalton2e7ed262020-02-21 15:17:59 -0700195 SkASSERT(DynamicStateStatus::kUninitialized != fScissorStatus);
196 SkASSERT(DynamicStateStatus::kUninitialized != fTextureBindingStatus);
Chris Dalton4386ad12020-02-19 16:42:06 -0700197
Chris Dalton2e7ed262020-02-21 15:17:59 -0700198 if (kNone_GrXferBarrierType != fXferBarrierType) {
199 this->gpu()->xferBarrier(fRenderTarget, fXferBarrierType);
Chris Dalton4386ad12020-02-19 16:42:06 -0700200 }
Chris Dalton33db9fc2020-02-25 18:52:12 -0700201 return true;
202}
203
Chris Daltonded43702020-03-02 11:45:27 -0700204void GrOpsRenderPass::draw(int vertexCount, int baseVertex) {
Chris Dalton33db9fc2020-02-25 18:52:12 -0700205 if (!this->prepareToDraw()) {
206 return;
207 }
Chris Daltonded43702020-03-02 11:45:27 -0700208 SkASSERT(!fHasIndexBuffer);
209 SkASSERT(DynamicStateStatus::kConfigured != fInstanceBufferStatus);
210 SkASSERT(DynamicStateStatus::kUninitialized != fVertexBufferStatus);
211 this->onDraw(vertexCount, baseVertex);
Chris Dalton33db9fc2020-02-25 18:52:12 -0700212}
213
Chris Daltonded43702020-03-02 11:45:27 -0700214void GrOpsRenderPass::drawIndexed(int indexCount, int baseIndex, uint16_t minIndexValue,
215 uint16_t maxIndexValue, int baseVertex) {
Chris Dalton33db9fc2020-02-25 18:52:12 -0700216 if (!this->prepareToDraw()) {
217 return;
218 }
Chris Daltonded43702020-03-02 11:45:27 -0700219 SkASSERT(fHasIndexBuffer);
220 SkASSERT(DynamicStateStatus::kConfigured != fInstanceBufferStatus);
221 SkASSERT(DynamicStateStatus::kUninitialized != fVertexBufferStatus);
222 this->onDrawIndexed(indexCount, baseIndex, minIndexValue, maxIndexValue, baseVertex);
Chris Dalton33db9fc2020-02-25 18:52:12 -0700223}
224
Chris Daltonded43702020-03-02 11:45:27 -0700225void GrOpsRenderPass::drawInstanced(int instanceCount, int baseInstance, int vertexCount,
Chris Dalton33db9fc2020-02-25 18:52:12 -0700226 int baseVertex) {
227 if (!this->prepareToDraw()) {
228 return;
229 }
Chris Daltonded43702020-03-02 11:45:27 -0700230 SkASSERT(!fHasIndexBuffer);
231 SkASSERT(DynamicStateStatus::kUninitialized != fInstanceBufferStatus);
232 SkASSERT(DynamicStateStatus::kUninitialized != fVertexBufferStatus);
233 this->onDrawInstanced(instanceCount, baseInstance, vertexCount, baseVertex);
Chris Dalton33db9fc2020-02-25 18:52:12 -0700234}
235
Chris Daltonded43702020-03-02 11:45:27 -0700236void GrOpsRenderPass::drawIndexedInstanced(int indexCount, int baseIndex, int instanceCount,
237 int baseInstance, int baseVertex) {
Chris Dalton33db9fc2020-02-25 18:52:12 -0700238 if (!this->prepareToDraw()) {
239 return;
240 }
Chris Daltonded43702020-03-02 11:45:27 -0700241 SkASSERT(fHasIndexBuffer);
242 SkASSERT(DynamicStateStatus::kUninitialized != fInstanceBufferStatus);
243 SkASSERT(DynamicStateStatus::kUninitialized != fVertexBufferStatus);
244 this->onDrawIndexedInstanced(indexCount, baseIndex, instanceCount, baseInstance, baseVertex);
egdaniel9cb63402016-06-23 08:37:05 -0700245}
Chris Daltonbb768422020-03-12 12:13:29 -0600246
247void GrOpsRenderPass::drawIndexPattern(int patternIndexCount, int patternRepeatCount,
248 int maxPatternRepetitionsInIndexBuffer,
249 int patternVertexCount, int baseVertex) {
250 int baseRepetition = 0;
251 while (baseRepetition < patternRepeatCount) {
252 int repeatCount = std::min(patternRepeatCount - baseRepetition,
253 maxPatternRepetitionsInIndexBuffer);
254 int drawIndexCount = repeatCount * patternIndexCount;
255 // A patterned index buffer must contain indices in the range [0..vertexCount].
256 int minIndexValue = 0;
257 int maxIndexValue = patternVertexCount * repeatCount - 1;
258 this->drawIndexed(drawIndexCount, 0, minIndexValue, maxIndexValue,
259 patternVertexCount * baseRepetition + baseVertex);
260 baseRepetition += repeatCount;
261 }
262}