X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=source%2Fprogram.cpp;h=729018a1a4b1edc69438d426c32426e82b19b09b;hb=01d2500733766710f4a11f49216a5b3dcc75a4a3;hp=7598bf1572adc036f7777fa8e9741c6086102689;hpb=101b961cbdcc3a2459bb7c12e3d8e6e5c320b94b;p=libs%2Fgl.git diff --git a/source/program.cpp b/source/program.cpp index 7598bf15..729018a1 100644 --- a/source/program.cpp +++ b/source/program.cpp @@ -1,10 +1,13 @@ #include +#include #include +#include #include #include "arb_shader_objects.h" +#include "arb_uniform_buffer_object.h" #include "arb_vertex_shader.h" +#include "buffer.h" #include "error.h" -#include "extension.h" #include "program.h" #include "shader.h" @@ -14,6 +17,7 @@ namespace { const char *standard_vertex_src[] = { + "s", "uniform int shadow_unit;\n", "n", "attribute vec3 tangent;\n", "n", "attribute vec3 binormal;\n", "t|n", "varying vec2 v_texcoord;\n", @@ -43,7 +47,7 @@ const char *standard_vertex_src[] = "p|en", "\tv_eye_dir = vec3(dot(eye_tangent, eye_dir), dot(eye_binormal, eye_dir), dot(eye_normal, eye_dir));\n", "p|e!n", "\tv_eye_dir = eye_dir;\n", "t|n", "\tv_texcoord = gl_MultiTexCoord0.xy;\n", - "s", "\tv_shadowcoord = vec3(dot(gl_EyePlaneS[3], eye_pos), dot(gl_EyePlaneT[3], eye_pos), dot(gl_EyePlaneR[3], eye_pos));\n", + "s", "\tv_shadowcoord = vec3(dot(gl_EyePlaneS[shadow_unit], eye_pos), dot(gl_EyePlaneT[shadow_unit], eye_pos), dot(gl_EyePlaneR[shadow_unit], eye_pos));\n", "!lm", "\tv_color = gl_Color;\n", 0, "}", 0, 0 @@ -75,9 +79,10 @@ const char *standard_fragment_src[] = "e", "\tvec4 reflection = textureCube(environment, n_normal*(dot(n_normal, v_eye_dir)*2.0)-v_eye_dir);\n", "t", "\tvec4 tex_sample = texture2D(texture, v_texcoord);\n", 0, "\tgl_FragColor.rgb = ", - "!t!l!m", "vec3(1.0)", + "!t!m", "vec3(1.0)", "t", "tex_sample.rgb", "l|mt", "*", + "l!m!t", "*", "!lm", "v_color.rgb", "l", "((l_diffuse", "lm", "*gl_FrontLightProduct[0].diffuse.rgb", @@ -90,10 +95,11 @@ const char *standard_fragment_src[] = "e", "+reflection.rgb*reflectivity", 0, ";\n", 0, "\tgl_FragColor.a = ", - "!m", "1.0", + "!t!m", "1.0", + "t", "tex_sample.a", + "tm", "*", "!lm", "v_color.a", "lm", "gl_FrontMaterial.diffuse.a", - "t", "*tex_sample.a", 0, ";\n", 0, "}\n", 0, 0 @@ -129,24 +135,24 @@ Program::Program(const string &vert, const string &frag) void Program::init() { - static RequireExtension _ext("GL_ARB_shader_objects"); + static Require _req(ARB_shader_objects); linked = false; - id = glCreateProgramObjectARB(); + id = glCreateProgram(); } Program::~Program() { - for(list::iterator i=owned_data.begin(); i!=owned_data.end(); ++i) + for(ShaderList::iterator i=owned_data.begin(); i!=owned_data.end(); ++i) delete *i; - glDeleteObjectARB(id); + glDeleteProgram(id); } void Program::attach_shader(Shader &shader) { if(find(shaders.begin(), shaders.end(), &shader)==shaders.end()) { - glAttachObjectARB(id, shader.get_id()); + glAttachShader(id, shader.get_id()); shaders.push_back(&shader); } } @@ -160,11 +166,11 @@ void Program::attach_shader_owned(Shader *shader) void Program::detach_shader(Shader &shader) { - list::iterator i = remove(shaders.begin(), shaders.end(), &shader); + ShaderList::iterator i = remove(shaders.begin(), shaders.end(), &shader); if(i!=shaders.end()) { shaders.erase(i, shaders.end()); - glDetachObjectARB(id, shader.get_id()); + glDetachShader(id, shader.get_id()); } } @@ -216,75 +222,161 @@ string Program::process_standard_source(const char **source, const string &flags void Program::bind_attribute(unsigned index, const string &name) { - static RequireExtension _ext("GL_ARB_vertex_shader"); - glBindAttribLocationARB(id, index, name.c_str()); + static Require _req(ARB_vertex_shader); + glBindAttribLocation(id, index, name.c_str()); } void Program::link() { - for(list::iterator i=shaders.begin(); i!=shaders.end(); ++i) + for(ShaderList::iterator i=shaders.begin(); i!=shaders.end(); ++i) if(!(*i)->is_compiled()) (*i)->compile(); uniforms.clear(); - glLinkProgramARB(id); + glLinkProgram(id); int value; - glGetObjectParameterivARB(id, GL_OBJECT_LINK_STATUS_ARB, &value); + glGetProgramiv(id, GL_LINK_STATUS, &value); if(!(linked = value)) throw compile_error(get_info_log()); - glGetObjectParameterivARB(id, GL_OBJECT_ACTIVE_UNIFORMS_ARB, &value); - for(int i=0; i uniforms_by_index(count); + for(unsigned i=0; i::const_iterator i = uniforms.begin(); i!=uniforms.end(); ++i) - if(i->second.location>=0) + if(ARB_uniform_buffer_object) + { + glGetProgramiv(id, GL_ACTIVE_UNIFORM_BLOCKS, &value); + count = value; + for(unsigned i=0; isecond.location, i->second.name, i->second.type); + char name[128]; + int len; + glGetActiveUniformBlockName(id, i, 128, &len, name); + UniformBlockInfo &info = uniform_blocks[name]; + info.name = name; + + glGetActiveUniformBlockiv(id, i, GL_UNIFORM_BLOCK_DATA_SIZE, &value); + info.data_size = value; + + glGetActiveUniformBlockiv(id, i, GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS, &value); + vector indices(value); + glGetActiveUniformBlockiv(id, i, GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES, &indices[0]); + for(vector::iterator j=indices.begin(); j!=indices.end(); ++j) + { + if(!uniforms_by_index[*j]) + throw logic_error("Program::link"); + info.uniforms.push_back(uniforms_by_index[*j]); + uniforms_by_index[*j]->block = &info; + } + + vector indices2(indices.begin(), indices.end()); + vector values(indices.size()); + glGetActiveUniformsiv(id, indices.size(), &indices2[0], GL_UNIFORM_OFFSET, &values[0]); + for(unsigned j=0; jlocation = values[j]; + + indices2.clear(); + for(vector::iterator j=indices.begin(); j!=indices.end(); ++j) + if(uniforms_by_index[*j]->size>1) + indices2.push_back(*j); + if(!indices2.empty()) + { + glGetActiveUniformsiv(id, indices2.size(), &indices2[0], GL_UNIFORM_ARRAY_STRIDE, &values[0]); + for(unsigned j=0; jarray_stride = values[j]; + } + + indices2.clear(); + for(vector::iterator j=indices.begin(); j!=indices.end(); ++j) + { + GLenum t = uniforms_by_index[*j]->type; + if(t==GL_FLOAT_MAT4 || t==GL_FLOAT_MAT3 || t==GL_FLOAT_MAT2 || + t==GL_FLOAT_MAT2x3 || t==GL_FLOAT_MAT2x4 || t==GL_FLOAT_MAT3x2 || + t==GL_FLOAT_MAT3x4 || t==GL_FLOAT_MAT4x2 || t==GL_FLOAT_MAT4x3) + indices2.push_back(*j); + } + if(!indices2.empty()) + { + glGetActiveUniformsiv(id, indices2.size(), &indices2[0], GL_UNIFORM_MATRIX_STRIDE, &values[0]); + for(unsigned j=0; jmatrix_stride = values[j]; + } + + sort(info.uniforms.begin(), info.uniforms.end(), uniform_location_compare); + info.layout_hash = compute_layout_hash(info.uniforms); + info.bind_point = info.layout_hash%BufferRange::get_n_uniform_buffer_bindings(); + glUniformBlockBinding(id, i, info.bind_point); } - uniform_layout_hash = hash32(layout_descriptor); + } + + vector blockless_uniforms; + for(UniformMap::iterator i=uniforms.begin(); i!=uniforms.end(); ++i) + if(!i->second.block) + { + i->second.location = glGetUniformLocation(id, i->second.name.c_str()); + blockless_uniforms.push_back(&i->second); + } + + uniform_layout_hash = compute_layout_hash(blockless_uniforms); +} + +unsigned Program::compute_layout_hash(const vector &uniforms) +{ + string layout_descriptor; + for(vector::const_iterator i = uniforms.begin(); i!=uniforms.end(); ++i) + layout_descriptor += format("%d:%s:%x:%d\n", (*i)->location, (*i)->name, (*i)->type, (*i)->size); + return hash32(layout_descriptor); +} + +bool Program::uniform_location_compare(const UniformInfo *uni1, const UniformInfo *uni2) +{ + return uni1->locationlocation; } string Program::get_info_log() const { GLsizei len = 0; - glGetObjectParameterivARB(id, GL_OBJECT_INFO_LOG_LENGTH_ARB, &len); + glGetProgramiv(id, GL_INFO_LOG_LENGTH, &len); char *buf = new char[len+1]; - glGetInfoLogARB(id, len+1, &len, buf); + glGetProgramInfoLog(id, len+1, &len, buf); string log(buf, len); delete[] buf; return log; } -void Program::bind() const +const Program::UniformBlockInfo &Program::get_uniform_block_info(const string &name) const { - if(!linked) - throw invalid_operation("Program::bind"); - - if(!set_current(this)) - return; + return get_item(uniform_blocks, name); +} - glUseProgramObjectARB(id); +const Program::UniformInfo &Program::get_uniform_info(const string &name) const +{ + return get_item(uniforms, name); } int Program::get_uniform_location(const string &n) const { - map::const_iterator i = uniforms.find(n); + UniformMap::const_iterator i = uniforms.find(n); if(i==uniforms.end()) { if(n[n.size()-1]==']') @@ -295,16 +387,27 @@ int Program::get_uniform_location(const string &n) const /* The requested name looks like an array. glGetActiveUniform only gives us the first element of the array, so try to look that up and add an offset. */ - int offset = lexical_cast(n.substr(open_bracket+1, n.size()-2-open_bracket)); + unsigned offset = lexical_cast(n.substr(open_bracket+1, n.size()-2-open_bracket)); i = uniforms.find(n.substr(0, open_bracket)+"[0]"); - if(i!=uniforms.end() && offsetsecond.size) + if(i!=uniforms.end() && !i->second.block && offsetsecond.size) return i->second.location+offset; } } return -1; } - return i->second.location; + return i->second.block ? -1 : i->second.location; +} + +void Program::bind() const +{ + if(!linked) + throw invalid_operation("Program::bind"); + + if(!set_current(this)) + return; + + glUseProgram(id); } void Program::unbind() @@ -312,7 +415,7 @@ void Program::unbind() if(!set_current(0)) return; - glUseProgramObjectARB(0); + glUseProgram(0); }