/** * Finds the shader locations of all uniforms and textures from a given material. * The input material descriptor has all the possible textures and uniforms * that can be used by this shader. (Any material used with this shader * will have the same descriptor.) * * This function uses the descriptor of the input material to find and save * the GL shader locations of each texture and uniform. The locations are * saved into vectors - mTextureLocs and mUniformLocs. Each vector has an * entry for all of the uniforms/textures in the input material * (not just the ones used by this shader). If the shader does not * reference a particular uniform or texture, that location will be -1. * This function must be called after the GL shader program has * been selected as the current program. * @param material can be any Material which uses this shader * @see #getUniformLoc */ void GLShader::findUniforms(const DataDescriptor& desc, int bindingPoint) { std::vector<int>& uniformLocs = mShaderLocs[bindingPoint]; if (uniformLocs.size() > 0) { return; } uniformLocs.resize(desc.getNumEntries(), -1); desc.forEachEntry([&](const DataDescriptor::DataEntry& entry) mutable { if (entry.NotUsed) { return; } int loc = glGetUniformLocation(getProgramId(), entry.Name); if (loc >= 0) { uniformLocs[entry.Index] = loc; #ifdef DEBUG_SHADER LOGV("SHADER: program %d uniform %s loc %d", getProgramId(), entry.Name, loc); #endif } else { #ifdef DEBUG_SHADER LOGV("SHADER: uniform %s has no location in shader %d", entry.Name, getProgramId()); #endif } }); checkGLError("GLShader::findUniforms"); }
std::string GLShader::makeLayout(const DataDescriptor& desc, const char* blockName, bool useGPUBuffer) { std::ostringstream stream; if (useGPUBuffer) { stream << "\nlayout (std140) uniform " << blockName << std::endl << "{" << std::endl; desc.forEachEntry([&stream](const DataDescriptor::DataEntry& entry) mutable { int nelems = entry.Count; stream << " " << entry.Type << " " << entry.Name; if (nelems > 1) { stream << "[" << nelems << "]"; } stream << ";" << std::endl; }); stream << "};" << std::endl; } else { desc.forEachEntry([&stream](const DataDescriptor::DataEntry& entry) mutable { if (entry.IsSet) { int nelems = entry.Count; stream << "uniform " << entry.Type << " " << entry.Name; if (nelems > 1) { stream << "[" << nelems << "]"; } stream << ";" << std::endl; } }); } return stream.str(); }