/** * @param nm: output name in the fragment shader, ex: "fragColor" */ void shader_add_fragment_output(shader_t *s, const char *nm) { struct shader_fragment_output_t *f_out = &s->outputs[s->noutputs]; GLuint loc = glGetFragDataLocation(s->program, nm); f_out->attachment = GL_COLOR_ATTACHMENT0 + loc; s->noutputs++; }
static void validate_location(GLuint prog, GLenum iface, const char *name, GLuint value) { GLuint loc = glGetProgramResourceLocation(prog, iface, name); /* Validate result against old API. */ switch (iface) { case GL_UNIFORM: if (glGetUniformLocation(prog, name) != loc) piglit_report_result(PIGLIT_FAIL); break; case GL_PROGRAM_INPUT: if (glGetAttribLocation(prog, name) != loc) piglit_report_result(PIGLIT_FAIL); break; case GL_PROGRAM_OUTPUT: if (glGetFragDataLocation(prog, name) != loc) piglit_report_result(PIGLIT_FAIL); break; } /* Expected value. */ if (loc != value) { fprintf(stderr, "got value %d for %s, expected %d\n", loc, name, value); piglit_report_result(PIGLIT_FAIL); } /* No errors should have happened. */ if (!piglit_check_gl_error(GL_NO_ERROR)) piglit_report_result(PIGLIT_FAIL); }
GLuint dake::gl::program::frag(const char *identifier) { check_valid(); if (!linked) { link(); } return glGetFragDataLocation(id, identifier); }
GLuint Shader::getColorLocation(const std::string& name) { std::map<std::string, ShaderColorData>::iterator it = _colorLocations.find(name); if(it != _colorLocations.end()){ return it->second.location; } GLint loc = glGetFragDataLocation(_programInfo->glID, name.c_str()); if(loc > 0) _colorLocations.at(name).location = loc; return loc; }
void ShaderCallback::test( unsigned long event, void *cbo) { std::cout << " START TEST" << std::endl; if(event == vtkCommand::UpdateShaderEvent) { std::cout << "--- START UpdateShaderEvent" << std::endl; vtkOpenGLHelper *cellBO = reinterpret_cast<vtkOpenGLHelper*>(cbo); report_gl_error(); if(cellBO && cellBO->VAO) { report_gl_error(); vtkShaderProgram *program = cellBO->Program; vtkOpenGLVertexArrayObject *vao = cellBO->VAO; std::cout << "Program is compiled? " << program->GetCompiled() << std::endl; std::cout << "Program is bound? " << program->isBound() << std::endl; std::cout << "IBO index count " << cellBO->IBO->IndexCount << std::endl; report_gl_error(); GLint color_frag_out_index = glGetFragDataLocation(cellBO->Program->GetHandle(), "color"); std::cout << "color index " << color_frag_out_index << std::endl; glBindFragDataLocation(cellBO->Program->GetHandle(), color_frag_out_index, "color"); //setting output of fragment shader std::cout << "ADDING ATTRIBUTE ARRAY" << std::endl; /* vao->Bind(); if (!vao->AddAttributeArray(program, vbo.Get(), "vertexMC", 0, sizeof(float)*3, VTK_FLOAT, 3, false)) { vtkGenericWarningMacro(<< "Error setting 'vertexMC' in shader VAO."); } */ vao->Bind(); //Input color int vec_size = 3; if (!vao->AddAttributeArray( program, //vtkShaderProgram mColorBufferObject.Get(), //vtkOpenGLBufferObject "COLOR_VSIN", //std::string 0, //int (offset) where to start reading g_color_buffer_data, offset != 0 == discard some of the first values sizeof(float)*3, //size_t (stride) If stride is 0, the generic vertex attributes are understood to be tightly packed in the array. VTK_FLOAT, //int (elementType) Specifies the data type of each component in the array vec_size, //int (elementTupleSize) Specifies the number of components per generic vertex attribute. Must be 1, 2, 3, 4. false //bool (normalize) )) { vtkGenericWarningMacro(<< "Error setting 'COLOR' in shader VAO."); }
void ShaderCallback::bindFSOutputVariable(vtkShaderProgram *program) { GLint color_frag_out_index = glGetFragDataLocation(program->GetHandle(), FS_Out_Vec4_Color.c_str()); if(color_frag_out_index != -1) { glBindFragDataLocation(program->GetHandle(), color_frag_out_index, FS_Out_Vec4_Color.c_str()); //setting output of fragment shader //CX_LOG_DEBUG() << "Binding fragmentshader output to " << FS_Out_Vec4_Color << " at index "<< color_frag_out_index; } else { CX_LOG_ERROR() << "Could not find glGetFragDataLocation for " << FS_Out_Vec4_Color; } }
void FrameBufferObject::textureAttach() { GLenum FBOstatus; glBindFramebuffer(GL_FRAMEBUFFER, FBOHandle); glReadBuffer(GL_NONE); vector<GLint> loc; for (int j = 0; j < shaderOut.size(); ++j) { GLint location = glGetFragDataLocation(shaderProg, (const GLchar*)shaderOut[j]); loc.push_back(location); } int numTextures = textures.size(); GLenum* drawBufs = new GLenum[numTextures]; for (int k = 0; k < texAttachLoc.size(); ++k) { GLint location = loc[k]; drawBufs[location] = texAttachLoc[k]; } glDrawBuffers(numTextures, drawBufs); for (int m = 0; m < numTextures; ++m) { glBindTexture(GL_TEXTURE_2D, textures[m]); glFramebufferTexture2D(GL_FRAMEBUFFER, drawBufs[loc[m]], GL_TEXTURE_2D, textures[m], 0); } FBOstatus = glCheckFramebufferStatus(GL_FRAMEBUFFER); if (FBOstatus != GL_FRAMEBUFFER_COMPLETE) { printf("GL_FRAMEBUFFER_COMPLETE FAILED\n"); checkFrameBufferStatus(FBOstatus); } delete drawBufs; }
void piglit_init(int argc, char **argv) { GLint max_draw_buffers; GLuint prog; GLuint vs; GLuint fs; GLint loc; piglit_require_gl_version(30); /* This test needs some number of draw buffers, so make sure the * implementation isn't broken. This enables the test to generate a * useful failure message. */ glGetIntegerv(GL_MAX_DRAW_BUFFERS, &max_draw_buffers); if (max_draw_buffers < 8) { fprintf(stderr, "OpenGL 3.0 requires GL_MAX_DRAW_BUFFERS >= 8. " "Only got %d!\n", max_draw_buffers); piglit_report_result(PIGLIT_FAIL); } prog = glCreateProgram(); vs = piglit_compile_shader_text(GL_VERTEX_SHADER, vs_text); fs = piglit_compile_shader_text(GL_FRAGMENT_SHADER, fs_text); glAttachShader(prog, vs); glAttachShader(prog, fs); if (!piglit_check_gl_error(GL_NO_ERROR)) piglit_report_result(PIGLIT_FAIL); if (!piglit_khr_no_error) { /* Page 237 (page 253 of the PDF) of the OpenGL 3.0 spec says: * * "If program has not been successfully linked, the error * INVALID OPERATION is generated. If name is not a varying * out variable, or if an error occurs, -1 will be * returned." */ printf("Querying location before linking...\n"); loc = glGetFragDataLocation(prog, "v"); if (!piglit_check_gl_error(GL_INVALID_OPERATION)) piglit_report_result(PIGLIT_FAIL); if (loc != -1) { fprintf(stderr, "Expected location = -1, got %d\n", loc); piglit_report_result(PIGLIT_FAIL); } } glLinkProgram(prog); if (!piglit_check_gl_error(GL_NO_ERROR)) piglit_report_result(PIGLIT_FAIL); if (!piglit_link_check_status(prog)) { piglit_report_result(PIGLIT_FAIL); } printf("Querying location of nonexistent variable...\n"); loc = glGetFragDataLocation(prog, "waldo"); if (!piglit_check_gl_error(GL_NO_ERROR)) piglit_report_result(PIGLIT_FAIL); if (loc != -1) { fprintf(stderr, "Expected location = -1, got %d\n", loc); piglit_report_result(PIGLIT_FAIL); } /* Page 236 (page 252 of the PDF) of the OpenGL 3.0 spec says: * * "BindFragDataLocation has no effect until the program is * linked. In particular, it doesn’t modify the bindings of * varying out variables in a program that has already been * linked." */ glBindFragDataLocation(prog, 0, "v"); glBindFragDataLocation(prog, 1, "a"); glLinkProgram(prog); if (!piglit_check_gl_error(GL_NO_ERROR)) piglit_report_result(PIGLIT_FAIL); if (!piglit_link_check_status(prog)) { piglit_report_result(PIGLIT_FAIL); } printf("Querying locations after binding and linking...\n"); loc = glGetFragDataLocation(prog, "v"); if (!piglit_check_gl_error(GL_NO_ERROR)) piglit_report_result(PIGLIT_FAIL); if (loc != 0) { fprintf(stderr, "Expected location = 0, got %d\n", loc); piglit_report_result(PIGLIT_FAIL); } loc = glGetFragDataLocation(prog, "a"); if (!piglit_check_gl_error(GL_NO_ERROR)) piglit_report_result(PIGLIT_FAIL); if (loc != 1) { fprintf(stderr, "Expected location = 1, got %d\n", loc); piglit_report_result(PIGLIT_FAIL); } printf("Querying locations after just binding...\n"); glBindFragDataLocation(prog, 2, "v"); glBindFragDataLocation(prog, 0, "a"); if (!piglit_check_gl_error(GL_NO_ERROR)) piglit_report_result(PIGLIT_FAIL); loc = glGetFragDataLocation(prog, "v"); if (!piglit_check_gl_error(GL_NO_ERROR)) piglit_report_result(PIGLIT_FAIL); if (loc != 0) { fprintf(stderr, "Expected location = 0, got %d\n", loc); piglit_report_result(PIGLIT_FAIL); } loc = glGetFragDataLocation(prog, "a"); if (!piglit_check_gl_error(GL_NO_ERROR)) piglit_report_result(PIGLIT_FAIL); if (loc != 1) { fprintf(stderr, "Expected location = 1, got %d\n", loc); piglit_report_result(PIGLIT_FAIL); } piglit_report_result(PIGLIT_PASS); }
void ShadersLoader::LoadShaderFBO(Shader* shader, TiXmlElement *root) { TiXmlElement *rootFBO = root->FirstChildElement("OutputFrame"); if (!rootFBO) { Logger::Log() << "[INFO] No FBO is available ... \n"; return; } // Get the depth buffer type std::string typeDepthString; TinyXMLGetAttributeValue<std::string>(rootFBO, "depthType", &typeDepthString); Logger::Log() << " * Depth buffer type " << typeDepthString << "\n"; FBODepthType typeDepth; if (typeDepthString == "None") { typeDepth = FBODEPTH_NONE; } else if (typeDepthString == "RenderTarget") { typeDepth = FBODEPTH_RENDERTARGET; } else if (typeDepthString == "Texture") { typeDepth = FBODEPTH_TEXTURE; } else throw CException("invalid buffer type"); // Get the size of buffer std::string typeSize; int X = 0; int Y = 0; TinyXMLGetAttributeValue<std::string>(rootFBO, "size", &typeSize); if (typeSize == "Screen") { Math::TVector2I sizeScreen = CSettingsManager::Instance().GetSizeRenderingWindow(); X = sizeScreen.x; Y = sizeScreen.y; } else if (typeSize == "HalfScreen") { Math::TVector2I sizeScreen = CSettingsManager::Instance().GetSizeRenderingWindow(); X = sizeScreen.x / 2; Y = sizeScreen.y / 2; } else if (typeSize == "Custom") { TinyXMLGetAttributeValue<int>(rootFBO, "width", &X); TinyXMLGetAttributeValue<int>(rootFBO, "height", &Y); } else { throw CException("unknow type of size"); } // Get all buffers std::map<std::string, FBOTextureBufferParam> buffers; Logger::Log() << " * Chargement des differents buffers .... \n"; TiXmlElement *frameNode = rootFBO->FirstChildElement("Frame"); shader->Begin(); while (frameNode) { std::string name; std::string typeString; TinyXMLGetAttributeValue<std::string>(frameNode, "name", &name); TinyXMLGetAttributeValue<std::string>(frameNode, "type", &typeString); Logger::Log() << " * Create buffer : " << name << " ( " << typeString << " ) \n"; FBOTextureBufferParam param; // Mipmapping parsing bool mipmapping = false; frameNode->Attribute("mipmapping", &mipmapping); if (mipmapping) { Logger::Log() << " * Mipmapping enable \n"; param.GenerateMipMapping = true; param.MinFiltering = GL_LINEAR_MIPMAP_NEAREST; param.MaxFiltering = GL_LINEAR; } bool bilinear = false; frameNode->Attribute("bilinear", &bilinear); if(bilinear) { Logger::Log() << " * Bilinear enable \n"; param.MinFiltering = GL_LINEAR; param.MaxFiltering = GL_LINEAR; } if(bilinear && mipmapping) throw CException("Impossible to activate Bilinear & mipmapping on the same texture"); // Parse the Image format if (typeString == "RGBA") { // Nothing to do } else if (typeString == "RGB16") { param.InternalFormat = GL_RGB16F; param.ExternalFormat = GL_RGB; } else if (typeString == "RGB32") { param.InternalFormat = GL_RGB32F; param.ExternalFormat = GL_RGB; } else if (typeString == "RGBA16") { param.InternalFormat = GL_RGBA16F; param.ExternalFormat = GL_RGBA; } else if (typeString == "RGBA32") { param.InternalFormat = GL_RGBA32F; param.ExternalFormat = GL_RGBA; } else if (typeString == "L") { param.InternalFormat = GL_LUMINANCE32F_ARB; param.ExternalFormat = GL_LUMINANCE; } else throw CException("unknow buffer type"); param.Attachment = glGetFragDataLocation(shader->GetProgramObject(), name.c_str()); Logger::Log() << " * Attachment : " << param.Attachment << "\n"; buffers[name] = param; frameNode = frameNode->NextSiblingElement("Frame"); } shader->End(); FBODepthBufferParam bufferDepth; FBO* fbo = new FBO(Math::TVector2I(X, Y), buffers, typeDepth, bufferDepth); // FIXME: Inversion des tailles ??? shader->SetFBO(fbo); }
GLint Program::getFragDataLocation(const std::string & name) const { return glGetFragDataLocation(id(), name.c_str()); }
GLint VSShaderLib::getProgramOutput(std::string name) { return glGetFragDataLocation(pProgram, name.c_str()); }
void piglit_init(int argc, char **argv) { GLint max_draw_buffers; GLuint prog; GLuint vs; GLuint fs; GLint loc; piglit_require_gl_version(30); /* This test needs some number of draw buffers, so make sure the * implementation isn't broken. This enables the test to generate a * useful failure message. */ glGetIntegerv(GL_MAX_DRAW_BUFFERS, &max_draw_buffers); if (max_draw_buffers < 8) { fprintf(stderr, "OpenGL 3.0 requires GL_MAX_DRAW_BUFFERS >= 8. " "Only got %d!\n", max_draw_buffers); piglit_report_result(PIGLIT_FAIL); } prog = glCreateProgram(); vs = piglit_compile_shader_text(GL_VERTEX_SHADER, vs_text); fs = piglit_compile_shader_text(GL_FRAGMENT_SHADER, fs_text); if (!piglit_check_gl_error(GL_NO_ERROR)) piglit_report_result(PIGLIT_FAIL); /* First, verify that the program will link without making any * location assignments through the API. */ printf("Basic test...\n"); glAttachShader(prog, vs); glAttachShader(prog, fs); glLinkProgram(prog); if (!piglit_check_gl_error(GL_NO_ERROR)) piglit_report_result(PIGLIT_FAIL); if (!piglit_link_check_status(prog)) { piglit_report_result(PIGLIT_FAIL); } /* Page 237 (page 253 of the PDF) of the OpenGL 3.0 spec says: * * "Assigned bindings for variables that do not exist are * ignored." */ printf("Binding `unicorn' to a non-conflicting location...\n"); glBindFragDataLocation(prog, 0, "v"); if (!piglit_check_gl_error(GL_NO_ERROR)) piglit_report_result(PIGLIT_FAIL); glBindFragDataLocation(prog, 1, "unicorn"); if (!piglit_check_gl_error(GL_NO_ERROR)) piglit_report_result(PIGLIT_FAIL); glLinkProgram(prog); if (!piglit_check_gl_error(GL_NO_ERROR)) piglit_report_result(PIGLIT_FAIL); if (!piglit_link_check_status(prog)) { fprintf(stderr, "Linking failed when it should have been " "successful.\n"); piglit_report_result(PIGLIT_FAIL); } loc = glGetFragDataLocation(prog, "unicorn"); if (!piglit_check_gl_error(GL_NO_ERROR)) piglit_report_result(PIGLIT_FAIL); if (loc != -1) { fprintf(stderr, "Expected location = -1, got %d\n", loc); piglit_report_result(PIGLIT_FAIL); } printf("Binding `unicorn' to a conflicting location...\n"); glBindFragDataLocation(prog, 0, "v"); if (!piglit_check_gl_error(GL_NO_ERROR)) piglit_report_result(PIGLIT_FAIL); glBindFragDataLocation(prog, 0, "unicorn"); if (!piglit_check_gl_error(GL_NO_ERROR)) piglit_report_result(PIGLIT_FAIL); glLinkProgram(prog); if (!piglit_check_gl_error(GL_NO_ERROR)) piglit_report_result(PIGLIT_FAIL); if (!piglit_link_check_status(prog)) { fprintf(stderr, "Linking failed when it should have been " "successful.\n"); piglit_report_result(PIGLIT_FAIL); } loc = glGetFragDataLocation(prog, "unicorn"); if (!piglit_check_gl_error(GL_NO_ERROR)) piglit_report_result(PIGLIT_FAIL); if (loc != -1) { fprintf(stderr, "Expected location = -1, got %d\n", loc); piglit_report_result(PIGLIT_FAIL); } piglit_report_result(PIGLIT_PASS); }
/*! adds a shader object */ shader_object* shader::add_shader_src(const string& identifier, const string& option, ext::GLSL_VERSION glsl_version, const char* vs_text, const char* gs_text, const char* fs_text) { // success flag (if it's 1 (true), we successfully created a shader object) int success; GLchar info_log[A2E_SHADER_LOG_SIZE]; if(gs_text != nullptr && strcmp(gs_text, "") == 0) gs_text = nullptr; // create a new shader object if none exists for this identifier if(shaders.count(identifier) == 0) { shaders[identifier] = new shader_object(identifier); } // add a new program object to this shader shaders[identifier]->programs.push_back(new shader_object::internal_shader_object()); if(option != "") { shaders[identifier]->options[option] = shaders[identifier]->programs.back(); } shader_object::internal_shader_object& shd_obj = *shaders[identifier]->programs.back(); shaders[identifier]->glsl_version = std::max(shaders[identifier]->glsl_version, glsl_version); // create the vertex shader object shd_obj.vertex_shader = glCreateShader(GL_VERTEX_SHADER); glShaderSource(shd_obj.vertex_shader, 1, (GLchar const**)&vs_text, nullptr); glCompileShader(shd_obj.vertex_shader); glGetShaderiv(shd_obj.vertex_shader, GL_COMPILE_STATUS, &success); if(!success) { glGetShaderInfoLog(shd_obj.vertex_shader, A2E_SHADER_LOG_SIZE, nullptr, info_log); log_error("Error in vertex shader \"%s/%s\" compilation!", identifier, option); log_pretty_print(info_log, vs_text); return 0; } #if !defined(FLOOR_IOS) // create the geometry shader object if(gs_text != nullptr && strcmp(gs_text, "") != 0) { shd_obj.geometry_shader = glCreateShader(GL_GEOMETRY_SHADER); glShaderSource(shd_obj.geometry_shader, 1, (GLchar const**)&gs_text, nullptr); glCompileShader(shd_obj.geometry_shader); glGetShaderiv(shd_obj.geometry_shader, GL_COMPILE_STATUS, &success); if(!success) { glGetShaderInfoLog(shd_obj.geometry_shader, A2E_SHADER_LOG_SIZE, nullptr, info_log); log_error("Error in geometry shader \"%s/%s\" compilation!", identifier, option); log_pretty_print(info_log, gs_text); return 0; } } else shd_obj.geometry_shader = 0; #else if(gs_text != nullptr && strcmp(gs_text, "") != 0) { log_error("geometry shaders are not supported in OpenGL ES 2.0 or 3.0!"); } shd_obj.geometry_shader = 0; #endif // create the fragment shader object shd_obj.fragment_shader = glCreateShader(GL_FRAGMENT_SHADER); glShaderSource(shd_obj.fragment_shader, 1, (GLchar const**)&fs_text, nullptr); glCompileShader(shd_obj.fragment_shader); glGetShaderiv(shd_obj.fragment_shader, GL_COMPILE_STATUS, &success); if(!success) { glGetShaderInfoLog(shd_obj.fragment_shader, A2E_SHADER_LOG_SIZE, nullptr, info_log); log_error("Error in fragment shader \"%s/%s\" compilation!", identifier, option); log_pretty_print(info_log, fs_text); return 0; } // create the program object shd_obj.program = glCreateProgram(); // attach the vertex and fragment shader progam to it glAttachShader(shd_obj.program, shd_obj.vertex_shader); glAttachShader(shd_obj.program, shd_obj.fragment_shader); if(gs_text != nullptr) { glAttachShader(shd_obj.program, shd_obj.geometry_shader); } // WIP: program binary #if defined(A2E_DEBUG_PROGRAM_BINARY) #if defined(__APPLE__) { fstream progcode_vs("/tmp/a2e_shd_code_vs.glsl", fstream::out); progcode_vs << vs_text << endl; progcode_vs.close(); if(shd_obj.geometry_shader != 0) { fstream progcode_gs("/tmp/a2e_shd_code_gs.glsl", fstream::out); progcode_gs << gs_text << endl; progcode_gs.close(); } fstream progcode_fs("/tmp/a2e_shd_code_fs.glsl", fstream::out); progcode_fs << fs_text << endl; progcode_fs.close(); string output_vs = "", output_gs = "", output_fs = ""; core::system("cgc -profile gp4vp -strict -oglsl /tmp/a2e_shd_code_vs.glsl 2>&1", output_vs); if(shd_obj.geometry_shader != 0) { core::system("cgc -profile gp4gp -strict -oglsl -po POINT /tmp/a2e_shd_code_gs.glsl 2>&1", output_gs); } core::system("cgc -profile gp4fp -strict -oglsl /tmp/a2e_shd_code_fs.glsl 2>&1", output_fs); system("rm /tmp/a2e_shd_code_vs.glsl"); if(shd_obj.geometry_shader != 0) { system("rm /tmp/a2e_shd_code_gs.glsl"); } system("rm /tmp/a2e_shd_code_fs.glsl"); // shader_debug::add(identifier, option, output_vs, output_gs, output_fs); } #else if(exts->is_ext_supported("GL_ARB_get_program_binary")) glProgramParameteri(shd_obj.program, GL_PROGRAM_BINARY_RETRIEVABLE_HINT, GL_TRUE); #endif #endif // now link the program object glLinkProgram(shd_obj.program); glGetProgramiv(shd_obj.program, GL_LINK_STATUS, &success); if(!success) { glGetProgramInfoLog(shd_obj.program, A2E_SHADER_LOG_SIZE, nullptr, info_log); log_error("Error in program \"%s/%s\" linkage!\nInfo log: %s", identifier, option, info_log); return 0; } glUseProgram(shd_obj.program); // bind frag data locations (frag_color, frag_color_2, frag_color_3, ...) bool fd_relink = false; #if !defined(FLOOR_IOS) const unsigned int max_draw_buffers = exts->get_max_draw_buffers(); for(unsigned int i = 0; i < max_draw_buffers; i++) { string name = "frag_color"; if(i >= 1) name += "_"+to_string(i+1); const GLint location = glGetFragDataLocation(shd_obj.program, name.c_str()); // check if the frag color exists and must be bound to a different location if(location >= 0 && i != (GLuint)location) { // if so, bind it to the correct location glBindFragDataLocation(shd_obj.program, i, name.c_str()); fd_relink = true; } } #else // NOTE: MRTs are not support in OpenGL ES 2.0 // in OpenGL ES 3.0 the locations are already set in the shader #endif if(fd_relink) { // program must be linked again after the frag data locations were modified // (double-linkage sucks, but there's no other way in opengl 3.2 ...) glLinkProgram(shd_obj.program); } // WIP: program binary #if defined(A2E_DEBUG_PROGRAM_BINARY) #if !defined(__APPLE__) if(exts->is_ext_supported("GL_ARB_get_program_binary")) { GLint binary_length = 0; glGetProgramiv(shd_obj.program, GL_PROGRAM_BINARY_LENGTH, &binary_length); unsigned char* binary = new unsigned char[binary_length]; GLenum binary_format = 0; glGetProgramBinary(shd_obj.program, binary_length, nullptr, &binary_format, binary); string binary_fname = "shader_binary_"+identifier+"_"+to_string(shaders[identifier]->programs.size()-1)+".dat"; f->open_file(binary_fname.c_str(), file_io::OT_WRITE_BINARY); f->write_block((const char*)binary, binary_length, false); f->close_file(); delete [] binary; } #endif #endif // grab number and names of all attributes and uniforms and get their locations (needs to be done before validation, b/c we have to set sampler locations) GLint attr_count = 0, uni_count = 0, max_attr_len = 0, max_uni_len = 0; GLint var_location = 0; GLint var_size = 0; GLenum var_type = 0; glGetProgramiv(shd_obj.program, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &max_attr_len); glGetProgramiv(shd_obj.program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &max_uni_len); glGetProgramiv(shd_obj.program, GL_ACTIVE_ATTRIBUTES, &attr_count); glGetProgramiv(shd_obj.program, GL_ACTIVE_UNIFORMS, &uni_count); max_attr_len+=2; max_uni_len+=2; #if !defined(FLOOR_IOS) || defined(PLATFORM_X64) GLint uni_block_count = 0, max_uni_block_len = 0; glGetProgramiv(shd_obj.program, GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH, &max_uni_block_len); glGetProgramiv(shd_obj.program, GL_ACTIVE_UNIFORM_BLOCKS, &uni_block_count); max_uni_block_len+=2; #endif // note: this may report weird attribute/uniform names (and locations), if uniforms/attributes are optimized away by the compiler bool print_debug_info = false; //if(identifier == "SIMPLE") { /*if(identifier == "FONT") { print_debug_info = true; cout << endl << "## " << identifier << "::" << option << endl; }*/ GLchar* attr_name = new GLchar[(size_t)max_attr_len]; if(print_debug_info) log_undecorated("## shader: %s", identifier); if(print_debug_info) log_undecorated("GL_ACTIVE_ATTRIBUTES: %u", attr_count); for(GLuint attr = 0; attr < (GLuint)attr_count; attr++) { memset(attr_name, 0, (size_t)max_attr_len); glGetActiveAttrib(shd_obj.program, attr, max_attr_len-1, nullptr, &var_size, &var_type, attr_name); var_location = glGetAttribLocation(shd_obj.program, attr_name); if(var_location < 0) { if(print_debug_info) log_error("Warning: could not get location for attribute \"%s\" in shader #%s/%s!", attr_name, identifier, option); continue; } if(print_debug_info) log_undecorated("attribute #%u: %s", var_location, attr_name); string attribute_name = attr_name; if(attribute_name.find("[") != string::npos) attribute_name = attribute_name.substr(0, attribute_name.find("[")); shd_obj.attributes.insert(make_pair(attribute_name, shader_object::internal_shader_object::shader_variable((size_t)var_location, (size_t)var_size, var_type))); } delete [] attr_name; GLchar* uni_name = new GLchar[(size_t)max_uni_len]; if(print_debug_info) log_undecorated("GL_ACTIVE_UNIFORMS: %u", uni_count); for(GLuint uniform = 0; uniform < (GLuint)uni_count; uniform++) { memset(uni_name, 0, (size_t)max_uni_len); glGetActiveUniform(shd_obj.program, uniform, max_uni_len-1, nullptr, &var_size, &var_type, uni_name); var_location = glGetUniformLocation(shd_obj.program, uni_name); if(var_location < 0) { if(print_debug_info) log_error("Warning: could not get location for uniform \"%s\" in shader #%s/%s!", uni_name, identifier, option); continue; } if(print_debug_info) log_undecorated("uniform #%u: %s", var_location, uni_name); string uniform_name = uni_name; if(uniform_name.find("[") != string::npos) uniform_name = uniform_name.substr(0, uniform_name.find("[")); shd_obj.uniforms.insert(make_pair(uniform_name, shader_object::internal_shader_object::shader_variable((size_t)var_location, (size_t)var_size, var_type))); // if the uniform is a sampler, add it to the sampler mapping (with increasing id/num) if(shader_class::is_gl_sampler_type(var_type)) { shd_obj.samplers.insert(make_pair(uniform_name, shd_obj.samplers.size())); // while we are at it, also set the sampler location to a dummy value (this has to be done to satisfy program validation) glUniform1i(var_location, (GLint)shd_obj.samplers.size()-1); } } delete [] uni_name; #if !defined(FLOOR_IOS) || defined(PLATFORM_X64) GLchar* uni_block_name = new GLchar[(size_t)max_uni_block_len]; if(print_debug_info) log_undecorated("GL_ACTIVE_UNIFORM_BLOCKS: %u", uni_block_count); for(GLuint block = 0; block < (GLuint)uni_block_count; block++) { memset(uni_block_name, 0, (size_t)max_uni_block_len); glGetActiveUniformBlockName(shd_obj.program, (GLuint)block, max_uni_block_len-1, nullptr, uni_block_name); GLuint block_index = glGetUniformBlockIndex(shd_obj.program, uni_block_name); if(block_index == GL_INVALID_INDEX) { if(print_debug_info) log_error("Warning: could not get index for uniform block \"%s\" in shader #%s/%s!", uni_block_name, identifier, option); continue; } GLint data_size = 0; glGetActiveUniformBlockiv(shd_obj.program, block_index, GL_UNIFORM_BLOCK_DATA_SIZE, &data_size); if(print_debug_info) log_undecorated("uniform block #%u (size: %u): %s", block_index, data_size, uni_block_name); const string uniform_block_name = uni_block_name; shd_obj.blocks.insert(make_pair(uniform_block_name, shader_object::internal_shader_object::shader_variable(block_index, (size_t)data_size, GL_UNIFORM_BUFFER))); // TODO: handle samplers? } delete [] uni_block_name; #endif // validate the program object glValidateProgram(shd_obj.program); glGetProgramiv(shd_obj.program, GL_VALIDATE_STATUS, &success); if(!success) { glGetProgramInfoLog(shd_obj.program, A2E_SHADER_LOG_SIZE, nullptr, info_log); log_error("Error in program \"%s/%s\" validation!\nInfo log: %s", identifier, option, info_log); return 0; } else { glGetProgramInfoLog(shd_obj.program, A2E_SHADER_LOG_SIZE, nullptr, info_log); // check if shader will run in software (if so, print out a debug message) if(strstr((const char*)info_log, (const char*)"software") != nullptr) { log_debug("program \"%s/%s\" validation: %s", identifier, option, info_log); } } // glUseProgram(0); return shaders[identifier]; }