diff --git a/src/d_main.c b/src/d_main.c index 59bcc24ea9d4ba892871b669a3754c0c55e8134c..0d4577bae70235a3c76462affef19977194dfd5a 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -76,7 +76,8 @@ #endif #ifdef HWRENDER -#include "hardware/hw_main.h" // 3D View Rendering +#include "hardware/hw_main.h" +#include "hardware/hw_shaders.h" #endif #ifdef _WINDOWS @@ -1286,6 +1287,15 @@ void D_SRB2Main(void) W_InitMultipleFiles(startuppwads); D_CleanFile(startuppwads); +#if defined(HWRENDER) && defined(GL_SHADERS) + // Lactozilla: Recompile shaders after adding extra PWADs. + if (vid.glstate == VID_GL_LIBRARY_LOADED) + { + HWR_LoadAllShaders(); + gl_shadersavailable = HWR_CompileShaders(); + } +#endif + CONS_Printf("HU_LoadGraphics()...\n"); HU_LoadGraphics(); diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 8b7737db5f337dbfbd90dbd9ccc264b187bb76e1..ef48a1e8273ad1f09723f39a0ae712f69db27000 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -6339,17 +6339,22 @@ void HWR_Startup(void) { CONS_Printf("HWR_Startup()...\n"); - HWR_InitPolyPool(); HWR_AddSessionCommands(); + + HWR_InitPolyPool(); HWR_InitMapTextures(); HWR_InitModels(); #ifdef ALAM_LIGHTING HWR_InitLight(); #endif - HWR_LoadShaders(); +#ifdef GL_SHADERS + HWR_LoadAllShaders(); if (!HWR_CompileShaders()) gl_shadersavailable = false; +#else + gl_shadersavailable = false; +#endif } gl_patchformat = gl_textureformat = GPU_TEXFMT_RGBA; diff --git a/src/hardware/hw_shaders.c b/src/hardware/hw_shaders.c index 28dcd51d4ca2fdad5e388f1580d6165147901547..dcf4e143bfc78a4c416a7898afcecac164bed909 100644 --- a/src/hardware/hw_shaders.c +++ b/src/hardware/hw_shaders.c @@ -194,15 +194,15 @@ const char *HWR_GetShaderName(INT32 shader) return "Unknown"; } -void HWR_LoadShaders(void) +void HWR_LoadAllShaders(void) { INT32 i; for (i = 0; i < numwadfiles; i++) - { - HWR_ReadShaderDefinitions(i, wadfiles[i]->numlumps); HWR_LoadLegacyShadersFromFile(i, (wadfiles[i]->type == RET_PK3)); - } + + for (i = 0; i < numwadfiles; i++) + HWR_ReadShaderDefinitions(i, wadfiles[i]->numlumps); } void HWR_WriteShaderSource(char **dest, UINT8 stage, FShaderProgram *program, char *code, size_t size) @@ -309,7 +309,7 @@ static char **includesList = NULL; static UINT8 *includesStages = NULL; static INT32 includesCount = 0; -static void InsertIntoIncludesList(const char *include, INT32 stage) +static void CollectInclude(const char *include, INT32 stage) { includesCount++; includesList = Z_Realloc(includesList, includesCount * sizeof(char *), PU_STATIC, NULL); @@ -318,10 +318,49 @@ static void InsertIntoIncludesList(const char *include, INT32 stage) includesStages[includesCount - 1] = stage; } +static void InsertInclude(FShaderIncludes *includes, INT32 ref) +{ + includes->list = Z_Realloc(includes->list, (includes->count + 1) * sizeof(char *), PU_STATIC, NULL); + includes->stages = Z_Realloc(includes->stages, (includes->count + 1) * sizeof(UINT8), PU_STATIC, NULL); + includes->list[includes->count] = includesList[ref]; + includes->stages[includes->count] = includesStages[ref]; + includes->count++; +} + +static void RemoveInclude(FShaderIncludes *includes, INT32 index) +{ + Z_Free(includes->list[index]); + + if ((includes->count - 1) > 0) + { + memmove(includes->list + index, includes->list + (index + 1), (includes->count - index) * sizeof(char *)); + memmove(includes->stages + index, includes->stages + (index + 1), (includes->count - index) * sizeof(UINT8)); + } + + includes->count--; + + if (includes->count) + { + includes->list = Z_Realloc(includes->list, includes->count * sizeof(char *), PU_STATIC, NULL); + includes->stages = Z_Realloc(includes->stages, includes->count * sizeof(UINT8), PU_STATIC, NULL); + } + else + { + Z_Free(includes->list); + Z_Free(includes->stages); + + includes->list = NULL; + includes->stages = NULL; + } +} + static boolean ParseShaderDefinitions(size_t lumplength, boolean mainfile) { FShaderProgram *shader = NULL; - boolean builtin = false, isInclude = false, replace = false, removesoftwareshaders = false; + boolean builtin = false, replace = false; + boolean isInclude = false, removeSWIncludes = false; + UINT8 *clearIncludes = NULL; + INT32 numClearIncludes = 0; char *sources[NUMSHADERSTAGES - 1]; INT32 id, type = 0; @@ -584,7 +623,7 @@ static boolean ParseShaderDefinitions(size_t lumplength, boolean mainfile) if (src) { - InsertIntoIncludesList(inc, stage); + CollectInclude(inc, stage); addedSources++; } else if (numSources == 1) @@ -611,16 +650,53 @@ static boolean ParseShaderDefinitions(size_t lumplength, boolean mainfile) goto failure; } } + else if (!stricmp(tk, "ClearIncludes")) + { + INT32 idx = numClearIncludes; + UINT8 stage = SHADER_STAGE_NONE; + + Z_Free(tk); + tk = M_GetToken(NULL); + if (tk == NULL) + { + ParseError("EOF where include clear stage for shader \"%s\" should be", name); + goto failure; + } + + numClearIncludes++; + clearIncludes = Z_Realloc(clearIncludes, numClearIncludes * sizeof(UINT8), PU_STATIC, NULL); + + if (!stricmp(tk, "Vertex")) + stage = SHADER_STAGE_VERTEX; + else if (!stricmp(tk, "Fragment")) + stage = SHADER_STAGE_FRAGMENT; + else + M_UnGetToken(); + + if (stage == SHADER_STAGE_NONE) // Clear all + { + INT32 i = (SHADER_STAGE_NONE + 1); + for (; i < NUMSHADERSTAGES; i++) + { + idx = numClearIncludes; + numClearIncludes++; + clearIncludes = Z_Realloc(clearIncludes, numClearIncludes * sizeof(UINT8), PU_STATIC, NULL); + clearIncludes[idx] = i; + } + } + else + clearIncludes[idx] = stage; + } else if (!stricmp(tk, "IncludeSoftwareShaders")) { Z_Free(tk); - InsertIntoIncludesList(SHADER_INCLUDES_SOFTWARE, SHADER_STAGE_FRAGMENT); - removesoftwareshaders = false; + CollectInclude(SHADER_INCLUDES_SOFTWARE, SHADER_STAGE_FRAGMENT); + removeSWIncludes = false; } else if (!stricmp(tk, "RemoveSoftwareShaders")) { Z_Free(tk); - removesoftwareshaders = true; + removeSWIncludes = true; } else { @@ -711,25 +787,42 @@ static boolean ParseShaderDefinitions(size_t lumplength, boolean mainfile) M_Memcpy(shader->name, name, len); } - if (includesCount) + if (clearIncludes) { - INT32 i = 0, j, count = includesCount; + INT32 i = 0, j; - for (; i < count; i++) + for (; i < numClearIncludes; i++) { - j = shader->includes.count; - shader->includes.list = Z_Realloc(shader->includes.list, (j + 1) * sizeof(char *), PU_STATIC, NULL); - shader->includes.stages = Z_Realloc(shader->includes.stages, (j + 1) * sizeof(UINT8), PU_STATIC, NULL); - shader->includes.list[j] = includesList[i]; - shader->includes.stages[j] = includesStages[i]; - shader->includes.count++; + FShaderIncludes *inc = &shader->includes; + + for (j = 0; j < inc->count; j++) + { + INT32 count = inc->count; + + if (clearIncludes[i] == inc->stages[j]) + { + RemoveInclude(inc, j); + + count--; + j--; + + if (!count) + { + inc = NULL; + break; + } + } + } + + if (inc == NULL) + break; } - Z_Free(includesList); - Z_Free(includesStages); + removeSWIncludes = false; + Z_Free(clearIncludes); } - if (removesoftwareshaders) + if (removeSWIncludes) { INT32 i = 0, count = shader->includes.count; @@ -737,13 +830,33 @@ static boolean ParseShaderDefinitions(size_t lumplength, boolean mainfile) { if (!stricmp(SHADER_INCLUDES_SOFTWARE, shader->includes.list[i])) { - memmove(shader->includes.list + i, shader->includes.list + (i + 1), (shader->includes.count - i) * sizeof(char *)); - memmove(shader->includes.stages + i, shader->includes.stages + (i + 1), (shader->includes.count - i) * sizeof(UINT8)); - shader->includes.count--; - shader->includes.list = Z_Realloc(shader->includes.list, shader->includes.count * sizeof(char *), PU_STATIC, NULL); - shader->includes.stages = Z_Realloc(shader->includes.stages, shader->includes.count * sizeof(UINT8), PU_STATIC, NULL); + RemoveInclude(&shader->includes, i); + i--; + } + } + } + + if (includesCount) + { + INT32 i = 0, j, count = includesCount; + + for (; i < count; i++) + { + for (j = 0; j < shader->includes.count; j++) + { + if (!stricmp(shader->includes.list[j], includesList[i]) + && (shader->includes.stages[j] == includesStages[i])) + { + RemoveInclude(&shader->includes, j); + break; + } } + + InsertInclude(&shader->includes, i); } + + Z_Free(includesList); + Z_Free(includesStages); } if (sources[SHADER_STAGE_VERTEX - 1]) diff --git a/src/hardware/hw_shaders.h b/src/hardware/hw_shaders.h index 06209029e0501b183d30f927e07da22f701fedfb..e8c4baa9d32efb83d681c892c0e5c8d8e26ebc8a 100644 --- a/src/hardware/hw_shaders.h +++ b/src/hardware/hw_shaders.h @@ -19,7 +19,7 @@ #define SHADER_INCLUDES_SOFTWARE "SoftwareShaderIncludes" -void HWR_LoadShaders(void); +void HWR_LoadAllShaders(void); void HWR_ReadShaderDefinitions(UINT16 wadnum, UINT16 numlumps); boolean HWR_CompileShaders(void);