1 /* 2 * Copyright 2015 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 #include "GrShaderCaps.h" 9 #include "glsl/GrGLSLVarying.h" 10 #include "glsl/GrGLSLProgramBuilder.h" 11 12 void GrGLSLVaryingHandler::addPassThroughAttribute(const GrGeometryProcessor::Attribute& input, 13 const char* output, 14 Interpolation interpolation) { 15 SkASSERT(input.isInitialized()); 16 SkASSERT(!fProgramBuilder->primitiveProcessor().willUseGeoShader()); 17 GrGLSLVarying v(input.gpuType()); 18 this->addVarying(input.name(), &v, interpolation); 19 fProgramBuilder->fVS.codeAppendf("%s = %s;", v.vsOut(), input.name()); 20 fProgramBuilder->fFS.codeAppendf("%s = %s;", output, v.fsIn()); 21 } 22 23 static bool use_flat_interpolation(GrGLSLVaryingHandler::Interpolation interpolation, 24 const GrShaderCaps& shaderCaps) { 25 switch (interpolation) { 26 using Interpolation = GrGLSLVaryingHandler::Interpolation; 27 case Interpolation::kInterpolated: 28 return false; 29 case Interpolation::kCanBeFlat: 30 SkASSERT(!shaderCaps.preferFlatInterpolation() || 31 shaderCaps.flatInterpolationSupport()); 32 return shaderCaps.preferFlatInterpolation(); 33 case Interpolation::kMustBeFlat: 34 SkASSERT(shaderCaps.flatInterpolationSupport()); 35 return true; 36 } 37 SK_ABORT("Invalid interpolation"); 38 return false; 39 } 40 41 void GrGLSLVaryingHandler::addVarying(const char* name, GrGLSLVarying* varying, 42 Interpolation interpolation) { 43 SkASSERT(GrSLTypeIsFloatType(varying->type()) || Interpolation::kMustBeFlat == interpolation); 44 bool willUseGeoShader = fProgramBuilder->primitiveProcessor().willUseGeoShader(); 45 VaryingInfo& v = fVaryings.push_back(); 46 47 SkASSERT(varying); 48 SkASSERT(kVoid_GrSLType != varying->fType); 49 v.fType = varying->fType; 50 v.fIsFlat = use_flat_interpolation(interpolation, *fProgramBuilder->shaderCaps()); 51 fProgramBuilder->nameVariable(&v.fVsOut, 'v', name); 52 v.fVisibility = kNone_GrShaderFlags; 53 if (varying->isInVertexShader()) { 54 varying->fVsOut = v.fVsOut.c_str(); 55 v.fVisibility |= kVertex_GrShaderFlag; 56 } 57 if (willUseGeoShader) { 58 fProgramBuilder->nameVariable(&v.fGsOut, 'g', name); 59 varying->fGsIn = v.fVsOut.c_str(); 60 varying->fGsOut = v.fGsOut.c_str(); 61 v.fVisibility |= kGeometry_GrShaderFlag; 62 } 63 if (varying->isInFragmentShader()) { 64 varying->fFsIn = (willUseGeoShader ? v.fGsOut : v.fVsOut).c_str(); 65 v.fVisibility |= kFragment_GrShaderFlag; 66 } 67 } 68 69 void GrGLSLVaryingHandler::emitAttributes(const GrGeometryProcessor& gp) { 70 for (const auto& attr : gp.vertexAttributes()) { 71 this->addAttribute(attr.asShaderVar()); 72 } 73 for (const auto& attr : gp.instanceAttributes()) { 74 this->addAttribute(attr.asShaderVar()); 75 } 76 } 77 78 void GrGLSLVaryingHandler::addAttribute(const GrShaderVar& var) { 79 SkASSERT(GrShaderVar::kIn_TypeModifier == var.getTypeModifier()); 80 for (int j = 0; j < fVertexInputs.count(); ++j) { 81 const GrShaderVar& attr = fVertexInputs[j]; 82 // if attribute already added, don't add it again 83 if (attr.getName().equals(var.getName())) { 84 return; 85 } 86 } 87 fVertexInputs.push_back(var); 88 } 89 90 void GrGLSLVaryingHandler::setNoPerspective() { 91 const GrShaderCaps& caps = *fProgramBuilder->shaderCaps(); 92 if (!caps.noperspectiveInterpolationSupport()) { 93 return; 94 } 95 if (const char* extension = caps.noperspectiveInterpolationExtensionString()) { 96 int bit = 1 << GrGLSLFragmentBuilder::kNoPerspectiveInterpolation_GLSLPrivateFeature; 97 fProgramBuilder->fVS.addFeature(bit, extension); 98 if (fProgramBuilder->primitiveProcessor().willUseGeoShader()) { 99 fProgramBuilder->fGS.addFeature(bit, extension); 100 } 101 fProgramBuilder->fFS.addFeature(bit, extension); 102 } 103 fDefaultInterpolationModifier = "noperspective"; 104 } 105 106 void GrGLSLVaryingHandler::finalize() { 107 for (int i = 0; i < fVaryings.count(); ++i) { 108 const VaryingInfo& v = this->fVaryings[i]; 109 const char* modifier = v.fIsFlat ? "flat" : fDefaultInterpolationModifier; 110 if (v.fVisibility & kVertex_GrShaderFlag) { 111 fVertexOutputs.push_back().set(v.fType, v.fVsOut, GrShaderVar::kOut_TypeModifier, 112 kDefault_GrSLPrecision, nullptr, modifier); 113 if (v.fVisibility & kGeometry_GrShaderFlag) { 114 fGeomInputs.push_back().set(v.fType, v.fVsOut, GrShaderVar::kUnsizedArray, 115 GrShaderVar::kIn_TypeModifier, kDefault_GrSLPrecision, 116 nullptr, modifier); 117 } 118 } 119 if (v.fVisibility & kFragment_GrShaderFlag) { 120 const char* fsIn = v.fVsOut.c_str(); 121 if (v.fVisibility & kGeometry_GrShaderFlag) { 122 fGeomOutputs.push_back().set(v.fType, v.fGsOut, GrShaderVar::kOut_TypeModifier, 123 kDefault_GrSLPrecision, nullptr, modifier); 124 fsIn = v.fGsOut.c_str(); 125 } 126 fFragInputs.push_back().set(v.fType, fsIn, GrShaderVar::kIn_TypeModifier, 127 kDefault_GrSLPrecision, nullptr, modifier); 128 } 129 } 130 this->onFinalize(); 131 } 132 133 void GrGLSLVaryingHandler::appendDecls(const VarArray& vars, SkString* out) const { 134 for (int i = 0; i < vars.count(); ++i) { 135 vars[i].appendDecl(fProgramBuilder->shaderCaps(), out); 136 out->append(";"); 137 } 138 } 139 140 void GrGLSLVaryingHandler::getVertexDecls(SkString* inputDecls, SkString* outputDecls) const { 141 this->appendDecls(fVertexInputs, inputDecls); 142 this->appendDecls(fVertexOutputs, outputDecls); 143 } 144 145 void GrGLSLVaryingHandler::getGeomDecls(SkString* inputDecls, SkString* outputDecls) const { 146 this->appendDecls(fGeomInputs, inputDecls); 147 this->appendDecls(fGeomOutputs, outputDecls); 148 } 149 150 void GrGLSLVaryingHandler::getFragDecls(SkString* inputDecls, SkString* outputDecls) const { 151 // We should not have any outputs in the fragment shader when using version 1.10 152 SkASSERT(k110_GrGLSLGeneration != fProgramBuilder->shaderCaps()->generation() || 153 fFragOutputs.empty()); 154 this->appendDecls(fFragInputs, inputDecls); 155 this->appendDecls(fFragOutputs, outputDecls); 156 } 157