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