xref: /aosp_15_r20/external/skia/src/gpu/ganesh/glsl/GrGLSLProgramBuilder.h (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1 /*
2  * Copyright 2015 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 
8 #ifndef GrGLSLProgramBuilder_DEFINED
9 #define GrGLSLProgramBuilder_DEFINED
10 
11 #include "include/private/base/SkDebug.h"
12 #include "include/private/base/SkTArray.h"
13 #include "include/private/gpu/ganesh/GrTypesPriv.h"
14 #include "src/gpu/Swizzle.h"
15 #include "src/gpu/ganesh/GrCaps.h"
16 #include "src/gpu/ganesh/GrFragmentProcessor.h"
17 #include "src/gpu/ganesh/GrGeometryProcessor.h"
18 #include "src/gpu/ganesh/GrPipeline.h"
19 #include "src/gpu/ganesh/GrProgramInfo.h"
20 #include "src/gpu/ganesh/GrSamplerState.h"
21 #include "src/gpu/ganesh/GrShaderVar.h"
22 #include "src/gpu/ganesh/GrXferProcessor.h"
23 #include "src/gpu/ganesh/glsl/GrGLSLFragmentShaderBuilder.h"
24 #include "src/gpu/ganesh/glsl/GrGLSLUniformHandler.h"
25 #include "src/gpu/ganesh/glsl/GrGLSLVertexGeoBuilder.h"
26 
27 #include <cstdint>
28 #include <memory>
29 #include <string>
30 #include <vector>
31 
32 class GrBackendFormat;
33 class GrGLSLVaryingHandler;
34 class GrProgramDesc;
35 class SkString;
36 enum GrSurfaceOrigin : int;
37 struct GrShaderCaps;
38 
39 class GrGLSLProgramBuilder {
40 public:
41     using UniformHandle      = GrGLSLUniformHandler::UniformHandle;
42     using SamplerHandle      = GrGLSLUniformHandler::SamplerHandle;
43 
44     virtual ~GrGLSLProgramBuilder();
45 
46     virtual const GrCaps* caps() const = 0;
shaderCaps()47     const GrShaderCaps* shaderCaps() const { return this->caps()->shaderCaps(); }
48 
origin()49     GrSurfaceOrigin origin() const { return fProgramInfo.origin(); }
pipeline()50     const GrPipeline& pipeline() const { return fProgramInfo.pipeline(); }
geometryProcessor()51     const GrGeometryProcessor& geometryProcessor() const { return fProgramInfo.geomProc(); }
snapVerticesToPixelCenters()52     bool snapVerticesToPixelCenters() const {
53         return fProgramInfo.pipeline().snapVerticesToPixelCenters();
54     }
hasPointSize()55     bool hasPointSize() const { return fProgramInfo.primitiveType() == GrPrimitiveType::kPoints; }
56 
desc()57     const GrProgramDesc& desc() const { return fDesc; }
58 
59     void appendUniformDecls(GrShaderFlags visibility, SkString*) const;
60 
samplerVariable(SamplerHandle handle)61     const char* samplerVariable(SamplerHandle handle) const {
62         return this->uniformHandler()->samplerVariable(handle);
63     }
64 
samplerSwizzle(SamplerHandle handle)65     skgpu::Swizzle samplerSwizzle(SamplerHandle handle) const {
66         return this->uniformHandler()->samplerSwizzle(handle);
67     }
68 
inputSamplerVariable(SamplerHandle handle)69     const char* inputSamplerVariable(SamplerHandle handle) const {
70         return this->uniformHandler()->inputSamplerVariable(handle);
71     }
72 
inputSamplerSwizzle(SamplerHandle handle)73     skgpu::Swizzle inputSamplerSwizzle(SamplerHandle handle) const {
74         return this->uniformHandler()->inputSamplerSwizzle(handle);
75     }
76 
77     // Used to add a uniform for render target flip (used for dFdy, sk_Clockwise, and sk_FragCoord)
78     // without mangling the name of the uniform inside of a stage.
79     void addRTFlipUniform(const char* name);
80 
81     // Generates a name for a variable. The generated string will be name prefixed by the prefix
82     // char (unless the prefix is '\0'). It also will mangle the name to be stage-specific unless
83     // explicitly asked not to. `nameVariable` can also be used to generate names for functions or
84     // other types of symbols where unique names are important.
85     SkString nameVariable(char prefix, const char* name, bool mangle = true);
86 
87     /**
88      * Emits samplers for TextureEffect fragment processors as needed. `fp` can be a TextureEffect,
89      * or a tree containing zero or more TextureEffects.
90      */
91     bool emitTextureSamplersForFPs(const GrFragmentProcessor& fp,
92                                    GrFragmentProcessor::ProgramImpl& impl,
93                                    int* samplerIndex);
94 
95     /**
96      * advanceStage is called by program creator between each processor's emit code.  It increments
97      * the stage index for variable name mangling, and also ensures verification variables in the
98      * fragment shader are cleared.
99      */
advanceStage()100     void advanceStage() {
101         fStageIndex++;
102         SkDEBUGCODE(fFS.debugOnly_resetPerStageVerification();)
103         fFS.nextStage();
104     }
105 
106     /** Adds the SkSL function that implements an FP assuming its children are already written. */
107     void writeFPFunction(const GrFragmentProcessor& fp, GrFragmentProcessor::ProgramImpl& impl);
108 
109     /**
110      * Returns a function-call invocation of `fp` in string form, passing the appropriate
111      * combination of `inputColor`, `destColor` and `fLocalCoordsVar` for the FP.
112      */
113     std::string invokeFP(const GrFragmentProcessor& fp,
114                          const GrFragmentProcessor::ProgramImpl& impl,
115                          const char* inputColor,
116                          const char* destColor,
117                          const char* coords) const;
118     /**
119      * If the FP's coords are unused or all uses have been lifted to interpolated varyings then
120      * don't put coords in the FP's function signature or call sites.
121      */
122     bool fragmentProcessorHasCoordsParam(const GrFragmentProcessor*) const;
123 
124     virtual GrGLSLUniformHandler* uniformHandler() = 0;
125     virtual const GrGLSLUniformHandler* uniformHandler() const = 0;
126     virtual GrGLSLVaryingHandler* varyingHandler() = 0;
127 
128     // Used for backend customization of the secondary color variable from the fragment processor.
129     // Only used if the output is explicitly declared in the shaders.
finalizeFragmentSecondaryColor(GrShaderVar & outputColor)130     virtual void finalizeFragmentSecondaryColor(GrShaderVar& outputColor) {}
131 
132     // number of each input/output type in a single allocation block, used by many builders
133     static const int kVarsPerBlock;
134 
135     GrGLSLVertexBuilder          fVS;
136     GrGLSLFragmentShaderBuilder  fFS;
137 
138     const GrProgramDesc&         fDesc;
139     const GrProgramInfo&         fProgramInfo;
140 
141     GrGLSLBuiltinUniformHandles  fUniformHandles;
142 
143     std::unique_ptr<GrGeometryProcessor::ProgramImpl>               fGPImpl;
144     std::unique_ptr<GrXferProcessor::ProgramImpl>                   fXPImpl;
145     std::vector<std::unique_ptr<GrFragmentProcessor::ProgramImpl>>  fFPImpls;
146 
147     SamplerHandle fDstTextureSamplerHandle;
148     GrSurfaceOrigin fDstTextureOrigin;
149 
150 protected:
151     explicit GrGLSLProgramBuilder(const GrProgramDesc&, const GrProgramInfo&);
152 
153     void addFeature(GrShaderFlags shaders, uint32_t featureBit, const char* extensionName);
154 
155     bool emitAndInstallProcs();
156 
157     void finalizeShaders();
158 
fragColorIsInOut()159     bool fragColorIsInOut() const { return fFS.primaryColorOutputIsInOut(); }
160 
161 private:
162     SkString getMangleSuffix() const;
163 
164     // Generates a possibly mangled name for a stage variable and writes it to the fragment shader.
165     void nameExpression(SkString*, const char* baseName);
166 
167     bool emitAndInstallPrimProc(SkString* outputColor, SkString* outputCoverage);
168     bool emitAndInstallDstTexture();
169     /** Adds the root FPs */
170     bool emitAndInstallFragProcs(SkString* colorInOut, SkString* coverageInOut);
171     /** Adds a single root FP tree. */
172     SkString emitRootFragProc(const GrFragmentProcessor& fp,
173                               GrFragmentProcessor::ProgramImpl& impl,
174                               const SkString& input,
175                               SkString output);
176     /** Recursive step to write out children FPs' functions before parent's. */
177     void writeChildFPFunctions(const GrFragmentProcessor& fp,
178                                GrFragmentProcessor::ProgramImpl& impl);
179     bool emitAndInstallXferProc(const SkString& colorIn, const SkString& coverageIn);
180     SamplerHandle emitSampler(const GrBackendFormat&, GrSamplerState, const skgpu::Swizzle&,
181                               const char* name);
182     SamplerHandle emitInputSampler(const skgpu::Swizzle& swizzle, const char* name);
183     bool checkSamplerCounts();
184 
185 #ifdef SK_DEBUG
186     void verify(const GrGeometryProcessor&);
187     void verify(const GrFragmentProcessor&);
188     void verify(const GrXferProcessor&);
189 #endif
190 
191     // This is used to check that we don't excede the allowable number of resources in a shader.
192     int fNumFragmentSamplers;
193 
194     GrGeometryProcessor::ProgramImpl::FPCoordsMap fFPCoordsMap;
195     GrShaderVar                                   fLocalCoordsVar;
196 
197     /**
198      * Each root processor has an stage index. The GP is stage 0. The first root FP is stage 1,
199      * the second root FP is stage 2, etc. The XP's stage index is last and its value depends on
200      * how many root FPs there are. Names are mangled by appending _S<stage-index>.
201      */
202     int fStageIndex = -1;
203 
204     /**
205      * When emitting FP stages we track the children FPs as "substages" and do additional name
206      * mangling based on where in the FP hierarchy we are. The first FP is stage index 1. It's first
207      * child would be substage 0 of stage 1. If that FP also has three children then its third child
208      * would be substage 2 of stubstage 0 of stage 1 and would be mangled as "_S1_c0_c2".
209      */
210     skia_private::TArray<int> fSubstageIndices;
211 };
212 
213 #endif
214