Skip to content

Commit cc876f8

Browse files
committed
Implemented callback and shader recompile, but there is still strange behaviour
1 parent 2e63246 commit cc876f8

5 files changed

Lines changed: 90 additions & 37 deletions

File tree

code/graphics/2d.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -754,7 +754,8 @@ typedef struct screen {
754754

755755
void (*gf_sphere)(material *material_def, float rad);
756756

757-
int (*gf_maybe_create_shader)(shader_type type, unsigned int flags);
757+
int (*gf_maybe_create_shader)(shader_type type, unsigned int flags);
758+
void (*gf_recompile_all_shaders)(std::function<void(size_t, size_t)>progress_callback);
758759

759760
void (*gf_clear_states)();
760761

@@ -989,6 +990,7 @@ inline void gr_post_process_restore_zbuffer() {
989990
#define gr_sphere GR_CALL(*gr_screen.gf_sphere)
990991

991992
#define gr_maybe_create_shader GR_CALL(*gr_screen.gf_maybe_create_shader)
993+
#define gr_recompile_all_shaders GR_CALL(*gr_screen.gf_recompile_all_shaders)
992994
#define gr_set_animated_effect GR_CALL(*gr_screen.gf_set_animated_effect)
993995

994996
#define gr_clear_states GR_CALL(*gr_screen.gf_clear_states)

code/graphics/opengl/gropengl.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1148,6 +1148,7 @@ void opengl_setup_function_pointers()
11481148
gr_screen.gf_sphere = gr_opengl_sphere;
11491149

11501150
gr_screen.gf_maybe_create_shader = gr_opengl_maybe_create_shader;
1151+
gr_screen.gf_recompile_all_shaders = gr_opengl_recompile_all_shaders;
11511152
gr_screen.gf_shadow_map_start = gr_opengl_shadow_map_start;
11521153
gr_screen.gf_shadow_map_end = gr_opengl_shadow_map_end;
11531154

code/graphics/opengl/gropenglshader.cpp

Lines changed: 58 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,17 @@ void opengl_shader_set_current(int handle)
285285
opengl_shader_set_current(&GL_shader[handle]);
286286
}
287287

288+
size_t opengl_get_shader_idx(shader_type shader_t, unsigned int flags)
289+
{
290+
for (size_t idx = 0; idx < GL_shader.size(); idx++) {
291+
if (GL_shader[idx].shader == shader_t && GL_shader[idx].flags == flags) {
292+
return idx;
293+
}
294+
}
295+
296+
return GL_shader.size();
297+
}
298+
288299
/**
289300
* Given a set of flags, determine whether a shader with these flags exists within the GL_shader vector. If no shader with the requested flags exists, attempt to compile one.
290301
*
@@ -294,14 +305,10 @@ void opengl_shader_set_current(int handle)
294305
*/
295306
int gr_opengl_maybe_create_shader(shader_type shader_t, unsigned int flags)
296307
{
297-
size_t idx;
298-
size_t max = GL_shader.size();
308+
size_t idx = opengl_get_shader_idx(shader_t, flags);
299309

300-
for (idx = 0; idx < max; idx++) {
301-
if (GL_shader[idx].shader == shader_t && GL_shader[idx].flags == flags) {
302-
return (int)idx;
303-
}
304-
}
310+
if (idx < GL_shader.size())
311+
return (int)idx;
305312

306313
// If we are here, it means we need to compile a new shader
307314
return opengl_compile_shader(shader_t, flags);
@@ -313,7 +320,7 @@ void opengl_delete_shader(int sdr_handle)
313320
Assert(sdr_handle < (int)GL_shader.size());
314321

315322
GL_shader[sdr_handle].program.reset();
316-
323+
317324
GL_shader[sdr_handle].flags = 0;
318325
GL_shader[sdr_handle].flags2 = 0;
319326
GL_shader[sdr_handle].shader = NUM_SHADER_TYPES;
@@ -636,23 +643,8 @@ static void cache_program_binary(GLuint program, const SCP_string& hash) {
636643
cfclose(binary_fp);
637644
}
638645

639-
/**
640-
* Compiles a new shader, and creates an opengl_shader_t that will be put into the GL_shader vector
641-
* if compilation is successful.
642-
*
643-
* @param sdr Identifier defined with the program we wish to compile
644-
* @param flags Combination of SDR_* flags
645-
*/
646-
int opengl_compile_shader(shader_type sdr, uint flags)
646+
void opengl_compile_shader_actual(shader_type sdr, const uint &flags, opengl_shader_t &new_shader)
647647
{
648-
GR_DEBUG_SCOPE("Creating new shader");
649-
650-
int sdr_index = -1;
651-
int empty_idx;
652-
opengl_shader_t new_shader;
653-
654-
Assert(sdr < NUM_SHADER_TYPES);
655-
656648
opengl_shader_type_t *sdr_info = &GL_shader_types[sdr];
657649

658650
Assert(sdr_info->type_id == sdr);
@@ -663,7 +655,7 @@ int opengl_compile_shader(shader_type sdr, uint flags)
663655
bool use_geo_sdr = false;
664656

665657
// do we even have a geometry shader?
666-
if ( sdr_info->geo != NULL ) {
658+
if (sdr_info->geo != NULL) {
667659
for (int i = 0; i < GL_num_shader_variants; ++i) {
668660
opengl_shader_variant_t *variant = &GL_shader_variants[i];
669661

@@ -697,10 +689,10 @@ int opengl_compile_shader(shader_type sdr, uint flags)
697689

698690
for (size_t i = 0; i < GL_vertex_attrib_info.size(); ++i) {
699691
// Check that the enum values match the position in the vector to make accessing that information more efficient
700-
Assertion(GL_vertex_attrib_info[i].attribute_id == (int) i, "Mistmatch between enum values and attribute vector detected!");
692+
Assertion(GL_vertex_attrib_info[i].attribute_id == (int)i, "Mistmatch between enum values and attribute vector detected!");
701693

702694
// assign vert attribute binding locations before we link the shader
703-
glBindAttribLocation(program->getShaderHandle(), (GLint) i, GL_vertex_attrib_info[i].name.c_str());
695+
glBindAttribLocation(program->getShaderHandle(), (GLint)i, GL_vertex_attrib_info[i].name.c_str());
704696
}
705697

706698
// bind fragment data locations before we link the shader
@@ -716,7 +708,8 @@ int opengl_compile_shader(shader_type sdr, uint flags)
716708
}
717709

718710
program->linkProgram();
719-
} catch (const std::exception&) {
711+
}
712+
catch (const std::exception&) {
720713
// Since all shaders are required a compilation failure is a fatal error
721714
Error(LOCATION, "A shader failed to compile! Check the debug log for more information.");
722715
}
@@ -746,10 +739,10 @@ int opengl_compile_shader(shader_type sdr, uint flags)
746739
mprintf(("Shader Variant Features:\n"));
747740

748741
// initialize all uniforms and attributes that are specific to this variant
749-
for ( int i = 0; i < GL_num_shader_variants; ++i ) {
742+
for (int i = 0; i < GL_num_shader_variants; ++i) {
750743
opengl_shader_variant_t &variant = GL_shader_variants[i];
751744

752-
if ( sdr_info->type_id == variant.type_id && variant.flag & flags ) {
745+
if (sdr_info->type_id == variant.type_id && variant.flag & flags) {
753746
for (auto& attr : variant.attributes) {
754747
auto& attr_info = GL_vertex_attrib_info[attr];
755748
new_shader.program->initAttribute(attr_info.name, attr_info.attribute_id, attr_info.default_value);
@@ -758,14 +751,36 @@ int opengl_compile_shader(shader_type sdr, uint flags)
758751
mprintf((" %s\n", variant.description));
759752
}
760753
}
754+
}
755+
756+
/**
757+
* Compiles a new shader, and creates an opengl_shader_t that will be put into the GL_shader vector
758+
* if compilation is successful.
759+
*
760+
* @param sdr Identifier defined with the program we wish to compile
761+
* @param flags Combination of SDR_* flags
762+
* @param replacement_idx The index of the shader this replaces. If -1, the newly compiled shader will be appended to the GL_shader vector
763+
* or inserted at the first available empty slot
764+
*/
765+
int opengl_compile_shader(shader_type sdr, uint flags)
766+
{
767+
GR_DEBUG_SCOPE("Creating new shader");
768+
769+
int sdr_index = -1;
770+
int empty_idx;
771+
opengl_shader_t new_shader;
772+
773+
Assert(sdr < NUM_SHADER_TYPES);
774+
775+
opengl_compile_shader_actual(sdr, flags, new_shader);
761776

762777
opengl_shader_set_current();
763778

764779
// add it to our list of embedded shaders
765780
// see if we have empty shader slots
766781
empty_idx = -1;
767-
for ( int i = 0; i < (int)GL_shader.size(); ++i ) {
768-
if ( GL_shader[i].shader == NUM_SHADER_TYPES ) {
782+
for (int i = 0; i < (int)GL_shader.size(); ++i) {
783+
if (GL_shader[i].shader == NUM_SHADER_TYPES) {
769784
empty_idx = i;
770785
break;
771786
}
@@ -783,6 +798,17 @@ int opengl_compile_shader(shader_type sdr, uint flags)
783798
return sdr_index;
784799
}
785800

801+
void gr_opengl_recompile_all_shaders(std::function<void(size_t, size_t)>progress_callback)
802+
{
803+
for (auto sdr = GL_shader.begin(); sdr != GL_shader.end(); ++sdr)
804+
{
805+
if (progress_callback)
806+
progress_callback(std::distance(GL_shader.begin(), sdr), GL_shader.size());
807+
sdr->program.reset();
808+
opengl_compile_shader_actual(sdr->shader, sdr->flags, *sdr);
809+
}
810+
}
811+
786812
/**
787813
* Initializes the shader system. Creates a 1x1 texture that can be used as a fallback texture when framebuffer support is missing.
788814
* Also compiles the shaders used for particle rendering.

code/graphics/opengl/gropenglshader.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,7 @@ extern SCP_vector<opengl_shader_t> GL_shader;
144144
extern opengl_shader_t *Current_shader;
145145

146146
int gr_opengl_maybe_create_shader(shader_type shader_t, unsigned int flags);
147+
void gr_opengl_recompile_all_shaders(std::function<void(size_t, size_t)> progress_callback = nullptr);
147148
void opengl_delete_shader(int sdr_handle);
148149
void opengl_shader_set_current(opengl_shader_t *shader_obj = NULL);
149150
void opengl_shader_set_current(int handle);

code/menuui/optionsmenu.cpp

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1356,12 +1356,26 @@ void options_detail_init()
13561356
options_detail_synch_sliders();
13571357
}
13581358

1359+
void shader_recompile_callback(size_t current, size_t total)
1360+
{
1361+
SCP_string msg = "";
1362+
msg += "Recompiling shader ";
1363+
msg += std::to_string(current);
1364+
msg += "/";
1365+
msg += std::to_string(total);
1366+
1367+
//popup_change_text(msg.c_str());
1368+
1369+
//if (current == total)
1370+
// popup_kill_any_active();
1371+
}
1372+
13591373
void options_detail_sliders_update()
13601374
{
13611375
int i;
13621376

1363-
for ( i = 0; i < NUM_DETAIL_SLIDERS; i++ ) {
1364-
if ( Detail_sliders[gr_screen.res][i].slider.pos != Detail_slider_pos[i] ) {
1377+
for (i = 0; i < NUM_DETAIL_SLIDERS; i++) {
1378+
if (Detail_sliders[gr_screen.res][i].slider.pos != Detail_slider_pos[i]) {
13651379
Detail_slider_pos[i] = Detail_sliders[gr_screen.res][i].slider.pos;
13661380
gamesnd_play_iface(SND_USER_SELECT);
13671381
}
@@ -1374,12 +1388,21 @@ void options_detail_sliders_update()
13741388
Detail.nebula_detail = Detail_sliders[gr_screen.res][NEBULA_DETAIL_SLIDER].slider.pos;
13751389
neb2_set_detail_level(Detail.nebula_detail);
13761390

1377-
Detail.hardware_textures = Detail_sliders[gr_screen.res][HARDWARE_TEXTURES_SLIDER].slider.pos;
1391+
Detail.hardware_textures = Detail_sliders[gr_screen.res][HARDWARE_TEXTURES_SLIDER].slider.pos;
13781392
Detail.num_small_debris = Detail_sliders[gr_screen.res][SHARD_CULLING_SLIDER].slider.pos;
13791393
Detail.shield_effects = Detail_sliders[gr_screen.res][SHIELD_DETAIL_SLIDER].slider.pos;
13801394
Detail.num_stars = Detail_sliders[gr_screen.res][NUM_STARS_SLIDER].slider.pos;
13811395
Detail.num_particles = Detail_sliders[gr_screen.res][NUM_PARTICLES_SLIDER].slider.pos;
1382-
Detail.lighting = Detail_sliders[gr_screen.res][LIGHTING_SLIDER].slider.pos;
1396+
1397+
// If the new lighting setting is above 3 and the old one was below or the reverse,
1398+
// we need to recompile all shaders we have to account for the changed lighting model.
1399+
1400+
if (Detail.lighting != Detail_sliders[gr_screen.res][LIGHTING_SLIDER].slider.pos) {
1401+
Detail.lighting = Detail_sliders[gr_screen.res][LIGHTING_SLIDER].slider.pos;
1402+
//if (!popup_active())
1403+
// popup(PF_BODY_BIG | PF_RUN_STATE, 1, POPUP_OK, "Recompiling shaders...");
1404+
gr_recompile_all_shaders(shader_recompile_callback);
1405+
}
13831406
}
13841407

13851408
void options_detail_hide_stuff()

0 commit comments

Comments
 (0)