X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=source%2Fcore%2Fprogram.cpp;h=789fa32473392d75a0bd34a13aac7208ddf14637;hb=c93e0613e96ec6817e26b533e90dc49d45787941;hp=2a34feb32706c161c602a151c7217d47955aa4d2;hpb=dccad64b2ec82249d850b9745614042171499972;p=libs%2Fgl.git diff --git a/source/core/program.cpp b/source/core/program.cpp index 2a34feb3..789fa324 100644 --- a/source/core/program.cpp +++ b/source/core/program.cpp @@ -35,7 +35,7 @@ Program::Program(const std::string &source) { init(); - Module mod; + GlslModule mod; mod.set_source(source); add_stages(mod); @@ -55,6 +55,13 @@ Program::Program(const string &vert, const string &frag) link(); } +Program::Program(const Module &mod, const map &spec_values) +{ + init(); + add_stages(mod, spec_values); + link(); +} + void Program::init() { static Require _req(ARB_shader_objects); @@ -66,45 +73,63 @@ void Program::init() Program::~Program() { - for(vector::iterator i=shader_ids.begin(); i!=shader_ids.end(); ++i) + for(vector::iterator i=stage_ids.begin(); i!=stage_ids.end(); ++i) glDeleteShader(*i); glDeleteProgram(id); } -void Program::add_stages(const Module &mod) +void Program::add_stages(const Module &mod, const map &spec_values) +{ + switch(mod.get_format()) + { + case Module::GLSL: return add_glsl_stages(static_cast(mod), spec_values); + default: throw invalid_argument("Program::add_stages"); + } +} + +unsigned Program::add_stage(GLenum type) +{ + switch(type) + { + case GL_VERTEX_SHADER: { static Require _req(ARB_vertex_shader); } break; + case GL_GEOMETRY_SHADER: { static Require _req(ARB_geometry_shader4); } break; + case GL_FRAGMENT_SHADER: { static Require _req(ARB_fragment_shader); } break; + default: throw invalid_argument("Program::add_stage"); + } + + unsigned stage_id = glCreateShader(type); + stage_ids.push_back(stage_id); + glAttachShader(id, stage_id); + + return stage_id; +} + +void Program::add_glsl_stages(const GlslModule &mod, const map &spec_values) { module = &mod; SL::Compiler compiler; - compiler.set_source(module->get_prepared_source(), ""); + compiler.set_source(mod.get_prepared_source(), ""); + compiler.specialize(spec_values); compiler.compile(SL::Compiler::PROGRAM); +#ifdef DEBUG + string diagnostics = compiler.get_diagnostics(); + if(!diagnostics.empty()) + IO::print("Program diagnostics:\n%s\n", diagnostics); +#endif vector stages = compiler.get_stages(); for(vector::const_iterator i=stages.begin(); i!=stages.end(); ++i) { - GLenum type; + unsigned stage_id = 0; switch(*i) { - case SL::Stage::VERTEX: - { static Require _req(ARB_vertex_shader); } - type = GL_VERTEX_SHADER; - break; - case SL::Stage::GEOMETRY: - { static Require _req(ARB_geometry_shader4); } - type = GL_GEOMETRY_SHADER; - break; - case SL::Stage::FRAGMENT: - { static Require _req(ARB_fragment_shader); } - type = GL_FRAGMENT_SHADER; - break; - default: - throw invalid_operation("Program::add_stages"); + 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; + default: throw invalid_operation("Program::add_glsl_stages"); } - unsigned stage_id = glCreateShader(type); - shader_ids.push_back(stage_id); - glAttachShader(id, stage_id); - string stage_src = compiler.get_stage_glsl(*i); const char *src_ptr = stage_src.data(); int src_len = stage_src.size(); @@ -123,9 +148,31 @@ void Program::add_stages(const Module &mod) for(map::const_iterator j=frag_outs.begin(); j!=frag_outs.end(); ++j) glBindFragDataLocation(id, j->second, j->first.c_str()); } + + compile_glsl_stage(stage_id); } } +void Program::compile_glsl_stage(unsigned stage_id) +{ + glCompileShader(stage_id); + bool compiled = get_shader_i(stage_id, GL_COMPILE_STATUS); + + GLsizei info_log_len = get_shader_i(stage_id, GL_INFO_LOG_LENGTH); + string info_log(info_log_len+1, 0); + glGetShaderInfoLog(stage_id, info_log_len+1, &info_log_len, &info_log[0]); + info_log.erase(info_log_len); + if(module && module->get_format()==Module::GLSL) + info_log = static_cast(module)->get_source_map().translate_errors(info_log); + + if(!compiled) + throw compile_error(info_log); +#ifdef DEBUG + if(!info_log.empty()) + IO::print("Shader compile info log:\n%s", info_log); +#endif +} + #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wdeprecated-declarations" void Program::attach_shader(Shader &shader) @@ -133,7 +180,8 @@ void Program::attach_shader(Shader &shader) unsigned shader_id = shader.steal_id(); if(!shader_id) throw invalid_argument("Program::attach_shader"); - shader_ids.push_back(shader_id); + stage_ids.push_back(shader_id); + compile_glsl_stage(shader_id); } void Program::attach_shader_owned(Shader *shader) @@ -158,9 +206,9 @@ void Program::bind_attribute(unsigned index, const string &name) glBindAttribLocation(id, index, name.c_str()); } -void Program::bind_attribute(VertexComponent comp, const string &name) +void Program::bind_attribute(VertexAttribute attr, const string &name) { - bind_attribute(get_component_type(comp), name); + bind_attribute(get_attribute_semantic(attr), name); } void Program::bind_fragment_data(unsigned index, const string &name) @@ -172,25 +220,6 @@ void Program::bind_fragment_data(unsigned index, const string &name) void Program::link() { - for(vector::const_iterator i=shader_ids.begin(); i!=shader_ids.end(); ++i) - { - glCompileShader(*i); - bool compiled = get_shader_i(*i, GL_COMPILE_STATUS); - - GLsizei info_log_len = get_shader_i(*i, GL_INFO_LOG_LENGTH); - string info_log(info_log_len+1, 0); - glGetShaderInfoLog(*i, info_log_len+1, &info_log_len, &info_log[0]); - info_log.erase(info_log_len); - info_log = module->get_source_map().translate_errors(info_log); - - if(!compiled) - throw compile_error(info_log); -#ifdef DEBUG - if(!info_log.empty()) - IO::print("Shader compile info log:\n%s", info_log); -#endif - } - uniforms.clear(); glLinkProgram(id); @@ -200,7 +229,8 @@ void Program::link() string info_log(info_log_len+1, 0); glGetProgramInfoLog(id, info_log_len+1, &info_log_len, &info_log[0]); info_log.erase(info_log_len); - info_log = module->get_source_map().translate_errors(info_log); + if(module && module->get_format()==Module::GLSL) + info_log = static_cast(module)->get_source_map().translate_errors(info_log); if(!linked) throw compile_error(info_log); @@ -479,7 +509,10 @@ void Program::Loader::finish() void Program::Loader::module(const string &n) { - obj.add_stages(get_collection().get(n)); + map spec_values; + SpecializationLoader ldr(spec_values); + load_sub_with(ldr); + obj.add_stages(get_collection().get(n), spec_values); } #pragma GCC diagnostic push @@ -505,5 +538,30 @@ void Program::Loader::vertex_shader(const string &src) } #pragma GCC diagnostic pop + +DataFile::Loader::ActionMap Program::SpecializationLoader::shared_actions; + +Program::SpecializationLoader::SpecializationLoader(map &sv): + spec_values(sv) +{ + set_actions(shared_actions); +} + +void Program::SpecializationLoader::init_actions() +{ + add("specialize", &SpecializationLoader::specialize_bool); + add("specialize", &SpecializationLoader::specialize_int); +} + +void Program::SpecializationLoader::specialize_bool(const string &name, bool value) +{ + spec_values[name] = value; +} + +void Program::SpecializationLoader::specialize_int(const string &name, int value) +{ + spec_values[name] = value; +} + } // namespace GL } // namespace Msp