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 "src/gpu/ganesh/GrShaderCaps.h"
9 #include "src/gpu/ganesh/glsl/GrGLSLProgramBuilder.h"
10 #include "src/gpu/ganesh/glsl/GrGLSLVarying.h"
11
addPassThroughAttribute(const GrShaderVar & vsVar,const char * output,Interpolation interpolation)12 void GrGLSLVaryingHandler::addPassThroughAttribute(const GrShaderVar& vsVar,
13 const char* output,
14 Interpolation interpolation) {
15 SkASSERT(vsVar.getType() != SkSLType::kVoid);
16 GrGLSLVarying v(vsVar.getType());
17 this->addVarying(vsVar.c_str(), &v, interpolation);
18 fProgramBuilder->fVS.codeAppendf("%s = %s;", v.vsOut(), vsVar.c_str());
19 fProgramBuilder->fFS.codeAppendf("%s = %s;", output, v.fsIn());
20 }
21
use_flat_interpolation(GrGLSLVaryingHandler::Interpolation interpolation,const GrShaderCaps & shaderCaps)22 static bool use_flat_interpolation(GrGLSLVaryingHandler::Interpolation interpolation,
23 const GrShaderCaps& shaderCaps) {
24 switch (interpolation) {
25 using Interpolation = GrGLSLVaryingHandler::Interpolation;
26 case Interpolation::kInterpolated:
27 return false;
28 case Interpolation::kCanBeFlat:
29 SkASSERT(!shaderCaps.fPreferFlatInterpolation || shaderCaps.fFlatInterpolationSupport);
30 return shaderCaps.fPreferFlatInterpolation;
31 case Interpolation::kMustBeFlat:
32 SkASSERT(shaderCaps.fFlatInterpolationSupport);
33 return true;
34 }
35 SK_ABORT("Invalid interpolation");
36 }
37
addVarying(const char * name,GrGLSLVarying * varying,Interpolation interpolation)38 void GrGLSLVaryingHandler::addVarying(const char* name, GrGLSLVarying* varying,
39 Interpolation interpolation) {
40 SkASSERT(SkSLTypeIsFloatType(varying->type()) || Interpolation::kMustBeFlat == interpolation);
41 VaryingInfo& v = fVaryings.push_back();
42
43 SkASSERT(varying);
44 SkASSERT(SkSLType::kVoid != varying->fType);
45 v.fType = varying->fType;
46 v.fIsFlat = use_flat_interpolation(interpolation, *fProgramBuilder->shaderCaps());
47 v.fVsOut = fProgramBuilder->nameVariable('v', name);
48 v.fVisibility = kNone_GrShaderFlags;
49 if (varying->isInVertexShader()) {
50 varying->fVsOut = v.fVsOut.c_str();
51 v.fVisibility |= kVertex_GrShaderFlag;
52 }
53 if (varying->isInFragmentShader()) {
54 varying->fFsIn = v.fVsOut.c_str();
55 v.fVisibility |= kFragment_GrShaderFlag;
56 }
57 }
58
emitAttributes(const GrGeometryProcessor & gp)59 void GrGLSLVaryingHandler::emitAttributes(const GrGeometryProcessor& gp) {
60 for (auto attr : gp.vertexAttributes()) {
61 this->addAttribute(attr.asShaderVar());
62 }
63 for (auto attr : gp.instanceAttributes()) {
64 this->addAttribute(attr.asShaderVar());
65 }
66 }
67
addAttribute(const GrShaderVar & var)68 void GrGLSLVaryingHandler::addAttribute(const GrShaderVar& var) {
69 SkASSERT(GrShaderVar::TypeModifier::In == var.getTypeModifier());
70 for (const GrShaderVar& attr : fVertexInputs.items()) {
71 // if attribute already added, don't add it again
72 if (attr.getName().equals(var.getName())) {
73 return;
74 }
75 }
76 fVertexInputs.push_back(var);
77 }
78
setNoPerspective()79 void GrGLSLVaryingHandler::setNoPerspective() {
80 const GrShaderCaps& caps = *fProgramBuilder->shaderCaps();
81 if (!caps.fNoPerspectiveInterpolationSupport) {
82 return;
83 }
84 if (const char* extension = caps.noperspectiveInterpolationExtensionString()) {
85 int bit = 1 << GrGLSLShaderBuilder::kNoPerspectiveInterpolation_GLSLPrivateFeature;
86 fProgramBuilder->fVS.addFeature(bit, extension);
87 fProgramBuilder->fFS.addFeature(bit, extension);
88 }
89 fDefaultInterpolationModifier = "noperspective";
90 }
91
finalize()92 void GrGLSLVaryingHandler::finalize() {
93 for (const VaryingInfo& v : fVaryings.items()) {
94 const char* modifier = v.fIsFlat ? "flat" : fDefaultInterpolationModifier;
95 if (v.fVisibility & kVertex_GrShaderFlag) {
96 fVertexOutputs.emplace_back(v.fVsOut, v.fType, GrShaderVar::TypeModifier::Out,
97 GrShaderVar::kNonArray, SkString(), SkString(modifier));
98 }
99 if (v.fVisibility & kFragment_GrShaderFlag) {
100 const char* fsIn = v.fVsOut.c_str();
101 fFragInputs.emplace_back(SkString(fsIn), v.fType, GrShaderVar::TypeModifier::In,
102 GrShaderVar::kNonArray, SkString(), SkString(modifier));
103 }
104 }
105 this->onFinalize();
106 }
107
appendDecls(const VarArray & vars,SkString * out) const108 void GrGLSLVaryingHandler::appendDecls(const VarArray& vars, SkString* out) const {
109 for (const GrShaderVar& varying : vars.items()) {
110 varying.appendDecl(fProgramBuilder->shaderCaps(), out);
111 out->append(";");
112 }
113 }
114
getVertexDecls(SkString * inputDecls,SkString * outputDecls) const115 void GrGLSLVaryingHandler::getVertexDecls(SkString* inputDecls, SkString* outputDecls) const {
116 this->appendDecls(fVertexInputs, inputDecls);
117 this->appendDecls(fVertexOutputs, outputDecls);
118 }
119
getFragDecls(SkString * inputDecls,SkString * outputDecls) const120 void GrGLSLVaryingHandler::getFragDecls(SkString* inputDecls, SkString* outputDecls) const {
121 // We should not have any outputs in the fragment shader when using version 1.10
122 SkASSERT(SkSL::GLSLGeneration::k110 != fProgramBuilder->shaderCaps()->fGLSLGeneration ||
123 fFragOutputs.empty());
124 this->appendDecls(fFragInputs, inputDecls);
125 this->appendDecls(fFragOutputs, outputDecls);
126 }
127