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); } }
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; }
/** * Dump an uniform that belows to an uniform block. */ static void dumpUniformBlock(JSONWriter &json, GLint program, GLint size, GLenum type, const GLchar *name, GLuint index, GLuint block_index) { GLint offset = 0; GLint array_stride = 0; GLint matrix_stride = 0; GLint is_row_major = GL_FALSE; glGetActiveUniformsiv(program, 1, &index, GL_UNIFORM_OFFSET, &offset); glGetActiveUniformsiv(program, 1, &index, GL_UNIFORM_ARRAY_STRIDE, &array_stride); glGetActiveUniformsiv(program, 1, &index, GL_UNIFORM_MATRIX_STRIDE, &matrix_stride); glGetActiveUniformsiv(program, 1, &index, GL_UNIFORM_IS_ROW_MAJOR, &is_row_major); GLint slot = -1; glGetActiveUniformBlockiv(program, block_index, GL_UNIFORM_BLOCK_BINDING, &slot); if (slot == -1) { return; } AttribDesc desc(type, size, array_stride, matrix_stride, is_row_major); if (!desc) { return; } if (0) { GLint active_uniform_block_max_name_length = 0; glGetProgramiv(program, GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH, &active_uniform_block_max_name_length); GLchar* block_name = new GLchar[active_uniform_block_max_name_length]; GLint block_data_size = 0; glGetActiveUniformBlockiv(program, index, GL_UNIFORM_BLOCK_DATA_SIZE, &block_data_size); GLsizei length = 0; glGetActiveUniformBlockName(program, index, active_uniform_block_max_name_length, &length, block_name); std::cerr << "uniform `" << name << "`, size " << size << ", type " << enumToString(desc.type) << "\n" << " block " << block_index << ", name `" << block_name << "`, size " << block_data_size << "; binding " << slot << "; \n" << " offset " << offset << ", array stride " << array_stride << ", matrix stride " << matrix_stride << ", row_major " << is_row_major << "\n" ; delete block_name; } GLint ubo = 0; glGetIntegeri_v(GL_UNIFORM_BUFFER_BINDING, slot, &ubo); GLint start = 0; glGetIntegeri_v(GL_UNIFORM_BUFFER_START, slot, &start); GLint previous_ubo = 0; glGetIntegerv(GL_UNIFORM_BUFFER_BINDING, &previous_ubo); glBindBuffer(GL_UNIFORM_BUFFER, ubo); const GLbyte *raw_data = (const GLbyte *)glMapBuffer(GL_UNIFORM_BUFFER, GL_READ_ONLY); if (raw_data) { std::string qualifiedName = resolveUniformName(name, size); dumpAttribArray(json, qualifiedName, desc, raw_data + start + offset); glUnmapBuffer(GL_UNIFORM_BUFFER); } glBindBuffer(GL_UNIFORM_BUFFER, previous_ubo); }
static bool test_format(const struct uniform_type *type, bool row_major) { /* Using 140 to get unsigned ints. */ const char *fs_template = "#version 140\n" "layout(std140) uniform ubo {\n" " float pad;\n" " %s %s u;\n" " float size_test;\n" "};\n" "\n" "void main() {\n" " gl_FragColor = vec4(pad) + vec4(%s) + vec4(size_test);\n" "}\n"; char *fs_source; GLuint prog; const char *uniform_names[] = { "u", "size_test" }; GLuint uniform_indices[2]; GLint offsets[2]; int offset, size, expected_offset; const struct uniform_type *transposed_type; bool pass; const char *deref; if (row_major) transposed_type = get_transposed_type(type); else transposed_type = type; if (type->size == 4) deref = "u"; else if (type->size <= 16) deref = "u.x"; else deref = "u[0].x"; asprintf(&fs_source, fs_template, row_major && type->size > 16 ? "layout(row_major) " : "", type->type, deref); prog = piglit_build_simple_program(NULL, fs_source); free(fs_source); glGetUniformIndices(prog, 2, uniform_names, uniform_indices); glGetActiveUniformsiv(prog, 2, uniform_indices, GL_UNIFORM_OFFSET, offsets); glDeleteProgram(prog); offset = offsets[0]; size = offsets[1] - offsets[0]; /* "pad" at the start of the UBO is a float, so our test * uniform would start at byte 4 if not for alignment. */ expected_offset = 4; expected_offset = align(expected_offset, transposed_type->alignment); pass = (offset == expected_offset && size == transposed_type->size); printf("%-10s %10s %8d %-16d %8d %-16d%s\n", type->type, row_major ? "y" : "n", offset, expected_offset, size, transposed_type->size, pass ? "" : " FAIL"); return pass; }
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 Program::getActiveUniforms(GLsizei uniformCount, const GLuint * uniformIndices, GLenum pname, GLint * params) const { checkDirty(); glGetActiveUniformsiv(id(), uniformCount, uniformIndices, pname, params); }
int main(int argc, char **argv) { wrt = (struct warp_runtime *)malloc(sizeof(struct warp_runtime)); assert(NULL != wrt); memset(wrt, 0, sizeof(struct warp_runtime)); create_warp_runtime(wrt); glViewport(0, 0, 500, 500); /* setup shader & program */ GLchar message[512]; GLint status; GLchar *source = NULL; GLuint vertex_shader = glCreateShader(GL_VERTEX_SHADER); load_shader_from_file("shaders/es3_ubo.vert", &source); glShaderSource(vertex_shader, 1, (const GLchar * const*)&source, NULL); glCompileShader(vertex_shader); glGetShaderiv(vertex_shader, GL_COMPILE_STATUS, &status); if (!status) { glGetShaderInfoLog(vertex_shader, 512, NULL, message); printf("%s\n", message); } GLuint fragment_shader = glCreateShader(GL_FRAGMENT_SHADER); free(source); load_shader_from_file("shaders/es3_ubo.frag", &source); glShaderSource(fragment_shader, 1, (const GLchar * const*)&source, NULL); glCompileShader(fragment_shader); glGetShaderiv(fragment_shader, GL_COMPILE_STATUS, &status); if (!status) { glGetShaderInfoLog(fragment_shader, 512, NULL, message); printf("%s\n", message); } GLuint prog = glCreateProgram(); glAttachShader(prog, vertex_shader); glAttachShader(prog, fragment_shader); glLinkProgram(prog); glGetProgramiv(prog, GL_LINK_STATUS, &status); if (!status) { glGetProgramInfoLog(prog, 512, NULL, message); printf("%s\n", message); } glUseProgram(prog); /* set up resource */ GLfloat pos_buf[] = { -0.25f, 0.25f, 0.0f, 0.25f, -0.25f, 0.0f, -0.25f, -0.25f, 0.0f, 0.25f, 0.25f, 0.0f }; GLfloat color_buf[] = { 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, }; GLushort index_buf[] = { 2, 0, 1, 3 }; GLuint vao; glGenVertexArrays(1, &vao); glBindVertexArray(vao); /* setup array buffer for position and color */ GLuint vbo_pos; glGenBuffers(1, &vbo_pos); glBindBuffer(GL_ARRAY_BUFFER, vbo_pos); glBufferData(GL_ARRAY_BUFFER, sizeof(pos_buf), pos_buf, GL_STATIC_DRAW); glEnableVertexAttribArray(0); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid *)0); GLuint vbo_color; glGenBuffers(1, &vbo_color); glBindBuffer(GL_ARRAY_BUFFER, vbo_color); glBufferData(GL_ARRAY_BUFFER, sizeof(color_buf), color_buf, GL_STATIC_DRAW); glEnableVertexAttribArray(1); glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat), (GLvoid *)0); /* setup index buffer for index */ GLuint vbo_index; glGenBuffers(1, &vbo_index); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo_index); glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(index_buf), index_buf, GL_STATIC_DRAW); /* updating uniform block */ glm::mat4 model_mat = glm::mat4(1.0f); glm::mat4 view_mat = glm::lookAt( glm::vec3(-2, 1, 2), glm::vec3(0, 0, 0), glm::vec3(0, 1, 0) ); glm::mat4 proj_mat = glm::perspective(glm::radians(45.0f), 1.0f, 0.1f, 100.0f); GLuint ubo_blk_idx = glGetUniformBlockIndex(prog, "MVP"); GLint ubo_sz; glGetActiveUniformBlockiv(prog, ubo_blk_idx, GL_UNIFORM_BLOCK_DATA_SIZE, &ubo_sz); const char *names[3] = {"uModel", "uView", "uProj"}; GLuint indices[3]; GLint size[3]; GLint offset[3]; GLint type[3]; glGetUniformIndices(prog, 3, names, indices); glGetActiveUniformsiv(prog, 3, indices, GL_UNIFORM_OFFSET, offset); glGetActiveUniformsiv(prog, 3, indices, GL_UNIFORM_SIZE, size); glGetActiveUniformsiv(prog, 3, indices, GL_UNIFORM_TYPE, type); /* mat4 here is 4x4=16 GLfloat */ GLubyte *buffer = (GLubyte *)malloc(ubo_sz); memcpy(buffer + offset[0], &model_mat[0][0], size[0] * sizeof(GLfloat) * 16); memcpy(buffer + offset[1], &view_mat[0][0], size[1] * sizeof(GLfloat) * 16); memcpy(buffer + offset[2], &proj_mat[0][0], size[2] * sizeof(GLfloat) * 16); GLuint ubo; glGenBuffers(1, &ubo); glBindBuffer(GL_UNIFORM_BUFFER, ubo); glBufferData(GL_UNIFORM_BUFFER, ubo_sz, buffer, GL_STATIC_DRAW); glBindBufferBase(GL_UNIFORM_BUFFER, ubo_blk_idx, ubo); /* game loop */ while (1) { XNextEvent(wrt->x11_display, &(wrt->event)); switch(wrt->event.type) { case Expose: /* do the render */ glClearColor(0.3f, 0.3f, 0.3f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); glBindVertexArray(vao); glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, (void*)0); glBindVertexArray(0); eglSwapBuffers(wrt->egl_display, wrt->egl_surface); break; case ButtonPress: case KeyPress: goto finish; default: break; } } finish: glDeleteBuffers(1, &vbo_pos); glDeleteBuffers(1, &vbo_color); glDeleteBuffers(1, &vbo_index); glDeleteBuffers(1, &ubo); glDeleteVertexArrays(1, &vao); glDeleteShader(vertex_shader); glDeleteShader(fragment_shader); glDeleteProgram(prog); destroy_warp_runtime(wrt); return 0; }
void LightSystem::renderLight() { // creating temporary data that will be send to light buffer glGenBuffers(1, &LightBuffer); glBindBuffer(GL_UNIFORM_BUFFER, LightBuffer); int lc = lightList.size(); const GLchar *uniformNames[1] = { "Lights.cont" }; GLuint uniformIndices; glGetUniformIndices(*shader, 1, uniformNames, &uniformIndices); GLint uniformOffsets[1]; glGetActiveUniformsiv(*shader, 1, &uniformIndices, GL_UNIFORM_OFFSET, uniformOffsets); GLuint uniformIndex = glGetUniformBlockIndex(*shader, "Lights"); GLsizei uniformBlockSize(0); glGetActiveUniformBlockiv(*shader, uniformIndex, GL_UNIFORM_BLOCK_DATA_SIZE, &uniformBlockSize); GLint maxSize; glGetIntegerv(GL_MAX_UNIFORM_BLOCK_SIZE, &maxSize); GLint bufferAlignment; glGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &bufferAlignment); //std::cout << "Uniform Block size: " << uniformBlockSize << std::endl; //std::cout << "Uniform Block max size: " << maxSize << std::endl; //std::cout << "Uniform Buffer alignment: " << bufferAlignment << std::endl; GLuint indices[lc * 2]; glGetUniformIndices(*shader, lc * 2, names, indices); lightUniformOffsets.clear(); lightUniformOffsets.resize(lc * 2); glGetActiveUniformsiv(*shader, lightUniformOffsets.size(), indices, GL_UNIFORM_OFFSET, &lightUniformOffsets[0]); GLint *offsets = &lightUniformOffsets[0]; unsigned int bSize(uniformBlockSize); std::vector<unsigned char> buffer(bSize); int offset; for (unsigned int n = 0; n < lightList.size(); ++n) { offset = offsets[0 + n * 2]; *(reinterpret_cast<GLfloat*>(&buffer[0] + offset)) = lightList[n].position.x; offset += sizeof(GLfloat); *(reinterpret_cast<GLfloat*>(&buffer[0] + offset)) = lightList[n].position.y; offset += sizeof(GLfloat); *(reinterpret_cast<GLfloat*>(&buffer[0] + offset)) = lightList[n].position.z; offset += sizeof(GLfloat); offset = offsets[1 + n * 2]; *(reinterpret_cast<GLfloat*>(&buffer[0] + offset)) = lightList[n].color.x; offset += sizeof(GLfloat); *(reinterpret_cast<GLfloat*>(&buffer[0] + offset)) = lightList[n].color.y; offset += sizeof(GLfloat); *(reinterpret_cast<GLfloat*>(&buffer[0] + offset)) = lightList[n].color.z; offset += sizeof(GLfloat); } glUniform1i(LightCount, lc); glBufferData(GL_UNIFORM_BUFFER, bSize, &buffer[0], GL_DYNAMIC_DRAW); glBindBufferBase(GL_UNIFORM_BUFFER, 0, LightBuffer); glUniformBlockBinding(*shader, uniformIndex, 0); glBindBuffer(GL_UNIFORM_BUFFER, 0); }
JNIEXPORT void JNICALL Java_org_lwjgl_opengl_GL31_nglGetActiveUniformsiv(JNIEnv *env, jclass clazz, jint program, jint uniformCount, jlong uniformIndices, jint pname, jlong params, jlong function_pointer) { const GLuint *uniformIndices_address = (const GLuint *)(intptr_t)uniformIndices; GLint *params_address = (GLint *)(intptr_t)params; glGetActiveUniformsivPROC glGetActiveUniformsiv = (glGetActiveUniformsivPROC)((intptr_t)function_pointer); glGetActiveUniformsiv(program, uniformCount, uniformIndices_address, pname, params_address); }
void SharedProjectionAndViewing::findOffsets(GLuint shaderProgram) { const int numberOfNames = 4; GLuint uniformIndices[numberOfNames] = { 0 }; GLint uniformOffsets[numberOfNames] = { 0 }; const GLchar * charStringNames[] = { "modelMatrix", "viewingMatrix", "projectionMatrix", "normalModelMatrix" }; glGetUniformIndices(shaderProgram, numberOfNames, (const GLchar **)charStringNames, uniformIndices); if (uniformIndices[0] != GL_INVALID_INDEX && uniformIndices[1] != GL_INVALID_INDEX) { for (int i = 0; i < numberOfNames; i++) { checkLocationFound(charStringNames[i], uniformIndices[i]); } //Get the offsets of the uniforms. The offsets in the buffer will be the same. glGetActiveUniformsiv(shaderProgram, numberOfNames, uniformIndices, GL_UNIFORM_OFFSET, uniformOffsets); for (int i = 0; i < numberOfNames; i++) { cout << '\t' << charStringNames[i] << " offset is " << uniformOffsets[i] << endl; } // Save locations modelLocation = uniformOffsets[0]; viewLocation = uniformOffsets[1]; projectionLocation = uniformOffsets[2]; normalModelLocation = uniformOffsets[3]; } else { cout << " Did not find names in " << transformBlockName.c_str() << endl; } GLuint uniformEyeIndice = 0; GLint uniformEyeOffset = 0; const GLchar * eyeName[] = { "worldEyePosition" }; glGetUniformIndices(shaderProgram, 1, eyeName, &uniformEyeIndice); if (uniformEyeIndice != GL_INVALID_INDEX) { //Get the offsets of the uniforms. The offsets in the buffer will be the same. glGetActiveUniformsiv(shaderProgram, 1, &uniformEyeIndice, GL_UNIFORM_OFFSET, &uniformEyeOffset); cout << '\t' << eyeName[0] << " offset is " << uniformEyeOffset << endl; // Save location eyePositionLocation = uniformEyeOffset; } else { cout << " Did not find names in " << eyeBlockName.c_str() << endl; } checkOpenGLErrors("findOffets"); } // findOffsets
void TopazSample::renderStandartWeightedBlendedOIT() { glEnable(GL_DEPTH_TEST); glDisable(GL_POLYGON_OFFSET_FILL); glBindBufferBase(GL_UNIFORM_BUFFER, UBO_SCENE, ubos.sceneUbo); glBindBufferBase(GL_UNIFORM_BUFFER, UBO_IDENTITY, ubos.identityUbo); glBindFramebuffer(GL_FRAMEBUFFER, fbos.scene); drawModel(GL_TRIANGLES, *shaderPrograms["draw"], *models.at(0)); glBindFramebuffer(GL_FRAMEBUFFER, 0); /* first pass oit */ glDisable(GL_DEPTH_TEST); // TODO : change on transparent list of models for (auto model = models.begin() + 1; model != models.end(); model++) { /* geometry pass */ { glBindFramebuffer(GL_FRAMEBUFFER, oit->getFramebufferID()); const GLenum drawBuffers[] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1 }; glDrawBuffers(2, drawBuffers); GLfloat clearColorZero[4] = { 0.0f }; GLfloat clearColorOne[4] = { 1.0f }; glClearBufferfv(GL_COLOR, 0, clearColorZero); glClearBufferfv(GL_COLOR, 1, clearColorOne); glEnable(GL_BLEND); glBlendEquation(GL_FUNC_ADD); glBlendFunci(0, GL_ONE, GL_ONE); glBlendFunci(1, GL_ZERO, GL_ONE_MINUS_SRC_COLOR); objectData.objectColor = nv::vec4f(1.0f, 1.0f, 1.0f, oit->getOpacity()); glNamedBufferSubDataEXT((*model)->getBufferID("ubo"), 0, sizeof(ObjectData), &objectData); objectData.objectColor = nv::vec4f(1.0f, 0.0f, 0.0f, oit->getOpacity()); glNamedBufferSubDataEXT((*model)->getCornerBufferID("ubo"), 0, sizeof(ObjectData), &objectData); drawModel(GL_TRIANGLES, *shaderPrograms["weightBlended"], **model); glDisable(GL_BLEND); CHECK_GL_ERROR(); } /* composition pass */ { glBindFramebuffer(GL_FRAMEBUFFER, fbos.scene); glBindBufferRange(GL_UNIFORM_BUFFER, UBO_OIT, ubos.weightBlendedUbo, 0, sizeof(WeightBlendedData)); // check uniform buffer offset { const char* uniformNames[] = { "weightBlendedData.background", "weightBlendedData.colorTex0", "weightBlendedData.colorTex1" }; std::unique_ptr<GLint> parameters(new GLint[3]); std::unique_ptr<GLuint> uniformIndices(new GLuint[3]); glGetUniformIndices(shaderPrograms["weightBlendedFinal"]->getProgram(), 3, uniformNames, uniformIndices.get()); glGetActiveUniformsiv(shaderPrograms["weightBlendedFinal"]->getProgram(), 3, uniformIndices.get(), GL_UNIFORM_OFFSET, parameters.get()); GLint* offset = parameters.get(); } { shaderPrograms["weightBlendedFinal"]->enable(); glVertexAttribFormat(VERTEX_POS, 3, GL_FLOAT, GL_FALSE, 0); glVertexAttribBinding(VERTEX_POS, 0); glEnableVertexAttribArray(VERTEX_POS); glBindVertexBuffer(0, fullScreenRectangle.vboFullScreen, 0, sizeof(nv::vec3f)); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); shaderPrograms["weightBlendedFinal"]->disable(); } CHECK_GL_ERROR(); } } }
bool ShaderProgram::Link() { Release(); if (!vertexShader_ || !pixelShader_ || !vertexShader_->GetGPUObject() || !pixelShader_->GetGPUObject()) return false; object_ = glCreateProgram(); if (!object_) { linkerOutput_ = "Could not create shader program"; return false; } glAttachShader(object_, vertexShader_->GetGPUObject()); glAttachShader(object_, pixelShader_->GetGPUObject()); glLinkProgram(object_); int linked, length; glGetProgramiv(object_, GL_LINK_STATUS, &linked); if (!linked) { glGetProgramiv(object_, GL_INFO_LOG_LENGTH, &length); linkerOutput_.Resize((unsigned)length); int outLength; glGetProgramInfoLog(object_, length, &outLength, &linkerOutput_[0]); glDeleteProgram(object_); object_ = 0; } else linkerOutput_.Clear(); if (!object_) return false; const int MAX_NAME_LENGTH = 256; char nameBuffer[MAX_NAME_LENGTH]; int attributeCount, uniformCount, elementCount, nameLength; GLenum type; glUseProgram(object_); // Check for vertex attributes glGetProgramiv(object_, GL_ACTIVE_ATTRIBUTES, &attributeCount); for (int i = 0; i < attributeCount; ++i) { glGetActiveAttrib(object_, i, (GLsizei)MAX_NAME_LENGTH, &nameLength, &elementCount, &type, nameBuffer); String name = String(nameBuffer, nameLength); VertexElementSemantic semantic = MAX_VERTEX_ELEMENT_SEMANTICS; unsigned char semanticIndex = 0; // Go in reverse order so that "binormal" is detected before "normal" for (unsigned j = MAX_VERTEX_ELEMENT_SEMANTICS - 1; j < MAX_VERTEX_ELEMENT_SEMANTICS; --j) { if (name.Contains(elementSemanticNames[j], false)) { semantic = (VertexElementSemantic)j; unsigned index = NumberPostfix(name); if (index != M_MAX_UNSIGNED) semanticIndex = (unsigned char)index; break; } } if (semantic == MAX_VERTEX_ELEMENT_SEMANTICS) { URHO3D_LOGWARNING("Found vertex attribute " + name + " with no known semantic in shader program " + vertexShader_->GetFullName() + " " + pixelShader_->GetFullName()); continue; } int location = glGetAttribLocation(object_, name.CString()); vertexAttributes_[MakePair((unsigned char)semantic, semanticIndex)] = location; usedVertexAttributes_ |= (1 << location); } // Check for constant buffers #ifndef GL_ES_VERSION_2_0 HashMap<unsigned, unsigned> blockToBinding; if (Graphics::GetGL3Support()) { int numUniformBlocks = 0; glGetProgramiv(object_, GL_ACTIVE_UNIFORM_BLOCKS, &numUniformBlocks); for (int i = 0; i < numUniformBlocks; ++i) { glGetActiveUniformBlockName(object_, (GLuint)i, MAX_NAME_LENGTH, &nameLength, nameBuffer); String name(nameBuffer, (unsigned)nameLength); unsigned blockIndex = glGetUniformBlockIndex(object_, name.CString()); unsigned group = M_MAX_UNSIGNED; // Try to recognize the use of the buffer from its name for (unsigned j = 0; j < MAX_SHADER_PARAMETER_GROUPS; ++j) { if (name.Contains(shaderParameterGroups[j], false)) { group = j; break; } } // If name is not recognized, search for a digit in the name and use that as the group index if (group == M_MAX_UNSIGNED) group = NumberPostfix(name); if (group >= MAX_SHADER_PARAMETER_GROUPS) { URHO3D_LOGWARNING("Skipping unrecognized uniform block " + name + " in shader program " + vertexShader_->GetFullName() + " " + pixelShader_->GetFullName()); continue; } // Find total constant buffer data size int dataSize; glGetActiveUniformBlockiv(object_, blockIndex, GL_UNIFORM_BLOCK_DATA_SIZE, &dataSize); if (!dataSize) continue; unsigned bindingIndex = group; // Vertex shader constant buffer bindings occupy slots starting from zero to maximum supported, pixel shader bindings // from that point onward if (name.Contains("PS", false)) bindingIndex += MAX_SHADER_PARAMETER_GROUPS; glUniformBlockBinding(object_, blockIndex, bindingIndex); blockToBinding[blockIndex] = bindingIndex; constantBuffers_[bindingIndex] = graphics_->GetOrCreateConstantBuffer(bindingIndex, (unsigned)dataSize); } } #endif // Check for shader parameters and texture units glGetProgramiv(object_, GL_ACTIVE_UNIFORMS, &uniformCount); for (int i = 0; i < uniformCount; ++i) { glGetActiveUniform(object_, (GLuint)i, MAX_NAME_LENGTH, 0, &elementCount, &type, nameBuffer); int location = glGetUniformLocation(object_, nameBuffer); // Check for array index included in the name and strip it String name(nameBuffer); unsigned index = name.Find('['); if (index != String::NPOS) { // If not the first index, skip if (name.Find("[0]", index) == String::NPOS) continue; name = name.Substring(0, index); } if (name[0] == 'c') { // Store constant uniform String paramName = name.Substring(1); ShaderParameter newParam; newParam.type_ = type; newParam.location_ = location; #ifndef GL_ES_VERSION_2_0 // If running OpenGL 3, the uniform may be inside a constant buffer if (newParam.location_ < 0 && Graphics::GetGL3Support()) { int blockIndex, blockOffset; glGetActiveUniformsiv(object_, 1, (const GLuint*)&i, GL_UNIFORM_BLOCK_INDEX, &blockIndex); glGetActiveUniformsiv(object_, 1, (const GLuint*)&i, GL_UNIFORM_OFFSET, &blockOffset); if (blockIndex >= 0) { newParam.location_ = blockOffset; newParam.bufferPtr_ = constantBuffers_[blockToBinding[blockIndex]]; } } #endif if (newParam.location_ >= 0) shaderParameters_[StringHash(paramName)] = newParam; } else if (location >= 0 && name[0] == 's') { // Set the samplers here so that they do not have to be set later unsigned unit = graphics_->GetTextureUnit(name.Substring(1)); if (unit >= MAX_TEXTURE_UNITS) unit = NumberPostfix(name); if (unit < MAX_TEXTURE_UNITS) { useTextureUnit_[unit] = true; glUniform1iv(location, 1, reinterpret_cast<int*>(&unit)); } } } // Rehash the parameter & vertex attributes maps to ensure minimal load factor vertexAttributes_.Rehash(NextPowerOfTwo(vertexAttributes_.Size())); shaderParameters_.Rehash(NextPowerOfTwo(shaderParameters_.Size())); return true; }
bool UniformBlock::Create(GLuint program, const char* blockName, const char** uniformNames, const int* uniformIndices, int uniformCount) { free(_bufferData); _bufferData = NULL; if (glIsBuffer(_buffer)) { glDeleteBuffers(1, &_buffer); } _buffer = 0; _indexRemap.resize(uniformCount, -1); _sizes.resize(uniformCount, -1); _offsets.resize(uniformCount, -1); _types.resize(uniformCount, -1); glBindBuffer(GL_UNIFORM_BUFFER, 0); _blockIndex = glGetUniformBlockIndex(program, blockName); glGetActiveUniformBlockiv(program, _blockIndex, GL_UNIFORM_BLOCK_DATA_SIZE, &_blockSize); // Get the indices to check which ones are valid. This is reqired to assure that // writing happens at the correct offsets. std::vector<GLuint> indices; indices.resize(uniformCount, 0); glGetUniformIndices(program, uniformCount, uniformNames, indices.data()); vector<GLuint> actualIndices; actualIndices.reserve(uniformCount); // Attention: actualIndices.size() <= uniformCount! int actualIndexPos = 0; for (int k = 0; k < uniformCount; ++k) { if (indices[k] != GL_INVALID_INDEX) { actualIndices.push_back(indices[k]); _indexRemap[uniformIndices[k]] = actualIndexPos++; } else { LOGE("UniformBlock::Create: The uniform '%s' doesn't exist in uniform block '%s'.", uniformNames[k], blockName); } } glGetActiveUniformsiv(program, actualIndices.size(), actualIndices.data(), GL_UNIFORM_OFFSET, _offsets.data()); glGetActiveUniformsiv(program, actualIndices.size(), actualIndices.data(), GL_UNIFORM_SIZE, _sizes.data()); glGetActiveUniformsiv(program, actualIndices.size(), actualIndices.data(), GL_UNIFORM_TYPE, _types.data()); // Allocate an initialize client memory. _bufferData = static_cast<char*>(malloc(_blockSize)); if (_bufferData == NULL) { return false; } memset(_bufferData, 0, _blockSize); glGenBuffers(1, &_buffer); return (GetGLErrorVerbose() == GL_NO_ERROR); }
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; } } 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); }
UniformBufferMetaInfo::UniformBufferMetaInfo( GLint numMaxArrayElements, String bufferName, String arrayName, std::vector<String> memberStrings, Shader* queryShader) : mNumArrayElements(numMaxArrayElements), //mArrayName(arrayName), mMemberStrings(memberStrings), mRequiredBufferSize(0), mNumMemberElements(memberStrings.size() == 0 ? 1 : memberStrings.size() ), mBufferOffsets(0) { LOG<<DEBUG_LOG_LEVEL<<bufferName<<"\n"; GLuint shaderGLProgramHandle = queryShader->getGLProgramHandle(); GLuint uniBlockIndex = GUARD( glGetUniformBlockIndex(shaderGLProgramHandle, bufferName.c_str()) ); //query needed buffer size GUARD( glGetActiveUniformBlockiv( shaderGLProgramHandle, uniBlockIndex, GL_UNIFORM_BLOCK_DATA_SIZE, & mRequiredBufferSize ) ); //-------------------------------------------------------------------------------- mBufferOffsets = new GLint*[mNumArrayElements]; // const String memberStrings[] = // { // "position","diffuseColor","specularColor","direction", // "innerSpotCutOff_Radians","outerSpotCutOff_Radians","spotExponent","shadowMapLayer" // }; const char** indexQuery_C_StringArray= new const char*[mNumMemberElements]; String* indexQueryStringArray= new String[mNumMemberElements]; GLuint* currentUniformIndices= new GLuint[mNumMemberElements]; for(int arrayElementRunner=0; arrayElementRunner< mNumArrayElements; arrayElementRunner++) { String baseString = arrayName + String("[") + HelperFunctions::toString(arrayElementRunner) + String("]") ; mBufferOffsets[arrayElementRunner]= new GLint[mNumMemberElements]; if(memberStrings.size() != 0) { //we have a structure as array elements; construct the GL referencation strings: for(int memberRunner=0; memberRunner< mNumMemberElements; memberRunner++) { indexQueryStringArray[memberRunner]= String(baseString+ String(".") + memberStrings[memberRunner]); indexQuery_C_StringArray[memberRunner]= indexQueryStringArray[memberRunner].c_str(); } } else { //the array element constist of a single built-in type, i.e. the GL referencation strings //are a single string, beeing the base string: indexQuery_C_StringArray[0]= baseString.c_str(); } //first, get indices of current lightsource members: GUARD( glGetUniformIndices( shaderGLProgramHandle, mNumMemberElements, indexQuery_C_StringArray, currentUniformIndices ) ); //second, get offset in buffer for those members, indentified by the queried indices: GUARD( glGetActiveUniformsiv( shaderGLProgramHandle, mNumMemberElements, currentUniformIndices, GL_UNIFORM_OFFSET, mBufferOffsets[arrayElementRunner] ) ); // for(int memberRunner=0; memberRunner< mNumMemberElements; memberRunner++) // { // LOG<<DEBUG_LOG_LEVEL << String(indexQuery_C_StringArray[memberRunner])<<" ;\n"; // LOG<<DEBUG_LOG_LEVEL <<"uniform index: "<< currentUniformIndices[memberRunner] <<" ;\n"; // LOG<<DEBUG_LOG_LEVEL <<"uniform offset: "<< mBufferOffsets[arrayElementRunner][memberRunner] <<" ;\n"; // assert( "member should be active in shader, otherwise uniform buffer filling would turn out even more complicated :@" // && ( currentUniformIndices[memberRunner] != GL_INVALID_INDEX) ); // } } //endfor delete[] indexQuery_C_StringArray; delete[] indexQueryStringArray; delete[] currentUniformIndices; }