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