Home | History | Annotate | Download | only in glsl
      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 "GrAllocator.h"
     12 #include "GrShaderVar.h"
     13 #include "glsl/GrGLSLUniformHandler.h"
     14 #include "SkTDArray.h"
     15 
     16 #include <stdarg.h>
     17 
     18 class GrGLSLColorSpaceXformHelper;
     19 
     20 /**
     21   base class for all shaders builders
     22 */
     23 class GrGLSLShaderBuilder {
     24 public:
     25     GrGLSLShaderBuilder(GrGLSLProgramBuilder* program);
     26     virtual ~GrGLSLShaderBuilder() {}
     27 
     28     using SamplerHandle      = GrGLSLUniformHandler::SamplerHandle;
     29 
     30     /** Appends a 2D texture sample with projection if necessary. coordType must either be Vec2f or
     31         Vec3f. The latter is interpreted as projective texture coords. The vec length and swizzle
     32         order of the result depends on the GrProcessor::TextureSampler associated with the
     33         SamplerHandle.
     34         */
     35     void appendTextureLookup(SkString* out,
     36                              SamplerHandle,
     37                              const char* coordName,
     38                              GrSLType coordType = kHalf2_GrSLType) const;
     39 
     40     /** Version of above that appends the result to the shader code instead.*/
     41     void appendTextureLookup(SamplerHandle,
     42                              const char* coordName,
     43                              GrSLType coordType = kHalf2_GrSLType,
     44                              GrGLSLColorSpaceXformHelper* colorXformHelper = nullptr);
     45 
     46 
     47     /** Does the work of appendTextureLookup and modulates the result by modulation. The result is
     48         always a half4. modulation and the swizzle specified by SamplerHandle must both be
     49         half4 or half. If modulation is "" or nullptr it this function acts as though
     50         appendTextureLookup were called. */
     51     void appendTextureLookupAndModulate(const char* modulation,
     52                                         SamplerHandle,
     53                                         const char* coordName,
     54                                         GrSLType coordType = kHalf2_GrSLType,
     55                                         GrGLSLColorSpaceXformHelper* colorXformHelper = nullptr);
     56 
     57     /** Adds a helper function to facilitate color gamut transformation, and produces code that
     58         returns the srcColor transformed into a new gamut (via multiplication by the xform from
     59         colorXformHelper). Premultiplied sources are also handled correctly (colorXformHelper
     60         determines if the source is premultipled or not). */
     61     void appendColorGamutXform(SkString* out, const char* srcColor,
     62                                GrGLSLColorSpaceXformHelper* colorXformHelper);
     63 
     64     /** Version of above that appends the result to the shader code instead. */
     65     void appendColorGamutXform(const char* srcColor, GrGLSLColorSpaceXformHelper* colorXformHelper);
     66 
     67     /**
     68     * Adds a constant declaration to the top of the shader.
     69     */
     70     void defineConstant(const char* type, const char* name, const char* value) {
     71         this->definitions().appendf("const %s %s = %s;\n", type, name, value);
     72     }
     73 
     74     void defineConstant(const char* name, int value) {
     75         this->definitions().appendf("const int %s = %i;\n", name, value);
     76     }
     77 
     78     void defineConstant(const char* name, float value) {
     79         this->definitions().appendf("const float %s = %f;\n", name, value);
     80     }
     81 
     82     void defineConstantf(const char* type, const char* name, const char* fmt, ...) {
     83        this->definitions().appendf("const %s %s = ", type, name);
     84        va_list args;
     85        va_start(args, fmt);
     86        this->definitions().appendVAList(fmt, args);
     87        va_end(args);
     88        this->definitions().append(";\n");
     89     }
     90 
     91     void declareGlobal(const GrShaderVar&);
     92 
     93     /**
     94     * Called by GrGLSLProcessors to add code to one of the shaders.
     95     */
     96     void codeAppendf(const char format[], ...) SK_PRINTF_LIKE(2, 3) {
     97        va_list args;
     98        va_start(args, format);
     99        this->code().appendVAList(format, args);
    100        va_end(args);
    101     }
    102 
    103     void codeAppend(const char* str) { this->code().append(str); }
    104 
    105     void codeAppend(const char* str, size_t length) { this->code().append(str, length); }
    106 
    107     void codePrependf(const char format[], ...) SK_PRINTF_LIKE(2, 3) {
    108        va_list args;
    109        va_start(args, format);
    110        this->code().prependVAList(format, args);
    111        va_end(args);
    112     }
    113 
    114     /**
    115      * Appends a variable declaration to one of the shaders
    116      */
    117     void declAppend(const GrShaderVar& var);
    118 
    119     /** Emits a helper function outside of main() in the fragment shader. */
    120     void emitFunction(GrSLType returnType,
    121                       const char* name,
    122                       int argCnt,
    123                       const GrShaderVar* args,
    124                       const char* body,
    125                       SkString* outName);
    126 
    127     /*
    128      * Combines the various parts of the shader to create a single finalized shader string.
    129      */
    130     void finalize(uint32_t visibility);
    131 
    132     /*
    133      * Get parent builder for adding uniforms
    134      */
    135     GrGLSLProgramBuilder* getProgramBuilder() { return fProgramBuilder; }
    136 
    137     /**
    138      * Helper for begining and ending a block in the shader code.
    139      */
    140     class ShaderBlock {
    141     public:
    142         ShaderBlock(GrGLSLShaderBuilder* builder) : fBuilder(builder) {
    143             SkASSERT(builder);
    144             fBuilder->codeAppend("{");
    145         }
    146 
    147         ~ShaderBlock() {
    148             fBuilder->codeAppend("}");
    149         }
    150     private:
    151         GrGLSLShaderBuilder* fBuilder;
    152     };
    153 
    154 protected:
    155     typedef GrTAllocator<GrShaderVar> VarArray;
    156     void appendDecls(const VarArray& vars, SkString* out) const;
    157 
    158     /**
    159      * Features that should only be enabled internally by the builders.
    160      */
    161     enum GLSLPrivateFeature {
    162         kFragCoordConventions_GLSLPrivateFeature,
    163         kBlendEquationAdvanced_GLSLPrivateFeature,
    164         kBlendFuncExtended_GLSLPrivateFeature,
    165         kFramebufferFetch_GLSLPrivateFeature,
    166         kNoPerspectiveInterpolation_GLSLPrivateFeature,
    167         kSampleVariables_GLSLPrivateFeature,
    168         kLastGLSLPrivateFeature = kSampleVariables_GLSLPrivateFeature
    169     };
    170 
    171     /*
    172      * A general function which enables an extension in a shader if the feature bit is not present
    173      *
    174      * @return true if the feature bit was not yet present, false otherwise.
    175      */
    176     bool addFeature(uint32_t featureBit, const char* extensionName);
    177 
    178     enum InterfaceQualifier {
    179         kIn_InterfaceQualifier,
    180         kOut_InterfaceQualifier,
    181         kLastInterfaceQualifier = kOut_InterfaceQualifier
    182     };
    183 
    184     /*
    185      * A low level function to build default layout qualifiers.
    186      *
    187      *   e.g. layout(param1, param2, ...) out;
    188      *
    189      * GLSL allows default layout qualifiers for in, out, and uniform.
    190      */
    191     void addLayoutQualifier(const char* param, InterfaceQualifier);
    192 
    193     void compileAndAppendLayoutQualifiers();
    194 
    195     void nextStage() {
    196         fShaderStrings.push_back();
    197         fCompilerStrings.push_back(this->code().c_str());
    198         fCompilerStringLengths.push_back((int)this->code().size());
    199         fCodeIndex++;
    200     }
    201 
    202     SkString& versionDecl() { return fShaderStrings[kVersionDecl]; }
    203     SkString& extensions() { return fShaderStrings[kExtensions]; }
    204     SkString& definitions() { return fShaderStrings[kDefinitions]; }
    205     SkString& precisionQualifier() { return fShaderStrings[kPrecisionQualifier]; }
    206     SkString& layoutQualifiers() { return fShaderStrings[kLayoutQualifiers]; }
    207     SkString& uniforms() { return fShaderStrings[kUniforms]; }
    208     SkString& inputs() { return fShaderStrings[kInputs]; }
    209     SkString& outputs() { return fShaderStrings[kOutputs]; }
    210     SkString& functions() { return fShaderStrings[kFunctions]; }
    211     SkString& main() { return fShaderStrings[kMain]; }
    212     SkString& code() { return fShaderStrings[fCodeIndex]; }
    213 
    214     virtual void onFinalize() = 0;
    215 
    216     enum {
    217         kVersionDecl,
    218         kExtensions,
    219         kDefinitions,
    220         kPrecisionQualifier,
    221         kLayoutQualifiers,
    222         kUniforms,
    223         kInputs,
    224         kOutputs,
    225         kFunctions,
    226         kMain,
    227         kCode,
    228     };
    229 
    230     GrGLSLProgramBuilder* fProgramBuilder;
    231     SkSTArray<kCode, const char*, true> fCompilerStrings;
    232     SkSTArray<kCode, int, true> fCompilerStringLengths;
    233     SkSTArray<kCode, SkString> fShaderStrings;
    234     SkString fCode;
    235     SkString fFunctions;
    236     SkString fExtensions;
    237 
    238     VarArray fInputs;
    239     VarArray fOutputs;
    240     uint32_t fFeaturesAddedMask;
    241     SkSTArray<1, SkString> fLayoutParams[kLastInterfaceQualifier + 1];
    242     int fCodeIndex;
    243     bool fFinalized;
    244 
    245     friend class GrCCCoverageProcessor; // to access code().
    246     friend class GrGLSLProgramBuilder;
    247     friend class GrGLProgramBuilder;
    248     friend class GrGLSLVaryingHandler; // to access noperspective interpolation feature.
    249     friend class GrGLPathProgramBuilder; // to access fInputs.
    250     friend class GrVkPipelineStateBuilder;
    251     friend class GrMtlPipelineStateBuilder;
    252 };
    253 #endif
    254