@@ -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 */
295306int 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.
0 commit comments