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 "gl/GrGLUniformHandler.h" 9 10#include "gl/GrGLCaps.h" 11#include "gl/GrGLGpu.h" 12#include "gl/builders/GrGLProgramBuilder.h" 13 14#define GL_CALL(X) GR_GL_CALL(this->glGpu()->glInterface(), X) 15#define GL_CALL_RET(R, X) GR_GL_CALL_RET(this->glGpu()->glInterface(), R, X) 16 17GrGLSLUniformHandler::UniformHandle GrGLUniformHandler::internalAddUniformArray( 18 uint32_t visibility, 19 GrSLType type, 20 GrSLPrecision precision, 21 const char* name, 22 bool mangleName, 23 int arrayCount, 24 const char** outName) { 25 SkASSERT(name && strlen(name)); 26 SkASSERT(0 != visibility); 27 SkASSERT(kDefault_GrSLPrecision == precision || GrSLTypeAcceptsPrecision(type)); 28 29 UniformInfo& uni = fUniforms.push_back(); 30 uni.fVariable.setType(type); 31 uni.fVariable.setTypeModifier(GrShaderVar::kUniform_TypeModifier); 32 // TODO this is a bit hacky, lets think of a better way. Basically we need to be able to use 33 // the uniform view matrix name in the GP, and the GP is immutable so it has to tell the PB 34 // exactly what name it wants to use for the uniform view matrix. If we prefix anythings, then 35 // the names will mismatch. I think the correct solution is to have all GPs which need the 36 // uniform view matrix, they should upload the view matrix in their setData along with regular 37 // uniforms. 38 char prefix = 'u'; 39 if ('u' == name[0]) { 40 prefix = '\0'; 41 } 42 fProgramBuilder->nameVariable(uni.fVariable.accessName(), prefix, name, mangleName); 43 uni.fVariable.setArrayCount(arrayCount); 44 uni.fVisibility = visibility; 45 uni.fVariable.setPrecision(precision); 46 uni.fLocation = -1; 47 48 if (outName) { 49 *outName = uni.fVariable.c_str(); 50 } 51 return GrGLSLUniformHandler::UniformHandle(fUniforms.count() - 1); 52} 53 54GrGLSLUniformHandler::SamplerHandle GrGLUniformHandler::addSampler(uint32_t visibility, 55 GrSwizzle swizzle, 56 GrSLType type, 57 GrSLPrecision precision, 58 const char* name) { 59 SkASSERT(name && strlen(name)); 60 SkASSERT(0 != visibility); 61 62 SkString mangleName; 63 char prefix = 'u'; 64 fProgramBuilder->nameVariable(&mangleName, prefix, name, true); 65 66 UniformInfo& sampler = fSamplers.push_back(); 67 SkASSERT(GrSLTypeIsCombinedSamplerType(type)); 68 sampler.fVariable.setType(type); 69 sampler.fVariable.setTypeModifier(GrShaderVar::kUniform_TypeModifier); 70 sampler.fVariable.setPrecision(precision); 71 sampler.fVariable.setName(mangleName); 72 sampler.fLocation = -1; 73 sampler.fVisibility = visibility; 74 fSamplerSwizzles.push_back(swizzle); 75 SkASSERT(fSamplers.count() == fSamplerSwizzles.count()); 76 return GrGLSLUniformHandler::SamplerHandle(fSamplers.count() - 1); 77} 78 79GrGLSLUniformHandler::TexelBufferHandle GrGLUniformHandler::addTexelBuffer(uint32_t visibility, 80 GrSLPrecision precision, 81 const char* name) { 82 SkASSERT(name && strlen(name)); 83 SkASSERT(0 != visibility); 84 85 SkString mangleName; 86 char prefix = 'u'; 87 fProgramBuilder->nameVariable(&mangleName, prefix, name, true); 88 89 UniformInfo& texelBuffer = fTexelBuffers.push_back(); 90 texelBuffer.fVariable.setType(kBufferSampler_GrSLType); 91 texelBuffer.fVariable.setTypeModifier(GrShaderVar::kUniform_TypeModifier); 92 texelBuffer.fVariable.setPrecision(precision); 93 texelBuffer.fVariable.setName(mangleName); 94 texelBuffer.fLocation = -1; 95 texelBuffer.fVisibility = visibility; 96 return GrGLSLUniformHandler::TexelBufferHandle(fTexelBuffers.count() - 1); 97} 98 99GrGLSLUniformHandler::ImageStorageHandle GrGLUniformHandler::addImageStorage( 100 uint32_t visibility, GrSLType type, GrImageStorageFormat format, GrSLMemoryModel model, 101 GrSLRestrict restrict, GrIOType ioType, const char* name) { 102 SkASSERT(name && strlen(name)); 103 SkASSERT(0 != visibility); 104 SkString mangleName; 105 char prefix = 'u'; 106 fProgramBuilder->nameVariable(&mangleName, prefix, name, true); 107 108 UniformInfo& imageStorage = fImageStorages.push_back(); 109 imageStorage.fVariable.setName(mangleName); 110 111 SkASSERT(GrSLTypeIsImageStorage(type)); 112 imageStorage.fVariable.setType(type); 113 imageStorage.fVariable.setTypeModifier(GrShaderVar::kUniform_TypeModifier); 114 imageStorage.fVariable.setImageStorageFormat(format); 115 imageStorage.fVariable.setMemoryModel(model); 116 imageStorage.fVariable.setRestrict(restrict); 117 imageStorage.fVariable.setIOType(ioType); 118 imageStorage.fVariable.setPrecision(kHigh_GrSLPrecision); 119 imageStorage.fLocation = -1; 120 imageStorage.fVisibility = visibility; 121 return GrGLSLUniformHandler::ImageStorageHandle(fImageStorages.count() - 1); 122} 123 124void GrGLUniformHandler::appendUniformDecls(GrShaderFlags visibility, SkString* out) const { 125 for (int i = 0; i < fUniforms.count(); ++i) { 126 if (fUniforms[i].fVisibility & visibility) { 127 fUniforms[i].fVariable.appendDecl(fProgramBuilder->shaderCaps(), out); 128 out->append(";"); 129 } 130 } 131 for (int i = 0; i < fSamplers.count(); ++i) { 132 if (fSamplers[i].fVisibility & visibility) { 133 fSamplers[i].fVariable.appendDecl(fProgramBuilder->shaderCaps(), out); 134 out->append(";\n"); 135 } 136 } 137 for (int i = 0; i < fTexelBuffers.count(); ++i) { 138 if (fTexelBuffers[i].fVisibility & visibility) { 139 fTexelBuffers[i].fVariable.appendDecl(fProgramBuilder->shaderCaps(), out); 140 out->append(";\n"); 141 } 142 } 143 for (int i = 0; i < fImageStorages.count(); ++i) { 144 if (fImageStorages[i].fVisibility & visibility) { 145 fImageStorages[i].fVariable.appendDecl(fProgramBuilder->shaderCaps(), out); 146 out->append(";"); 147 } 148 } 149} 150 151void GrGLUniformHandler::bindUniformLocations(GrGLuint programID, const GrGLCaps& caps) { 152 if (caps.bindUniformLocationSupport()) { 153 int currUniform = 0; 154 for (int i = 0; i < fUniforms.count(); ++i, ++currUniform) { 155 GL_CALL(BindUniformLocation(programID, currUniform, fUniforms[i].fVariable.c_str())); 156 fUniforms[i].fLocation = currUniform; 157 } 158 for (int i = 0; i < fSamplers.count(); ++i, ++currUniform) { 159 GL_CALL(BindUniformLocation(programID, currUniform, fSamplers[i].fVariable.c_str())); 160 fSamplers[i].fLocation = currUniform; 161 } 162 for (int i = 0; i < fTexelBuffers.count(); ++i, ++currUniform) { 163 GL_CALL(BindUniformLocation(programID, currUniform, 164 fTexelBuffers[i].fVariable.c_str())); 165 fTexelBuffers[i].fLocation = currUniform; 166 } 167 for (int i = 0; i < fImageStorages.count(); ++i, ++currUniform) { 168 GL_CALL(BindUniformLocation(programID, currUniform, 169 fImageStorages[i].fVariable.c_str())); 170 fImageStorages[i].fLocation = currUniform; 171 } 172 } 173} 174 175void GrGLUniformHandler::getUniformLocations(GrGLuint programID, const GrGLCaps& caps) { 176 if (!caps.bindUniformLocationSupport()) { 177 int count = fUniforms.count(); 178 for (int i = 0; i < count; ++i) { 179 GrGLint location; 180 GL_CALL_RET(location, GetUniformLocation(programID, fUniforms[i].fVariable.c_str())); 181 fUniforms[i].fLocation = location; 182 } 183 for (int i = 0; i < fSamplers.count(); ++i) { 184 GrGLint location; 185 GL_CALL_RET(location, GetUniformLocation(programID, fSamplers[i].fVariable.c_str())); 186 fSamplers[i].fLocation = location; 187 } 188 for (int i = 0; i < fTexelBuffers.count(); ++i) { 189 GrGLint location; 190 GL_CALL_RET(location, GetUniformLocation(programID, 191 fTexelBuffers[i].fVariable.c_str())); 192 fTexelBuffers[i].fLocation = location; 193 } 194 for (int i = 0; i < fImageStorages.count(); ++i) { 195 GrGLint location; 196 GL_CALL_RET(location, GetUniformLocation(programID, 197 fImageStorages[i].fVariable.c_str())); 198 fImageStorages[i].fLocation = location; 199 } 200 } 201} 202 203const GrGLGpu* GrGLUniformHandler::glGpu() const { 204 GrGLProgramBuilder* glPB = (GrGLProgramBuilder*) fProgramBuilder; 205 return glPB->gpu(); 206} 207