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(!fProgramBuilder->primitiveProcessor().willUseGeoShader()); 16 GrSLType type = GrVertexAttribTypeToSLType(input->fType); 17 GrGLSLVarying v(type); 18 this->addVarying(input->fName, &v, interpolation); 19 fProgramBuilder->fVS.codeAppendf("%s = %s;", v.vsOut(), input->fName); 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 int vaCount = gp.numAttribs(); 71 for (int i = 0; i < vaCount; i++) { 72 const GrGeometryProcessor::Attribute& attr = gp.getAttrib(i); 73 this->addAttribute(GrShaderVar(attr.fName, 74 GrVertexAttribTypeToSLType(attr.fType), 75 GrShaderVar::kIn_TypeModifier, 76 GrShaderVar::kNonArray)); 77 } 78 } 79 80 void GrGLSLVaryingHandler::addAttribute(const GrShaderVar& var) { 81 SkASSERT(GrShaderVar::kIn_TypeModifier == var.getTypeModifier()); 82 for (int j = 0; j < fVertexInputs.count(); ++j) { 83 const GrShaderVar& attr = fVertexInputs[j]; 84 // if attribute already added, don't add it again 85 if (attr.getName().equals(var.getName())) { 86 return; 87 } 88 } 89 fVertexInputs.push_back(var); 90 } 91 92 void GrGLSLVaryingHandler::setNoPerspective() { 93 const GrShaderCaps& caps = *fProgramBuilder->shaderCaps(); 94 if (!caps.noperspectiveInterpolationSupport()) { 95 return; 96 } 97 if (const char* extension = caps.noperspectiveInterpolationExtensionString()) { 98 int bit = 1 << GrGLSLFragmentBuilder::kNoPerspectiveInterpolation_GLSLPrivateFeature; 99 fProgramBuilder->fVS.addFeature(bit, extension); 100 if (fProgramBuilder->primitiveProcessor().willUseGeoShader()) { 101 fProgramBuilder->fGS.addFeature(bit, extension); 102 } 103 fProgramBuilder->fFS.addFeature(bit, extension); 104 } 105 fDefaultInterpolationModifier = "noperspective"; 106 } 107 108 void GrGLSLVaryingHandler::finalize() { 109 for (int i = 0; i < fVaryings.count(); ++i) { 110 const VaryingInfo& v = this->fVaryings[i]; 111 const char* modifier = v.fIsFlat ? "flat" : fDefaultInterpolationModifier; 112 if (v.fVisibility & kVertex_GrShaderFlag) { 113 fVertexOutputs.push_back().set(v.fType, v.fVsOut, GrShaderVar::kOut_TypeModifier, 114 kDefault_GrSLPrecision, nullptr, modifier); 115 if (v.fVisibility & kGeometry_GrShaderFlag) { 116 fGeomInputs.push_back().set(v.fType, v.fVsOut, GrShaderVar::kUnsizedArray, 117 GrShaderVar::kIn_TypeModifier, kDefault_GrSLPrecision, 118 nullptr, modifier); 119 } 120 } 121 if (v.fVisibility & kFragment_GrShaderFlag) { 122 const char* fsIn = v.fVsOut.c_str(); 123 if (v.fVisibility & kGeometry_GrShaderFlag) { 124 fGeomOutputs.push_back().set(v.fType, v.fGsOut, GrShaderVar::kOut_TypeModifier, 125 kDefault_GrSLPrecision, nullptr, modifier); 126 fsIn = v.fGsOut.c_str(); 127 } 128 fFragInputs.push_back().set(v.fType, fsIn, GrShaderVar::kIn_TypeModifier, 129 kDefault_GrSLPrecision, nullptr, modifier); 130 } 131 } 132 this->onFinalize(); 133 } 134 135 void GrGLSLVaryingHandler::appendDecls(const VarArray& vars, SkString* out) const { 136 for (int i = 0; i < vars.count(); ++i) { 137 vars[i].appendDecl(fProgramBuilder->shaderCaps(), out); 138 out->append(";"); 139 } 140 } 141 142 void GrGLSLVaryingHandler::getVertexDecls(SkString* inputDecls, SkString* outputDecls) const { 143 this->appendDecls(fVertexInputs, inputDecls); 144 this->appendDecls(fVertexOutputs, outputDecls); 145 } 146 147 void GrGLSLVaryingHandler::getGeomDecls(SkString* inputDecls, SkString* outputDecls) const { 148 this->appendDecls(fGeomInputs, inputDecls); 149 this->appendDecls(fGeomOutputs, outputDecls); 150 } 151 152 void GrGLSLVaryingHandler::getFragDecls(SkString* inputDecls, SkString* outputDecls) const { 153 // We should not have any outputs in the fragment shader when using version 1.10 154 SkASSERT(k110_GrGLSLGeneration != fProgramBuilder->shaderCaps()->generation() || 155 fFragOutputs.empty()); 156 this->appendDecls(fFragInputs, inputDecls); 157 this->appendDecls(fFragOutputs, outputDecls); 158 } 159