// used for debugging to print the offsets of uniform buffer members void printUniformOffsets(GLuint program, GLuint uniformBlock) { GLchar name[256]; GLint uniformCount; glGetActiveUniformBlockiv( program, uniformBlock, GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS, &uniformCount ); GLint *indices = new GLint[uniformCount]; glGetActiveUniformBlockiv( program, uniformBlock, GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES, indices ); for ( GLint i = 0; i < uniformCount; ++i ) { const GLuint index = (GLuint)indices[i]; GLint type, offset; glGetActiveUniformName(program, index, 256, 0, name); glGetActiveUniformsiv(program, 1, &index, GL_UNIFORM_TYPE, &type); glGetActiveUniformsiv(program, 1, &index, GL_UNIFORM_OFFSET, &offset); std::cout << " " << name << " (offset) : " << offset << std::endl; } std::cout << std::endl; delete [] indices; }
//---------------------------------------------------------- static void GetUniforms(GLuint shader, Shader::ShaderParamList& params) { GLint numUniforms = 0; glGetProgramiv(shader, GL_ACTIVE_UNIFORMS, &numUniforms); std::vector<GLuint> indices(numUniforms); std::vector<GLint> nameLengths(numUniforms); std::vector<GLint> blockIndices(numUniforms); for (int i = 0; i < numUniforms; ++i) { indices[i] = i; } glGetActiveUniformsiv(shader, numUniforms, indices.data(), GL_UNIFORM_BLOCK_INDEX, blockIndices.data()); glGetActiveUniformsiv(shader, numUniforms, indices.data(), GL_UNIFORM_NAME_LENGTH, nameLengths.data()); for (int i = 0; i < numUniforms; ++i) { if (blockIndices[i] == -1) // Uniform is not a block... { std::vector<char> buffer(nameLengths[i]); glGetActiveUniformName(shader, i, buffer.size(), NULL, buffer.data()); ShaderParamPtr p(new ShaderParam(shader, buffer.data())); std::string name(buffer.data()); params[name] = p; } } }
void ShaderPair::PrintActiveUniforms() { if(ready) { GLint numUniforms; glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &numUniforms); if(numUniforms > 0) { std::vector<std::string> nameList; nameList.reserve(numUniforms); for(int i = 0; i < numUniforms; ++i) { GLchar name[64]; GLint len; glGetActiveUniformName(program, i, 64, &len, &name[0]); nameList.push_back(std::string(name)); } LogMessage("\nCurrent active Uniform variables in program:\n"); for(size_t i = 0; i < nameList.size(); i++) { LogError("%s\n",nameList[i].c_str()); } } } }
std::string Program::getActiveUniformName(GLuint uniformIndex) const { checkDirty(); GLint length = getActiveUniform(uniformIndex, GL_UNIFORM_NAME_LENGTH); std::vector<char> name(length); glGetActiveUniformName(id(), uniformIndex, length, nullptr, name.data()); return std::string(name.data(), length); }
bool effect::create() { _program = createProgram(&_shaders[0], _shaders.size()); if (!_program) return false; std::vector<std::string> uniformNames; GLint numUniforms, maxLength; glGetProgramiv(_program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxLength); glGetProgramiv(_program, GL_ACTIVE_UNIFORMS, &numUniforms); char* buf = new char[maxLength]; for (int i = 0; i < numUniforms; ++i) { GLsizei size; glGetActiveUniformName(_program, i, maxLength, &size, buf); std::string name(buf); if (uniformNames.size() > 0 && uniformNames[i - 1] == name) break; else uniformNames.push_back(name); } delete[] buf; for (int i = 0; i < uniformNames.size(); ++i) { GLint uniformLocation = glGetUniformLocation(_program, uniformNames[i].c_str()); if (uniformLocation != -1) _uniforms[uniformNames[i]] = uniformLocation; } std::vector<std::string> uniformBlockNames; glGetProgramiv(_program, GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH, &maxLength); glGetProgramiv(_program, GL_ACTIVE_UNIFORM_BLOCKS, &numUniforms); buf = new char[maxLength]; for (int i = 0; i < numUniforms; ++i) { GLsizei size; glGetActiveUniformBlockName(_program, i, maxLength, &size, buf); std::string name(buf); if (uniformBlockNames.size() > 0 && uniformBlockNames[i - 1] == name) break; else uniformBlockNames.push_back(name); } delete[] buf; for (int i = 0; i < uniformBlockNames.size(); ++i) { GLuint blockIndex = glGetUniformBlockIndex(_program, uniformBlockNames[i].c_str()); glUniformBlockBinding(_program, blockIndex, i); _blockUniforms[uniformBlockNames[i]] = i; } return true; }
void PrintActiveUniforms(GLuint handle){ GLint activeUniforms,length; glGetProgramiv(handle,GL_ACTIVE_UNIFORMS,&activeUniforms); for(int index = 0; index < activeUniforms; index++){ char* uniformName = new char[50]; glGetActiveUniformName(handle,index,50,&length,uniformName); printf(uniformName); delete [] uniformName; } }
std::string Program::getActiveUniformName(const GLuint uniformIndex) const { checkDirty(); GLint length = getActiveUniform(uniformIndex, GL_UNIFORM_NAME_LENGTH); assert(length > 1); // Has to include at least 1 char and '\0' std::vector<char> name(length); glGetActiveUniformName(id(), uniformIndex, length, nullptr, name.data()); // glGetActiveUniformName() insists we query '\0' as well, but it // shouldn't be passed to std::string(), otherwise std::string::size() // returns <actual size> + 1 (on clang) auto numChars = length - 1; return std::string(name.data(), numChars); }
bool ShaderUniformBuffer::createUniforms(UNIFORM_BUFFER_DESC* pdescs, int nr) { glGetActiveUniformBlockiv(mProgram, mBlock, GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS, &mElementNr); GLuint* pindices = new GLuint[mElementNr]; glGetActiveUniformBlockiv(mProgram, mBlock, GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES, (GLint*) pindices); GLint maxlength; glGetProgramiv(mProgram, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxlength); GLchar* pname = new GLchar[maxlength]; mpElements = new BLOCK_UNIFORM[mElementNr]; for ( int index = 0; index < mElementNr; ++index ) { BLOCK_UNIFORM& element = mpElements[index]; int length; glGetActiveUniformName(mProgram, pindices[index], maxlength, &length, pname); element.name = String::fromUtf8(pname); glGetActiveUniformsiv(mProgram, 1, &pindices[index], GL_UNIFORM_OFFSET, &element.offset); int offset = 0; for ( int src = 0; src < nr; ++src ) { UNIFORM_BUFFER_DESC& desc = pdescs[src]; if ( desc.name == element.name ) { element.source_offset = offset; element.size = desc.size; break; } else { offset += desc.size; } } } // determine total buffer size that needs to be allocated glGetActiveUniformBlockiv(mProgram, mBlock, GL_UNIFORM_BLOCK_DATA_SIZE, &mBufferSize); return true; }
bool GLUniform::CreateUBO(GLuint program, GLuint location, GLenum draw) { GLint size; GLint type; GLint offset; std::string uname; GLsizei dataSize = 0; GLsizeiptr uniformSize; Uniform unif; this->location = location; GLint numUniforms; GLuint index; GLint padding = 0; this->block = glGetUniformBlockIndex(program, this->name.c_str()); std::cout<<"Block index "<<block<< " and location "<<location<<std::endl; glGetActiveUniformBlockiv( program, this->block, GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS, &numUniforms ); GLint *indices = new GLint[numUniforms]; glGetActiveUniformBlockiv( program, this->block, GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES, indices ); for( int i = 0; i < numUniforms; i++) { index = (GLuint)indices[i]; glGetActiveUniformName(program, index, 256, 0, &uname[0]); glGetActiveUniformsiv(program, 1, &index, GL_UNIFORM_TYPE, &type); glGetActiveUniformsiv(program, 1, &index, GL_UNIFORM_OFFSET, &offset); glGetActiveUniformsiv(program, 1, &index, GL_UNIFORM_SIZE, &size); if(type == GL_FLOAT_VEC3) uniformSize = sizeof(glm::vec3); else if(type == GL_FLOAT_VEC2) uniformSize = sizeof(glm::vec2); else if(type == GL_FLOAT_VEC4) uniformSize = sizeof(glm::vec4); else if(type == GL_FLOAT_MAT4) uniformSize = sizeof(glm::mat4); else if(type == GL_FLOAT_MAT3) uniformSize = sizeof(glm::mat3); else if(type == GL_INT) { uniformSize = sizeof(int); padding += 3*sizeof(int); } else if(type == GL_FLOAT) { uniformSize = sizeof(float); padding += 3*sizeof(float); } else uniformSize = 0.0f; dataSize += size*uniformSize; unif = {&uname[0], static_cast<GLint>(size*uniformSize), index, offset}; this->uniforms[&uname[0]] = unif; std::cout << "Uniform <" << unif.name << "> (offset): " << unif.offset <<", (size): " <<unif.size<< ", (index): "<<unif.index<< std::endl; } GLBufferObject ubo(name.c_str(), dataSize + padding, (GLuint)1, GL_UNIFORM_BUFFER, draw); if( ubo.Status(GL_UNIFORM_BUFFER, dataSize) ) { std::cerr << "[E] Buffer " << name << " not created."<<std::endl; return false; } glBindBufferBase(ubo.Type(), location, ubo.Buffer()); this->block = glGetUniformBlockIndex(program, this->name.c_str()); std::cout<<"Block index "<<this->block<< " after bind "<<std::endl; ubo.SetBlockIndex(this->block); this->id = ubo.Buffer(); glBindBuffer(GL_UNIFORM_BUFFER, 0); delete [] indices; return true; }
void piglit_init(int argc, char **argv) { struct atomic_counters_limits ls = atomic_counters_get_limits(); bool visited_buffers[8] = { false }; bool visited_counters[8] = { false }; GLuint prog = glCreateProgram(); int i, j, n, ret; piglit_require_gl_version(31); piglit_require_extension("GL_ARB_shader_atomic_counters"); if (ls.fragment_counters < 9) { fprintf(stderr, "Insufficient number of supported atomic " "counters.\n"); piglit_report_result(PIGLIT_SKIP); } if (ls.fragment_buffers < 4) { fprintf(stderr, "Insufficient number of supported atomic " "counter buffers.\n"); piglit_report_result(PIGLIT_SKIP); } if (!atomic_counters_compile(prog, GL_FRAGMENT_SHADER, fs_source)) { fprintf(stderr, "Program failed to compile.\n"); piglit_report_result(PIGLIT_FAIL); } if (!atomic_counters_link(prog)) { fprintf(stderr, "Program failed to link.\n"); piglit_report_result(PIGLIT_FAIL); } glGetProgramiv(prog, GL_ACTIVE_ATOMIC_COUNTER_BUFFERS, &n); if (n != 4) { fprintf(stderr, "Unexpected number of active counter " "buffers.\n"); piglit_report_result(PIGLIT_FAIL); } ret = 0xdeadbeef; glGetActiveAtomicCounterBufferiv( prog, n, GL_ATOMIC_COUNTER_BUFFER_BINDING, &ret); if (!piglit_check_gl_error(GL_INVALID_VALUE)) { fprintf(stderr, "glGetActiveAtomicCounterBufferiv should have " "failed when trying to query a non-existent buffer.\n"); piglit_report_result(PIGLIT_FAIL); } if (ret != 0xdeadbeef) { fprintf(stderr, "Failed call to glGetActiveAtomicCounterBufferiv" "didn't preserve the output parameter contents.\n"); piglit_report_result(PIGLIT_FAIL); } for (i = 0; i < n; ++i) { const struct buffer_info *binfo; int binding, data_size, num_counters, ref; GLuint counters[4]; glGetActiveAtomicCounterBufferiv( prog, i, GL_ATOMIC_COUNTER_BUFFER_BINDING, &binding); if (!piglit_check_gl_error(GL_NO_ERROR)) { fprintf(stderr, "Couldn't obtain counter buffer binding" " point.\n"); piglit_report_result(PIGLIT_FAIL); } binfo = expected_buffer_info(binding); if (!binfo) { fprintf(stderr, "Got unexpected buffer binding " "point.\n"); piglit_report_result(PIGLIT_FAIL); } glGetActiveAtomicCounterBufferiv( prog, i, GL_ATOMIC_COUNTER_BUFFER_DATA_SIZE, &data_size); if (!piglit_check_gl_error(GL_NO_ERROR) || data_size < binfo->min_reasonable_size) { fprintf(stderr, "Invalid buffer data size: %d," " expected at least: %d.\n", data_size, binfo->min_reasonable_size); piglit_report_result(PIGLIT_FAIL); } glGetActiveAtomicCounterBufferiv( prog, i, GL_ATOMIC_COUNTER_BUFFER_ACTIVE_ATOMIC_COUNTERS, &num_counters); if (!piglit_check_gl_error(GL_NO_ERROR) || num_counters != binfo->num_counters) { fprintf(stderr, "Invalid number of atomic counters: %d," " expected: %d.\n", num_counters, binfo->num_counters); piglit_report_result(PIGLIT_FAIL); } if (visited_buffers[i]) { fprintf(stderr, "Buffer at binding point %d seen twice." "\n", binding); piglit_report_result(PIGLIT_FAIL); } visited_buffers[i] = true; glGetActiveAtomicCounterBufferiv(prog, i, GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_VERTEX_SHADER, &ref); if (!piglit_check_gl_error(GL_NO_ERROR) || ref) { fprintf(stderr, "Buffer incorrectly reported to be " "referenced by vertex shader.\n"); piglit_report_result(PIGLIT_FAIL); } glGetActiveAtomicCounterBufferiv(prog, i, GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_TESS_CONTROL_SHADER, &ref); if (!piglit_check_gl_error(GL_NO_ERROR) || ref) { fprintf(stderr, "Buffer incorrectly reported to be " "referenced by tessellation control shader.\n"); piglit_report_result(PIGLIT_FAIL); } glGetActiveAtomicCounterBufferiv(prog, i, GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_TESS_EVALUATION_SHADER, &ref); if (!piglit_check_gl_error(GL_NO_ERROR) || ref) { fprintf(stderr, "Buffer incorrectly reported to be " "referenced by tessellation evaluation shader." "\n"); piglit_report_result(PIGLIT_FAIL); } glGetActiveAtomicCounterBufferiv(prog, i, GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_GEOMETRY_SHADER, &ref); if (!piglit_check_gl_error(GL_NO_ERROR) || ref) { fprintf(stderr, "Buffer incorrectly reported to be " "referenced by geometry shader.\n"); piglit_report_result(PIGLIT_FAIL); } glGetActiveAtomicCounterBufferiv(prog, i, GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_FRAGMENT_SHADER, &ref); if (!piglit_check_gl_error(GL_NO_ERROR) || !ref) { fprintf(stderr, "Buffer incorrectly reported as " "unreferenced from the fragment shader.\n"); piglit_report_result(PIGLIT_FAIL); } glGetActiveAtomicCounterBufferiv(prog, i, GL_ATOMIC_COUNTER_BUFFER_ACTIVE_ATOMIC_COUNTER_INDICES, (GLint *)counters); if (!piglit_check_gl_error(GL_NO_ERROR)) { fprintf(stderr, "Couldn't obtain list of active atomic " "counters for buffer at binding point %d.\n", binding); piglit_report_result(PIGLIT_FAIL); } for (j = 0; j < num_counters; ++j) { const struct counter_info *cinfo; int unif_type, unif_size, unif_name_len, unif_block_idx, unif_offset, unif_stride, unif_buffer_idx; char unif_name[8]; glGetActiveUniformName(prog, counters[j], sizeof(unif_name), NULL, unif_name); cinfo = expected_counter_info(unif_name); if (!piglit_check_gl_error(GL_NO_ERROR) || !cinfo) { fprintf(stderr, "Unknown atomic counter \"%s\"." "\n", unif_name); piglit_report_result(PIGLIT_FAIL); } glGetActiveUniformsiv(prog, 1, &counters[j], GL_UNIFORM_TYPE, &unif_type); if (!piglit_check_gl_error(GL_NO_ERROR) || unif_type != GL_UNSIGNED_INT_ATOMIC_COUNTER) { fprintf(stderr, "Atomic counter \"%s\" has " "invalid type 0x%x, expected 0x%x.\n", unif_name, unif_type, GL_UNSIGNED_INT_ATOMIC_COUNTER); piglit_report_result(PIGLIT_FAIL); } glGetActiveUniformsiv(prog, 1, &counters[j], GL_UNIFORM_SIZE, &unif_size); if (!piglit_check_gl_error(GL_NO_ERROR) || unif_size != cinfo->size) { fprintf(stderr, "Atomic counter \"%s\" has " "invalid size %d, expected: %d.\n", unif_name, unif_size, cinfo->size); piglit_report_result(PIGLIT_FAIL); } glGetActiveUniformsiv(prog, 1, &counters[j], GL_UNIFORM_NAME_LENGTH, &unif_name_len); if (!piglit_check_gl_error(GL_NO_ERROR) || unif_name_len != strlen(unif_name) + 1) { fprintf(stderr, "Atomic counter \"%s\" has " "invalid name length %d, expected: %d." "\n", unif_name, unif_name_len, (int)strlen(unif_name) + 1); piglit_report_result(PIGLIT_FAIL); } glGetActiveUniformsiv(prog, 1, &counters[j], GL_UNIFORM_BLOCK_INDEX, &unif_block_idx); if (!piglit_check_gl_error(GL_NO_ERROR) || unif_block_idx != -1) { fprintf(stderr, "Atomic counter \"%s\" has " "invalid block index %d, expected: -1." "\n", unif_name, unif_block_idx); piglit_report_result(PIGLIT_FAIL); } glGetActiveUniformsiv(prog, 1, &counters[j], GL_UNIFORM_OFFSET, &unif_offset); if (!piglit_check_gl_error(GL_NO_ERROR) || unif_offset != cinfo->offset) { fprintf(stderr, "Atomic counter \"%s\" has " "invalid offset %d, expected: %d.\n", unif_name, unif_offset, cinfo->offset); piglit_report_result(PIGLIT_FAIL); } glGetActiveUniformsiv(prog, 1, &counters[j], GL_UNIFORM_ARRAY_STRIDE, &unif_stride); if (!piglit_check_gl_error(GL_NO_ERROR) || (cinfo->size > 1 && unif_stride < 4) || (cinfo->size == 1 && unif_stride != 0)) { fprintf(stderr, "Atomic counter \"%s\" has " "invalid array stride %d.\n", unif_name, unif_stride); piglit_report_result(PIGLIT_FAIL); } glGetActiveUniformsiv(prog, 1, &counters[j], GL_UNIFORM_ATOMIC_COUNTER_BUFFER_INDEX, &unif_buffer_idx); if (!piglit_check_gl_error(GL_NO_ERROR) || unif_buffer_idx != i) { fprintf(stderr, "Atomic counter \"%s\" has " "invalid buffer index %d, expected %d." "\n", unif_name, unif_buffer_idx, i); piglit_report_result(PIGLIT_FAIL); } if (cinfo->binding != binding) { fprintf(stderr, "Atomic counter \"%s\" belongs " "to the wrong binding point %d.\n", unif_name, binding); piglit_report_result(PIGLIT_FAIL); } if (visited_counters[counters[j]]) { fprintf(stderr, "Atomic counter \"%s\" seen " "twice.\n", unif_name); piglit_report_result(PIGLIT_FAIL); } visited_counters[counters[j]] = true; } } glDeleteProgram(prog); piglit_report_result(PIGLIT_PASS); }
UniformBuffer::UniformBuffer(const Shader& shader, const string& block_name) { GLuint program = shader.get_program_ID(); GLint max_uniform_length; GLint uniform_count; glGetProgramiv(program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &max_uniform_length); GLuint block_index = glGetUniformBlockIndex(program, block_name.c_str()); glGetActiveUniformBlockiv(program, block_index, GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS, &uniform_count); char* uniform_name = new char[max_uniform_length]; GLint* uniform_indices = new GLint[uniform_count]; glGetActiveUniformBlockiv(program, block_index, GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES, uniform_indices); GLint uniform_block_size; glGetActiveUniformBlockiv(program, block_index, GL_UNIFORM_BLOCK_DATA_SIZE, &uniform_block_size); _buffer = new byte[uniform_block_size]; _buffer_size = uniform_block_size; const boost::regex pattern(block_name+"\\.(.*)$"); // ..fourth boost::match_results<std::string::const_iterator> match; for (int i = 0; i < uniform_count; ++i) { glGetActiveUniformName(program, uniform_indices[i], max_uniform_length, NULL, uniform_name); GLint size; GLint offset; GLint array_stride; GLint matrix_stride; GLint is_row_major; glGetActiveUniformsiv(program, 1, (GLuint*)uniform_indices + i, GL_UNIFORM_SIZE, &size); glGetActiveUniformsiv(program, 1, (GLuint*)uniform_indices + i, GL_UNIFORM_OFFSET, &offset); glGetActiveUniformsiv(program, 1, (GLuint*)uniform_indices + i, GL_UNIFORM_ARRAY_STRIDE, &array_stride); glGetActiveUniformsiv(program, 1, (GLuint*)uniform_indices + i, GL_UNIFORM_MATRIX_STRIDE, &matrix_stride); glGetActiveUniformsiv(program, 1, (GLuint*)uniform_indices + i, GL_UNIFORM_IS_ROW_MAJOR, &is_row_major); Entry entry = {(size_t)offset, (size_t)matrix_stride, (is_row_major == GL_TRUE) ? true : false, (size_t)array_stride, (size_t)size}; string uniform_name_str(uniform_name); if (boost::regex_match(uniform_name_str, match, pattern)) { _entries[string(match[1])] = entry; } else { _entries[uniform_name_str] = entry; } } delete[] uniform_name; delete[] uniform_indices; glGenBuffers(1, &_buffer_object); glBindBuffer(GL_UNIFORM_BUFFER, _buffer_object); glBufferData(GL_UNIFORM_BUFFER, _buffer_size, _buffer, GL_DYNAMIC_DRAW); glBindBuffer(GL_UNIFORM_BUFFER, 0); _block_index = block_index; _buffer_binding = 0xffffffff; }
JNIEXPORT void JNICALL Java_org_lwjgl_opengl_GL31_nglGetActiveUniformName(JNIEnv *env, jclass clazz, jint program, jint uniformIndex, jint bufSize, jlong length, jlong uniformName, jlong function_pointer) { GLsizei *length_address = (GLsizei *)(intptr_t)length; GLchar *uniformName_address = (GLchar *)(intptr_t)uniformName; glGetActiveUniformNamePROC glGetActiveUniformName = (glGetActiveUniformNamePROC)((intptr_t)function_pointer); glGetActiveUniformName(program, uniformIndex, bufSize, length_address, uniformName_address); }
bool initProgram() { bool Validated = true; compiler Compiler; // Create program if(Validated) { compiler Compiler; GLuint VertShaderName = Compiler.create(GL_VERTEX_SHADER, getDataDirectory() + VERT_SHADER_SOURCE, "--version 150 --profile core"); GLuint FragShaderName = Compiler.create(GL_FRAGMENT_SHADER, getDataDirectory() + FRAG_SHADER_SOURCE, "--version 150 --profile core"); ProgramName = glCreateProgram(); glAttachShader(ProgramName, VertShaderName); glAttachShader(ProgramName, FragShaderName); glBindAttribLocation(ProgramName, semantic::attr::POSITION, "Position"); glBindFragDataLocation(ProgramName, semantic::frag::COLOR, "Color"); glLinkProgram(ProgramName); Validated = Validated && Compiler.check(); Validated = Validated && Compiler.checkProgram(ProgramName); } // Get variables locations if(Validated) { UniformMaterial = glGetUniformBlockIndex(ProgramName, "material"); UniformTransform = glGetUniformBlockIndex(ProgramName, "transform"); glUniformBlockBinding(ProgramName, UniformTransform, semantic::uniform::TRANSFORM0); glUniformBlockBinding(ProgramName, UniformMaterial, semantic::uniform::MATERIAL); } GLint ActiveUniformBlocks(0); glGetProgramiv(ProgramName, GL_ACTIVE_UNIFORM_BLOCKS, &ActiveUniformBlocks); for(GLint i = 0; i < ActiveUniformBlocks; ++i) { char Name[128]; memset(Name, '\0', sizeof(Name)); GLsizei Length(0); glGetActiveUniformBlockName(ProgramName, i, GLsizei(sizeof(Name)), &Length, Name); std::string StringName(Name); Validated = Validated && (StringName == std::string("material") || StringName == std::string("transform")); } GLint ActiveUniform(0); glGetProgramiv(ProgramName, GL_ACTIVE_UNIFORMS, &ActiveUniform); for(GLint i = 0; i < ActiveUniformBlocks; ++i) { char Name[128]; memset(Name, '\0', sizeof(Name)); GLsizei Length(0); glGetActiveUniformName(ProgramName, i, GLsizei(sizeof(Name)), &Length, Name); std::string StringName(Name); Validated = Validated && ( StringName == std::string("material.Diffuse") || StringName == std::string("transform.MVP")); } return Validated && this->checkError("initProgram"); }
void OGLShaderObject::_initActiveUniformBlock() noexcept { GLint numUniformBlock = 0; GLint maxUniformBlockLength = 0; GLint maxUniformLength = 0; glGetProgramiv(_program, GL_ACTIVE_UNIFORM_BLOCKS, &numUniformBlock); glGetProgramiv(_program, GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH, &maxUniformBlockLength); glGetProgramiv(_program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxUniformLength); if (numUniformBlock) { auto nameUniformBlock = make_scope<GLchar[]>(maxUniformBlockLength + 1); nameUniformBlock[maxUniformBlockLength] = 0; for (GLint i = 0; i < numUniformBlock; ++i) { GLsizei lengthUniformBlock; glGetActiveUniformBlockName(_program, (GLuint)i, maxUniformBlockLength, &lengthUniformBlock, nameUniformBlock.get()); GLuint location = glGetUniformBlockIndex(_program, nameUniformBlock.get()); if (location == GL_INVALID_INDEX) continue; glUniformBlockBinding(_program, location, location); GLint size; GLint count; glGetActiveUniformBlockiv(_program, location, GL_UNIFORM_BLOCK_DATA_SIZE, &size); glGetActiveUniformBlockiv(_program, location, GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS, &count); if (count) { std::vector<GLint> indices(count); glGetActiveUniformBlockiv(_program, location, GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES, indices.data()); std::vector<GLint> offset((std::size_t)count); std::vector<GLint> type((std::size_t)count); std::vector<GLint> datasize((std::size_t)count); std::vector<std::string> varlist((std::size_t)count); std::vector<GLchar> name(maxUniformLength); glGetActiveUniformsiv(_program, count, (GLuint*)&indices[0], GL_UNIFORM_OFFSET, &offset[0]); glGetActiveUniformsiv(_program, count, (GLuint*)&indices[0], GL_UNIFORM_TYPE, &type[0]); glGetActiveUniformsiv(_program, count, (GLuint*)&indices[0], GL_UNIFORM_SIZE, &datasize[0]); for (GLint j = 0; j < count; ++j) { GLsizei length = 0; #if !defined(EGLAPI) glGetActiveUniformName(_program, indices[j], maxUniformLength, &length, name.data()); #else glGetActiveUniform(_program, indices[j], maxUniformLength, &length, &datasize[j], (GLenum*)&type[j], name.data()); #endif varlist[j].append(name.data(), length); } auto uniformblock = std::make_shared<ShaderUniform>(); uniformblock->setName(nameUniformBlock.get()); uniformblock->setType(ShaderVariantType::SPT_BUFFER); uniformblock->setLocation(location); _activeUniforms.push_back(uniformblock); } } } }
void VSShaderLib::addBlocks() { int count, dataSize, actualLen, activeUnif, maxUniLength; int uniType, uniSize, uniOffset, uniMatStride, uniArrayStride, auxSize; char *name, *name2; UniformBlock block; glGetProgramiv(pProgram, GL_ACTIVE_UNIFORM_BLOCKS, &count); for (int i = 0; i < count; ++i) { // Get buffers name glGetActiveUniformBlockiv(pProgram, i, GL_UNIFORM_BLOCK_NAME_LENGTH, &actualLen); name = (char *)malloc(sizeof(char) * actualLen); glGetActiveUniformBlockName(pProgram, i, actualLen, NULL, name); if (!spBlocks.count(name)) { // Get buffers size block = spBlocks[name]; glGetActiveUniformBlockiv(pProgram, i, GL_UNIFORM_BLOCK_DATA_SIZE, &dataSize); //printf("DataSize:%d\n", dataSize); glGenBuffers(1, &block.buffer); glBindBuffer(GL_UNIFORM_BUFFER, block.buffer); glBufferData(GL_UNIFORM_BUFFER, dataSize, NULL, GL_DYNAMIC_DRAW); glUniformBlockBinding(pProgram, i, spBlockCount); glBindBufferRange(GL_UNIFORM_BUFFER, spBlockCount, block.buffer, 0, dataSize); glGetActiveUniformBlockiv(pProgram, i, GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS, &activeUnif); unsigned int *indices; indices = (unsigned int *)malloc(sizeof(unsigned int) * activeUnif); glGetActiveUniformBlockiv(pProgram, i, GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES, (int *)indices); glGetProgramiv(pProgram, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxUniLength); name2 = (char *)malloc(sizeof(char) * maxUniLength); for (int k = 0; k < activeUnif; ++k) { myBlockUniform bUni; glGetActiveUniformName(pProgram, indices[k], maxUniLength, &actualLen, name2); glGetActiveUniformsiv(pProgram, 1, &indices[k], GL_UNIFORM_TYPE, &uniType); glGetActiveUniformsiv(pProgram, 1, &indices[k], GL_UNIFORM_SIZE, &uniSize); glGetActiveUniformsiv(pProgram, 1, &indices[k], GL_UNIFORM_OFFSET, &uniOffset); glGetActiveUniformsiv(pProgram, 1, &indices[k], GL_UNIFORM_MATRIX_STRIDE, &uniMatStride); glGetActiveUniformsiv(pProgram, 1, &indices[k], GL_UNIFORM_ARRAY_STRIDE, &uniArrayStride); if (uniArrayStride > 0) auxSize = uniArrayStride * uniSize; else if (uniMatStride > 0) { switch(uniType) { case GL_FLOAT_MAT2: case GL_FLOAT_MAT2x3: case GL_FLOAT_MAT2x4: case GL_DOUBLE_MAT2: case GL_DOUBLE_MAT2x3: case GL_DOUBLE_MAT2x4: auxSize = 2 * uniMatStride; break; case GL_FLOAT_MAT3: case GL_FLOAT_MAT3x2: case GL_FLOAT_MAT3x4: case GL_DOUBLE_MAT3: case GL_DOUBLE_MAT3x2: case GL_DOUBLE_MAT3x4: auxSize = 3 * uniMatStride; break; case GL_FLOAT_MAT4: case GL_FLOAT_MAT4x2: case GL_FLOAT_MAT4x3: case GL_DOUBLE_MAT4: case GL_DOUBLE_MAT4x2: case GL_DOUBLE_MAT4x3: auxSize = 4 * uniMatStride; break; } } else auxSize = typeSize(uniType); bUni.offset = uniOffset; bUni.type = uniType; bUni.size = auxSize; bUni.arrayStride = uniArrayStride; block.uniformOffsets[name2] = bUni; } free(name2); block.size = dataSize; block.bindingIndex = spBlockCount; spBlocks[name] = block; spBlockCount++; } else glUniformBlockBinding(pProgram, i, spBlocks[name].bindingIndex); } }
PIGLIT_GL_TEST_CONFIG_END void piglit_init(int argc, char **argv) { unsigned int i; GLuint prog; const char *source = "#extension GL_ARB_uniform_buffer_object : enable\n" "uniform ubo1 { float a; };\n" "uniform ubo2 { float bb; float c; };\n" "uniform float dddd;\n" "void main() {\n" " gl_FragColor = vec4(a + bb + c + dddd);\n" "}\n"; int uniforms; bool pass = true; const char *names[4] = {"a", "bb", "c", "dddd"}; bool found[4] = {false, false, false, false}; char no_write; char fill_char = 0xd0; piglit_require_extension("GL_ARB_uniform_buffer_object"); prog = piglit_build_simple_program(NULL, source); glGetProgramiv(prog, GL_ACTIVE_UNIFORMS, &uniforms); assert(uniforms == 4); for (i = 0; i < uniforms; i++) { GLint written_strlen = 0; GLint namelen = 9999; char name[1000]; int name_index; /* This is the size including null terminator. */ glGetActiveUniformsiv(prog, 1, &i, GL_UNIFORM_NAME_LENGTH, &namelen); memset(name, 0xd0, sizeof(name)); glGetActiveUniformName(prog, i, sizeof(name), &written_strlen, name); if (written_strlen >= sizeof(name) - 1) { fprintf(stderr, "return strlen %d, longer than the buffer size\n", written_strlen); pass = false; continue; } else if (name[written_strlen] != 0) { fprintf(stderr, "return name[%d] was %d, expected 0\n", written_strlen, name[written_strlen]); pass = false; continue; } else if (strlen(name) != written_strlen) { fprintf(stderr, "return strlen was %d, but \"%s\" " "has strlen %d\n", written_strlen, name, (int)strlen(name)); pass = false; continue; } for (name_index = 0; name_index < ARRAY_SIZE(names); name_index++) { if (strcmp(names[name_index], name) == 0) { if (found[name_index]) { fprintf(stderr, "Uniform name \"%s\" " "returned twice.\n", name); pass = false; } found[name_index] = true; break; } } if (name_index == ARRAY_SIZE(names)) { fprintf(stderr, "uniform \"%s\" is not a known name\n", name); pass = false; continue; } if (namelen != written_strlen + 1) { fprintf(stderr, "uniform \"%s\" had " "GL_UNIFORM_NAME_LENGTH %d, expected %d\n", name, namelen, written_strlen + 1); pass = false; continue; } /* Test for overflow by writing to a bufSize equal to * strlen and checking if a null terminator or * something landed past that. */ memset(name, fill_char, sizeof(name)); glGetActiveUniformName(prog, i, written_strlen, NULL, name); if (name[written_strlen] != fill_char) { fprintf(stderr, "glGetActiveUniformName overflowed: " "name[%d] = 0x%02x instead of 0x%02x\n", written_strlen, name[written_strlen], fill_char); pass = false; } } if (!piglit_khr_no_error) { no_write = fill_char; glGetActiveUniformName(0xd0d0, 0, 1, NULL, &no_write); pass = piglit_check_gl_error(GL_INVALID_VALUE) && pass; if (no_write != fill_char) pass = false; no_write = fill_char; glGetActiveUniformName(prog, 0, -1, NULL, &no_write); pass = piglit_check_gl_error(GL_INVALID_VALUE) && pass; if (no_write != fill_char) pass = false; no_write = fill_char; glGetActiveUniformName(prog, uniforms, 1, NULL, &no_write); pass = piglit_check_gl_error(GL_INVALID_VALUE) && pass; if (no_write != fill_char) pass = false; } glDeleteProgram(prog); piglit_report_result(pass ? PIGLIT_PASS : PIGLIT_FAIL); }
ofxUboLayout ofxUboShader::getLayout(const string &blockName){ ofxUboLayout layout; layout.blockName = blockName; // get block Index GLuint blockIndex = glGetUniformBlockIndex(getProgram(),blockName.c_str()); if (blockIndex == GL_INVALID_INDEX) { ofLogError("ofxUbo") << "The block '" << blockName << "' does not exist in program:" << getProgram() << " make sure you are actually using the block '" << blockName << "' inside your GLSL program, otherwise openGL will not consider your block active"; layout.blockName = ""; layout.size = -99; return layout; } // get the Size of the Uniform Block int uboSize; glGetActiveUniformBlockiv(getProgram(), blockIndex, GL_UNIFORM_BLOCK_DATA_SIZE, &uboSize); layout.size = uboSize; // get the number of active uniforms of the Uniform Block int activeUnif; glGetActiveUniformBlockiv(getProgram(), blockIndex, GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS, &activeUnif); // get each unifom inside the Uniform block unsigned int *indices = new unsigned int[activeUnif]; glGetActiveUniformBlockiv(getProgram(), blockIndex, GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES, (int *)indices); // loop through all active Uniforms and get each, uniform's name,type,offset,size,arrayStride,and MatrixStride int actualLen, index, uniType,uniSize, uniMatStride, uniArrayStride, uniOffset; char name[256]; for (int k = 0; k < activeUnif; ++k) { glGetActiveUniformName(getProgram(), indices[k], 256, &actualLen, name); glGetActiveUniformsiv(getProgram(), 1, &indices[k], GL_UNIFORM_TYPE, &uniType); glGetActiveUniformsiv(getProgram(), 1, &indices[k], GL_UNIFORM_OFFSET, &uniOffset); // This function retrives array length, not the actual size; glGetActiveUniformsiv(getProgram(), 1, &indices[k], GL_UNIFORM_SIZE, &uniSize); glGetActiveUniformsiv(getProgram(), 1, &indices[k], GL_UNIFORM_ARRAY_STRIDE, &uniArrayStride); glGetActiveUniformsiv(getProgram(), 1, &indices[k], GL_UNIFORM_MATRIX_STRIDE, &uniMatStride); int auxSize; if (uniArrayStride > 0) auxSize = uniArrayStride * uniSize; else if (uniMatStride > 0) { switch(uniType) { case GL_FLOAT_MAT2: case GL_FLOAT_MAT2x3: case GL_FLOAT_MAT2x4: case GL_DOUBLE_MAT2: auxSize = 2 * uniMatStride; break; case GL_FLOAT_MAT3: case GL_FLOAT_MAT3x2: case GL_FLOAT_MAT3x4: case GL_DOUBLE_MAT3: auxSize = 3 * uniMatStride; break; case GL_FLOAT_MAT4: case GL_FLOAT_MAT4x2: case GL_FLOAT_MAT4x3: case GL_DOUBLE_MAT4: auxSize = 4 * uniMatStride; break; } } else auxSize = ofxUboSingeltons::spGLSLTypeSize[uniType]; ofxUniformInfo info; info.name = name; info.type = uniType; info.offest = uniOffset; info.size = auxSize; info.arrayStride = uniArrayStride; info.matrixStride = uniMatStride; layout.uniformData.push_back(info); } // Sort unifoms based on offset. Some opengl drivers seem to fetch uniforms in a non sequential order. // The offset data is still correct but glGetActiveUniformBlockiv feeds you uniforms in a random order. ofSort(layout.uniformData); delete[] indices; return layout; }