X-Git-Url: http://git.tdb.fi/?p=libs%2Fgl.git;a=blobdiff_plain;f=source%2Fbackends%2Fopengl%2Fprogram_backend.cpp;h=a9328488cedc9bc12b5399bf55d2b032771dd52a;hp=3b1c4293326fd1edfe21e3aa7806e2dde4597df0;hb=5871764de7aa23d2c40cac03ad9d07088fb57e06;hpb=160e9eea29bd10034733d59507fa1bcca36be401 diff --git a/source/backends/opengl/program_backend.cpp b/source/backends/opengl/program_backend.cpp index 3b1c4293..a9328488 100644 --- a/source/backends/opengl/program_backend.cpp +++ b/source/backends/opengl/program_backend.cpp @@ -12,6 +12,7 @@ #include #include #include +#include "device.h" #include "error.h" #include "program.h" #include "program_backend.h" @@ -38,13 +39,22 @@ void uniform_matrix_wrapper(unsigned index, unsigned count, const void *data) namespace Msp { namespace GL { -OpenGLProgram::OpenGLProgram(): - linked(false) +OpenGLProgram::OpenGLProgram() { static Require _req(ARB_shader_objects); id = glCreateProgram(); - fill(stage_ids, stage_ids+MAX_STAGES, 0); +} + +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() @@ -71,11 +81,11 @@ unsigned OpenGLProgram::add_stage(Stage type) case VERTEX: { static Require _req(ARB_vertex_shader); gl_type = GL_VERTEX_SHADER; } break; case GEOMETRY: { static Require _req(ARB_geometry_shader4); gl_type = GL_GEOMETRY_SHADER; } break; case FRAGMENT: { static Require _req(ARB_fragment_shader); gl_type = GL_FRAGMENT_SHADER; } break; - default: throw invalid_argument("Program::add_stage"); + default: throw invalid_argument("OpenGLProgram::add_stage"); } if(stage_ids[type]) - throw invalid_operation("Program::add_stage"); + throw invalid_operation("OpenGLProgram::add_stage"); unsigned stage_id = glCreateShader(gl_type); stage_ids[type] = stage_id; @@ -91,7 +101,7 @@ unsigned OpenGLProgram::add_stage(Stage type) void OpenGLProgram::add_glsl_stages(const GlslModule &mod, const map &spec_values, TransientData &transient) { - 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); @@ -103,7 +113,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) { @@ -113,7 +123,7 @@ void OpenGLProgram::add_glsl_stages(const GlslModule &mod, const map(this)->reflect_data; + rd.n_clip_distances = compiler.get_n_clip_distances(); } void OpenGLProgram::compile_glsl_stage(const GlslModule &mod, unsigned stage_id) @@ -161,7 +174,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); @@ -176,14 +189,14 @@ 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); @@ -200,7 +213,6 @@ void OpenGLProgram::add_spirv_stages(const SpirVModule &mod, const mapsecond); - transient.spec_values[c.constant_id] = i->second; } } @@ -210,7 +222,7 @@ void OpenGLProgram::add_spirv_stages(const SpirVModule &mod, const mapname.c_str(), spec_id_array.size(), &spec_id_array[0], &spec_value_array[0]); } -void OpenGLProgram::finalize(const Module &mod) +void OpenGLProgram::finalize(const Module &mod, TransientData &transient) { glLinkProgram(id); int status = 0; @@ -231,6 +243,13 @@ void OpenGLProgram::finalize(const Module &mod) if(!info_log.empty()) IO::print("Program link info log:\n%s", info_log); #endif + + if(mod.get_format()==Module::GLSL) + { + query_uniforms(); + query_attributes(); + apply_bindings(transient); + } } void OpenGLProgram::query_uniforms() @@ -255,7 +274,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; @@ -277,7 +296,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) @@ -290,57 +309,11 @@ 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(); - if(!default_block.uniforms.empty()) - { - const ReflectData::UniformInfo &uni = *default_block.uniforms.back(); - default_block.data_size = uni.location*16+uni.array_size*get_type_size(uni.type); - } default_block.update_layout_hash(); rd.update_layout_hash(); } @@ -358,7 +331,7 @@ void OpenGLProgram::query_uniform_blocks(const vectorblock = &info; } @@ -435,7 +408,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); @@ -474,6 +447,72 @@ void OpenGLProgram::apply_bindings(const TransientData &transient) } } +void OpenGLProgram::finalize_uniforms() +{ + ReflectData &rd = static_cast(this)->reflect_data; + + auto i = find_if(rd.uniform_blocks, [](const ReflectData::UniformBlockInfo &b){ return b.bind_point<0; }); + if(i!=rd.uniform_blocks.end() && !i->uniforms.empty()) + { + 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(func) + uniform_calls.push_back(UniformCall(u->location, u->array_size, func)); + } + + if(i->data_size<=0) + { + const ReflectData::UniformInfo &last = *i->uniforms.back(); + i->data_size = last.location*16+last.array_size*get_type_size(last.type); + } + } +} + void OpenGLProgram::set_debug_name(const string &name) { #ifdef DEBUG