| /* |
| * Copyright 2015 Google Inc. |
| * |
| * Use of this source code is governed by a BSD-style license that can be |
| * found in the LICENSE file. |
| */ |
| |
| #ifndef GrGLSLProgramBuilder_DEFINED |
| #define GrGLSLProgramBuilder_DEFINED |
| |
| #include "GrCaps.h" |
| #include "GrGeometryProcessor.h" |
| #include "GrGpu.h" |
| #include "glsl/GrGLSLFragmentProcessor.h" |
| #include "glsl/GrGLSLFragmentShaderBuilder.h" |
| #include "glsl/GrGLSLGeometryShaderBuilder.h" |
| #include "glsl/GrGLSLPrimitiveProcessor.h" |
| #include "glsl/GrGLSLProgramDataManager.h" |
| #include "glsl/GrGLSLUniformHandler.h" |
| #include "glsl/GrGLSLVertexShaderBuilder.h" |
| #include "glsl/GrGLSLXferProcessor.h" |
| |
| class GrShaderVar; |
| class GrGLSLVaryingHandler; |
| class GrGLSLExpr4; |
| class GrShaderCaps; |
| |
| typedef SkSTArray<8, GrGLSLFragmentProcessor*, true> GrGLSLFragProcs; |
| |
| class GrGLSLProgramBuilder { |
| public: |
| using UniformHandle = GrGLSLUniformHandler::UniformHandle; |
| using SamplerHandle = GrGLSLUniformHandler::SamplerHandle; |
| using ImageStorageHandle = GrGLSLUniformHandler::ImageStorageHandle; |
| |
| virtual ~GrGLSLProgramBuilder() {} |
| |
| virtual const GrCaps* caps() const = 0; |
| const GrShaderCaps* shaderCaps() const { return this->caps()->shaderCaps(); } |
| |
| const GrPrimitiveProcessor& primitiveProcessor() const { return fPrimProc; } |
| const GrPipeline& pipeline() const { return fPipeline; } |
| const GrProgramDesc& desc() const { return fDesc; } |
| const GrProgramDesc::KeyHeader& header() const { return fDesc.header(); } |
| |
| void appendUniformDecls(GrShaderFlags visibility, SkString*) const; |
| |
| const GrShaderVar& samplerVariable(SamplerHandle handle) const { |
| return this->uniformHandler()->samplerVariable(handle); |
| } |
| |
| GrSwizzle samplerSwizzle(SamplerHandle handle) const { |
| return this->uniformHandler()->samplerSwizzle(handle); |
| } |
| |
| const GrShaderVar& imageStorageVariable(ImageStorageHandle handle) const { |
| return this->uniformHandler()->imageStorageVariable(handle); |
| } |
| |
| // Handles for program uniforms (other than per-effect uniforms) |
| struct BuiltinUniformHandles { |
| UniformHandle fRTAdjustmentUni; |
| |
| // We use the render target height to provide a y-down frag coord when specifying |
| // origin_upper_left is not supported. |
| UniformHandle fRTHeightUni; |
| }; |
| |
| // Used to add a uniform in the vertex shader for transforming into normalized device space. |
| void addRTAdjustmentUniform(GrSLPrecision precision, const char* name, const char** outName); |
| const char* rtAdjustment() const { return "rtAdjustment"; } |
| |
| // Used to add a uniform for the RenderTarget height (used for frag position) without mangling |
| // the name of the uniform inside of a stage. |
| void addRTHeightUniform(const char* name, const char** outName); |
| |
| // Generates a name for a variable. The generated string will be name prefixed by the prefix |
| // char (unless the prefix is '\0'). It also will mangle the name to be stage-specific unless |
| // explicitly asked not to. |
| void nameVariable(SkString* out, char prefix, const char* name, bool mangle = true); |
| |
| virtual GrGLSLUniformHandler* uniformHandler() = 0; |
| virtual const GrGLSLUniformHandler* uniformHandler() const = 0; |
| virtual GrGLSLVaryingHandler* varyingHandler() = 0; |
| |
| // Used for backend customization of the output color and secondary color variables from the |
| // fragment processor. Only used if the outputs are explicitly declared in the shaders |
| virtual void finalizeFragmentOutputColor(GrShaderVar& outputColor) {} |
| virtual void finalizeFragmentSecondaryColor(GrShaderVar& outputColor) {} |
| |
| // number of each input/output type in a single allocation block, used by many builders |
| static const int kVarsPerBlock; |
| |
| GrGLSLVertexBuilder fVS; |
| GrGLSLGeometryBuilder fGS; |
| GrGLSLFragmentShaderBuilder fFS; |
| |
| int fStageIndex; |
| |
| const GrPipeline& fPipeline; |
| const GrPrimitiveProcessor& fPrimProc; |
| const GrProgramDesc& fDesc; |
| |
| BuiltinUniformHandles fUniformHandles; |
| |
| GrGLSLPrimitiveProcessor* fGeometryProcessor; |
| GrGLSLXferProcessor* fXferProcessor; |
| GrGLSLFragProcs fFragmentProcessors; |
| |
| protected: |
| explicit GrGLSLProgramBuilder(const GrPipeline&, |
| const GrPrimitiveProcessor&, |
| const GrProgramDesc&); |
| |
| void addFeature(GrShaderFlags shaders, uint32_t featureBit, const char* extensionName); |
| |
| bool emitAndInstallProcs(GrGLSLExpr4* inputColor, GrGLSLExpr4* inputCoverage); |
| |
| void cleanupFragmentProcessors(); |
| |
| void finalizeShaders(); |
| |
| private: |
| // reset is called by program creator between each processor's emit code. It increments the |
| // stage offset for variable name mangling, and also ensures verfication variables in the |
| // fragment shader are cleared. |
| void reset() { |
| this->addStage(); |
| SkDEBUGCODE(fFS.resetVerification();) |
| } |
| void addStage() { fStageIndex++; } |
| |
| class AutoStageAdvance { |
| public: |
| AutoStageAdvance(GrGLSLProgramBuilder* pb) |
| : fPB(pb) { |
| fPB->reset(); |
| // Each output to the fragment processor gets its own code section |
| fPB->fFS.nextStage(); |
| } |
| ~AutoStageAdvance() {} |
| private: |
| GrGLSLProgramBuilder* fPB; |
| }; |
| |
| // Generates a possibly mangled name for a stage variable and writes it to the fragment shader. |
| // If GrGLSLExpr4 has a valid name then it will use that instead |
| void nameExpression(GrGLSLExpr4*, const char* baseName); |
| |
| void emitAndInstallPrimProc(const GrPrimitiveProcessor&, |
| GrGLSLExpr4* outputColor, |
| GrGLSLExpr4* outputCoverage); |
| void emitAndInstallFragProcs(GrGLSLExpr4* colorInOut, GrGLSLExpr4* coverageInOut); |
| void emitAndInstallFragProc(const GrFragmentProcessor&, |
| int index, |
| int transformedCoordVarsIdx, |
| const GrGLSLExpr4& input, |
| GrGLSLExpr4* output); |
| void emitAndInstallXferProc(const GrXferProcessor&, |
| const GrGLSLExpr4& colorIn, |
| const GrGLSLExpr4& coverageIn, |
| bool ignoresCoverage, |
| GrPixelLocalStorageState plsState); |
| void emitSamplersAndImageStorages(const GrProcessor& processor, |
| SkTArray<SamplerHandle>* outTexSamplerHandles, |
| SkTArray<SamplerHandle>* outBufferSamplerHandles, |
| SkTArray<ImageStorageHandle>* outImageStorageHandles); |
| void emitSampler(GrSLType samplerType, GrPixelConfig, const char* name, |
| GrShaderFlags visibility, SkTArray<SamplerHandle >* outSamplerHandles); |
| void emitImageStorage(const GrProcessor::ImageStorageAccess&, |
| const char* name, |
| SkTArray<ImageStorageHandle>* outImageStorageHandles); |
| void emitFSOutputSwizzle(bool hasSecondaryOutput); |
| bool checkSamplerCounts(); |
| bool checkImageStorageCounts(); |
| |
| #ifdef SK_DEBUG |
| void verify(const GrPrimitiveProcessor&); |
| void verify(const GrXferProcessor&); |
| void verify(const GrFragmentProcessor&); |
| #endif |
| |
| int fNumVertexSamplers; |
| int fNumGeometrySamplers; |
| int fNumFragmentSamplers; |
| int fNumVertexImageStorages; |
| int fNumGeometryImageStorages; |
| int fNumFragmentImageStorages; |
| SkSTArray<4, GrShaderVar> fTransformedCoordVars; |
| }; |
| |
| #endif |