1cb93a386Sopenharmony_ci/* 2cb93a386Sopenharmony_ci * Copyright 2020 Google Inc. 3cb93a386Sopenharmony_ci * 4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be 5cb93a386Sopenharmony_ci * found in the LICENSE file. 6cb93a386Sopenharmony_ci */ 7cb93a386Sopenharmony_ci 8cb93a386Sopenharmony_ci#include "src/gpu/ops/DrawAtlasPathOp.h" 9cb93a386Sopenharmony_ci 10cb93a386Sopenharmony_ci#include "src/gpu/BufferWriter.h" 11cb93a386Sopenharmony_ci#include "src/gpu/GrGeometryProcessor.h" 12cb93a386Sopenharmony_ci#include "src/gpu/GrOpFlushState.h" 13cb93a386Sopenharmony_ci#include "src/gpu/GrOpsRenderPass.h" 14cb93a386Sopenharmony_ci#include "src/gpu/GrProgramInfo.h" 15cb93a386Sopenharmony_ci#include "src/gpu/GrResourceProvider.h" 16cb93a386Sopenharmony_ci#include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h" 17cb93a386Sopenharmony_ci#include "src/gpu/glsl/GrGLSLVarying.h" 18cb93a386Sopenharmony_ci#include "src/gpu/glsl/GrGLSLVertexGeoBuilder.h" 19cb93a386Sopenharmony_ci 20cb93a386Sopenharmony_cinamespace { 21cb93a386Sopenharmony_ci 22cb93a386Sopenharmony_ciclass DrawAtlasPathShader : public GrGeometryProcessor { 23cb93a386Sopenharmony_cipublic: 24cb93a386Sopenharmony_ci DrawAtlasPathShader(bool usesLocalCoords, 25cb93a386Sopenharmony_ci const skgpu::v1::AtlasInstancedHelper* atlasHelper, 26cb93a386Sopenharmony_ci const GrShaderCaps& shaderCaps) 27cb93a386Sopenharmony_ci : GrGeometryProcessor(kDrawAtlasPathShader_ClassID) 28cb93a386Sopenharmony_ci , fUsesLocalCoords(usesLocalCoords) 29cb93a386Sopenharmony_ci , fAtlasHelper(atlasHelper) 30cb93a386Sopenharmony_ci , fAtlasAccess(GrSamplerState::Filter::kNearest, 31cb93a386Sopenharmony_ci fAtlasHelper->proxy()->backendFormat(), 32cb93a386Sopenharmony_ci fAtlasHelper->atlasSwizzle()) { 33cb93a386Sopenharmony_ci if (!shaderCaps.vertexIDSupport()) { 34cb93a386Sopenharmony_ci constexpr static Attribute kUnitCoordAttrib( 35cb93a386Sopenharmony_ci "unitCoord", kFloat2_GrVertexAttribType, kFloat2_GrSLType); 36cb93a386Sopenharmony_ci this->setVertexAttributes(&kUnitCoordAttrib, 1); 37cb93a386Sopenharmony_ci } 38cb93a386Sopenharmony_ci fAttribs.emplace_back("fillBounds", kFloat4_GrVertexAttribType, kFloat4_GrSLType); 39cb93a386Sopenharmony_ci if (fUsesLocalCoords) { 40cb93a386Sopenharmony_ci fAttribs.emplace_back("affineMatrix", kFloat4_GrVertexAttribType, kFloat4_GrSLType); 41cb93a386Sopenharmony_ci fAttribs.emplace_back("translate", kFloat2_GrVertexAttribType, kFloat2_GrSLType); 42cb93a386Sopenharmony_ci } 43cb93a386Sopenharmony_ci SkASSERT(fAttribs.count() == this->colorAttribIdx()); 44cb93a386Sopenharmony_ci fAttribs.emplace_back("color", kFloat4_GrVertexAttribType, kHalf4_GrSLType); 45cb93a386Sopenharmony_ci fAtlasHelper->appendInstanceAttribs(&fAttribs); 46cb93a386Sopenharmony_ci SkASSERT(fAttribs.count() <= kMaxInstanceAttribs); 47cb93a386Sopenharmony_ci this->setInstanceAttributes(fAttribs.data(), fAttribs.count()); 48cb93a386Sopenharmony_ci this->setTextureSamplerCnt(1); 49cb93a386Sopenharmony_ci } 50cb93a386Sopenharmony_ci 51cb93a386Sopenharmony_ciprivate: 52cb93a386Sopenharmony_ci class Impl; 53cb93a386Sopenharmony_ci 54cb93a386Sopenharmony_ci int colorAttribIdx() const { return fUsesLocalCoords ? 3 : 1; } 55cb93a386Sopenharmony_ci const char* name() const override { return "DrawAtlasPathShader"; } 56cb93a386Sopenharmony_ci SkString getShaderDfxInfo() const override { 57cb93a386Sopenharmony_ci SkString format; 58cb93a386Sopenharmony_ci format.printf("ShaderDfx_DrawAtlasPathShader_%d", fUsesLocalCoords); 59cb93a386Sopenharmony_ci return format; 60cb93a386Sopenharmony_ci } 61cb93a386Sopenharmony_ci void addToKey(const GrShaderCaps&, GrProcessorKeyBuilder* b) const override { 62cb93a386Sopenharmony_ci b->addBits(1, fUsesLocalCoords, "localCoords"); 63cb93a386Sopenharmony_ci fAtlasHelper->getKeyBits(b); 64cb93a386Sopenharmony_ci } 65cb93a386Sopenharmony_ci const TextureSampler& onTextureSampler(int) const override { return fAtlasAccess; } 66cb93a386Sopenharmony_ci std::unique_ptr<ProgramImpl> makeProgramImpl(const GrShaderCaps&) const override; 67cb93a386Sopenharmony_ci 68cb93a386Sopenharmony_ci const bool fUsesLocalCoords; 69cb93a386Sopenharmony_ci const skgpu::v1::AtlasInstancedHelper* const fAtlasHelper; 70cb93a386Sopenharmony_ci TextureSampler fAtlasAccess; 71cb93a386Sopenharmony_ci constexpr static int kMaxInstanceAttribs = 6; 72cb93a386Sopenharmony_ci SkSTArray<kMaxInstanceAttribs, GrGeometryProcessor::Attribute> fAttribs; 73cb93a386Sopenharmony_ci}; 74cb93a386Sopenharmony_ci 75cb93a386Sopenharmony_ciclass DrawAtlasPathShader::Impl : public ProgramImpl { 76cb93a386Sopenharmony_cipublic: 77cb93a386Sopenharmony_ci void setData(const GrGLSLProgramDataManager& pdman, 78cb93a386Sopenharmony_ci const GrShaderCaps&, 79cb93a386Sopenharmony_ci const GrGeometryProcessor& geomProc) override { 80cb93a386Sopenharmony_ci auto* atlasHelper = geomProc.cast<DrawAtlasPathShader>().fAtlasHelper; 81cb93a386Sopenharmony_ci atlasHelper->setUniformData(pdman, fAtlasAdjustUniform); 82cb93a386Sopenharmony_ci } 83cb93a386Sopenharmony_ci 84cb93a386Sopenharmony_ciprivate: 85cb93a386Sopenharmony_ci void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override { 86cb93a386Sopenharmony_ci const auto& shader = args.fGeomProc.cast<DrawAtlasPathShader>(); 87cb93a386Sopenharmony_ci args.fVaryingHandler->emitAttributes(shader); 88cb93a386Sopenharmony_ci 89cb93a386Sopenharmony_ci if (args.fShaderCaps->vertexIDSupport()) { 90cb93a386Sopenharmony_ci // If we don't have sk_VertexID support then "unitCoord" already came in as a vertex 91cb93a386Sopenharmony_ci // attrib. 92cb93a386Sopenharmony_ci args.fVertBuilder->codeAppendf(R"( 93cb93a386Sopenharmony_ci float2 unitCoord = float2(sk_VertexID & 1, sk_VertexID >> 1);)"); 94cb93a386Sopenharmony_ci } 95cb93a386Sopenharmony_ci 96cb93a386Sopenharmony_ci args.fVertBuilder->codeAppendf(R"( 97cb93a386Sopenharmony_ci float2 devCoord = mix(fillBounds.xy, fillBounds.zw, unitCoord);)"); 98cb93a386Sopenharmony_ci gpArgs->fPositionVar.set(kFloat2_GrSLType, "devCoord"); 99cb93a386Sopenharmony_ci 100cb93a386Sopenharmony_ci if (shader.fUsesLocalCoords) { 101cb93a386Sopenharmony_ci args.fVertBuilder->codeAppendf(R"( 102cb93a386Sopenharmony_ci float2x2 M = float2x2(affineMatrix); 103cb93a386Sopenharmony_ci float2 localCoord = inverse(M) * (devCoord - translate);)"); 104cb93a386Sopenharmony_ci gpArgs->fLocalCoordVar.set(kFloat2_GrSLType, "localCoord"); 105cb93a386Sopenharmony_ci } 106cb93a386Sopenharmony_ci 107cb93a386Sopenharmony_ci args.fFragBuilder->codeAppendf("half4 %s = half4(1);", args.fOutputCoverage); 108cb93a386Sopenharmony_ci shader.fAtlasHelper->injectShaderCode(args, gpArgs->fPositionVar, &fAtlasAdjustUniform); 109cb93a386Sopenharmony_ci 110cb93a386Sopenharmony_ci args.fFragBuilder->codeAppendf("half4 %s;", args.fOutputColor); 111cb93a386Sopenharmony_ci args.fVaryingHandler->addPassThroughAttribute( 112cb93a386Sopenharmony_ci shader.fAttribs[shader.colorAttribIdx()].asShaderVar(), 113cb93a386Sopenharmony_ci args.fOutputColor, 114cb93a386Sopenharmony_ci GrGLSLVaryingHandler::Interpolation::kCanBeFlat); 115cb93a386Sopenharmony_ci } 116cb93a386Sopenharmony_ci 117cb93a386Sopenharmony_ci GrGLSLUniformHandler::UniformHandle fAtlasAdjustUniform; 118cb93a386Sopenharmony_ci}; 119cb93a386Sopenharmony_ci 120cb93a386Sopenharmony_cistd::unique_ptr<GrGeometryProcessor::ProgramImpl> DrawAtlasPathShader::makeProgramImpl( 121cb93a386Sopenharmony_ci const GrShaderCaps&) const { 122cb93a386Sopenharmony_ci return std::make_unique<Impl>(); 123cb93a386Sopenharmony_ci} 124cb93a386Sopenharmony_ci 125cb93a386Sopenharmony_ci} // anonymous namespace 126cb93a386Sopenharmony_ci 127cb93a386Sopenharmony_cinamespace skgpu::v1 { 128cb93a386Sopenharmony_ci 129cb93a386Sopenharmony_ciGrProcessorSet::Analysis DrawAtlasPathOp::finalize(const GrCaps& caps, const GrAppliedClip* clip, 130cb93a386Sopenharmony_ci GrClampType clampType) { 131cb93a386Sopenharmony_ci const GrProcessorSet::Analysis& analysis = fProcessors.finalize( 132cb93a386Sopenharmony_ci fHeadInstance->fColor, GrProcessorAnalysisCoverage::kSingleChannel, clip, 133cb93a386Sopenharmony_ci &GrUserStencilSettings::kUnused, caps, clampType, &fHeadInstance->fColor); 134cb93a386Sopenharmony_ci fUsesLocalCoords = analysis.usesLocalCoords(); 135cb93a386Sopenharmony_ci return analysis; 136cb93a386Sopenharmony_ci} 137cb93a386Sopenharmony_ci 138cb93a386Sopenharmony_ciGrOp::CombineResult DrawAtlasPathOp::onCombineIfPossible(GrOp* op, SkArenaAlloc*, const GrCaps&) { 139cb93a386Sopenharmony_ci auto that = op->cast<DrawAtlasPathOp>(); 140cb93a386Sopenharmony_ci 141cb93a386Sopenharmony_ci if (!fAtlasHelper.isCompatible(that->fAtlasHelper) || 142cb93a386Sopenharmony_ci fProcessors != that->fProcessors) { 143cb93a386Sopenharmony_ci return CombineResult::kCannotCombine; 144cb93a386Sopenharmony_ci } 145cb93a386Sopenharmony_ci 146cb93a386Sopenharmony_ci SkASSERT(fUsesLocalCoords == that->fUsesLocalCoords); 147cb93a386Sopenharmony_ci *fTailInstance = that->fHeadInstance; 148cb93a386Sopenharmony_ci fTailInstance = that->fTailInstance; 149cb93a386Sopenharmony_ci fInstanceCount += that->fInstanceCount; 150cb93a386Sopenharmony_ci return CombineResult::kMerged; 151cb93a386Sopenharmony_ci} 152cb93a386Sopenharmony_ci 153cb93a386Sopenharmony_civoid DrawAtlasPathOp::prepareProgram(const GrCaps& caps, SkArenaAlloc* arena, 154cb93a386Sopenharmony_ci const GrSurfaceProxyView& writeView, bool usesMSAASurface, 155cb93a386Sopenharmony_ci GrAppliedClip&& appliedClip, 156cb93a386Sopenharmony_ci const GrDstProxyView& dstProxyView, 157cb93a386Sopenharmony_ci GrXferBarrierFlags renderPassXferBarriers, 158cb93a386Sopenharmony_ci GrLoadOp colorLoadOp) { 159cb93a386Sopenharmony_ci SkASSERT(!fProgram); 160cb93a386Sopenharmony_ci GrPipeline::InitArgs initArgs; 161cb93a386Sopenharmony_ci initArgs.fCaps = ∩︀ 162cb93a386Sopenharmony_ci initArgs.fDstProxyView = dstProxyView; 163cb93a386Sopenharmony_ci initArgs.fWriteSwizzle = writeView.swizzle(); 164cb93a386Sopenharmony_ci auto pipeline = arena->make<GrPipeline>(initArgs, std::move(fProcessors), 165cb93a386Sopenharmony_ci std::move(appliedClip)); 166cb93a386Sopenharmony_ci auto shader = arena->make<DrawAtlasPathShader>(fUsesLocalCoords, &fAtlasHelper, 167cb93a386Sopenharmony_ci *caps.shaderCaps()); 168cb93a386Sopenharmony_ci fProgram = arena->make<GrProgramInfo>(caps, writeView, usesMSAASurface, pipeline, 169cb93a386Sopenharmony_ci &GrUserStencilSettings::kUnused, shader, 170cb93a386Sopenharmony_ci GrPrimitiveType::kTriangleStrip, 0, 171cb93a386Sopenharmony_ci renderPassXferBarriers, colorLoadOp); 172cb93a386Sopenharmony_ci} 173cb93a386Sopenharmony_ci 174cb93a386Sopenharmony_civoid DrawAtlasPathOp::onPrePrepare(GrRecordingContext* rContext, 175cb93a386Sopenharmony_ci const GrSurfaceProxyView& writeView, 176cb93a386Sopenharmony_ci GrAppliedClip* appliedClip, const GrDstProxyView& dstProxyView, 177cb93a386Sopenharmony_ci GrXferBarrierFlags renderPassXferBarriers, 178cb93a386Sopenharmony_ci GrLoadOp colorLoadOp) { 179cb93a386Sopenharmony_ci // DMSAA is not supported on DDL. 180cb93a386Sopenharmony_ci bool usesMSAASurface = writeView.asRenderTargetProxy()->numSamples() > 1; 181cb93a386Sopenharmony_ci this->prepareProgram(*rContext->priv().caps(), rContext->priv().recordTimeAllocator(), 182cb93a386Sopenharmony_ci writeView, usesMSAASurface, std::move(*appliedClip), dstProxyView, 183cb93a386Sopenharmony_ci renderPassXferBarriers, colorLoadOp); 184cb93a386Sopenharmony_ci SkASSERT(fProgram); 185cb93a386Sopenharmony_ci rContext->priv().recordProgramInfo(fProgram); 186cb93a386Sopenharmony_ci} 187cb93a386Sopenharmony_ci 188cb93a386Sopenharmony_ciGR_DECLARE_STATIC_UNIQUE_KEY(gUnitQuadBufferKey); 189cb93a386Sopenharmony_ci 190cb93a386Sopenharmony_civoid DrawAtlasPathOp::onPrepare(GrOpFlushState* flushState) { 191cb93a386Sopenharmony_ci if (!fProgram) { 192cb93a386Sopenharmony_ci this->prepareProgram(flushState->caps(), flushState->allocator(), flushState->writeView(), 193cb93a386Sopenharmony_ci flushState->usesMSAASurface(), flushState->detachAppliedClip(), 194cb93a386Sopenharmony_ci flushState->dstProxyView(), flushState->renderPassBarriers(), 195cb93a386Sopenharmony_ci flushState->colorLoadOp()); 196cb93a386Sopenharmony_ci SkASSERT(fProgram); 197cb93a386Sopenharmony_ci } 198cb93a386Sopenharmony_ci 199cb93a386Sopenharmony_ci if (VertexWriter instanceWriter = flushState->makeVertexSpace( 200cb93a386Sopenharmony_ci fProgram->geomProc().instanceStride(), fInstanceCount, &fInstanceBuffer, 201cb93a386Sopenharmony_ci &fBaseInstance)) { 202cb93a386Sopenharmony_ci for (const Instance* i = fHeadInstance; i; i = i->fNext) { 203cb93a386Sopenharmony_ci instanceWriter << SkRect::Make(i->fFillBounds) 204cb93a386Sopenharmony_ci << VertexWriter::If(fUsesLocalCoords, 205cb93a386Sopenharmony_ci i->fLocalToDeviceIfUsingLocalCoords) 206cb93a386Sopenharmony_ci << i->fColor; 207cb93a386Sopenharmony_ci fAtlasHelper.writeInstanceData(&instanceWriter, &i->fAtlasInstance); 208cb93a386Sopenharmony_ci } 209cb93a386Sopenharmony_ci } 210cb93a386Sopenharmony_ci 211cb93a386Sopenharmony_ci if (!flushState->caps().shaderCaps()->vertexIDSupport()) { 212cb93a386Sopenharmony_ci constexpr static SkPoint kUnitQuad[4] = {{0,0}, {0,1}, {1,0}, {1,1}}; 213cb93a386Sopenharmony_ci 214cb93a386Sopenharmony_ci GR_DEFINE_STATIC_UNIQUE_KEY(gUnitQuadBufferKey); 215cb93a386Sopenharmony_ci 216cb93a386Sopenharmony_ci fVertexBufferIfNoIDSupport = flushState->resourceProvider()->findOrMakeStaticBuffer( 217cb93a386Sopenharmony_ci GrGpuBufferType::kVertex, sizeof(kUnitQuad), kUnitQuad, gUnitQuadBufferKey); 218cb93a386Sopenharmony_ci } 219cb93a386Sopenharmony_ci} 220cb93a386Sopenharmony_ci 221cb93a386Sopenharmony_civoid DrawAtlasPathOp::onExecute(GrOpFlushState* flushState, const SkRect& chainBounds) { 222cb93a386Sopenharmony_ci if (fProgram->geomProc().hasVertexAttributes() && !fVertexBufferIfNoIDSupport) { 223cb93a386Sopenharmony_ci return; 224cb93a386Sopenharmony_ci } 225cb93a386Sopenharmony_ci flushState->bindPipelineAndScissorClip(*fProgram, this->bounds()); 226cb93a386Sopenharmony_ci flushState->bindTextures(fProgram->geomProc(), *fAtlasHelper.proxy(), fProgram->pipeline()); 227cb93a386Sopenharmony_ci flushState->bindBuffers(nullptr, std::move(fInstanceBuffer), fVertexBufferIfNoIDSupport); 228cb93a386Sopenharmony_ci flushState->drawInstanced(fInstanceCount, fBaseInstance, 4, 0); 229cb93a386Sopenharmony_ci} 230cb93a386Sopenharmony_ci 231cb93a386Sopenharmony_ci} // namespace skgpu::v1 232