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 GrGLProgramBuilder_DEFINED 9 #define GrGLProgramBuilder_DEFINED 10 11 #include "GrGLFragmentShaderBuilder.h" 12 #include "GrGLGeometryShaderBuilder.h" 13 #include "GrGLVertexShaderBuilder.h" 14 #include "../GrGLProgramDataManager.h" 15 #include "../GrGLUniformHandle.h" 16 #include "../GrGLPrimitiveProcessor.h" 17 #include "../GrGLXferProcessor.h" 18 #include "../../GrPendingFragmentStage.h" 19 #include "../../GrPipeline.h" 20 21 /* 22 * This is the base class for a series of interfaces. This base class *MUST* remain abstract with 23 * NO data members because it is used in multiple interface inheritance. 24 * Heirarchy: 25 * GrGLUniformBuilder 26 * / \ 27 * GrGLFPBuilder GrGLGPBuilder 28 * \ / 29 * GrGLProgramBuilder(internal use only) 30 */ 31 class GrGLUniformBuilder { 32 public: 33 enum ShaderVisibility { 34 kVertex_Visibility = 1 << kVertex_GrShaderType, 35 kGeometry_Visibility = 1 << kGeometry_GrShaderType, 36 kFragment_Visibility = 1 << kFragment_GrShaderType, 37 }; 38 ~GrGLUniformBuilder()39 virtual ~GrGLUniformBuilder() {} 40 41 typedef GrGLProgramDataManager::UniformHandle UniformHandle; 42 43 /** Add a uniform variable to the current program, that has visibility in one or more shaders. 44 visibility is a bitfield of ShaderVisibility values indicating from which shaders the 45 uniform should be accessible. At least one bit must be set. Geometry shader uniforms are not 46 supported at this time. The actual uniform name will be mangled. If outName is not NULL then 47 it will refer to the final uniform name after return. Use the addUniformArray variant to add 48 an array of uniforms. */ 49 UniformHandle addUniform(uint32_t visibility, 50 GrSLType type, 51 GrSLPrecision precision, 52 const char* name, 53 const char** outName = NULL) { 54 return this->addUniformArray(visibility, type, precision, name, 0, outName); 55 } 56 57 virtual UniformHandle addUniformArray( 58 uint32_t visibility, 59 GrSLType type, 60 GrSLPrecision precision, 61 const char* name, 62 int arrayCount, 63 const char** outName = NULL) = 0; 64 65 virtual const GrGLShaderVar& getUniformVariable(UniformHandle u) const = 0; 66 67 /** 68 * Shortcut for getUniformVariable(u).c_str() 69 */ 70 virtual const char* getUniformCStr(UniformHandle u) const = 0; 71 72 virtual const GrGLContextInfo& ctxInfo() const = 0; 73 74 virtual GrGLGpu* gpu() const = 0; 75 76 /* 77 * *NOTE* NO MEMBERS ALLOWED, MULTIPLE INHERITANCE 78 */ 79 }; 80 81 // TODO move this into GrGLGPBuilder and move them both out of this file 82 class GrGLVarying { 83 public: vsVarying()84 bool vsVarying() const { return kVertToFrag_Varying == fVarying || 85 kVertToGeo_Varying == fVarying; } fsVarying()86 bool fsVarying() const { return kVertToFrag_Varying == fVarying || 87 kGeoToFrag_Varying == fVarying; } vsOut()88 const char* vsOut() const { return fVsOut; } gsIn()89 const char* gsIn() const { return fGsIn; } gsOut()90 const char* gsOut() const { return fGsOut; } fsIn()91 const char* fsIn() const { return fFsIn; } type()92 GrSLType type() const { return fType; } 93 94 protected: 95 enum Varying { 96 kVertToFrag_Varying, 97 kVertToGeo_Varying, 98 kGeoToFrag_Varying, 99 }; 100 GrGLVarying(GrSLType type,Varying varying)101 GrGLVarying(GrSLType type, Varying varying) 102 : fVarying(varying), fType(type), fVsOut(NULL), fGsIn(NULL), fGsOut(NULL), 103 fFsIn(NULL) {} 104 105 Varying fVarying; 106 107 private: 108 GrSLType fType; 109 const char* fVsOut; 110 const char* fGsIn; 111 const char* fGsOut; 112 const char* fFsIn; 113 114 friend class GrGLVertexBuilder; 115 friend class GrGLGeometryBuilder; 116 friend class GrGLXferBuilder; 117 friend class GrGLFragmentShaderBuilder; 118 }; 119 120 struct GrGLVertToFrag : public GrGLVarying { GrGLVertToFragGrGLVertToFrag121 GrGLVertToFrag(GrSLType type) 122 : GrGLVarying(type, kVertToFrag_Varying) {} 123 }; 124 125 struct GrGLVertToGeo : public GrGLVarying { GrGLVertToGeoGrGLVertToGeo126 GrGLVertToGeo(GrSLType type) 127 : GrGLVarying(type, kVertToGeo_Varying) {} 128 }; 129 130 struct GrGLGeoToFrag : public GrGLVarying { GrGLGeoToFragGrGLGeoToFrag131 GrGLGeoToFrag(GrSLType type) 132 : GrGLVarying(type, kGeoToFrag_Varying) {} 133 }; 134 135 /* a specialization of the above for GPs. Lets the user add uniforms, varyings, and VS / FS code */ 136 class GrGLGPBuilder : public virtual GrGLUniformBuilder { 137 public: 138 /* 139 * addVarying allows fine grained control for setting up varyings between stages. If you just 140 * need to take an attribute and pass it through to an output value in a fragment shader, use 141 * addPassThroughAttribute. 142 * TODO convert most uses of addVarying to addPassThroughAttribute 143 */ 144 virtual void addVarying(const char* name, 145 GrGLVarying*, 146 GrSLPrecision fsPrecision = kDefault_GrSLPrecision) = 0; 147 148 /* 149 * This call can be used by GP to pass an attribute through all shaders directly to 'output' in 150 * the fragment shader. Though this call effects both the vertex shader and fragment shader, 151 * it expects 'output' to be defined in the fragment shader before this call is made. 152 * TODO it might be nicer behavior to have a flag to declare output inside this call 153 */ 154 virtual void addPassThroughAttribute(const GrGeometryProcessor::Attribute*, 155 const char* output) = 0; 156 157 // TODO rename getFragmentBuilder 158 virtual GrGLFragmentBuilder* getFragmentShaderBuilder() = 0; 159 virtual GrGLVertexBuilder* getVertexShaderBuilder() = 0; 160 161 /* 162 * *NOTE* NO MEMBERS ALLOWED, MULTIPLE INHERITANCE 163 */ 164 }; 165 166 /* a specializations for FPs. Lets the user add uniforms and FS code */ 167 class GrGLFPBuilder : public virtual GrGLUniformBuilder { 168 public: 169 virtual GrGLFragmentBuilder* getFragmentShaderBuilder() = 0; 170 171 /* 172 * *NOTE* NO MEMBERS ALLOWED, MULTIPLE INHERITANCE 173 */ 174 }; 175 176 /* a specializations for XPs. Lets the user add uniforms and FS code */ 177 class GrGLXPBuilder : public virtual GrGLUniformBuilder { 178 public: 179 virtual GrGLXPFragmentBuilder* getFragmentShaderBuilder() = 0; 180 181 /* 182 * *NOTE* NO MEMBERS ALLOWED, MULTIPLE INHERITANCE 183 */ 184 }; 185 186 /** 187 * The below struct represent processors installed in programs. 188 */ 189 template <class Proc> 190 struct GrGLInstalledProc { 191 typedef GrGLProgramDataManager::UniformHandle UniformHandle; 192 193 struct Sampler { 194 SkDEBUGCODE(Sampler() : fTextureUnit(-1) {}) 195 UniformHandle fUniform; 196 int fTextureUnit; 197 }; 198 SkSTArray<4, Sampler, true> fSamplers; 199 SkAutoTDelete<Proc> fGLProc; 200 }; 201 202 typedef GrGLInstalledProc<GrGLPrimitiveProcessor> GrGLInstalledGeoProc; 203 typedef GrGLInstalledProc<GrGLXferProcessor> GrGLInstalledXferProc; 204 typedef GrGLInstalledProc<GrGLFragmentProcessor> GrGLInstalledFragProc; 205 206 struct GrGLInstalledFragProcs : public SkRefCnt { 207 virtual ~GrGLInstalledFragProcs(); 208 SkSTArray<8, GrGLInstalledFragProc*, true> fProcs; 209 }; 210 211 /* 212 * Please note - no diamond problems because of virtual inheritance. Also, both base classes 213 * are pure virtual with no data members. This is the base class for program building. 214 * Subclasses are nearly identical but each has their own way of emitting transforms. State for 215 * each of the elements of the shader pipeline, ie vertex, fragment, geometry, etc, lives in those 216 * respective builders 217 */ 218 class GrGLProgramBuilder : public GrGLGPBuilder, 219 public GrGLFPBuilder, 220 public GrGLXPBuilder { 221 public: 222 typedef GrGpu::DrawArgs DrawArgs; 223 /** Generates a shader program. 224 * 225 * The program implements what is specified in the stages given as input. 226 * After successful generation, the builder result objects are available 227 * to be used. 228 * @return true if generation was successful. 229 */ 230 static GrGLProgram* CreateProgram(const DrawArgs&, GrGLGpu*); 231 232 UniformHandle addUniformArray(uint32_t visibility, 233 GrSLType type, 234 GrSLPrecision precision, 235 const char* name, 236 int arrayCount, 237 const char** outName) override; 238 getUniformVariable(UniformHandle u)239 const GrGLShaderVar& getUniformVariable(UniformHandle u) const override { 240 return fUniforms[u.toShaderBuilderIndex()].fVariable; 241 } 242 getUniformCStr(UniformHandle u)243 const char* getUniformCStr(UniformHandle u) const override { 244 return this->getUniformVariable(u).c_str(); 245 } 246 247 const GrGLContextInfo& ctxInfo() const override; 248 gpu()249 GrGLGpu* gpu() const override { return fGpu; } 250 getFragmentShaderBuilder()251 GrGLXPFragmentBuilder* getFragmentShaderBuilder() override { return &fFS; } getVertexShaderBuilder()252 GrGLVertexBuilder* getVertexShaderBuilder() override { return &fVS; } 253 254 void addVarying( 255 const char* name, 256 GrGLVarying*, 257 GrSLPrecision fsPrecision = kDefault_GrSLPrecision) override; 258 259 void addPassThroughAttribute(const GrPrimitiveProcessor::Attribute*, 260 const char* output) override; 261 262 263 // Handles for program uniforms (other than per-effect uniforms) 264 struct BuiltinUniformHandles { 265 UniformHandle fRTAdjustmentUni; 266 267 // We use the render target height to provide a y-down frag coord when specifying 268 // origin_upper_left is not supported. 269 UniformHandle fRTHeightUni; 270 }; 271 272 protected: 273 typedef GrGLProgramDataManager::UniformInfo UniformInfo; 274 typedef GrGLProgramDataManager::UniformInfoArray UniformInfoArray; 275 276 static GrGLProgramBuilder* CreateProgramBuilder(const DrawArgs&, GrGLGpu*); 277 278 GrGLProgramBuilder(GrGLGpu*, const DrawArgs&); 279 primitiveProcessor()280 const GrPrimitiveProcessor& primitiveProcessor() const { return *fArgs.fPrimitiveProcessor; } pipeline()281 const GrPipeline& pipeline() const { return *fArgs.fPipeline; } desc()282 const GrProgramDesc& desc() const { return *fArgs.fDesc; } batchTracker()283 const GrBatchTracker& batchTracker() const { return *fArgs.fBatchTracker; } header()284 const GrProgramDesc::KeyHeader& header() const { return fArgs.fDesc->header(); } 285 286 // Generates a name for a variable. The generated string will be name prefixed by the prefix 287 // char (unless the prefix is '\0'). It also mangles the name to be stage-specific if we're 288 // generating stage code. 289 void nameVariable(SkString* out, char prefix, const char* name); 290 // Generates a possibly mangled name for a stage variable and writes it to the fragment shader. 291 // If GrGLSLExpr4 has a valid name then it will use that instead 292 void nameExpression(GrGLSLExpr4*, const char* baseName); 293 bool emitAndInstallProcs(GrGLSLExpr4* inputColor, GrGLSLExpr4* inputCoverage); 294 void emitAndInstallFragProcs(int procOffset, int numProcs, GrGLSLExpr4* inOut); 295 void emitAndInstallProc(const GrPendingFragmentStage&, 296 int index, 297 const GrGLSLExpr4& input, 298 GrGLSLExpr4* output); 299 300 void emitAndInstallProc(const GrPrimitiveProcessor&, 301 GrGLSLExpr4* outputColor, 302 GrGLSLExpr4* outputCoverage); 303 304 // these emit functions help to keep the createAndEmitProcessors template general 305 void emitAndInstallProc(const GrPendingFragmentStage&, 306 int index, 307 const char* outColor, 308 const char* inColor); 309 void emitAndInstallProc(const GrPrimitiveProcessor&, 310 const char* outColor, 311 const char* outCoverage); 312 void emitAndInstallXferProc(const GrXferProcessor&, 313 const GrGLSLExpr4& colorIn, 314 const GrGLSLExpr4& coverageIn); 315 316 void verify(const GrPrimitiveProcessor&); 317 void verify(const GrXferProcessor&); 318 void verify(const GrFragmentProcessor&); 319 template <class Proc> 320 void emitSamplers(const GrProcessor&, 321 GrGLProcessor::TextureSamplerArray* outSamplers, 322 GrGLInstalledProc<Proc>*); 323 324 GrGLProgram* finalize(); 325 void bindUniformLocations(GrGLuint programID); 326 bool checkLinkStatus(GrGLuint programID); 327 void resolveUniformLocations(GrGLuint programID); 328 void cleanupProgram(GrGLuint programID, const SkTDArray<GrGLuint>& shaderIDs); 329 void cleanupShaders(const SkTDArray<GrGLuint>& shaderIDs); 330 331 // Subclasses create different programs 332 virtual GrGLProgram* createProgram(GrGLuint programID); 333 334 void appendUniformDecls(ShaderVisibility, SkString*) const; 335 336 // reset is called by program creator between each processor's emit code. It increments the 337 // stage offset for variable name mangling, and also ensures verfication variables in the 338 // fragment shader are cleared. reset()339 void reset() { 340 this->enterStage(); 341 this->addStage(); 342 fFS.reset(); 343 } addStage()344 void addStage() { fStageIndex++; } 345 346 // This simple class exits the stage and then restores the stage when it goes out of scope 347 class AutoStageRestore { 348 public: AutoStageRestore(GrGLProgramBuilder * pb)349 AutoStageRestore(GrGLProgramBuilder* pb) 350 : fPB(pb), fOutOfStage(pb->fOutOfStage) { pb->exitStage(); } ~AutoStageRestore()351 ~AutoStageRestore() { fPB->fOutOfStage = fOutOfStage; } 352 private: 353 GrGLProgramBuilder* fPB; 354 bool fOutOfStage; 355 }; 356 class AutoStageAdvance { 357 public: AutoStageAdvance(GrGLProgramBuilder * pb)358 AutoStageAdvance(GrGLProgramBuilder* pb) 359 : fPB(pb) { 360 fPB->reset(); 361 // Each output to the fragment processor gets its own code section 362 fPB->fFS.nextStage(); 363 } ~AutoStageAdvance()364 ~AutoStageAdvance() { fPB->exitStage(); } 365 private: 366 GrGLProgramBuilder* fPB; 367 }; exitStage()368 void exitStage() { fOutOfStage = true; } enterStage()369 void enterStage() { fOutOfStage = false; } stageIndex()370 int stageIndex() const { return fStageIndex; } 371 rtAdjustment()372 const char* rtAdjustment() const { return "rtAdjustment"; } 373 374 // number of each input/output type in a single allocation block, used by many builders 375 static const int kVarsPerBlock; 376 377 BuiltinUniformHandles fUniformHandles; 378 GrGLVertexBuilder fVS; 379 GrGLGeometryBuilder fGS; 380 GrGLFragmentShaderBuilder fFS; 381 bool fOutOfStage; 382 int fStageIndex; 383 384 GrGLInstalledGeoProc* fGeometryProcessor; 385 GrGLInstalledXferProc* fXferProcessor; 386 SkAutoTUnref<GrGLInstalledFragProcs> fFragmentProcessors; 387 388 const DrawArgs& fArgs; 389 GrGLGpu* fGpu; 390 UniformInfoArray fUniforms; 391 GrGLPrimitiveProcessor::TransformsIn fCoordTransforms; 392 GrGLPrimitiveProcessor::TransformsOut fOutCoords; 393 394 friend class GrGLShaderBuilder; 395 friend class GrGLVertexBuilder; 396 friend class GrGLFragmentShaderBuilder; 397 friend class GrGLGeometryBuilder; 398 }; 399 #endif 400