2 #include <msp/core/algorithm.h>
3 #include <msp/gl/extensions/arb_compute_shader.h>
4 #include <msp/gl/extensions/arb_es2_compatibility.h>
5 #include <msp/gl/extensions/arb_fragment_shader.h>
6 #include <msp/gl/extensions/arb_gl_spirv.h>
7 #include <msp/gl/extensions/arb_geometry_shader4.h>
8 #include <msp/gl/extensions/arb_separate_shader_objects.h>
9 #include <msp/gl/extensions/arb_shader_objects.h>
10 #include <msp/gl/extensions/arb_uniform_buffer_object.h>
11 #include <msp/gl/extensions/arb_tessellation_shader.h>
12 #include <msp/gl/extensions/arb_vertex_shader.h>
13 #include <msp/gl/extensions/ext_gpu_shader4.h>
14 #include <msp/gl/extensions/khr_debug.h>
15 #include <msp/gl/extensions/nv_non_square_matrices.h>
16 #include <msp/io/print.h>
20 #include "program_backend.h"
21 #include "glsl/compiler.h"
27 template<typename T, void (*&func)(GLint, GLsizei, const T *)>
28 void uniform_wrapper(unsigned index, unsigned count, const void *data)
30 func(index, count, static_cast<const T *>(data));
33 template<typename T, void (*&func)(GLint, GLsizei, GLboolean, const T *)>
34 void uniform_matrix_wrapper(unsigned index, unsigned count, const void *data)
36 func(index, count, false, static_cast<const T *>(data));
44 OpenGLProgram::OpenGLProgram()
46 static Require _req(ARB_shader_objects);
48 id = glCreateProgram();
51 OpenGLProgram::OpenGLProgram(OpenGLProgram &&other):
54 uniform_calls(move(other.uniform_calls)),
55 debug_name(move(other.debug_name))
57 move(other.stage_ids, other.stage_ids+MAX_STAGES, stage_ids);
59 fill(other.stage_ids, other.stage_ids+MAX_STAGES, 0);
62 OpenGLProgram::~OpenGLProgram()
64 for(unsigned i=0; i<MAX_STAGES; ++i)
66 glDeleteShader(stage_ids[i]);
70 bool OpenGLProgram::has_stages() const
72 for(unsigned i=0; i<MAX_STAGES; ++i)
78 unsigned OpenGLProgram::add_stage(Stage type)
83 case VERTEX: { static Require _req(ARB_vertex_shader); gl_type = GL_VERTEX_SHADER; } break;
84 case TESS_CONTROL: { static Require _req(ARB_tessellation_shader); gl_type = GL_TESS_CONTROL_SHADER; } break;
85 case TESS_EVAL: { static Require _req(ARB_tessellation_shader); gl_type = GL_TESS_EVALUATION_SHADER; } break;
86 case GEOMETRY: { static Require _req(ARB_geometry_shader4); gl_type = GL_GEOMETRY_SHADER; } break;
87 case FRAGMENT: { static Require _req(ARB_fragment_shader); gl_type = GL_FRAGMENT_SHADER; } break;
88 case COMPUTE: { static Require _req(ARB_compute_shader); gl_type = GL_COMPUTE_SHADER; } break;
89 default: throw invalid_argument("OpenGLProgram::add_stage");
93 throw invalid_operation("OpenGLProgram::add_stage");
95 unsigned stage_id = glCreateShader(gl_type);
96 stage_ids[type] = stage_id;
97 glAttachShader(id, stage_id);
100 if(!debug_name.empty() && KHR_debug)
101 set_stage_debug_name(stage_id, type);
107 void OpenGLProgram::add_glsl_stages(const GlslModule &mod, const map<string, int> &spec_values)
109 SL::Compiler compiler(Device::get_current().get_info().glsl_features);
110 compiler.set_source(mod.get_prepared_source(), "<module>");
111 compiler.specialize(spec_values);
112 compiler.compile(SL::Compiler::PROGRAM);
114 string diagnostics = compiler.get_diagnostics();
115 if(!diagnostics.empty())
116 IO::print("Program diagnostics:\n%s\n", diagnostics);
119 vector<SL::Stage::Type> stages = compiler.get_stages();
121 throw invalid_argument("OpenGLProgram::add_glsl_stages");
123 for(SL::Stage::Type st: stages)
125 unsigned stage_id = 0;
128 case SL::Stage::VERTEX: stage_id = add_stage(VERTEX); break;
129 case SL::Stage::TESS_CONTROL: stage_id = add_stage(TESS_CONTROL); break;
130 case SL::Stage::TESS_EVAL: stage_id = add_stage(TESS_EVAL); break;
131 case SL::Stage::GEOMETRY: stage_id = add_stage(GEOMETRY); break;
132 case SL::Stage::FRAGMENT: stage_id = add_stage(FRAGMENT); break;
133 case SL::Stage::COMPUTE: stage_id = add_stage(COMPUTE); break;
134 default: throw invalid_operation("OpenGLProgram::add_glsl_stages");
137 string stage_src = compiler.get_stage_glsl(st);
138 const char *src_ptr = stage_src.data();
139 int src_len = stage_src.size();
140 glShaderSource(stage_id, 1, &src_ptr, &src_len);
142 if(st==SL::Stage::VERTEX)
144 for(const auto &kvp: compiler.get_vertex_attributes())
145 glBindAttribLocation(id, kvp.second, kvp.first.c_str());
148 if(st==SL::Stage::FRAGMENT && EXT_gpu_shader4)
150 for(const auto &kvp: compiler.get_fragment_outputs())
151 glBindFragDataLocation(id, kvp.second, kvp.first.c_str());
154 compile_glsl_stage(mod, stage_id);
157 ReflectData &rd = static_cast<Program *>(this)->reflect_data;
158 rd.n_clip_distances = compiler.get_n_clip_distances();
166 glGetProgramiv(id, GL_COMPUTE_WORK_GROUP_SIZE, wg_size);
167 rd.compute_wg_size = LinAl::Vector<unsigned, 3>(wg_size[0], wg_size[1], wg_size[2]);
170 const map<string, unsigned> &block_bindings = compiler.get_uniform_block_bindings();
171 if(!block_bindings.empty())
173 for(unsigned i=0; i<rd.uniform_blocks.size(); ++i)
175 auto j = block_bindings.find(rd.uniform_blocks[i].name);
176 if(j!=block_bindings.end())
178 glUniformBlockBinding(id, i, j->second);
179 rd.uniform_blocks[i].bind_point = j->second;
184 const map<string, unsigned> &tex_bindings = compiler.get_texture_bindings();
185 if(!tex_bindings.empty())
187 if(!ARB_separate_shader_objects)
189 for(const auto &kvp: tex_bindings)
191 int location = static_cast<const Program *>(this)->get_uniform_location(kvp.first);
194 if(ARB_separate_shader_objects)
195 glProgramUniform1i(id, location, kvp.second);
197 glUniform1i(location, kvp.second);
203 void OpenGLProgram::compile_glsl_stage(const GlslModule &mod, unsigned stage_id)
205 glCompileShader(stage_id);
207 glGetShaderiv(stage_id, GL_COMPILE_STATUS, &status);
209 int info_log_len = 0;
210 glGetShaderiv(stage_id, GL_INFO_LOG_LENGTH, &info_log_len);
211 string info_log(info_log_len+1, 0);
212 glGetShaderInfoLog(stage_id, info_log_len+1, &info_log_len, &info_log[0]);
213 info_log.erase(info_log_len);
214 info_log = mod.get_source_map().translate_errors(info_log);
217 throw compile_error(info_log);
219 if(!info_log.empty())
220 IO::print("Shader compile info log:\n%s", info_log);
224 void OpenGLProgram::add_spirv_stages(const SpirVModule &mod, const map<string, int> &spec_values)
226 static Require _req(ARB_gl_spirv);
227 static Require _req2(ARB_ES2_compatibility);
229 unsigned n_stages = 0;
230 unsigned used_stage_ids[MAX_STAGES];
231 for(const SpirVModule::EntryPoint &e: mod.get_entry_points())
233 unsigned stage_id = 0;
236 case SpirVModule::VERTEX: stage_id = add_stage(VERTEX); break;
237 case SpirVModule::TESS_CONTROL: stage_id = add_stage(TESS_CONTROL); break;
238 case SpirVModule::TESS_EVAL: stage_id = add_stage(TESS_EVAL); break;
239 case SpirVModule::GEOMETRY: stage_id = add_stage(GEOMETRY); break;
240 case SpirVModule::FRAGMENT: stage_id = add_stage(FRAGMENT); break;
241 case SpirVModule::COMPUTE: stage_id = add_stage(COMPUTE); break;
242 default: throw invalid_operation("OpenGLProgram::add_spirv_stages");
245 used_stage_ids[n_stages++] = stage_id;
249 throw invalid_argument("OpenGLProgram::add_spirv_stages");
251 const vector<uint32_t> &code = mod.get_code();
252 glShaderBinary(n_stages, used_stage_ids, GL_SHADER_BINARY_FORMAT_SPIR_V, &code[0], code.size()*4);
254 const vector<SpirVModule::Constant> &spec_consts = mod.get_spec_constants();
255 vector<unsigned> spec_id_array;
256 vector<unsigned> spec_value_array;
257 spec_id_array.reserve(spec_consts.size());
258 spec_value_array.reserve(spec_consts.size());
259 for(const SpirVModule::Constant &c: spec_consts)
261 auto i = spec_values.find(c.name);
262 if(i!=spec_values.end())
264 spec_id_array.push_back(c.constant_id);
265 spec_value_array.push_back(i->second);
269 auto j = mod.get_entry_points().begin();
270 for(unsigned i=0; i<MAX_STAGES; ++i)
272 glSpecializeShader(stage_ids[i], j->name.c_str(), spec_id_array.size(), &spec_id_array[0], &spec_value_array[0]);
277 void OpenGLProgram::link(const Module &mod)
281 glGetProgramiv(id, GL_LINK_STATUS, &status);
284 int info_log_len = 0;
285 glGetProgramiv(id, GL_INFO_LOG_LENGTH, &info_log_len);
286 string info_log(info_log_len+1, 0);
287 glGetProgramInfoLog(id, info_log_len+1, &info_log_len, &info_log[0]);
288 info_log.erase(info_log_len);
289 if(mod.get_format()==Module::GLSL)
290 info_log = static_cast<const GlslModule &>(mod).get_source_map().translate_errors(info_log);
293 throw compile_error(info_log);
295 if(!info_log.empty())
296 IO::print("Program link info log:\n%s", info_log);
300 void OpenGLProgram::query_uniforms()
302 ReflectData &rd = static_cast<Program *>(this)->reflect_data;
305 glGetProgramiv(id, GL_ACTIVE_UNIFORMS, reinterpret_cast<int *>(&count));
306 rd.uniforms.reserve(count);
307 vector<string> uniform_names(count);
308 for(unsigned i=0; i<count; ++i)
314 glGetActiveUniform(id, i, sizeof(name), &len, &size, &type, name);
315 if(len && strncmp(name, "gl_", 3))
317 /* Some implementations report the first element of a uniform array,
318 others report just the name of the array itself. */
319 if(len>3 && !strcmp(name+len-3, "[0]"))
322 rd.uniforms.emplace_back();
323 ReflectData::UniformInfo &info = rd.uniforms.back();
326 info.array_size = size;
327 info.type = from_gl_type(type);
328 uniform_names[i] = name;
332 sort_member(rd.uniforms, &ReflectData::UniformInfo::tag);
334 if(ARB_uniform_buffer_object)
336 vector<ReflectData::UniformInfo *> uniforms_by_index(count);
337 for(unsigned i=0; i<count; ++i)
338 if(!uniform_names[i].empty())
339 // The element is already known to be present
340 uniforms_by_index[i] = &*lower_bound_member(rd.uniforms, Tag(uniform_names[i]), &ReflectData::UniformInfo::tag);
341 query_uniform_blocks(uniforms_by_index);
344 rd.uniform_blocks.emplace_back();
345 ReflectData::UniformBlockInfo &default_block = rd.uniform_blocks.back();
347 for(ReflectData::UniformInfo &u: rd.uniforms)
350 u.location = glGetUniformLocation(id, u.name.c_str());
351 u.block = &default_block;
352 u.array_stride = get_type_size(u.type);
353 if(is_matrix(u.type))
354 u.matrix_stride = get_type_size(get_matrix_column_type(u.type));
355 default_block.uniforms.push_back(&u);
357 if(is_image(u.type) && u.location>=0)
358 glGetUniformiv(id, u.location, &u.binding);
361 default_block.sort_uniforms();
362 default_block.update_layout_hash();
363 rd.update_layout_hash();
366 void OpenGLProgram::query_uniform_blocks(const vector<ReflectData::UniformInfo *> &uniforms_by_index)
368 ReflectData &rd = static_cast<Program *>(this)->reflect_data;
371 glGetProgramiv(id, GL_ACTIVE_UNIFORM_BLOCKS, reinterpret_cast<int *>(&count));
372 // Reserve an extra index for the default block
373 rd.uniform_blocks.reserve(count+1);
374 for(unsigned i=0; i<count; ++i)
378 glGetActiveUniformBlockName(id, i, sizeof(name), &len, name);
379 rd.uniform_blocks.emplace_back();
380 ReflectData::UniformBlockInfo &info = rd.uniform_blocks.back();
384 glGetActiveUniformBlockiv(id, i, GL_UNIFORM_BLOCK_DATA_SIZE, &value);
385 info.data_size = value;
387 glGetActiveUniformBlockiv(id, i, GL_UNIFORM_BLOCK_BINDING, &value);
388 info.bind_point = value;
390 glGetActiveUniformBlockiv(id, i, GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS, &value);
391 vector<int> indices(value);
392 glGetActiveUniformBlockiv(id, i, GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES, &indices[0]);
395 if(!uniforms_by_index[j])
396 throw logic_error("OpenGLProgram::query_uniform_blocks");
397 info.uniforms.push_back(uniforms_by_index[j]);
398 uniforms_by_index[j]->block = &info;
401 vector<unsigned> query_indices(indices.begin(), indices.end());
402 vector<int> values(indices.size());
403 glGetActiveUniformsiv(id, query_indices.size(), &query_indices[0], GL_UNIFORM_OFFSET, &values[0]);
404 for(unsigned j=0; j<indices.size(); ++j)
405 uniforms_by_index[indices[j]]->offset = values[j];
407 query_indices.clear();
409 if(uniforms_by_index[j]->array_size>1)
410 query_indices.push_back(j);
411 if(!query_indices.empty())
413 glGetActiveUniformsiv(id, query_indices.size(), &query_indices[0], GL_UNIFORM_ARRAY_STRIDE, &values[0]);
414 for(unsigned j=0; j<query_indices.size(); ++j)
415 uniforms_by_index[query_indices[j]]->array_stride = values[j];
418 query_indices.clear();
421 DataType t = uniforms_by_index[j]->type;
423 query_indices.push_back(j);
425 if(!query_indices.empty())
427 glGetActiveUniformsiv(id, query_indices.size(), &query_indices[0], GL_UNIFORM_MATRIX_STRIDE, &values[0]);
428 for(unsigned j=0; j<query_indices.size(); ++j)
429 uniforms_by_index[query_indices[j]]->matrix_stride = values[j];
432 info.sort_uniforms();
433 info.update_layout_hash();
437 void OpenGLProgram::query_attributes()
439 ReflectData &rd = static_cast<Program *>(this)->reflect_data;
442 glGetProgramiv(id, GL_ACTIVE_ATTRIBUTES, reinterpret_cast<int *>(&count));
443 rd.attributes.reserve(count);
444 for(unsigned i=0; i<count; ++i)
450 glGetActiveAttrib(id, i, sizeof(name), &len, &size, &type, name);
451 if(len && strncmp(name, "gl_", 3))
453 if(len>3 && !strcmp(name+len-3, "[0]"))
456 rd.attributes.emplace_back();
457 ReflectData::AttributeInfo &info = rd.attributes.back();
459 info.location = glGetAttribLocation(id, name);
460 info.array_size = size;
461 info.type = from_gl_type(type);
465 sort_member(rd.attributes, &ReflectData::AttributeInfo::name);
468 void OpenGLProgram::finalize_uniforms()
470 ReflectData &rd = static_cast<Program *>(this)->reflect_data;
472 auto i = find_if(rd.uniform_blocks, [](const ReflectData::UniformBlockInfo &b){ return b.bind_point<0; });
473 if(i!=rd.uniform_blocks.end() && !i->uniforms.empty())
475 for(const ReflectData::UniformInfo *u: i->uniforms)
478 UniformCall::FuncPtr func = 0;
480 func = &uniform_wrapper<float, glUniform1fv>;
481 else if(u->type==FLOAT_VEC2)
482 func = &uniform_wrapper<float, glUniform2fv>;
483 else if(u->type==FLOAT_VEC3)
484 func = &uniform_wrapper<float, glUniform3fv>;
485 else if(u->type==FLOAT_VEC4)
486 func = &uniform_wrapper<float, glUniform4fv>;
487 else if(u->type==INT)
488 func = &uniform_wrapper<int, glUniform1iv>;
489 else if(u->type==INT_VEC2)
490 func = &uniform_wrapper<int, glUniform2iv>;
491 else if(u->type==INT_VEC3)
492 func = &uniform_wrapper<int, glUniform3iv>;
493 else if(u->type==INT_VEC4)
494 func = &uniform_wrapper<int, glUniform4iv>;
495 else if(u->type==UNSIGNED_INT)
496 func = &uniform_wrapper<unsigned, glUniform1uiv>;
497 else if(u->type==UINT_VEC2)
498 func = &uniform_wrapper<unsigned, glUniform2uiv>;
499 else if(u->type==UINT_VEC3)
500 func = &uniform_wrapper<unsigned, glUniform3uiv>;
501 else if(u->type==UINT_VEC4)
502 func = &uniform_wrapper<unsigned, glUniform4uiv>;
503 else if(u->type==FLOAT_MAT2)
504 func = &uniform_matrix_wrapper<float, glUniformMatrix2fv>;
505 else if(u->type==FLOAT_MAT3)
506 func = &uniform_matrix_wrapper<float, glUniformMatrix3fv>;
507 else if(u->type==FLOAT_MAT4)
508 func = &uniform_matrix_wrapper<float, glUniformMatrix4fv>;
509 else if(u->type==FLOAT_MAT2x3)
510 func = &uniform_matrix_wrapper<float, glUniformMatrix2x3fv>;
511 else if(u->type==FLOAT_MAT3x2)
512 func = &uniform_matrix_wrapper<float, glUniformMatrix3x2fv>;
513 else if(u->type==FLOAT_MAT2x4)
514 func = &uniform_matrix_wrapper<float, glUniformMatrix2x4fv>;
515 else if(u->type==FLOAT_MAT4x2)
516 func = &uniform_matrix_wrapper<float, glUniformMatrix4x2fv>;
517 else if(u->type==FLOAT_MAT3x4)
518 func = &uniform_matrix_wrapper<float, glUniformMatrix3x4fv>;
519 else if(u->type==FLOAT_MAT4x3)
520 func = &uniform_matrix_wrapper<float, glUniformMatrix4x3fv>;
523 uniform_calls.push_back(UniformCall(u->location, u->array_size, func));
528 const ReflectData::UniformInfo &last = *i->uniforms.back();
529 i->data_size = last.location*16+last.array_size*get_type_size(last.type);
534 void OpenGLProgram::set_debug_name(const string &name)
540 glObjectLabel(GL_PROGRAM, id, name.size(), name.c_str());
541 for(unsigned i=0; i<MAX_STAGES; ++i)
543 set_stage_debug_name(stage_ids[i], static_cast<Stage>(i));
550 void OpenGLProgram::set_stage_debug_name(unsigned stage_id, Stage type)
553 static const char *const suffixes[] = { " [VS]", " [TCS]", " [TES]", " [GS]", " [FS]", " [CS]" };
554 string name = debug_name+suffixes[type];
555 glObjectLabel(GL_SHADER, stage_id, name.size(), name.c_str());
557 (void)stage_id; (void)type;