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 17 GrGLSLUniformHandler::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 54 GrGLSLUniformHandler::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 79 GrGLSLUniformHandler::ImageStorageHandle GrGLUniformHandler::addImageStorage( 80 uint32_t visibility, GrSLType type, GrImageStorageFormat format, GrSLMemoryModel model, 81 GrSLRestrict restrict, GrIOType ioType, const char* name) { 82 SkASSERT(name && strlen(name)); 83 SkASSERT(0 != visibility); 84 SkString mangleName; 85 char prefix = 'u'; 86 fProgramBuilder->nameVariable(&mangleName, prefix, name, true); 87 88 UniformInfo& imageStorage = fImageStorages.push_back(); 89 imageStorage.fVariable.setName(mangleName); 90 91 SkASSERT(GrSLTypeIsImageStorage(type)); 92 imageStorage.fVariable.setType(type); 93 imageStorage.fVariable.setTypeModifier(GrShaderVar::kUniform_TypeModifier); 94 imageStorage.fVariable.setImageStorageFormat(format); 95 imageStorage.fVariable.setMemoryModel(model); 96 imageStorage.fVariable.setRestrict(restrict); 97 imageStorage.fVariable.setIOType(ioType); 98 imageStorage.fVariable.setPrecision(kHigh_GrSLPrecision); 99 imageStorage.fLocation = -1; 100 imageStorage.fVisibility = visibility; 101 return GrGLSLUniformHandler::ImageStorageHandle(fImageStorages.count() - 1); 102 } 103 104 void GrGLUniformHandler::appendUniformDecls(GrShaderFlags visibility, SkString* out) const { 105 for (int i = 0; i < fUniforms.count(); ++i) { 106 if (fUniforms[i].fVisibility & visibility) { 107 fUniforms[i].fVariable.appendDecl(fProgramBuilder->shaderCaps(), out); 108 out->append(";"); 109 } 110 } 111 for (int i = 0; i < fSamplers.count(); ++i) { 112 if (fSamplers[i].fVisibility & visibility) { 113 fSamplers[i].fVariable.appendDecl(fProgramBuilder->shaderCaps(), out); 114 out->append(";\n"); 115 } 116 } 117 for (int i = 0; i < fImageStorages.count(); ++i) { 118 if (fImageStorages[i].fVisibility & visibility) { 119 fImageStorages[i].fVariable.appendDecl(fProgramBuilder->shaderCaps(), out); 120 out->append(";"); 121 } 122 } 123 } 124 125 void GrGLUniformHandler::bindUniformLocations(GrGLuint programID, const GrGLCaps& caps) { 126 if (caps.bindUniformLocationSupport()) { 127 int currUniform = 0; 128 for (int i = 0; i < fUniforms.count(); ++i, ++currUniform) { 129 GL_CALL(BindUniformLocation(programID, currUniform, fUniforms[i].fVariable.c_str())); 130 fUniforms[i].fLocation = currUniform; 131 } 132 for (int i = 0; i < fSamplers.count(); ++i, ++currUniform) { 133 GL_CALL(BindUniformLocation(programID, currUniform, fSamplers[i].fVariable.c_str())); 134 fSamplers[i].fLocation = currUniform; 135 } 136 for (int i = 0; i < fImageStorages.count(); ++i) { 137 GL_CALL(BindUniformLocation(programID, currUniform, 138 fImageStorages[i].fVariable.c_str())); 139 fImageStorages[i].fLocation = currUniform; 140 } 141 } 142 } 143 144 void GrGLUniformHandler::getUniformLocations(GrGLuint programID, const GrGLCaps& caps) { 145 if (!caps.bindUniformLocationSupport()) { 146 int count = fUniforms.count(); 147 for (int i = 0; i < count; ++i) { 148 GrGLint location; 149 GL_CALL_RET(location, GetUniformLocation(programID, fUniforms[i].fVariable.c_str())); 150 fUniforms[i].fLocation = location; 151 } 152 for (int i = 0; i < fSamplers.count(); ++i) { 153 GrGLint location; 154 GL_CALL_RET(location, GetUniformLocation(programID, fSamplers[i].fVariable.c_str())); 155 fSamplers[i].fLocation = location; 156 } 157 for (int i = 0; i < fImageStorages.count(); ++i) { 158 GrGLint location; 159 GL_CALL_RET(location, GetUniformLocation(programID, 160 fImageStorages[i].fVariable.c_str())); 161 fImageStorages[i].fLocation = location; 162 } 163 } 164 } 165 166 const GrGLGpu* GrGLUniformHandler::glGpu() const { 167 GrGLProgramBuilder* glPB = (GrGLProgramBuilder*) fProgramBuilder; 168 return glPB->gpu(); 169 } 170