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