X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=source%2Fbackends%2Fopengl%2Fprogram_backend.cpp;h=398d35ce7a6c364aba56634cb7aa0be67ad174d6;hb=cebf1330ef6773b7b4496dc279ec02a7ca4351bb;hp=b902db5f6a99043df53af71632230ff9eed263e1;hpb=f82ef715f0d7e1e7d0b93be4b7b89c8ce6bba40b;p=libs%2Fgl.git diff --git a/source/backends/opengl/program_backend.cpp b/source/backends/opengl/program_backend.cpp index b902db5f..398d35ce 100644 --- a/source/backends/opengl/program_backend.cpp +++ b/source/backends/opengl/program_backend.cpp @@ -1,5 +1,6 @@ #include #include +#include #include #include #include @@ -12,6 +13,7 @@ #include #include #include +#include "device.h" #include "error.h" #include "program.h" #include "program_backend.h" @@ -45,6 +47,17 @@ OpenGLProgram::OpenGLProgram() id = glCreateProgram(); } +OpenGLProgram::OpenGLProgram(OpenGLProgram &&other): + id(other.id), + linked(other.linked), + uniform_calls(move(other.uniform_calls)), + debug_name(move(other.debug_name)) +{ + move(other.stage_ids, other.stage_ids+MAX_STAGES, stage_ids); + other.id = 0; + fill(other.stage_ids, other.stage_ids+MAX_STAGES, 0); +} + OpenGLProgram::~OpenGLProgram() { for(unsigned i=0; i &spec_values, TransientData &transient) +void OpenGLProgram::add_glsl_stages(const GlslModule &mod, const map &spec_values) { - SL::Compiler compiler; + SL::Compiler compiler(Device::get_current().get_info().glsl_features); compiler.set_source(mod.get_prepared_source(), ""); compiler.specialize(spec_values); compiler.compile(SL::Compiler::PROGRAM); @@ -101,7 +115,7 @@ void OpenGLProgram::add_glsl_stages(const GlslModule &mod, const map stages = compiler.get_stages(); if(stages.empty()) - throw invalid_argument("Program::add_glsl_stages"); + throw invalid_argument("OpenGLProgram::add_glsl_stages"); for(SL::Stage::Type st: stages) { @@ -111,7 +125,8 @@ void OpenGLProgram::add_glsl_stages(const GlslModule &mod, const map(this)->reflect_data; rd.n_clip_distances = compiler.get_n_clip_distances(); + + link(mod); + query_uniforms(); + query_attributes(); + if(is_compute()) + { + int wg_size[3]; + glGetProgramiv(id, GL_COMPUTE_WORK_GROUP_SIZE, wg_size); + rd.compute_wg_size = LinAl::Vector(wg_size[0], wg_size[1], wg_size[2]); + } + + const map &block_bindings = compiler.get_uniform_block_bindings(); + if(!block_bindings.empty()) + { + for(unsigned i=0; isecond); + rd.uniform_blocks[i].bind_point = j->second; + } + } + } + + const map &tex_bindings = compiler.get_texture_bindings(); + if(!tex_bindings.empty()) + { + if(!ARB_separate_shader_objects) + glUseProgram(id); + for(const auto &kvp: tex_bindings) + { + int location = static_cast(this)->get_uniform_location(kvp.first); + if(location>=0) + { + if(ARB_separate_shader_objects) + glProgramUniform1i(id, location, kvp.second); + else + glUniform1i(location, kvp.second); + } + } + } } void OpenGLProgram::compile_glsl_stage(const GlslModule &mod, unsigned stage_id) @@ -162,7 +216,7 @@ void OpenGLProgram::compile_glsl_stage(const GlslModule &mod, unsigned stage_id) #endif } -void OpenGLProgram::add_spirv_stages(const SpirVModule &mod, const map &spec_values, TransientData &transient) +void OpenGLProgram::add_spirv_stages(const SpirVModule &mod, const map &spec_values) { static Require _req(ARB_gl_spirv); static Require _req2(ARB_ES2_compatibility); @@ -177,14 +231,15 @@ void OpenGLProgram::add_spirv_stages(const SpirVModule &mod, const map &code = mod.get_code(); glShaderBinary(n_stages, used_stage_ids, GL_SHADER_BINARY_FORMAT_SPIR_V, &code[0], code.size()*4); @@ -201,7 +256,6 @@ void OpenGLProgram::add_spirv_stages(const SpirVModule &mod, const mapsecond); - transient.spec_values[c.constant_id] = i->second; } } @@ -209,9 +263,11 @@ void OpenGLProgram::add_spirv_stages(const SpirVModule &mod, const mapname.c_str(), spec_id_array.size(), &spec_id_array[0], &spec_value_array[0]); + + link(mod); } -void OpenGLProgram::finalize(const Module &mod) +void OpenGLProgram::link(const Module &mod) { glLinkProgram(id); int status = 0; @@ -256,7 +312,7 @@ void OpenGLProgram::query_uniforms() if(len>3 && !strcmp(name+len-3, "[0]")) name[len-3] = 0; - rd.uniforms.push_back(ReflectData::UniformInfo()); + rd.uniforms.emplace_back(); ReflectData::UniformInfo &info = rd.uniforms.back(); info.name = name; info.tag = name; @@ -278,7 +334,7 @@ void OpenGLProgram::query_uniforms() query_uniform_blocks(uniforms_by_index); } - rd.uniform_blocks.push_back(ReflectData::UniformBlockInfo()); + rd.uniform_blocks.emplace_back(); ReflectData::UniformBlockInfo &default_block = rd.uniform_blocks.back(); for(ReflectData::UniformInfo &u: rd.uniforms) @@ -291,49 +347,8 @@ void OpenGLProgram::query_uniforms() u.matrix_stride = get_type_size(get_matrix_column_type(u.type)); default_block.uniforms.push_back(&u); - if(u.location>=0) - { - UniformCall::FuncPtr func = 0; - if(is_image(u.type)) - glGetUniformiv(id, u.location, &u.binding); - else if(u.type==FLOAT) - func = &uniform_wrapper; - else if(u.type==FLOAT_VEC2) - func = &uniform_wrapper; - else if(u.type==FLOAT_VEC3) - func = &uniform_wrapper; - else if(u.type==FLOAT_VEC4) - func = &uniform_wrapper; - else if(u.type==INT) - func = &uniform_wrapper; - else if(u.type==INT_VEC2) - func = &uniform_wrapper; - else if(u.type==INT_VEC3) - func = &uniform_wrapper; - else if(u.type==INT_VEC4) - func = &uniform_wrapper; - else if(u.type==FLOAT_MAT2) - func = &uniform_matrix_wrapper; - else if(u.type==FLOAT_MAT3) - func = &uniform_matrix_wrapper; - else if(u.type==FLOAT_MAT4) - func = &uniform_matrix_wrapper; - else if(u.type==FLOAT_MAT2x3) - func = &uniform_matrix_wrapper; - else if(u.type==FLOAT_MAT3x2) - func = &uniform_matrix_wrapper; - else if(u.type==FLOAT_MAT2x4) - func = &uniform_matrix_wrapper; - else if(u.type==FLOAT_MAT4x2) - func = &uniform_matrix_wrapper; - else if(u.type==FLOAT_MAT3x4) - func = &uniform_matrix_wrapper; - else if(u.type==FLOAT_MAT4x3) - func = &uniform_matrix_wrapper; - - if(func) - uniform_calls.push_back(UniformCall(u.location, u.array_size, func)); - } + if(is_image(u.type) && u.location>=0) + glGetUniformiv(id, u.location, &u.binding); } default_block.sort_uniforms(); @@ -354,7 +369,7 @@ void OpenGLProgram::query_uniform_blocks(const vectorblock = &info; } @@ -431,7 +446,7 @@ void OpenGLProgram::query_attributes() if(len>3 && !strcmp(name+len-3, "[0]")) name[len-3] = 0; - rd.attributes.push_back(ReflectData::AttributeInfo()); + rd.attributes.emplace_back(); ReflectData::AttributeInfo &info = rd.attributes.back(); info.name = name; info.location = glGetAttribLocation(id, name); @@ -439,33 +454,72 @@ void OpenGLProgram::query_attributes() info.type = from_gl_type(type); } } + + sort_member(rd.attributes, &ReflectData::AttributeInfo::name); } -void OpenGLProgram::apply_bindings(const TransientData &transient) +void OpenGLProgram::finalize_uniforms() { ReflectData &rd = static_cast(this)->reflect_data; - for(unsigned i=0; iuniforms.empty()) { - auto j = transient.blocks.find(rd.uniform_blocks[i].name); - if(j!=transient.blocks.end()) - { - glUniformBlockBinding(id, i, j->second); - rd.uniform_blocks[i].bind_point = j->second; - } - } + for(const ReflectData::UniformInfo *u: i->uniforms) + if(u->location>=0) + { + UniformCall::FuncPtr func = 0; + if(u->type==FLOAT) + func = &uniform_wrapper; + else if(u->type==FLOAT_VEC2) + func = &uniform_wrapper; + else if(u->type==FLOAT_VEC3) + func = &uniform_wrapper; + else if(u->type==FLOAT_VEC4) + func = &uniform_wrapper; + else if(u->type==INT) + func = &uniform_wrapper; + else if(u->type==INT_VEC2) + func = &uniform_wrapper; + else if(u->type==INT_VEC3) + func = &uniform_wrapper; + else if(u->type==INT_VEC4) + func = &uniform_wrapper; + else if(u->type==UNSIGNED_INT) + func = &uniform_wrapper; + else if(u->type==UINT_VEC2) + func = &uniform_wrapper; + else if(u->type==UINT_VEC3) + func = &uniform_wrapper; + else if(u->type==UINT_VEC4) + func = &uniform_wrapper; + else if(u->type==FLOAT_MAT2) + func = &uniform_matrix_wrapper; + else if(u->type==FLOAT_MAT3) + func = &uniform_matrix_wrapper; + else if(u->type==FLOAT_MAT4) + func = &uniform_matrix_wrapper; + else if(u->type==FLOAT_MAT2x3) + func = &uniform_matrix_wrapper; + else if(u->type==FLOAT_MAT3x2) + func = &uniform_matrix_wrapper; + else if(u->type==FLOAT_MAT2x4) + func = &uniform_matrix_wrapper; + else if(u->type==FLOAT_MAT4x2) + func = &uniform_matrix_wrapper; + else if(u->type==FLOAT_MAT3x4) + func = &uniform_matrix_wrapper; + else if(u->type==FLOAT_MAT4x3) + func = &uniform_matrix_wrapper; - if(!ARB_separate_shader_objects) - glUseProgram(id); - for(const auto &kvp: transient.textures) - { - int location = static_cast(this)->get_uniform_location(kvp.first); - if(location>=0) + if(func) + uniform_calls.push_back(UniformCall(u->location, u->array_size, func)); + } + + if(i->data_size<=0) { - if(ARB_separate_shader_objects) - glProgramUniform1i(id, location, kvp.second); - else - glUniform1i(location, kvp.second); + const ReflectData::UniformInfo &last = *i->uniforms.back(); + i->data_size = last.location*16+last.array_size*get_type_size(last.type); } } } @@ -489,7 +543,7 @@ void OpenGLProgram::set_debug_name(const string &name) void OpenGLProgram::set_stage_debug_name(unsigned stage_id, Stage type) { #ifdef DEBUG - static const char *const suffixes[] = { " [VS]", " [GS]", " [FS]" }; + static const char *const suffixes[] = { " [VS]", " [GS]", " [FS]", " [CS]" }; string name = debug_name+suffixes[type]; glObjectLabel(GL_SHADER, stage_id, name.size(), name.c_str()); #else