Coverage Report

Created: 2021-08-22 09:07

/src/skia/src/gpu/glsl/GrGLSLShaderBuilder.h
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright 2014 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 GrGLSLShaderBuilder_DEFINED
9
#define GrGLSLShaderBuilder_DEFINED
10
11
#include "include/core/SkSpan.h"
12
#include "include/private/SkSLStatement.h"
13
#include "include/private/SkSLString.h"
14
#include "include/private/SkTDArray.h"
15
#include "src/gpu/GrShaderVar.h"
16
#include "src/gpu/GrTBlockList.h"
17
#include "src/gpu/glsl/GrGLSLUniformHandler.h"
18
19
#include <stdarg.h>
20
21
class GrGLSLColorSpaceXformHelper;
22
23
namespace SkSL {
24
    namespace dsl {
25
        class DSLWriter;
26
    }
27
}
28
29
/**
30
  base class for all shaders builders
31
*/
32
class GrGLSLShaderBuilder {
33
public:
34
    GrGLSLShaderBuilder(GrGLSLProgramBuilder* program);
35
0
    virtual ~GrGLSLShaderBuilder() {}
36
37
    using SamplerHandle      = GrGLSLUniformHandler::SamplerHandle;
38
39
    /** Appends a 2D texture sample with projection if necessary. The vec length and swizzle
40
        order of the result depends on the GrProcessor::TextureSampler associated with the
41
        SamplerHandle.
42
        */
43
    void appendTextureLookup(SkString* out, SamplerHandle, const char* coordName) const;
44
45
    /** Version of above that appends the result to the shader code instead.*/
46
    void appendTextureLookup(SamplerHandle,
47
                             const char* coordName,
48
                             GrGLSLColorSpaceXformHelper* colorXformHelper = nullptr);
49
50
    /** Does the work of appendTextureLookup and blends the result by dst, treating the texture
51
        lookup as the src input to the blend. The dst is assumed to be half4 and the result is
52
        always a half4. If dst is nullptr we use half4(1) as the blend dst. */
53
    void appendTextureLookupAndBlend(const char* dst,
54
                                     SkBlendMode,
55
                                     SamplerHandle,
56
                                     const char* coordName,
57
                                     GrGLSLColorSpaceXformHelper* colorXformHelper = nullptr);
58
59
    /** Appends a load of an input attachment into the shader code. */
60
    void appendInputLoad(SamplerHandle);
61
62
    /** Adds a helper function to facilitate color gamut transformation, and produces code that
63
        returns the srcColor transformed into a new gamut (via multiplication by the xform from
64
        colorXformHelper). Premultiplied sources are also handled correctly (colorXformHelper
65
        determines if the source is premultipled or not). */
66
    void appendColorGamutXform(SkString* out, const char* srcColor,
67
                               GrGLSLColorSpaceXformHelper* colorXformHelper);
68
69
    /** Version of above that appends the result to the shader code instead. */
70
    void appendColorGamutXform(const char* srcColor, GrGLSLColorSpaceXformHelper* colorXformHelper);
71
72
    /**
73
    * Adds a constant declaration to the top of the shader.
74
    */
75
0
    void defineConstant(const char* type, const char* name, const char* value) {
76
0
        this->definitions().appendf("const %s %s = %s;\n", type, name, value);
77
0
    }
78
79
0
    void defineConstant(const char* name, int value) {
80
0
        this->definitions().appendf("const int %s = %i;\n", name, value);
81
0
    }
82
83
0
    void defineConstant(const char* name, float value) {
84
0
        this->definitions().appendf("const float %s = %f;\n", name, value);
85
0
    }
86
87
0
    void defineConstantf(const char* type, const char* name, const char* fmt, ...) {
88
0
       this->definitions().appendf("const %s %s = ", type, name);
89
0
       va_list args;
90
0
       va_start(args, fmt);
91
0
       this->definitions().appendVAList(fmt, args);
92
0
       va_end(args);
93
0
       this->definitions().append(";\n");
94
0
    }
95
96
0
    void definitionAppend(const char* str) { this->definitions().append(str); }
97
98
    void declareGlobal(const GrShaderVar&);
99
100
    // Generates a unique variable name for holding the result of a temporary expression when it's
101
    // not reasonable to just add a new block for scoping. Does not declare anything.
102
0
    SkString newTmpVarName(const char* suffix) {
103
0
        int tmpIdx = fTmpVariableCounter++;
104
0
        return SkStringPrintf("_tmp_%d_%s", tmpIdx, suffix);
105
0
    }
106
107
    /**
108
     * Called by GrGLSLProcessors to add code to one of the shaders.
109
     */
110
0
    void codeAppendf(const char format[], ...) SK_PRINTF_LIKE(2, 3) {
111
0
       va_list args;
112
0
       va_start(args, format);
113
0
       this->code().appendVAList(format, args);
114
0
       va_end(args);
115
0
    }
116
117
0
    void codeAppend(const char* str) { this->code().append(str); }
118
119
0
    void codeAppend(const char* str, size_t length) { this->code().append(str, length); }
120
121
    void codeAppend(std::unique_ptr<SkSL::Statement> stmt);
122
123
0
    void codePrependf(const char format[], ...) SK_PRINTF_LIKE(2, 3) {
124
0
       va_list args;
125
0
       va_start(args, format);
126
0
       this->code().prependVAList(format, args);
127
0
       va_end(args);
128
0
    }
129
130
    /**
131
     * Appends a variable declaration to one of the shaders
132
     */
133
    void declAppend(const GrShaderVar& var);
134
135
    /**
136
     * Generates a mangled name for a helper function in the fragment shader. Will give consistent
137
     * results if called more than once.
138
     */
139
    SkString getMangledFunctionName(const char* baseName);
140
141
    /** Emits a prototype for a helper function outside of main() in the fragment shader. */
142
    void emitFunctionPrototype(GrSLType returnType,
143
                               const char* mangledName,
144
                               SkSpan<const GrShaderVar> args);
145
146
    /** Emits a helper function outside of main() in the fragment shader. */
147
    void emitFunction(GrSLType returnType,
148
                      const char* mangledName,
149
                      SkSpan<const GrShaderVar> args,
150
                      const char* body);
151
152
    void emitFunction(const char* declaration, const char* body);
153
154
    /**
155
     * Combines the various parts of the shader to create a single finalized shader string.
156
     */
157
    void finalize(uint32_t visibility);
158
159
    /**
160
     * Get parent builder for adding uniforms.
161
     */
162
0
    GrGLSLProgramBuilder* getProgramBuilder() { return fProgramBuilder; }
163
164
    /**
165
     * Helper for begining and ending a block in the shader code.
166
     */
167
    class ShaderBlock {
168
    public:
169
0
        ShaderBlock(GrGLSLShaderBuilder* builder) : fBuilder(builder) {
170
0
            SkASSERT(builder);
171
0
            fBuilder->codeAppend("{");
172
0
        }
Unexecuted instantiation: GrGLSLShaderBuilder::ShaderBlock::ShaderBlock(GrGLSLShaderBuilder*)
Unexecuted instantiation: GrGLSLShaderBuilder::ShaderBlock::ShaderBlock(GrGLSLShaderBuilder*)
173
174
0
        ~ShaderBlock() {
175
0
            fBuilder->codeAppend("}");
176
0
        }
177
    private:
178
        GrGLSLShaderBuilder* fBuilder;
179
    };
180
181
protected:
182
    typedef GrTBlockList<GrShaderVar> VarArray;
183
    void appendDecls(const VarArray& vars, SkString* out) const;
184
185
    void appendFunctionDecl(GrSLType returnType,
186
                            const char* mangledName,
187
                            SkSpan<const GrShaderVar> args);
188
189
    /**
190
     * Features that should only be enabled internally by the builders.
191
     */
192
    enum GLSLPrivateFeature {
193
        kFragCoordConventions_GLSLPrivateFeature,
194
        kBlendEquationAdvanced_GLSLPrivateFeature,
195
        kBlendFuncExtended_GLSLPrivateFeature,
196
        kFramebufferFetch_GLSLPrivateFeature,
197
        kNoPerspectiveInterpolation_GLSLPrivateFeature,
198
        kSampleVariables_GLSLPrivateFeature,
199
        kLastGLSLPrivateFeature = kSampleVariables_GLSLPrivateFeature
200
    };
201
202
    /*
203
     * A general function which enables an extension in a shader if the feature bit is not present
204
     *
205
     * @return true if the feature bit was not yet present, false otherwise.
206
     */
207
    bool addFeature(uint32_t featureBit, const char* extensionName);
208
209
    enum InterfaceQualifier {
210
        kIn_InterfaceQualifier,
211
        kOut_InterfaceQualifier,
212
        kLastInterfaceQualifier = kOut_InterfaceQualifier
213
    };
214
215
    /*
216
     * A low level function to build default layout qualifiers.
217
     *
218
     *   e.g. layout(param1, param2, ...) out;
219
     *
220
     * GLSL allows default layout qualifiers for in, out, and uniform.
221
     */
222
    void addLayoutQualifier(const char* param, InterfaceQualifier);
223
224
    void compileAndAppendLayoutQualifiers();
225
226
0
    void nextStage() {
227
0
        fShaderStrings.push_back();
228
0
        fCodeIndex++;
229
0
    }
230
231
0
    void deleteStage() {
232
0
        fShaderStrings.pop_back();
233
0
        fCodeIndex--;
234
0
    }
235
236
0
    SkString& extensions() { return fShaderStrings[kExtensions]; }
237
0
    SkString& definitions() { return fShaderStrings[kDefinitions]; }
238
0
    SkString& precisionQualifier() { return fShaderStrings[kPrecisionQualifier]; }
239
0
    SkString& layoutQualifiers() { return fShaderStrings[kLayoutQualifiers]; }
240
0
    SkString& uniforms() { return fShaderStrings[kUniforms]; }
241
0
    SkString& inputs() { return fShaderStrings[kInputs]; }
242
0
    SkString& outputs() { return fShaderStrings[kOutputs]; }
243
0
    SkString& functions() { return fShaderStrings[kFunctions]; }
244
0
    SkString& main() { return fShaderStrings[kMain]; }
245
0
    SkString& code() { return fShaderStrings[fCodeIndex]; }
246
247
    virtual void onFinalize() = 0;
248
249
    enum {
250
        kExtensions,
251
        kDefinitions,
252
        kPrecisionQualifier,
253
        kLayoutQualifiers,
254
        kUniforms,
255
        kInputs,
256
        kOutputs,
257
        kFunctions,
258
        kMain,
259
        kCode,
260
261
        kPrealloc = kCode + 6,  // 6 == Reasonable upper bound on number of processor stages
262
    };
263
264
    GrGLSLProgramBuilder* fProgramBuilder;
265
    SkSL::String fCompilerString;
266
    SkSTArray<kPrealloc, SkString> fShaderStrings;
267
    SkString fCode;
268
    SkString fFunctions;
269
    SkString fExtensions;
270
    // Hangs onto Declarations so we don't destroy them prior to the variables that refer to them.
271
    SkSL::StatementArray fDeclarations;
272
273
    VarArray fInputs;
274
    VarArray fOutputs;
275
    uint32_t fFeaturesAddedMask;
276
    SkSTArray<1, SkString> fLayoutParams[kLastInterfaceQualifier + 1];
277
    int fCodeIndex;
278
    bool fFinalized;
279
280
    // Counter for generating unique scratch variable names in a shader.
281
    int fTmpVariableCounter;
282
283
    friend class GrGLSLProgramBuilder;
284
    friend class GrGLProgramBuilder;
285
    friend class GrD3DPipelineStateBuilder;
286
    friend class GrDawnProgramBuilder;
287
    friend class GrGLSLVaryingHandler; // to access noperspective interpolation feature.
288
    friend class GrGLPathProgramBuilder; // to access fInputs.
289
    friend class GrVkPipelineStateBuilder;
290
    friend class GrMtlPipelineStateBuilder;
291
    friend class SkSL::dsl::DSLWriter;
292
};
293
#endif