/** * Extract Shader Storage Buffer data from the shader */ void Program::ExtractStorageBlockData() { GLint numBlocks = 0; glGetProgramInterfaceiv(_program, GL_SHADER_STORAGE_BLOCK, GL_ACTIVE_RESOURCES, &numBlocks); char tempNameAR[1024]; Log("\tBuffer :") for (int blockIdx = 0; blockIdx < numBlocks; blockIdx++) { std::vector<BufferVariableInfo> vars; glGetProgramResourceName(_program, GL_SHADER_STORAGE_BLOCK, blockIdx, 1024, NULL, tempNameAR); std::string bufferName(tempNameAR); GLint binding = 0; { GLenum prop[] = { GL_BUFFER_BINDING }; glGetProgramResourceiv(_program, GL_SHADER_STORAGE_BLOCK, blockIdx, 1, prop, 1, NULL, &binding); } Log("\t\t" + bufferName + " index " + ToString(blockIdx) + " binding " + ToString(binding)); GLint vcount = 0; { GLenum prop[] = { GL_NUM_ACTIVE_VARIABLES }; glGetProgramResourceiv(_program, GL_SHADER_STORAGE_BLOCK, blockIdx, 1, prop, 1, NULL, &vcount); } std::vector<GLint> variables(vcount); { GLenum prop[] = { GL_ACTIVE_VARIABLES }; glGetProgramResourceiv(_program, GL_SHADER_STORAGE_BLOCK, blockIdx, 1, prop, vcount, NULL, &variables.front()); } GLchar vnameAR[128] = { 0 }; for (int k = 0; k < vcount; k++) { GLenum propsAR[] = { GL_OFFSET, GL_TYPE, GL_ARRAY_STRIDE, GL_MATRIX_STRIDE, GL_IS_ROW_MAJOR, GL_TOP_LEVEL_ARRAY_STRIDE }; GLint paramsAR[sizeof(propsAR) / sizeof(GLenum)]; glGetProgramResourceiv(_program, GL_BUFFER_VARIABLE, variables[k], sizeof(propsAR) / sizeof(GLenum), propsAR, sizeof(paramsAR) / sizeof(GLenum), NULL, paramsAR); glGetProgramResourceName(_program, GL_BUFFER_VARIABLE, variables[k], sizeof(vnameAR), NULL, vnameAR); Log("\t\t\t" + std::string(vnameAR) + " offset " + ToString(paramsAR[0]) + " type " + GLUtil::GLSLTypeToStr(GLenum(paramsAR[1])) + " array stride " + ToString(paramsAR[2]) + " top level stride " + ToString(paramsAR[5])); vars.push_back(BufferVariableInfo(std::string(vnameAR), paramsAR[0], GLenum(paramsAR[1]), paramsAR[2], paramsAR[3], GLboolean(paramsAR[4]), paramsAR[5])); } _buffers.insert(std::make_pair(bufferName, BufferInfo(bufferName, blockIdx, vars))); } }
/** * Extract Attribute data from the shader */ void Program::ExtractAttributeData() { Log("\tInput :"); char tempNameAR[1024]; { GLint numInput = 0; glGetProgramInterfaceiv(_program, GL_PROGRAM_INPUT, GL_ACTIVE_RESOURCES, &numInput); const GLenum propertiesAR[2] = { GL_TYPE, GL_LOCATION }; for (int input = 0; input < numInput; input++) { GLint valuesAR[2]; glGetProgramResourceiv(_program, GL_PROGRAM_INPUT, input, 2, propertiesAR, 2, NULL, valuesAR); glGetProgramResourceName(_program, GL_PROGRAM_INPUT, input, 1024, NULL, tempNameAR); std::string inputName(tempNameAR); if (inputName.size() >= 3 && inputName.substr(0, 3) == "gl_") continue; else { _inputs.insert(std::make_pair(inputName, AttributeInfo(inputName, GLenum(valuesAR[0]), valuesAR[1], GLUtil::SizeofGLSLType(GLenum(valuesAR[0]))))); Log("\t\t" + inputName + " " + ToString(valuesAR[1]) + " " + GLUtil::GLSLTypeToStr(GLenum(valuesAR[0]))); } } } Log("\tOutput :"); { GLint numOutput = 0; glGetProgramInterfaceiv(_program, GL_PROGRAM_OUTPUT, GL_ACTIVE_RESOURCES, &numOutput); const GLenum propertiesAR[2] = { GL_TYPE, GL_LOCATION }; for (int outpout = 0; outpout < numOutput; outpout++) { GLint valuesAR[2]; glGetProgramResourceiv(_program, GL_PROGRAM_OUTPUT, outpout, 2, propertiesAR, 2, NULL, valuesAR); glGetProgramResourceName(_program, GL_PROGRAM_OUTPUT, outpout, 1024, NULL, tempNameAR); std::string outputName(tempNameAR); if (outputName.size() >= 3 && outputName.substr(0, 3) != "gl_") { _outputs.insert(std::make_pair(outputName, AttributeInfo(outputName, GLenum(valuesAR[0]), valuesAR[1], GLUtil::SizeofGLSLType(GLenum(valuesAR[0]))))); Log("\t\t" + outputName + " " + ToString(valuesAR[1]) + " " + GLUtil::GLSLTypeToStr(GLenum(valuesAR[0]))); } } } }
static bool check_varyings_match(GLuint prog, GLint *values, unsigned num_values, unsigned buffer) { bool match = true; for (unsigned i = 0; i < num_values; i++) { char name[10]; glGetProgramResourceName(prog, GL_TRANSFORM_FEEDBACK_VARYING, values[i], 10, NULL, name); bool match_found = false; for (unsigned i = 0; i < num_values; i++) { if (strcmp(name, varying_names[buffer][i]) == 0) { match_found = true; break; } } if (!match_found) { match = false; printf("ACTIVE_VARIABLES did no return an index for " "%s\n", varying_names[buffer][i]); break; } } return match; }
JNIEXPORT void JNICALL Java_org_lwjgl_opengl_GL43_nglGetProgramResourceName(JNIEnv *__env, jclass clazz, jint program, jint programInterface, jint index, jint bufSize, jlong lengthAddress, jlong nameAddress, jlong __functionAddress) { GLsizei *length = (GLsizei *)(intptr_t)lengthAddress; GLchar *name = (GLchar *)(intptr_t)nameAddress; glGetProgramResourceNamePROC glGetProgramResourceName = (glGetProgramResourceNamePROC)(intptr_t)__functionAddress; UNUSED_PARAMS(__env, clazz) glGetProgramResourceName(program, programInterface, index, bufSize, length, name); }
JNIEXPORT void JNICALL Java_org_lwjgl_opengl_ARBProgramInterfaceQuery_nglGetProgramResourceName__IIIIJJ(JNIEnv *__env, jclass clazz, jint program, jint programInterface, jint index, jint bufSize, jlong lengthAddress, jlong nameAddress) { glGetProgramResourceNamePROC glGetProgramResourceName = (glGetProgramResourceNamePROC)tlsGetFunction(898); intptr_t length = (intptr_t)lengthAddress; intptr_t name = (intptr_t)nameAddress; UNUSED_PARAM(clazz) glGetProgramResourceName(program, programInterface, index, bufSize, length, name); }
void Shader::printActiveUniformBlocks() const { GLint numBlocks = 0; glGetProgramInterfaceiv(id_, GL_UNIFORM_BLOCK, GL_ACTIVE_RESOURCES, &numBlocks); GLenum blockProps[] = { GL_NUM_ACTIVE_VARIABLES, GL_NAME_LENGTH }; GLenum blockIndex[] = { GL_ACTIVE_VARIABLES }; GLenum props[] = { GL_NAME_LENGTH, GL_TYPE, GL_BLOCK_INDEX }; for (int block = 0; block < numBlocks; ++block) { GLint blockInfo[2]; glGetProgramResourceiv(id_, GL_UNIFORM_BLOCK, block, 2, blockProps, 2, NULL, blockInfo); GLint numUnis = blockInfo[0]; char *blockName = new char[blockInfo[1] + 1]; glGetProgramResourceName(id_, GL_UNIFORM_BLOCK, block, blockInfo[1] + 1, NULL, blockName); printf("Uniform block \"%s\":\n", blockName); delete[] blockName; GLint *unifIndexes = new GLint[numUnis]; glGetProgramResourceiv(id_, GL_UNIFORM_BLOCK, block, 1, blockIndex, numUnis, NULL, unifIndexes); for (int unif = 0; unif < numUnis; ++unif) { GLint uniIndex = unifIndexes[unif]; GLint results[3]; glGetProgramResourceiv(id_, GL_UNIFORM, uniIndex, 3, props, 3, NULL, results); GLint nameBufSize = results[0] + 1; char *name = new char[nameBufSize]; glGetProgramResourceName(id_, GL_UNIFORM, uniIndex, nameBufSize, NULL, name); printf(" %s (%s)\n", name, getTypeString(results[1])); delete[] name; } delete[] unifIndexes; } }
Program::Uniforms Program::getActiveBufferVariables( std::vector<GLuint> const & locationIndices ) { Program::Uniforms uniforms; GLint numActiveVariables; glGetProgramInterfaceiv( getGLId(), GL_BUFFER_VARIABLE, GL_ACTIVE_RESOURCES, &numActiveVariables ); for ( size_t idx = 0; idx < locationIndices.size(); ++idx ) { GLuint index = locationIndices[idx]; GLenum const properties[] = { GL_NAME_LENGTH // 0 , GL_BLOCK_INDEX // 1 , GL_TYPE // 2 , GL_ARRAY_SIZE // 3 , GL_OFFSET // 4 , GL_ARRAY_STRIDE // 5 , GL_MATRIX_STRIDE// 6 , GL_IS_ROW_MAJOR // 7 }; GLsizei const numProperties = sizeof dp::util::array(properties); GLint values[numProperties]; glGetProgramResourceiv( getGLId(), GL_BUFFER_VARIABLE, index, numProperties, properties, numProperties, NULL, values ); Uniform uniform; // get uniform name uniform.name.resize(values[0]); glGetProgramResourceName( getGLId(), GL_BUFFER_VARIABLE, index, GLsizei(uniform.name.size()), NULL, &uniform.name[0]); uniform.blockIndex = values[1]; uniform.uniformLocation = -1; uniform.type = values[2]; uniform.arraySize = values[3]; uniform.offset = values[4]; uniform.arrayStride = values[5]; uniform.matrixStride = values[6]; uniform.isRowMajor = (values[7] != 0); uniforms[uniform.name] = uniform; } return uniforms; }
void Shader::addAllUniforms() { /* Get all active uniforms except uniforms in blocks */ GLenum program_interface = GL_UNIFORM; GLint num_uniforms = 0; glGetProgramInterfaceiv(m_program_id, program_interface, GL_ACTIVE_RESOURCES, &num_uniforms); const GLenum properties[] = { GL_BLOCK_INDEX, GL_TYPE, GL_NAME_LENGTH, GL_LOCATION }; const GLint properties_size = sizeof(properties) / sizeof(properties[0]); for(GLint i = 0; i < num_uniforms; ++i) { GLint values[properties_size]; glGetProgramResourceiv(m_program_id, program_interface, i, properties_size, properties, properties_size, nullptr, values); /* Skip all uniforms in blocks */ if(values[0] != -1) { continue; } std::vector<char> name_data(values[2]); glGetProgramResourceName(m_program_id, program_interface, i, name_data.size(), nullptr, &name_data[0]); std::string uniform_name(name_data.begin(), name_data.end() - 1); std::string prefix = uniform_name.substr(0, 2); if(GLOBAL_UNIFORM_PREFIX == prefix) { m_global_uniforms_types.push_back(values[1]); m_global_uniforms_names.push_back(uniform_name); m_uniforms_locations[uniform_name] = values[3]; } else if(SKIP_UNIFORM_PREFIX == prefix) { m_uniforms_locations[uniform_name] = values[3]; } else { m_uniforms_types.push_back(values[1]); m_uniforms_names.push_back(uniform_name); m_uniforms_locations[uniform_name] = values[3]; } } }
void Shader::printActiveAttribs() const { GLint numAttribs; glGetProgramInterfaceiv(id_, GL_PROGRAM_INPUT, GL_ACTIVE_RESOURCES, &numAttribs); GLenum properties[] = { GL_NAME_LENGTH, GL_TYPE, GL_LOCATION }; printf("Active attributes:\n"); for (int i = 0; i < numAttribs; ++i) { GLint results[3]; glGetProgramResourceiv(id_, GL_PROGRAM_INPUT, i, 3, properties, 3, NULL, results); GLint nameBufSize = results[0] + 1; char *name = new char[nameBufSize]; glGetProgramResourceName(id_, GL_PROGRAM_INPUT, i, nameBufSize, NULL, name); printf("%-5d %s (%s)\n", results[2], name, getTypeString(results[1])); delete[] name; } }
int32 gfxGetShaderUniforms(uint32 program, uint8* namesBuffer, uint32 namesBufferSize, uint8* types, uint8* locations) { uint32 namesBufferOffset = 0; GLint numUniforms = 0; glGetProgramInterfaceiv(program, GL_UNIFORM, GL_ACTIVE_RESOURCES, &numUniforms); const GLenum properties[4] = {GL_BLOCK_INDEX, GL_TYPE, GL_NAME_LENGTH, GL_LOCATION}; for(int ii = 0; ii < numUniforms; ++ii) { GLint values[4]; glGetProgramResourceiv(program, GL_UNIFORM, ii, 4, properties, 4, NULL, values); //Skip any iiorms that are in a block. // values[0] = GL_BLOCK_INDEX if(values[0] != -1) continue; // values[2] = GL_NAME_LENGTH int32 len = values[2] + 1; if (namesBufferOffset + len > namesBufferSize) { break; } glGetProgramResourceName(program, GL_UNIFORM, ii, 128, NULL, s_uniformName); // Write to out buffers memcpy(namesBuffer+namesBufferOffset, s_uniformName, len); namesBufferOffset += len; locations[ii] = (uint8)values[3]; uint8 type = UNIFORM_TYPES; for (uint8 t=0; t < UNIFORM_TYPES; t++) { if (values[1] == s_uniformTypeMap[t]) { type = t; break; } } types[ii] = type; } return numUniforms; }
void Program::ExtractUniformData() { Log("\tUniform : "); char tempNameAR[1024]; GLint numUni = 0; glGetProgramInterfaceiv(_program, GL_UNIFORM, GL_ACTIVE_RESOURCES, &numUni); const GLenum propertiesAR[3] = { GL_TYPE, GL_LOCATION, GL_BLOCK_INDEX }; for (int uni = 0; uni < numUni; uni++) { GLint valuesAR[3]; glGetProgramResourceiv(_program, GL_UNIFORM, uni, 3, propertiesAR, 2, NULL, valuesAR); glGetProgramResourceName(_program, GL_UNIFORM, uni, 1024, NULL, tempNameAR); std::string uniName(tempNameAR); _uniforms.insert(std::make_pair(uniName,AttributeInfo(uniName, GLenum(valuesAR[0]), valuesAR[1], GLUtil::SizeofGLSLType(GLenum(valuesAR[0]))))); Log("\t\t" + uniName + " " + ToString(valuesAR[1]) + " " + GLUtil::GLSLTypeToStr(GLenum(valuesAR[0]))); } }
void kore::ShaderProgram::constructShaderOutputInfo(std::vector<ShaderOutput>& rOutputVector) { GLint iNumActiveElements = 0; glGetProgramInterfaceiv(_programHandle, GL_PROGRAM_OUTPUT, GL_ACTIVE_RESOURCES, &iNumActiveElements); const GLenum properties[3] = {GL_TYPE, GL_NAME_LENGTH, GL_LOCATION}; for (int i = 0; i < iNumActiveElements; ++i) { GLchar szNameBuf[BUFSIZE]; GLsizei iActualNameLength = 0; GLint iElementSize = 1; GLenum eElementType; GLint iElementLoc = -1; GLint values[3]; glGetProgramResourceiv(_programHandle, GL_PROGRAM_OUTPUT, i, 3, properties, BUFSIZE, NULL, values); eElementType = values[0]; iActualNameLength = values[1]; iElementLoc = values[2]; glGetProgramResourceName(_programHandle, GL_PROGRAM_OUTPUT, i, BUFSIZE, &iActualNameLength, szNameBuf); std::string szName = std::string(szNameBuf); ShaderOutput element; element.name = szName; element.type = eElementType; element.size = iElementSize; rOutputVector.push_back(element); } }
void gle::fill_input(GLuint pid, input_vars_map_t &input_vars, input_arrays_map_t &input_arrays) { GLint num_active; GLint max_name_length; glGetProgramInterfaceiv(pid, GL_PROGRAM_INPUT, GL_ACTIVE_RESOURCES, &num_active); glGetProgramInterfaceiv(pid, GL_PROGRAM_INPUT, GL_MAX_NAME_LENGTH, &max_name_length); std::vector<char> name_buf(max_name_length); char * name_buf_ptr = &name_buf[0]; for (int i = 0; i < num_active; i++) { glGetProgramResourceName(pid, GL_PROGRAM_INPUT, i, max_name_length, NULL, name_buf_ptr); static GLenum const props[] = { GL_LOCATION, GL_TYPE, GL_ARRAY_SIZE, GL_IS_PER_PATCH }; static const int num_props = sizeof(props) / sizeof(GLenum); #pragma pack(push, 1) struct params_t { GLint loc; GLint type; GLint arr_size; GLint is_per_patch; }; #pragma pack(pop) params_t params; glGetProgramResourceiv(pid, GL_PROGRAM_INPUT, i, num_props, props, num_props, NULL, reinterpret_cast<GLint*>(¶ms)); if (params.arr_size != 0) input_arrays.insert(std::make_pair(std::string(name_buf_ptr), iface_input_array_data_t(name_buf_ptr, params.arr_size, params.type, params.loc, params.is_per_patch))); else input_vars.insert(std::make_pair(std::string(name_buf_ptr), iface_input_variable_data_t(name_buf_ptr, params.type, params.loc, params.is_per_patch))); } }
void Shader::addAllSubroutines() { GLenum interfaces[] = { GL_VERTEX_SUBROUTINE, GL_FRAGMENT_SUBROUTINE }; GLenum shader_stages[] = { GL_VERTEX_SHADER, GL_FRAGMENT_SHADER }; GLint interfaces_count = sizeof(interfaces) / sizeof(interfaces[0]); for(GLint i = 0; i < interfaces_count; ++i) { /* Get all active subroutines */ GLenum program_interface = interfaces[i]; GLint num_subroutines = 0; glGetProgramInterfaceiv(m_program_id, program_interface, GL_ACTIVE_RESOURCES, &num_subroutines); const GLenum properties[] = { GL_NAME_LENGTH }; const GLint properties_size = sizeof(properties) / sizeof(properties[0]); GLint count_subroutine_locations = 0; glGetProgramStageiv(m_program_id, shader_stages[i], GL_ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS, &count_subroutine_locations); m_active_subroutine_uniform_locations[shader_stages[i]] = count_subroutine_locations; for (GLint j = 0; j < num_subroutines; ++j) { GLint values[properties_size]; GLint length = 0; glGetProgramResourceiv(m_program_id, program_interface, j, properties_size, properties, properties_size, &length, values); std::vector<char> name_data(values[0]); glGetProgramResourceName(m_program_id, program_interface, j, name_data.size(), nullptr, &name_data[0]); std::string subroutine_name(name_data.begin(), name_data.end() - 1); GLuint subroutine_index = glGetSubroutineIndex(m_program_id, shader_stages[i], subroutine_name.c_str()); m_subroutine_indices[subroutine_name] = subroutine_index; } } }
void Shader::printActiveUniforms() const { GLint numUniforms = 0; glGetProgramInterfaceiv(id_, GL_UNIFORM, GL_ACTIVE_RESOURCES, &numUniforms); GLenum properties[] = { GL_NAME_LENGTH, GL_TYPE, GL_LOCATION, GL_BLOCK_INDEX }; printf("Active uniforms:\n"); for (int i = 0; i < numUniforms; ++i) { GLint results[4]; glGetProgramResourceiv(id_, GL_UNIFORM, i, 4, properties, 4, NULL, results); if (results[3] != -1) continue; GLint nameBufSize = results[0] + 1; char *name = new char[nameBufSize]; glGetProgramResourceName(id_, GL_UNIFORM, i, nameBufSize, NULL, name); printf("%-5d %s (%s)\n", results[2], name, getTypeString(results[1])); delete[] name; } }
static void validate_resources(const struct subtest_t st, GLuint prog, bool *pass) { GLsizei max_size = 0, size, i; char * name; /* Do not run the test for GL_ATOMIC_COUNTER_BUFFER. * From the GL_ARB_program_interface_query extension: * * "The error INVALID_OPERATION is generated if <programInterface> * is ATOMIC_COUNTER_BUFFER, since active atomic counter buffer * resources are not assigned name strings." */ if (st.programInterface == GL_ATOMIC_COUNTER_BUFFER) return; name = (char *) malloc(st.max_length_name); for (i = 0; i < st.active_resources; i++) { GLuint index; glGetProgramResourceName(prog, st.programInterface, i, st.max_length_name, &size, name); piglit_check_gl_error(GL_NO_ERROR); /* keep track of the maximum size */ if (size > max_size) { max_size = size; } /* Check the names. Transform feedback requires the order to be * the same as the one given in glTransformFeedbackVaryings. * From the GL_ARB_program_interface_query extension: * * "The order of the active resource list is * implementation-dependent for all interfaces except for * TRANSFORM_FEEDBACK_VARYING. For TRANSFORM_FEEDBACK_VARYING, * the active resource list will use the variable order * specified in the the most recent call to * TransformFeedbackVaryings before the last call to * LinkProgram. */ if (st.resources && !is_resource_in_list(st.resources, name, i, st.programInterface == GL_TRANSFORM_FEEDBACK_VARYING)) { fprintf(stderr, "Resource '%s' not found in '%s' " "resource list or found at the wrong " "index\n", name, st.programInterface_str); *pass = false; } /* Check the position of the arguments and see if it matches * with the current position we are in. */ index = glGetProgramResourceIndex(prog, st.programInterface, name); if (index != i) { fprintf(stderr, "%s: Resource '%s' is not at the " "position reported by " "glGetProgramResourceIndex (%i instead " "of %i)\n", st.programInterface_str, name, index, i); *pass = false; } /* check the equivalence with the old API */ if (!consistency_check(prog, st.programInterface, name, index)) { *pass = false; } } free(name); /* glGetProgramResourceName does not count the NULL terminator as part * of the size contrarily to glGetProgramInterfaceiv. * From the GL_ARB_program_interface_query extension: * * "void GetProgramInterfaceiv(uint program, enum programInterface, * enum pname, int *params); * [...] * If <pname> is MAX_NAME_LENGTH, the value returned is the length of * the longest active name string for an active resource in * <programInterface>. This length includes an extra character for the * null terminator." * * "void GetProgramResourceName(uint program, enum programInterface, * uint index, sizei bufSize, * sizei *length, char *name); * [...] * The actual number of characters written into <name>, excluding the * null terminator, is returned in <length>." */ if (max_size != MAX2(0, st.max_length_name - 1)) { fprintf(stderr, "'%s actual max length' expected %i but got " "%i\n", st.programInterface_str, st.max_length_name - 1, max_size); *pass = false; } }
Shader::Shader(const std::string &vshaderFilename, const std::string &fshaderFilename){ std::string vshaderCode = readFile(vshaderFilename); std::string fshaderCode = readFile(fshaderFilename); if (vshaderCode == "ERR" || vshaderCode == "ERR"){ std::cout << "One or both of the shader files didn't load." << std::endl; return; } std::cout << "Read code for " << vshaderFilename << " and " << fshaderFilename << "." << std::endl; vshaderID = glCreateShader(GL_VERTEX_SHADER); fshaderID = glCreateShader(GL_FRAGMENT_SHADER); std::cout << "Read code for " << vshaderFilename << " and " << fshaderFilename << "." << std::endl; compileShader(vshaderID, vshaderCode, vshaderFilename); compileShader(fshaderID, fshaderCode, fshaderFilename); std::cout << "Linking program." << std::endl; programID = glCreateProgram(); glAttachShader(programID, vshaderID); glAttachShader(programID, fshaderID); glLinkProgram(programID); //check for linking errors GLint compileStatus = GL_FALSE; GLint infoLogLength; glGetProgramiv(programID, GL_LINK_STATUS, &compileStatus); glGetProgramiv(programID, GL_INFO_LOG_LENGTH, &infoLogLength); std::vector<char> linkErrorMessage( std::max(infoLogLength, int(1)) ); glGetProgramInfoLog(programID, infoLogLength, NULL, &linkErrorMessage[0]); std::cout << &linkErrorMessage[0] << std::endl; GLint numUniforms = 0; glGetProgramInterfaceiv(programID, GL_UNIFORM, GL_ACTIVE_RESOURCES, &numUniforms); std::vector<GLchar> nameData(256); for(GLint i=0; i<numUniforms; i++) { //Get name length. GLenum thingToGet = GL_NAME_LENGTH; GLint nameLength; glGetProgramResourceiv(programID, GL_UNIFORM, i, 1, &thingToGet, 1, NULL, &nameLength); //Read name into vector. nameData.resize(nameLength); //The length of the name. glGetProgramResourceName(programID, GL_UNIFORM, i, nameData.size(), NULL, &nameData[0]); //Put vector into string, add it to map. std::string name((char*)&nameData[0], nameData.size() - 1); GLint uniformID = glGetUniformLocation(programID, name.c_str()); std::cout << "Found uniform named " << name << " at ID " << uniformID << "." << std::endl; programUniformIDs[name] = uniformID; } std::cout << "Done with " << vshaderFilename << " and " << fshaderFilename << "." << std::endl << std::endl; }
JNIEXPORT void JNICALL Java_org_lwjgl_opengl_GL43_nglGetProgramResourceName(JNIEnv *env, jclass clazz, jint program, jint programInterface, jint index, jint bufSize, jlong length, jlong name, jlong function_pointer) { GLsizei *length_address = (GLsizei *)(intptr_t)length; GLchar *name_address = (GLchar *)(intptr_t)name; glGetProgramResourceNamePROC glGetProgramResourceName = (glGetProgramResourceNamePROC)((intptr_t)function_pointer); glGetProgramResourceName(program, programInterface, index, bufSize, length_address, name_address); }
void GLProgram::create(const GLShader& _vsh, const GLShader& _fsh) { m_id = glCreateProgram(); GLint linked(0); if (_vsh.m_id != 0) { GL_CHECK(glAttachShader(m_id, _vsh.m_id)); if (_fsh.m_id != 0) { GL_CHECK(glAttachShader(m_id, _fsh.m_id)); } GL_CHECK(glLinkProgram(m_id)); GL_CHECK(glGetProgramiv(m_id, GL_LINK_STATUS, &linked)); if (!linked) { char log[1024]; GL_CHECK(glGetProgramInfoLog(m_id, sizeof(log), NULL, log)); MOTI_TRACE("%d: %s", linked, log); } } if (!linked) { GL_CHECK(glDeleteProgram(m_id)); m_id = 0; MOTI_TRACE("Invalid shaders: vsh %d, fsh %d", _vsh.m_id, _fsh.m_id); return; } GLint numActiveAttribs{ 0 }; GLint numActiveUniforms{ 0 }; GL_CHECK(glGetProgramInterfaceiv(m_id, GL_PROGRAM_INPUT, GL_ACTIVE_RESOURCES, &numActiveAttribs)); GL_CHECK(glGetProgramInterfaceiv(m_id, GL_UNIFORM, GL_ACTIVE_RESOURCES, &numActiveUniforms)); glGetProgramiv(m_id, GL_ACTIVE_UNIFORMS, &numActiveUniforms); GLint max0, max1; GL_CHECK(glGetProgramiv(m_id, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &max0)); GL_CHECK(glGetProgramiv(m_id, GL_ACTIVE_UNIFORM_MAX_LENGTH, &max1)); uint32_t nameMaxLength = std::max(max0, max1); char* name = static_cast<char*>(alloca(nameMaxLength + 1)); MOTI_TRACE("Program %d", m_id); MOTI_TRACE("Attribute count %d", numActiveAttribs); for (int32_t i = 0; i < numActiveAttribs; ++i) { GLint size; GLenum type; glGetActiveAttrib(m_id, i, nameMaxLength + 1, nullptr, &size, &type, name); MOTI_TRACE("%s is at location %d", name, glGetAttribLocation(m_id, name)); } MOTI_TRACE("Uniform count %d", numActiveUniforms); for (int32_t i = 0; i < numActiveUniforms; ++i) { struct Info { GLenum type; GLint loc; GLint count; }; Info info; GLenum props[] = { GL_TYPE, GL_LOCATION, GL_ARRAY_SIZE }; GL_CHECK(glGetProgramResourceiv( m_id, GL_UNIFORM, i, MOTI_COUNTOF(props), props, MOTI_COUNTOF(props), NULL, (GLint*)&info)); GL_CHECK(glGetProgramResourceName( m_id, GL_UNIFORM, i, nameMaxLength + 1, NULL, name)); uint16_t count = std::max(info.count, 1); PredefinedUniform::Enum predef = nameToPredefinedUniform(name); if (predef != PredefinedUniform::Count) { m_predefinedUniforms[m_uniformCount].m_type = uint8_t(predef); m_predefinedUniforms[m_uniformCount].m_loc = info.loc; m_predefinedUniforms[m_uniformCount].m_count = count; m_uniformCount++; } else { // its user defined uniform const UniformInfo* uniformInfo = s_ctx->m_uniformReg.find(name); if (uniformInfo == nullptr) { MOTI_TRACE("User defined uniform %s is not found", name); } else { UniformType::Enum type = glTypeToUniformType(info.type); UniformDecl decl; decl.m_handle = uniformInfo->m_handle; decl.m_loc = info.loc; decl.m_count = count; decl.m_type = type; m_uniforms.push_back(decl); } } MOTI_TRACE("uniform %s is at location %d, count %d", name, info.loc, count); } memset(m_attributes, 0xff, sizeof(m_attributes)); uint32_t used(0); for (uint8_t i = 0; i < Attribute::Count; ++i) { GLint loc = glGetAttribLocation(m_id, s_attribNames[i]); if (loc != -1) { MOTI_TRACE("attribute %s: %d", s_attribNames[i], loc); m_attributes[i] = loc; m_used[used++] = i; } } MOTI_ASSERT(used < MOTI_COUNTOF(m_used), "Out of bounds %d > array size %d", used, MOTI_COUNTOF(m_used)); m_used[used] = Attribute::Count; }
void Shader::info() { std::cout << "------------------------------" << m_Name << " Interface-------------------------" << std::endl; GLint outputs = 0; glGetProgramInterfaceiv(m_Program, GL_PROGRAM_INPUT, GL_ACTIVE_RESOURCES, &outputs); static const GLenum props[] = {GL_TYPE, GL_LOCATION}; GLint params[2]; GLchar name[64]; const char *type_name; if (outputs > 0) std::cout << "***Input***" << std::endl; for (int i = 0; i != outputs; ++i) { glGetProgramResourceName(m_Program, GL_PROGRAM_INPUT, i, sizeof(name), NULL, name); glGetProgramResourceiv(m_Program, GL_PROGRAM_INPUT, i, 2, props, 2, NULL, params); type_name = name; //std::cout << "Index " << i << std::endl; std::cout << "(" << type_name << ")" << " locatoin: " << params[1] << std::endl; } glGetProgramInterfaceiv(m_Program, GL_PROGRAM_OUTPUT, GL_ACTIVE_RESOURCES, &outputs); if (outputs > 0) std::cout << "***Onput***" << std::endl; for (int i = 0; i != outputs; ++i) { glGetProgramResourceName(m_Program, GL_PROGRAM_OUTPUT, i, sizeof(name), NULL, name); glGetProgramResourceiv( m_Program, GL_PROGRAM_OUTPUT, i, 2, props, 2, NULL, params); type_name = name; //std::cout << "Index " << i << std::endl; std::cout << "(" << type_name << ")" << " locatoin: " << params[1] << std::endl; } glGetProgramInterfaceiv(m_Program, GL_UNIFORM_BLOCK, GL_ACTIVE_RESOURCES, &outputs); if (outputs > 0) std::cout << "***Uniform Block***" << std::endl; for (int i = 0; i != outputs; ++i) { glGetProgramResourceName(m_Program, GL_UNIFORM_BLOCK, i, sizeof(name), NULL, name); glGetProgramResourceiv( m_Program, GL_UNIFORM_BLOCK, i, 2, props, 2, NULL, params); type_name = name; //std::cout << "Index " << i << std::endl; std::cout << "(" << type_name << ")" << " locatoin: " << params[1] << std::endl; } glGetProgramInterfaceiv(m_Program, GL_UNIFORM, GL_ACTIVE_RESOURCES, &outputs); if (outputs > 0) std::cout << "***Uniform***" << std::endl; if (outputs > 100) return ; for (int i = 0; i != outputs; ++i) { glGetProgramResourceName(m_Program, GL_UNIFORM, i, sizeof(name), NULL, name); glGetProgramResourceiv( m_Program, GL_UNIFORM, i, 2, props, 2, NULL, params); type_name = name; //std::cout << "Index " << i << std::endl; std::cout << "(" << type_name << ")" << " locatoin: " << params[1] << std::endl; } std::cout << "--------------------------------------------------------------------------------" << std::endl; }
static void check_prop(GLuint prog, GLenum programInterface, int index, const char *name, void *inputs, struct check_t c, bool *pass) { int values[10], parent_idx, i; char subsubtest[150]; GLsizei length, tmp = -1; char buf[21]; GLenum pif; GLuint loc; /* skip the test if it is not supported */ if(!check_extensions_prop(c.prop)) { return; } /* generate the name of the subsubtest for error-reporting purposes */ snprintf(subsubtest, sizeof(subsubtest), "%s: %s on %s", name, piglit_get_gl_enum_name(c.prop), piglit_get_gl_enum_name(programInterface)); /* retrieve the property */ glGetProgramResourceiv(prog, programInterface, index, 1, &c.prop, 10, &length, values); if (!piglit_check_gl_error(GL_NO_ERROR)) { printf(" Latest error generated while running '%s'\n", subsubtest); *pass = false; return; } /* check the return value */ switch (c.prop) { case GL_OFFSET: case GL_ARRAY_STRIDE: case GL_ATOMIC_COUNTER_BUFFER_INDEX: basic_check(subsubtest, values[0], c.values[0], pass); break; case GL_BLOCK_INDEX: /* check that the index of the parent matches the name * of the parent */ switch (programInterface) { case GL_UNIFORM: pif = GL_UNIFORM_BLOCK; break; case GL_BUFFER_VARIABLE: pif = GL_SHADER_STORAGE_BLOCK; break; default: assert(!"unexpected programInterface value"); pif = GL_NONE; } parent_idx = glGetProgramResourceIndex(prog, pif, (char*)inputs); piglit_check_gl_error(GL_NO_ERROR); if (parent_idx != values[0]) { glGetProgramResourceName(prog, programInterface, values[0], sizeof(buf), NULL, buf); fprintf(stderr, "'%s' expected parent name to be %s" "(idx = %i) but got parent name %s(idx = %i)\n", subsubtest, (char*)inputs, parent_idx, buf, values[0]); *pass = false; } break; case GL_BUFFER_BINDING: if (values[0] < 0) { fprintf(stderr, "'%s' invalid buffer binding point\n", subsubtest); *pass = false; } /* Binding index is necessary for ATOMIC_COUNTER_BUFFER */ if (programInterface == GL_ATOMIC_COUNTER_BUFFER) { if (values[0] != c.values[0]) { fprintf(stderr, "'%s' expected binding point %i" " but got %i\n", subsubtest, c.values[0], values[0]); *pass = false; } break; } /* check against another API call */ if (programInterface != GL_UNIFORM_BLOCK) { break; } glGetActiveUniformBlockiv(prog, index, GL_UNIFORM_BLOCK_BINDING, &tmp); piglit_check_gl_error(GL_NO_ERROR); if (tmp != values[0]) { fprintf(stderr, "'%s' inconsistent buffer binding point" "(%i) with glGetActiveUniformBlockiv" "(%i)\n", subsubtest, values[0], tmp); *pass = false; } break; case GL_ACTIVE_VARIABLES: case GL_COMPATIBLE_SUBROUTINES: switch (programInterface) { case GL_UNIFORM_BLOCK: pif = GL_UNIFORM; break; case GL_SHADER_STORAGE_BLOCK: pif = GL_BUFFER_VARIABLE; break; case GL_VERTEX_SUBROUTINE_UNIFORM: pif = GL_VERTEX_SUBROUTINE; break; case GL_TESS_CONTROL_SUBROUTINE_UNIFORM: pif = GL_TESS_CONTROL_SUBROUTINE; break; case GL_COMPUTE_SUBROUTINE_UNIFORM: pif = GL_COMPUTE_SUBROUTINE; break; case GL_ATOMIC_COUNTER_BUFFER: /* do nothing */ break; default: assert(!"unexpected programInterface value"); pif = GL_NONE; } /* check that the return count is as expected */ if (c.count != length) { fprintf(stderr, "'%s' expected %zu entries but got %i" "\n", subsubtest, c.count, length); length = 1; *pass = false; break; } /* harcode the index test for GL_ATOMIC_COUNTER_BUFFER */ if (programInterface == GL_ATOMIC_COUNTER_BUFFER) { if (values[0] != 0) { fprintf(stderr, "'%s' expected index 0 but got " "%i", subsubtest, values[0]); *pass = false; } break; } for (i = 0; i < length; i++) { buf[0] = '\0'; glGetProgramResourceName(prog, pif, values[i], sizeof(buf), NULL, buf); piglit_check_gl_error(GL_NO_ERROR); if (!is_resource_in_list(inputs, buf, i, false)) { fprintf(stderr, "'%s' could not find active " "resource '%s' (idx = %i) in the active" " list\n", subsubtest, buf, values[i]); *pass = false; } } break; case GL_BUFFER_DATA_SIZE: /* Nothing we can check here... */ break; case GL_LOCATION: loc = glGetProgramResourceLocation(prog, programInterface, name); piglit_check_gl_error(GL_NO_ERROR); if (loc != values[0]) { fprintf(stderr, "'%s' inconsistent value between " "glGetProgramResourceiv(%i) and " "glGetProgramResourceLocation(%i).\n", subsubtest, values[0], loc); *pass = false; break; } if (prog == prog_loc && values[0] != c.values[0]) { fprintf(stderr, "'%s' expected location %i but got " "%i\n", subsubtest, c.values[0], values[0]); *pass = false; break; } /* continue by testing the (in)validity of the index */ basic_check(subsubtest, values[0], c.values[0], pass); break; case GL_LOCATION_INDEX: loc = glGetProgramResourceLocationIndex(prog, programInterface, name); piglit_check_gl_error(GL_NO_ERROR); if (loc != values[0]) { fprintf(stderr, "'%s' inconsistent value between " "glGetProgramResourceiv(%i) and " "glGetProgramResourceLocationIndex(%i)." "\n", subsubtest, values[0], loc); *pass = false; break; } /* continue by testing the (in)validity of the index */ basic_check(subsubtest, values[0], c.values[0], pass); break; default: /* check that the return count is as expected */ if (c.count != length) { fprintf(stderr, "'%s' expected %zu entries but got %i" "\n", subsubtest, c.count, length); length = 1; *pass = false; break; } /* go through all the values returned */ for (i = 0; i < length; i++) { if (values[i] != c.values[i]) { fprintf(stderr, "'%s' expected %i but got %i at" " index %i\n", subsubtest, c.values[i], values[i], i); *pass = false; } } break; } }
GLProgram *GLCompiler::make( ) { bool errors= false; bool shaders= false; for(unsigned int i= 0; i < GLProgram::SHADERTYPE_LAST; i++) { if(sources[i].source.empty()) continue; // construit le source shaders= true; sources[i].build= build_source(i); // cree le program if(program == GLProgram::null()) program= (new GLProgram(program_label))->create(); // cree le shader GLuint shader= program->shaders[i]; if(shader == 0) { shader= glCreateShader(GLProgram::types[i]); glAttachShader(program->name, shader); program->shaders[i]= shader; } // compile le shader const char *text[]= { sources[i].build.c_str() }; glShaderSource(shader, 1, text, NULL); glCompileShader(shader); GLint status= 0; glGetShaderiv(shader, GL_COMPILE_STATUS, &status); if(status == GL_FALSE) { errors= true; GLint length= 0; glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &length); if(length > 0) { char *log= new char[length +1]; glGetShaderInfoLog(shader, length, NULL, log); ERROR("error compiling %s shader:\n", GLProgram::labels[i]); printErrors(log, sources[i]); ERROR("shader defines:\n%s\n", sources[i].definitions.c_str()); delete [] log; } else MESSAGE("error compiling %s shader: no log. failed.\n", GLProgram::labels[i]); } #if 0 { GLint length= 0; glGetShaderiv(shader, GL_SHADER_SOURCE_LENGTH, &length); if(length > 0) { char log[4096]; glGetShaderSource(shader, sizeof(log), NULL, log); DEBUGLOG("shader:\n%s\n", log); } } #endif } if(shaders == false || program == GLProgram::null()) { ERROR("no shader. failed.\n"); return program; } if(errors == true) { program->resources(); program->errors= true; return program; } // link GLint status= 0; glLinkProgram(program->name); glGetProgramiv(program->name, GL_LINK_STATUS, &status); if(status == GL_FALSE) { GLint length= 0; glGetProgramiv(program->name, GL_INFO_LOG_LENGTH, &length); if(length > 0) { char *log= new char[length +1]; glGetProgramInfoLog(program->name, length, NULL, log); MESSAGE("error linking program:\n%s\nfailed.\n", log); delete [] log; } else MESSAGE("error linking program: no log. failed.\n"); program->errors= true; return program; } //~ #ifdef GK_OPENGL4 #if 0 { // interface matching // introspection opengl >= 4.3 // recompile chaque shader dans un program separe et recupere les varyings avec queryinterface(program_inputs / program_outputs)... std::vector<parameter> stage_inputs[GLProgram::SHADERTYPE_LAST]; std::vector<parameter> stage_outputs[GLProgram::SHADERTYPE_LAST]; for(unsigned int i= 0; i < GLProgram::SHADERTYPE_LAST; i++) { if(program->shaders[i] == 0) continue; // recupere le source du shader GLint stage_length= 0; glGetShaderiv(program->shaders[i], GL_SHADER_SOURCE_LENGTH, &stage_length); std::vector<GLchar> stage_source(stage_length +1); glGetShaderSource(program->shaders[i], stage_source.size(), NULL, &stage_source.front()); // construit un program pipeline avec uniquement ce shader const GLchar *sources[]= { &stage_source.front() }; GLuint stage= glCreateShader(GLProgram::types[i]); glShaderSource(stage, 1, sources, NULL); glCompileShader(stage); GLuint pipeline= glCreateProgram(); glProgramParameteri(pipeline, GL_PROGRAM_SEPARABLE, GL_TRUE); glAttachShader(pipeline, stage); glLinkProgram(pipeline); glValidateProgram(pipeline); // recupere les varyings in / out GLint inputs; glGetProgramInterfaceiv(pipeline, GL_PROGRAM_INPUT, GL_ACTIVE_RESOURCES, &inputs); for(int k= 0; k < inputs; k++) { GLenum properties[3]= { GL_TYPE, GL_LOCATION, GL_LOCATION_COMPONENT }; GLint values[3]= { 0, -1, -1 }; glGetProgramResourceiv(pipeline, GL_PROGRAM_INPUT, k, 3, properties, 3, NULL, values); GLchar name[4096]= { 0 }; glGetProgramResourceName(pipeline, GL_PROGRAM_INPUT, k, sizeof(name), NULL, name); stage_inputs[i].push_back( parameter(name, k, values[0], values[1], -1, values[2]) ); } std::stable_sort(stage_inputs[i].begin(), stage_inputs[i].end()); GLint outputs; glGetProgramInterfaceiv(pipeline, GL_PROGRAM_OUTPUT, GL_ACTIVE_RESOURCES, &outputs); for(int k= 0; k < outputs; k++) { GLenum properties[4]= { GL_TYPE, GL_LOCATION, GL_LOCATION_INDEX, GL_LOCATION_COMPONENT }; GLint values[4]= { 0, -1, -1, -1 }; glGetProgramResourceiv(pipeline, GL_PROGRAM_OUTPUT, k, 4, properties, 4, NULL, values); GLchar name[4096]= { 0 }; glGetProgramResourceName(pipeline, GL_PROGRAM_OUTPUT, k, sizeof(name), NULL, name); stage_outputs[i].push_back( parameter(name, k, values[0], values[1], values[2], values[3]) ); } std::stable_sort(stage_outputs[i].begin(), stage_outputs[i].end()); // nettoyage glDeleteShader(stage); glDeleteProgram(pipeline); } // affichage : les sorties d'un shader doivent correspondre aux entrees du shader suivant dans le pipeline printf("program interfaces...\n"); for(unsigned int i= 0; i < GLProgram::SHADERTYPE_LAST; i++) { if(stage_inputs[i].size()) { printf(" %s shader inputs:\n", GLProgram::labels[i]); for(unsigned int k= 0; k < stage_inputs[i].size(); k++) { const char *type= glsl::type_string(stage_inputs[i][k].type); if(type) printf(" %02d/-1: '%s', type '%s'\n", stage_inputs[i][k].location, stage_inputs[i][k].name.c_str(), type); else printf(" %02d/-1: '%s', type 0x%x\n", stage_inputs[i][k].location, stage_inputs[i][k].name.c_str(), stage_inputs[i][k].type); } } if(stage_outputs[i].size()) { printf(" %s shader outputs:\n", GLProgram::labels[i]); for(unsigned int k= 0; k < stage_outputs[i].size(); k++) { const char *type= glsl::type_string(stage_outputs[i][k].type); if(type) printf(" %02d/%02d: '%s', type '%s'\n", stage_outputs[i][k].location, stage_outputs[i][k].location_index, stage_outputs[i][k].name.c_str(), type); else printf(" %02d/%02d: '%s', type 0x%x\n", stage_outputs[i][k].location, stage_outputs[i][k].location_index, stage_outputs[i][k].name.c_str(), stage_outputs[i][k].type); } } //! \todo verification des interfaces } } #endif program->resources(); program->errors= false; MESSAGE("done.\n"); return program; }
void Program::getResourceName(gl::GLenum programInterface, gl::GLuint index, gl::GLsizei bufSize, gl::GLsizei * length, char * name) const { checkDirty(); glGetProgramResourceName(id(), programInterface, index, bufSize, length, name); }