blob: 189997da19493b1eeb1aefeaeb5aa37f4e0a6eba [file] [log] [blame]
Chris Dalton4e998532020-02-10 11:06:42 -07001/*
2 * Copyright 2020 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
Robert Phillips769b4882021-09-07 16:48:46 -04008#include "src/gpu/ops/DrawAtlasPathOp.h"
Chris Dalton4e998532020-02-10 11:06:42 -07009
Brian Salomon48959462021-08-11 13:01:06 -040010#include "src/gpu/GrGeometryProcessor.h"
Chris Dalton4e998532020-02-10 11:06:42 -070011#include "src/gpu/GrOpFlushState.h"
12#include "src/gpu/GrOpsRenderPass.h"
13#include "src/gpu/GrProgramInfo.h"
Robert Phillips1a82a4e2021-07-01 10:27:44 -040014#include "src/gpu/GrResourceProvider.h"
Chris Daltonbaae2dd2021-06-25 14:52:49 -060015#include "src/gpu/GrVertexWriter.h"
Chris Dalton4e998532020-02-10 11:06:42 -070016#include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h"
Chris Dalton4e998532020-02-10 11:06:42 -070017#include "src/gpu/glsl/GrGLSLVarying.h"
18#include "src/gpu/glsl/GrGLSLVertexGeoBuilder.h"
19
20namespace {
21
Chris Dalton4e998532020-02-10 11:06:42 -070022class DrawAtlasPathShader : public GrGeometryProcessor {
23public:
Brian Salomonbab2d112021-08-11 09:59:56 -040024 DrawAtlasPathShader(bool usesLocalCoords,
Robert Phillipsef80d7b2021-09-14 16:10:56 -040025 const skgpu::v1::AtlasInstancedHelper* atlasHelper,
Chris Daltonb1fd64e2021-07-08 15:38:51 -060026 const GrShaderCaps& shaderCaps)
Chris Dalton4e998532020-02-10 11:06:42 -070027 : GrGeometryProcessor(kDrawAtlasPathShader_ClassID)
Chris Daltonb1fd64e2021-07-08 15:38:51 -060028 , fUsesLocalCoords(usesLocalCoords)
29 , fAtlasHelper(atlasHelper)
Brian Salomonbab2d112021-08-11 09:59:56 -040030 , fAtlasAccess(GrSamplerState::Filter::kNearest,
31 fAtlasHelper->proxy()->backendFormat(),
Chris Daltonb1fd64e2021-07-08 15:38:51 -060032 fAtlasHelper->atlasSwizzle()) {
Chris Daltona05ccc32021-06-29 19:42:13 -060033 if (!shaderCaps.vertexIDSupport()) {
Brian Salomonbab2d112021-08-11 09:59:56 -040034 constexpr static Attribute kUnitCoordAttrib(
35 "unitCoord", kFloat2_GrVertexAttribType, kFloat2_GrSLType);
Chris Daltona05ccc32021-06-29 19:42:13 -060036 this->setVertexAttributes(&kUnitCoordAttrib, 1);
37 }
Chris Daltonee40d5a2021-07-07 16:34:36 -060038 fAttribs.emplace_back("fillBounds", kFloat4_GrVertexAttribType, kFloat4_GrSLType);
39 if (fUsesLocalCoords) {
40 fAttribs.emplace_back("affineMatrix", kFloat4_GrVertexAttribType, kFloat4_GrSLType);
41 fAttribs.emplace_back("translate", kFloat2_GrVertexAttribType, kFloat2_GrSLType);
42 }
43 SkASSERT(fAttribs.count() == this->colorAttribIdx());
44 fAttribs.emplace_back("color", kFloat4_GrVertexAttribType, kHalf4_GrSLType);
Chris Daltonb1fd64e2021-07-08 15:38:51 -060045 fAtlasHelper->appendInstanceAttribs(&fAttribs);
46 SkASSERT(fAttribs.count() <= kMaxInstanceAttribs);
Chris Daltonee40d5a2021-07-07 16:34:36 -060047 this->setInstanceAttributes(fAttribs.data(), fAttribs.count());
Chris Dalton4e998532020-02-10 11:06:42 -070048 this->setTextureSamplerCnt(1);
49 }
50
51private:
Brian Salomonbab2d112021-08-11 09:59:56 -040052 class Impl;
53
Chris Daltonee40d5a2021-07-07 16:34:36 -060054 int colorAttribIdx() const { return fUsesLocalCoords ? 3 : 1; }
Chris Dalton4e998532020-02-10 11:06:42 -070055 const char* name() const override { return "DrawAtlasPathShader"; }
Brian Salomon13b28732021-08-06 15:33:58 -040056 void addToKey(const GrShaderCaps&, GrProcessorKeyBuilder* b) const override {
Chris Daltonb1fd64e2021-07-08 15:38:51 -060057 b->addBits(1, fUsesLocalCoords, "localCoords");
58 fAtlasHelper->getKeyBits(b);
Chris Dalton4e998532020-02-10 11:06:42 -070059 }
60 const TextureSampler& onTextureSampler(int) const override { return fAtlasAccess; }
Brian Salomonf95940b2021-08-09 15:56:24 -040061 std::unique_ptr<ProgramImpl> makeProgramImpl(const GrShaderCaps&) const override;
Chris Dalton4e998532020-02-10 11:06:42 -070062
Chris Dalton4e998532020-02-10 11:06:42 -070063 const bool fUsesLocalCoords;
Robert Phillipsef80d7b2021-09-14 16:10:56 -040064 const skgpu::v1::AtlasInstancedHelper* const fAtlasHelper;
Chris Daltonb1fd64e2021-07-08 15:38:51 -060065 TextureSampler fAtlasAccess;
66 constexpr static int kMaxInstanceAttribs = 6;
67 SkSTArray<kMaxInstanceAttribs, GrGeometryProcessor::Attribute> fAttribs;
Chris Dalton4e998532020-02-10 11:06:42 -070068};
69
Brian Salomonf95940b2021-08-09 15:56:24 -040070class DrawAtlasPathShader::Impl : public ProgramImpl {
Brian Salomonbab2d112021-08-11 09:59:56 -040071public:
72 void setData(const GrGLSLProgramDataManager& pdman,
73 const GrShaderCaps&,
74 const GrGeometryProcessor& geomProc) override {
75 auto* atlasHelper = geomProc.cast<DrawAtlasPathShader>().fAtlasHelper;
76 atlasHelper->setUniformData(pdman, fAtlasAdjustUniform);
77 }
78
79private:
Chris Dalton4e998532020-02-10 11:06:42 -070080 void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override {
Robert Phillips787fd9d2021-03-22 14:48:09 -040081 const auto& shader = args.fGeomProc.cast<DrawAtlasPathShader>();
Chris Dalton4e998532020-02-10 11:06:42 -070082 args.fVaryingHandler->emitAttributes(shader);
83
Chris Daltona05ccc32021-06-29 19:42:13 -060084 if (args.fShaderCaps->vertexIDSupport()) {
Chris Daltonee40d5a2021-07-07 16:34:36 -060085 // If we don't have sk_VertexID support then "unitCoord" already came in as a vertex
Chris Daltona05ccc32021-06-29 19:42:13 -060086 // attrib.
87 args.fVertBuilder->codeAppendf(R"(
Chris Daltonee40d5a2021-07-07 16:34:36 -060088 float2 unitCoord = float2(sk_VertexID & 1, sk_VertexID >> 1);)");
Chris Daltona05ccc32021-06-29 19:42:13 -060089 }
90
Chris Dalton4e998532020-02-10 11:06:42 -070091 args.fVertBuilder->codeAppendf(R"(
Chris Daltonee40d5a2021-07-07 16:34:36 -060092 float2 devCoord = mix(fillBounds.xy, fillBounds.zw, unitCoord);)");
93 gpArgs->fPositionVar.set(kFloat2_GrSLType, "devCoord");
Chris Dalton4e998532020-02-10 11:06:42 -070094
Chris Dalton4e998532020-02-10 11:06:42 -070095 if (shader.fUsesLocalCoords) {
96 args.fVertBuilder->codeAppendf(R"(
Chris Daltonee40d5a2021-07-07 16:34:36 -060097 float2x2 M = float2x2(affineMatrix);
98 float2 localCoord = inverse(M) * (devCoord - translate);)");
99 gpArgs->fLocalCoordVar.set(kFloat2_GrSLType, "localCoord");
Chris Dalton4e998532020-02-10 11:06:42 -0700100 }
Chris Dalton4e998532020-02-10 11:06:42 -0700101
Chris Daltonb1fd64e2021-07-08 15:38:51 -0600102 args.fFragBuilder->codeAppendf("half4 %s = half4(1);", args.fOutputCoverage);
103 shader.fAtlasHelper->injectShaderCode(args, gpArgs->fPositionVar, &fAtlasAdjustUniform);
Chris Daltonee40d5a2021-07-07 16:34:36 -0600104
105 args.fFragBuilder->codeAppendf("half4 %s;", args.fOutputColor);
106 args.fVaryingHandler->addPassThroughAttribute(
Brian Salomon48959462021-08-11 13:01:06 -0400107 shader.fAttribs[shader.colorAttribIdx()].asShaderVar(),
108 args.fOutputColor,
Chris Daltonee40d5a2021-07-07 16:34:36 -0600109 GrGLSLVaryingHandler::Interpolation::kCanBeFlat);
Chris Dalton4e998532020-02-10 11:06:42 -0700110 }
111
Chris Dalton4e998532020-02-10 11:06:42 -0700112 GrGLSLUniformHandler::UniformHandle fAtlasAdjustUniform;
113};
114
Brian Salomonf95940b2021-08-09 15:56:24 -0400115std::unique_ptr<GrGeometryProcessor::ProgramImpl> DrawAtlasPathShader::makeProgramImpl(
116 const GrShaderCaps&) const {
117 return std::make_unique<Impl>();
Chris Dalton4e998532020-02-10 11:06:42 -0700118}
119
Robert Phillips769b4882021-09-07 16:48:46 -0400120} // anonymous namespace
Chris Dalton4e998532020-02-10 11:06:42 -0700121
Robert Phillips769b4882021-09-07 16:48:46 -0400122namespace skgpu::v1 {
123
124GrProcessorSet::Analysis DrawAtlasPathOp::finalize(const GrCaps& caps, const GrAppliedClip* clip,
125 GrClampType clampType) {
Chris Dalton4e998532020-02-10 11:06:42 -0700126 const GrProcessorSet::Analysis& analysis = fProcessors.finalize(
Chris Daltonee40d5a2021-07-07 16:34:36 -0600127 fHeadInstance->fColor, GrProcessorAnalysisCoverage::kSingleChannel, clip,
128 &GrUserStencilSettings::kUnused, caps, clampType, &fHeadInstance->fColor);
Chris Dalton4e998532020-02-10 11:06:42 -0700129 fUsesLocalCoords = analysis.usesLocalCoords();
130 return analysis;
131}
132
Robert Phillips769b4882021-09-07 16:48:46 -0400133GrOp::CombineResult DrawAtlasPathOp::onCombineIfPossible(GrOp* op, SkArenaAlloc*, const GrCaps&) {
134 auto that = op->cast<DrawAtlasPathOp>();
Chris Dalton4e998532020-02-10 11:06:42 -0700135
Chris Daltonb1fd64e2021-07-08 15:38:51 -0600136 if (!fAtlasHelper.isCompatible(that->fAtlasHelper) ||
137 fProcessors != that->fProcessors) {
Chris Dalton4e998532020-02-10 11:06:42 -0700138 return CombineResult::kCannotCombine;
139 }
140
141 SkASSERT(fUsesLocalCoords == that->fUsesLocalCoords);
Chris Daltonee40d5a2021-07-07 16:34:36 -0600142 *fTailInstance = that->fHeadInstance;
143 fTailInstance = that->fTailInstance;
Chris Dalton4e998532020-02-10 11:06:42 -0700144 fInstanceCount += that->fInstanceCount;
145 return CombineResult::kMerged;
146}
147
Robert Phillips769b4882021-09-07 16:48:46 -0400148void DrawAtlasPathOp::prepareProgram(const GrCaps& caps, SkArenaAlloc* arena,
149 const GrSurfaceProxyView& writeView, bool usesMSAASurface,
150 GrAppliedClip&& appliedClip,
151 const GrDstProxyView& dstProxyView,
152 GrXferBarrierFlags renderPassXferBarriers,
153 GrLoadOp colorLoadOp) {
Chris Daltonee40d5a2021-07-07 16:34:36 -0600154 SkASSERT(!fProgram);
Chris Dalton4e998532020-02-10 11:06:42 -0700155 GrPipeline::InitArgs initArgs;
Chris Daltonee40d5a2021-07-07 16:34:36 -0600156 initArgs.fCaps = &caps;
157 initArgs.fDstProxyView = dstProxyView;
158 initArgs.fWriteSwizzle = writeView.swizzle();
Chris Daltonbaae2dd2021-06-25 14:52:49 -0600159 auto pipeline = arena->make<GrPipeline>(initArgs, std::move(fProcessors),
Chris Daltonee40d5a2021-07-07 16:34:36 -0600160 std::move(appliedClip));
Chris Daltonb1fd64e2021-07-08 15:38:51 -0600161 auto shader = arena->make<DrawAtlasPathShader>(fUsesLocalCoords, &fAtlasHelper,
162 *caps.shaderCaps());
Chris Dalton2a26c502021-08-26 10:05:11 -0600163 fProgram = arena->make<GrProgramInfo>(caps, writeView, usesMSAASurface, pipeline,
164 &GrUserStencilSettings::kUnused, shader,
165 GrPrimitiveType::kTriangleStrip, 0,
Chris Daltonee40d5a2021-07-07 16:34:36 -0600166 renderPassXferBarriers, colorLoadOp);
167}
Chris Dalton012f8492020-03-05 11:49:15 -0700168
Robert Phillips769b4882021-09-07 16:48:46 -0400169void DrawAtlasPathOp::onPrePrepare(GrRecordingContext* rContext,
170 const GrSurfaceProxyView& writeView,
171 GrAppliedClip* appliedClip, const GrDstProxyView& dstProxyView,
172 GrXferBarrierFlags renderPassXferBarriers,
173 GrLoadOp colorLoadOp) {
Chris Dalton2a26c502021-08-26 10:05:11 -0600174 // DMSAA is not supported on DDL.
175 bool usesMSAASurface = writeView.asRenderTargetProxy()->numSamples() > 1;
Chris Daltonee40d5a2021-07-07 16:34:36 -0600176 this->prepareProgram(*rContext->priv().caps(), rContext->priv().recordTimeAllocator(),
Chris Dalton2a26c502021-08-26 10:05:11 -0600177 writeView, usesMSAASurface, std::move(*appliedClip), dstProxyView,
178 renderPassXferBarriers, colorLoadOp);
Chris Daltonee40d5a2021-07-07 16:34:36 -0600179 SkASSERT(fProgram);
180 rContext->priv().recordProgramInfo(fProgram);
181}
182
183GR_DECLARE_STATIC_UNIQUE_KEY(gUnitQuadBufferKey);
184
Robert Phillips769b4882021-09-07 16:48:46 -0400185void DrawAtlasPathOp::onPrepare(GrOpFlushState* flushState) {
Chris Daltonee40d5a2021-07-07 16:34:36 -0600186 if (!fProgram) {
187 this->prepareProgram(flushState->caps(), flushState->allocator(), flushState->writeView(),
Chris Daltoncc29a392021-07-12 15:16:29 -0600188 flushState->usesMSAASurface(), flushState->detachAppliedClip(),
189 flushState->dstProxyView(), flushState->renderPassBarriers(),
190 flushState->colorLoadOp());
Chris Daltonee40d5a2021-07-07 16:34:36 -0600191 SkASSERT(fProgram);
192 }
193
194 if (GrVertexWriter instanceWriter = flushState->makeVertexSpace(
195 fProgram->geomProc().instanceStride(), fInstanceCount, &fInstanceBuffer,
196 &fBaseInstance)) {
Chris Daltonb1fd64e2021-07-08 15:38:51 -0600197 for (const Instance* i = fHeadInstance; i; i = i->fNext) {
Chris Daltonbaae2dd2021-06-25 14:52:49 -0600198 instanceWriter.write(
Chris Daltonb1fd64e2021-07-08 15:38:51 -0600199 SkRect::Make(i->fFillBounds),
Chris Daltonee40d5a2021-07-07 16:34:36 -0600200 GrVertexWriter::If(fUsesLocalCoords,
Chris Daltonb1fd64e2021-07-08 15:38:51 -0600201 i->fLocalToDeviceIfUsingLocalCoords),
202 i->fColor);
203 fAtlasHelper.writeInstanceData(&instanceWriter, &i->fAtlasInstance);
Chris Daltonbaae2dd2021-06-25 14:52:49 -0600204 }
205 }
Chris Daltona05ccc32021-06-29 19:42:13 -0600206
Chris Daltonee40d5a2021-07-07 16:34:36 -0600207 if (!flushState->caps().shaderCaps()->vertexIDSupport()) {
Chris Daltona05ccc32021-06-29 19:42:13 -0600208 constexpr static SkPoint kUnitQuad[4] = {{0,0}, {0,1}, {1,0}, {1,1}};
209
210 GR_DEFINE_STATIC_UNIQUE_KEY(gUnitQuadBufferKey);
211
Chris Daltonee40d5a2021-07-07 16:34:36 -0600212 fVertexBufferIfNoIDSupport = flushState->resourceProvider()->findOrMakeStaticBuffer(
Chris Daltona05ccc32021-06-29 19:42:13 -0600213 GrGpuBufferType::kVertex, sizeof(kUnitQuad), kUnitQuad, gUnitQuadBufferKey);
214 }
Chris Daltonbaae2dd2021-06-25 14:52:49 -0600215}
Chris Dalton4e998532020-02-10 11:06:42 -0700216
Robert Phillips769b4882021-09-07 16:48:46 -0400217void DrawAtlasPathOp::onExecute(GrOpFlushState* flushState, const SkRect& chainBounds) {
Chris Daltonee40d5a2021-07-07 16:34:36 -0600218 flushState->bindPipelineAndScissorClip(*fProgram, this->bounds());
Chris Daltonb1fd64e2021-07-08 15:38:51 -0600219 flushState->bindTextures(fProgram->geomProc(), *fAtlasHelper.proxy(), fProgram->pipeline());
Chris Daltonee40d5a2021-07-07 16:34:36 -0600220 flushState->bindBuffers(nullptr, std::move(fInstanceBuffer), fVertexBufferIfNoIDSupport);
221 flushState->drawInstanced(fInstanceCount, fBaseInstance, 4, 0);
Chris Dalton4e998532020-02-10 11:06:42 -0700222}
Robert Phillips769b4882021-09-07 16:48:46 -0400223
224} // namespace skgpu::v1