blob: a05999c68dac0c1ca606ef91a5525d65948a9248 [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
Chris Daltonc3176002021-07-23 15:33:09 -06008#include "src/gpu/ops/GrDrawAtlasPathOp.h"
Chris Dalton4e998532020-02-10 11:06:42 -07009
10#include "src/gpu/GrOpFlushState.h"
11#include "src/gpu/GrOpsRenderPass.h"
12#include "src/gpu/GrProgramInfo.h"
Robert Phillips1a82a4e2021-07-01 10:27:44 -040013#include "src/gpu/GrResourceProvider.h"
Chris Daltonbaae2dd2021-06-25 14:52:49 -060014#include "src/gpu/GrVertexWriter.h"
Chris Dalton4e998532020-02-10 11:06:42 -070015#include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h"
16#include "src/gpu/glsl/GrGLSLGeometryProcessor.h"
17#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:
Chris Daltonb1fd64e2021-07-08 15:38:51 -060024 DrawAtlasPathShader(bool usesLocalCoords, const GrAtlasInstancedHelper* atlasHelper,
25 const GrShaderCaps& shaderCaps)
Chris Dalton4e998532020-02-10 11:06:42 -070026 : GrGeometryProcessor(kDrawAtlasPathShader_ClassID)
Chris Daltonb1fd64e2021-07-08 15:38:51 -060027 , fUsesLocalCoords(usesLocalCoords)
28 , fAtlasHelper(atlasHelper)
29 , fAtlasAccess(GrSamplerState::Filter::kNearest, fAtlasHelper->proxy()->backendFormat(),
30 fAtlasHelper->atlasSwizzle()) {
Chris Daltona05ccc32021-06-29 19:42:13 -060031 if (!shaderCaps.vertexIDSupport()) {
Chris Daltonee40d5a2021-07-07 16:34:36 -060032 constexpr static Attribute kUnitCoordAttrib("unitCoord", kFloat2_GrVertexAttribType,
Chris Daltona05ccc32021-06-29 19:42:13 -060033 kFloat2_GrSLType);
34 this->setVertexAttributes(&kUnitCoordAttrib, 1);
35 }
Chris Daltonee40d5a2021-07-07 16:34:36 -060036 fAttribs.emplace_back("fillBounds", kFloat4_GrVertexAttribType, kFloat4_GrSLType);
37 if (fUsesLocalCoords) {
38 fAttribs.emplace_back("affineMatrix", kFloat4_GrVertexAttribType, kFloat4_GrSLType);
39 fAttribs.emplace_back("translate", kFloat2_GrVertexAttribType, kFloat2_GrSLType);
40 }
41 SkASSERT(fAttribs.count() == this->colorAttribIdx());
42 fAttribs.emplace_back("color", kFloat4_GrVertexAttribType, kHalf4_GrSLType);
Chris Daltonb1fd64e2021-07-08 15:38:51 -060043 fAtlasHelper->appendInstanceAttribs(&fAttribs);
44 SkASSERT(fAttribs.count() <= kMaxInstanceAttribs);
Chris Daltonee40d5a2021-07-07 16:34:36 -060045 this->setInstanceAttributes(fAttribs.data(), fAttribs.count());
Chris Dalton4e998532020-02-10 11:06:42 -070046 this->setTextureSamplerCnt(1);
47 }
48
49private:
Chris Daltonee40d5a2021-07-07 16:34:36 -060050 int colorAttribIdx() const { return fUsesLocalCoords ? 3 : 1; }
Chris Dalton4e998532020-02-10 11:06:42 -070051 const char* name() const override { return "DrawAtlasPathShader"; }
52 void getGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder* b) const override {
Chris Daltonb1fd64e2021-07-08 15:38:51 -060053 b->addBits(1, fUsesLocalCoords, "localCoords");
54 fAtlasHelper->getKeyBits(b);
Chris Dalton4e998532020-02-10 11:06:42 -070055 }
56 const TextureSampler& onTextureSampler(int) const override { return fAtlasAccess; }
Robert Phillipsf10535f2021-03-23 09:30:45 -040057 GrGLSLGeometryProcessor* createGLSLInstance(const GrShaderCaps&) const override;
Chris Dalton4e998532020-02-10 11:06:42 -070058
Chris Dalton4e998532020-02-10 11:06:42 -070059 const bool fUsesLocalCoords;
Chris Daltonb1fd64e2021-07-08 15:38:51 -060060 const GrAtlasInstancedHelper* const fAtlasHelper;
61 TextureSampler fAtlasAccess;
62 constexpr static int kMaxInstanceAttribs = 6;
63 SkSTArray<kMaxInstanceAttribs, GrGeometryProcessor::Attribute> fAttribs;
Chris Dalton4e998532020-02-10 11:06:42 -070064
65 class Impl;
66};
67
68class DrawAtlasPathShader::Impl : public GrGLSLGeometryProcessor {
69 void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override {
Robert Phillips787fd9d2021-03-22 14:48:09 -040070 const auto& shader = args.fGeomProc.cast<DrawAtlasPathShader>();
Chris Dalton4e998532020-02-10 11:06:42 -070071 args.fVaryingHandler->emitAttributes(shader);
72
Chris Daltona05ccc32021-06-29 19:42:13 -060073 if (args.fShaderCaps->vertexIDSupport()) {
Chris Daltonee40d5a2021-07-07 16:34:36 -060074 // If we don't have sk_VertexID support then "unitCoord" already came in as a vertex
Chris Daltona05ccc32021-06-29 19:42:13 -060075 // attrib.
76 args.fVertBuilder->codeAppendf(R"(
Chris Daltonee40d5a2021-07-07 16:34:36 -060077 float2 unitCoord = float2(sk_VertexID & 1, sk_VertexID >> 1);)");
Chris Daltona05ccc32021-06-29 19:42:13 -060078 }
79
Chris Dalton4e998532020-02-10 11:06:42 -070080 args.fVertBuilder->codeAppendf(R"(
Chris Daltonee40d5a2021-07-07 16:34:36 -060081 float2 devCoord = mix(fillBounds.xy, fillBounds.zw, unitCoord);)");
82 gpArgs->fPositionVar.set(kFloat2_GrSLType, "devCoord");
Chris Dalton4e998532020-02-10 11:06:42 -070083
Chris Dalton4e998532020-02-10 11:06:42 -070084 if (shader.fUsesLocalCoords) {
85 args.fVertBuilder->codeAppendf(R"(
Chris Daltonee40d5a2021-07-07 16:34:36 -060086 float2x2 M = float2x2(affineMatrix);
87 float2 localCoord = inverse(M) * (devCoord - translate);)");
88 gpArgs->fLocalCoordVar.set(kFloat2_GrSLType, "localCoord");
Chris Dalton4e998532020-02-10 11:06:42 -070089 }
Chris Dalton4e998532020-02-10 11:06:42 -070090
Chris Daltonb1fd64e2021-07-08 15:38:51 -060091 args.fFragBuilder->codeAppendf("half4 %s = half4(1);", args.fOutputCoverage);
92 shader.fAtlasHelper->injectShaderCode(args, gpArgs->fPositionVar, &fAtlasAdjustUniform);
Chris Daltonee40d5a2021-07-07 16:34:36 -060093
94 args.fFragBuilder->codeAppendf("half4 %s;", args.fOutputColor);
95 args.fVaryingHandler->addPassThroughAttribute(
96 shader.fAttribs[shader.colorAttribIdx()], args.fOutputColor,
97 GrGLSLVaryingHandler::Interpolation::kCanBeFlat);
Chris Dalton4e998532020-02-10 11:06:42 -070098 }
99
Brian Osman609f1592020-07-01 15:14:39 -0400100 void setData(const GrGLSLProgramDataManager& pdman,
Brian Salomon5a328282021-04-14 10:32:25 -0400101 const GrShaderCaps&,
Robert Phillips787fd9d2021-03-22 14:48:09 -0400102 const GrGeometryProcessor& geomProc) override {
Chris Daltonb1fd64e2021-07-08 15:38:51 -0600103 auto* atlasHelper = geomProc.cast<DrawAtlasPathShader>().fAtlasHelper;
104 atlasHelper->setUniformData(pdman, fAtlasAdjustUniform);
Chris Dalton4e998532020-02-10 11:06:42 -0700105 }
106
107 GrGLSLUniformHandler::UniformHandle fAtlasAdjustUniform;
108};
109
Robert Phillipsf10535f2021-03-23 09:30:45 -0400110GrGLSLGeometryProcessor* DrawAtlasPathShader::createGLSLInstance(const GrShaderCaps&) const {
Chris Dalton4e998532020-02-10 11:06:42 -0700111 return new Impl();
112}
113
114} // namespace
115
116GrProcessorSet::Analysis GrDrawAtlasPathOp::finalize(const GrCaps& caps, const GrAppliedClip* clip,
Chris Dalton4e998532020-02-10 11:06:42 -0700117 GrClampType clampType) {
118 const GrProcessorSet::Analysis& analysis = fProcessors.finalize(
Chris Daltonee40d5a2021-07-07 16:34:36 -0600119 fHeadInstance->fColor, GrProcessorAnalysisCoverage::kSingleChannel, clip,
120 &GrUserStencilSettings::kUnused, caps, clampType, &fHeadInstance->fColor);
Chris Dalton4e998532020-02-10 11:06:42 -0700121 fUsesLocalCoords = analysis.usesLocalCoords();
122 return analysis;
123}
124
Chris Daltonb1fd64e2021-07-08 15:38:51 -0600125GrOp::CombineResult GrDrawAtlasPathOp::onCombineIfPossible(GrOp* op, SkArenaAlloc*, const GrCaps&) {
Chris Dalton4e998532020-02-10 11:06:42 -0700126 auto* that = op->cast<GrDrawAtlasPathOp>();
Chris Dalton4e998532020-02-10 11:06:42 -0700127
Chris Daltonb1fd64e2021-07-08 15:38:51 -0600128 if (!fAtlasHelper.isCompatible(that->fAtlasHelper) ||
129 fProcessors != that->fProcessors) {
Chris Dalton4e998532020-02-10 11:06:42 -0700130 return CombineResult::kCannotCombine;
131 }
132
133 SkASSERT(fUsesLocalCoords == that->fUsesLocalCoords);
Chris Daltonee40d5a2021-07-07 16:34:36 -0600134 *fTailInstance = that->fHeadInstance;
135 fTailInstance = that->fTailInstance;
Chris Dalton4e998532020-02-10 11:06:42 -0700136 fInstanceCount += that->fInstanceCount;
137 return CombineResult::kMerged;
138}
139
Chris Daltonee40d5a2021-07-07 16:34:36 -0600140void GrDrawAtlasPathOp::prepareProgram(const GrCaps& caps, SkArenaAlloc* arena,
Chris Daltoncc29a392021-07-12 15:16:29 -0600141 const GrSurfaceProxyView& writeView, bool usesMSAASurface,
Chris Daltonee40d5a2021-07-07 16:34:36 -0600142 GrAppliedClip&& appliedClip,
143 const GrDstProxyView& dstProxyView,
144 GrXferBarrierFlags renderPassXferBarriers,
145 GrLoadOp colorLoadOp) {
146 SkASSERT(!fProgram);
Chris Dalton4e998532020-02-10 11:06:42 -0700147 GrPipeline::InitArgs initArgs;
Chris Daltoncc29a392021-07-12 15:16:29 -0600148 if (usesMSAASurface) {
Chris Dalton4e998532020-02-10 11:06:42 -0700149 initArgs.fInputFlags |= GrPipeline::InputFlags::kHWAntialias;
150 }
Chris Daltonee40d5a2021-07-07 16:34:36 -0600151 initArgs.fCaps = &caps;
152 initArgs.fDstProxyView = dstProxyView;
153 initArgs.fWriteSwizzle = writeView.swizzle();
Chris Daltonbaae2dd2021-06-25 14:52:49 -0600154 auto pipeline = arena->make<GrPipeline>(initArgs, std::move(fProcessors),
Chris Daltonee40d5a2021-07-07 16:34:36 -0600155 std::move(appliedClip));
Chris Daltonb1fd64e2021-07-08 15:38:51 -0600156 auto shader = arena->make<DrawAtlasPathShader>(fUsesLocalCoords, &fAtlasHelper,
157 *caps.shaderCaps());
Chris Daltonee40d5a2021-07-07 16:34:36 -0600158 fProgram = arena->make<GrProgramInfo>(writeView, pipeline, &GrUserStencilSettings::kUnused,
159 shader, GrPrimitiveType::kTriangleStrip, 0,
160 renderPassXferBarriers, colorLoadOp);
161}
Chris Dalton012f8492020-03-05 11:49:15 -0700162
Chris Daltonee40d5a2021-07-07 16:34:36 -0600163void GrDrawAtlasPathOp::onPrePrepare(GrRecordingContext* rContext,
164 const GrSurfaceProxyView& writeView,
165 GrAppliedClip* appliedClip, const GrDstProxyView& dstProxyView,
166 GrXferBarrierFlags renderPassXferBarriers,
167 GrLoadOp colorLoadOp) {
168 this->prepareProgram(*rContext->priv().caps(), rContext->priv().recordTimeAllocator(),
Chris Daltoncc29a392021-07-12 15:16:29 -0600169 writeView, writeView.asRenderTargetProxy()->numSamples() > 1,
170 std::move(*appliedClip), dstProxyView, renderPassXferBarriers,
Chris Daltonee40d5a2021-07-07 16:34:36 -0600171 colorLoadOp);
172 SkASSERT(fProgram);
173 rContext->priv().recordProgramInfo(fProgram);
174}
175
176GR_DECLARE_STATIC_UNIQUE_KEY(gUnitQuadBufferKey);
177
178void GrDrawAtlasPathOp::onPrepare(GrOpFlushState* flushState) {
179 if (!fProgram) {
180 this->prepareProgram(flushState->caps(), flushState->allocator(), flushState->writeView(),
Chris Daltoncc29a392021-07-12 15:16:29 -0600181 flushState->usesMSAASurface(), flushState->detachAppliedClip(),
182 flushState->dstProxyView(), flushState->renderPassBarriers(),
183 flushState->colorLoadOp());
Chris Daltonee40d5a2021-07-07 16:34:36 -0600184 SkASSERT(fProgram);
185 }
186
Chris Daltoncc29a392021-07-12 15:16:29 -0600187 // FIXME(skbug.com/12201): Our draw's MSAA state should match the render target, but DDL doesn't
188 // yet communicate DMSAA state to onPrePrepare.
189 SkASSERT(fProgram->pipeline().isHWAntialiasState() == flushState->usesMSAASurface());
190
Chris Daltonee40d5a2021-07-07 16:34:36 -0600191 if (GrVertexWriter instanceWriter = flushState->makeVertexSpace(
192 fProgram->geomProc().instanceStride(), fInstanceCount, &fInstanceBuffer,
193 &fBaseInstance)) {
Chris Daltonb1fd64e2021-07-08 15:38:51 -0600194 for (const Instance* i = fHeadInstance; i; i = i->fNext) {
Chris Daltonbaae2dd2021-06-25 14:52:49 -0600195 instanceWriter.write(
Chris Daltonb1fd64e2021-07-08 15:38:51 -0600196 SkRect::Make(i->fFillBounds),
Chris Daltonee40d5a2021-07-07 16:34:36 -0600197 GrVertexWriter::If(fUsesLocalCoords,
Chris Daltonb1fd64e2021-07-08 15:38:51 -0600198 i->fLocalToDeviceIfUsingLocalCoords),
199 i->fColor);
200 fAtlasHelper.writeInstanceData(&instanceWriter, &i->fAtlasInstance);
Chris Daltonbaae2dd2021-06-25 14:52:49 -0600201 }
202 }
Chris Daltona05ccc32021-06-29 19:42:13 -0600203
Chris Daltonee40d5a2021-07-07 16:34:36 -0600204 if (!flushState->caps().shaderCaps()->vertexIDSupport()) {
Chris Daltona05ccc32021-06-29 19:42:13 -0600205 constexpr static SkPoint kUnitQuad[4] = {{0,0}, {0,1}, {1,0}, {1,1}};
206
207 GR_DEFINE_STATIC_UNIQUE_KEY(gUnitQuadBufferKey);
208
Chris Daltonee40d5a2021-07-07 16:34:36 -0600209 fVertexBufferIfNoIDSupport = flushState->resourceProvider()->findOrMakeStaticBuffer(
Chris Daltona05ccc32021-06-29 19:42:13 -0600210 GrGpuBufferType::kVertex, sizeof(kUnitQuad), kUnitQuad, gUnitQuadBufferKey);
211 }
Chris Daltonbaae2dd2021-06-25 14:52:49 -0600212}
Chris Dalton4e998532020-02-10 11:06:42 -0700213
Chris Daltonee40d5a2021-07-07 16:34:36 -0600214void GrDrawAtlasPathOp::onExecute(GrOpFlushState* flushState, const SkRect& chainBounds) {
Chris Daltonee40d5a2021-07-07 16:34:36 -0600215 flushState->bindPipelineAndScissorClip(*fProgram, this->bounds());
Chris Daltonb1fd64e2021-07-08 15:38:51 -0600216 flushState->bindTextures(fProgram->geomProc(), *fAtlasHelper.proxy(), fProgram->pipeline());
Chris Daltonee40d5a2021-07-07 16:34:36 -0600217 flushState->bindBuffers(nullptr, std::move(fInstanceBuffer), fVertexBufferIfNoIDSupport);
218 flushState->drawInstanced(fInstanceCount, fBaseInstance, 4, 0);
Chris Dalton4e998532020-02-10 11:06:42 -0700219}