X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=source%2Fcore%2Fprogram.cpp;h=ed2455f86aa315ec79f97bf2860563f7d40cc243;hb=e92de029768eef5f0fd744329e589161b46d0762;hp=038c031393ae33a5fcaeee27a1c00910f5da0c3c;hpb=52335491d6e3b568f2b19bd0ec15c8d7b5f011da;p=libs%2Fgl.git diff --git a/source/core/program.cpp b/source/core/program.cpp index 038c0313..ed2455f8 100644 --- a/source/core/program.cpp +++ b/source/core/program.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -70,6 +71,7 @@ void Program::init() static Require _req(ARB_shader_objects); id = glCreateProgram(); + fill(stage_ids, stage_ids+MAX_STAGES, 0); module = 0; transient = 0; linked = false; @@ -77,14 +79,15 @@ void Program::init() Program::~Program() { - for(vector::iterator i=stage_ids.begin(); i!=stage_ids.end(); ++i) - glDeleteShader(*i); + for(unsigned i=0; i &spec_values) { - if(!stage_ids.empty()) + if(has_stages()) throw invalid_operation("Program::add_stages"); switch(mod.get_format()) @@ -95,20 +98,37 @@ void Program::add_stages(const Module &mod, const map &spec_values) } } -unsigned Program::add_stage(GLenum type) +bool Program::has_stages() const { + for(unsigned i=0; i &spe unsigned stage_id = 0; switch(*i) { - case SL::Stage::VERTEX: stage_id = add_stage(GL_VERTEX_SHADER); break; - case SL::Stage::GEOMETRY: stage_id = add_stage(GL_GEOMETRY_SHADER); break; - case SL::Stage::FRAGMENT: stage_id = add_stage(GL_FRAGMENT_SHADER); break; + case SL::Stage::VERTEX: stage_id = add_stage(VERTEX); break; + case SL::Stage::GEOMETRY: stage_id = add_stage(GEOMETRY); break; + case SL::Stage::FRAGMENT: stage_id = add_stage(FRAGMENT); break; default: throw invalid_operation("Program::add_glsl_stages"); } @@ -194,25 +214,24 @@ void Program::add_spirv_stages(const SpirVModule &mod, const map &s module = &mod; const vector &entry_points = mod.get_entry_points(); - std::set stages; + unsigned n_stages = 0; + unsigned used_stage_ids[MAX_STAGES]; for(vector::const_iterator i=entry_points.begin(); i!=entry_points.end(); ++i) { - if(stages.count(i->stage)) - throw invalid_argument("Program::add_spirv_stages"); - + unsigned stage_id = 0; switch(i->stage) { - case SpirVModule::VERTEX: add_stage(GL_VERTEX_SHADER); break; - case SpirVModule::GEOMETRY: add_stage(GL_GEOMETRY_SHADER); break; - case SpirVModule::FRAGMENT: add_stage(GL_FRAGMENT_SHADER); break; + case SpirVModule::VERTEX: stage_id = add_stage(VERTEX); break; + case SpirVModule::GEOMETRY: stage_id = add_stage(GEOMETRY); break; + case SpirVModule::FRAGMENT: stage_id = add_stage(FRAGMENT); break; default: throw invalid_operation("Program::add_spirv_stages"); } - stages.insert(i->stage); + used_stage_ids[n_stages++] = stage_id; } const vector &code = mod.get_code(); - glShaderBinary(stage_ids.size(), &stage_ids[0], GL_SHADER_BINARY_FORMAT_SPIR_V, &code[0], code.size()*4); + glShaderBinary(n_stages, used_stage_ids, GL_SHADER_BINARY_FORMAT_SPIR_V, &code[0], code.size()*4); if(!spec_values.empty() && !transient) transient = new TransientData; @@ -234,8 +253,9 @@ void Program::add_spirv_stages(const SpirVModule &mod, const map &s } vector::const_iterator j=entry_points.begin(); - for(vector::const_iterator i=stage_ids.begin(); i!=stage_ids.end(); ++i, ++j) - glSpecializeShader(*i, j->name.c_str(), spec_id_array.size(), &spec_id_array[0], &spec_value_array[0]); + for(unsigned i=0; iname.c_str(), spec_id_array.size(), &spec_id_array[0], &spec_value_array[0]); } #pragma GCC diagnostic push @@ -245,7 +265,17 @@ void Program::attach_shader(Shader &shader) unsigned shader_id = shader.steal_id(); if(!shader_id) throw invalid_argument("Program::attach_shader"); - stage_ids.push_back(shader_id); + + int type; + glGetShaderiv(shader_id, GL_SHADER_TYPE, &type); + switch(type) + { + case GL_VERTEX_SHADER: stage_ids[VERTEX] = shader_id; break; + case GL_GEOMETRY_SHADER: stage_ids[GEOMETRY] = shader_id; break; + case GL_FRAGMENT_SHADER: stage_ids[FRAGMENT] = shader_id; break; + } + + glAttachShader(id, shader_id); compile_glsl_stage(shader_id); } @@ -285,7 +315,7 @@ void Program::bind_fragment_data(unsigned index, const string &name) void Program::link() { - if(stage_ids.empty()) + if(!has_stages()) throw invalid_operation("Program::link"); uniforms.clear(); @@ -325,7 +355,8 @@ void Program::link() } } - Conditional _bind(!ARB_separate_shader_objects, this); + if(!ARB_separate_shader_objects) + glUseProgram(id); for(map::const_iterator i=transient->textures.begin(); i!=transient->textures.end(); ++i) { int location = get_uniform_location(i->first); @@ -724,23 +755,31 @@ int Program::get_attribute_location(const string &name) const return i!=attributes.end() && i->name==name ? i->location : -1; } -void Program::bind() const +void Program::set_debug_name(const string &name) { - if(!linked) - throw invalid_operation("Program::bind"); - - if(!set_current(this)) - return; - - glUseProgram(id); +#ifdef DEBUG + debug_name = name; + if(KHR_debug) + { + glObjectLabel(GL_PROGRAM, id, name.size(), name.c_str()); + for(unsigned i=0; i(i)); + } +#else + (void)name; +#endif } -void Program::unbind() +void Program::set_stage_debug_name(unsigned stage_id, Stage type) { - if(!set_current(0)) - return; - - glUseProgram(0); +#ifdef DEBUG + static const char *const suffixes[] = { " [VS]", " [GS]", " [FS]" }; + string name = debug_name+suffixes[type]; + glObjectLabel(GL_SHADER, stage_id, name.size(), name.c_str()); +#else + (void)stage_id; (void)type; +#endif }