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/gl/GrGLUniformHandler.h"
9
10 #include "include/core/SkString.h"
11 #include "include/gpu/ganesh/GrBackendSurface.h"
12 #include "include/gpu/ganesh/gl/GrGLFunctions.h"
13 #include "include/gpu/ganesh/gl/GrGLInterface.h"
14 #include "include/private/base/SkAssert.h"
15 #include "src/gpu/ganesh/GrUtil.h"
16 #include "src/gpu/ganesh/gl/GrGLCaps.h"
17 #include "src/gpu/ganesh/gl/GrGLGpu.h"
18 #include "src/gpu/ganesh/gl/GrGLUtil.h"
19 #include "src/gpu/ganesh/gl/builders/GrGLProgramBuilder.h"
20 #include "src/gpu/ganesh/glsl/GrGLSLProgramBuilder.h"
21 #include "src/sksl/SkSLCompiler.h"
22
23 #include <string.h>
24 #include <utility>
25
26 #define GL_CALL(X) GR_GL_CALL(this->glGpu()->glInterface(), X)
27 #define GL_CALL_RET(R, X) GR_GL_CALL_RET(this->glGpu()->glInterface(), R, X)
28
valid_name(const char * name)29 bool valid_name(const char* name) {
30 // disallow unknown names that start with "sk_"
31 if (!strncmp(name, GR_NO_MANGLE_PREFIX, strlen(GR_NO_MANGLE_PREFIX))) {
32 return !strcmp(name, SkSL::Compiler::RTADJUST_NAME);
33 }
34 return true;
35 }
36
internalAddUniformArray(const GrProcessor * owner,uint32_t visibility,SkSLType type,const char * name,bool mangleName,int arrayCount,const char ** outName)37 GrGLSLUniformHandler::UniformHandle GrGLUniformHandler::internalAddUniformArray(
38 const GrProcessor* owner,
39 uint32_t visibility,
40 SkSLType type,
41 const char* name,
42 bool mangleName,
43 int arrayCount,
44 const char** outName) {
45 SkASSERT(name && strlen(name));
46 SkASSERT(valid_name(name));
47 SkASSERT(0 != visibility);
48
49 // TODO this is a bit hacky, lets think of a better way. Basically we need to be able to use
50 // the uniform view matrix name in the GP, and the GP is immutable so it has to tell the PB
51 // exactly what name it wants to use for the uniform view matrix. If we prefix anythings, then
52 // the names will mismatch. I think the correct solution is to have all GPs which need the
53 // uniform view matrix, they should upload the view matrix in their setData along with regular
54 // uniforms.
55 char prefix = 'u';
56 if ('u' == name[0] || !strncmp(name, GR_NO_MANGLE_PREFIX, strlen(GR_NO_MANGLE_PREFIX))) {
57 prefix = '\0';
58 }
59 SkString resolvedName = fProgramBuilder->nameVariable(prefix, name, mangleName);
60
61 GLUniformInfo tempInfo;
62 tempInfo.fVariable = GrShaderVar{std::move(resolvedName),
63 type,
64 GrShaderVar::TypeModifier::Uniform,
65 arrayCount};
66
67 tempInfo.fVisibility = visibility;
68 tempInfo.fOwner = owner;
69 tempInfo.fRawName = SkString(name);
70 tempInfo.fLocation = -1;
71
72 fUniforms.push_back(tempInfo);
73
74 if (outName) {
75 *outName = fUniforms.back().fVariable.c_str();
76 }
77 return GrGLSLUniformHandler::UniformHandle(fUniforms.count() - 1);
78 }
79
addSampler(const GrBackendFormat & backendFormat,GrSamplerState,const skgpu::Swizzle & swizzle,const char * name,const GrShaderCaps * shaderCaps)80 GrGLSLUniformHandler::SamplerHandle GrGLUniformHandler::addSampler(
81 const GrBackendFormat& backendFormat,
82 GrSamplerState,
83 const skgpu::Swizzle& swizzle,
84 const char* name,
85 const GrShaderCaps* shaderCaps) {
86 SkASSERT(name && strlen(name));
87
88 constexpr char prefix = 'u';
89 SkString mangleName = fProgramBuilder->nameVariable(prefix, name, true);
90
91 GrTextureType type = backendFormat.textureType();
92
93 GLUniformInfo tempInfo;
94 tempInfo.fVariable = GrShaderVar{std::move(mangleName),
95 SkSLCombinedSamplerTypeForTextureType(type)};
96
97 tempInfo.fVisibility = kFragment_GrShaderFlag;
98 tempInfo.fOwner = nullptr;
99 tempInfo.fRawName = SkString(name);
100 tempInfo.fLocation = -1;
101
102 fSamplers.push_back(tempInfo);
103 fSamplerSwizzles.push_back(swizzle);
104 SkASSERT(fSamplers.count() == fSamplerSwizzles.size());
105
106 return GrGLSLUniformHandler::SamplerHandle(fSamplers.count() - 1);
107 }
108
appendUniformDecls(GrShaderFlags visibility,SkString * out) const109 void GrGLUniformHandler::appendUniformDecls(GrShaderFlags visibility, SkString* out) const {
110 for (const UniformInfo& uniform : fUniforms.items()) {
111 if (uniform.fVisibility & visibility) {
112 uniform.fVariable.appendDecl(fProgramBuilder->shaderCaps(), out);
113 out->append(";");
114 }
115 }
116 for (const UniformInfo& sampler : fSamplers.items()) {
117 if (sampler.fVisibility & visibility) {
118 sampler.fVariable.appendDecl(fProgramBuilder->shaderCaps(), out);
119 out->append(";\n");
120 }
121 }
122 }
123
bindUniformLocations(GrGLuint programID,const GrGLCaps & caps)124 void GrGLUniformHandler::bindUniformLocations(GrGLuint programID, const GrGLCaps& caps) {
125 if (caps.bindUniformLocationSupport()) {
126 int currUniform = 0;
127 for (GLUniformInfo& uniform : fUniforms.items()) {
128 GL_CALL(BindUniformLocation(programID, currUniform, uniform.fVariable.c_str()));
129 uniform.fLocation = currUniform;
130 ++currUniform;
131 }
132 for (GLUniformInfo& sampler : fSamplers.items()) {
133 GL_CALL(BindUniformLocation(programID, currUniform, sampler.fVariable.c_str()));
134 sampler.fLocation = currUniform;
135 ++currUniform;
136 }
137 }
138 }
139
getUniformLocations(GrGLuint programID,const GrGLCaps & caps,bool force)140 void GrGLUniformHandler::getUniformLocations(GrGLuint programID, const GrGLCaps& caps, bool force) {
141 if (!caps.bindUniformLocationSupport() || force) {
142 for (GLUniformInfo& uniform : fUniforms.items()) {
143 GrGLint location;
144 GL_CALL_RET(location, GetUniformLocation(programID, uniform.fVariable.c_str()));
145 uniform.fLocation = location;
146 }
147 for (GLUniformInfo& sampler : fSamplers.items()) {
148 GrGLint location;
149 GL_CALL_RET(location, GetUniformLocation(programID, sampler.fVariable.c_str()));
150 sampler.fLocation = location;
151 }
152 }
153 }
154
glGpu() const155 const GrGLGpu* GrGLUniformHandler::glGpu() const {
156 GrGLProgramBuilder* glPB = (GrGLProgramBuilder*) fProgramBuilder;
157 return glPB->gpu();
158 }
159