The following patch implements hardware-specific shader files.
This patch is against the 0.8.8 open arena engine code.
These are placed in hardware/NAME/scripts (where NAME is "voodoo" or whatever), and get loaded after all the normal shaders, and hence a hardware-specific shader always takes precedence over a normal shader.
I think this should be used for GLSL support too, but that's not my ballpark.
diff -r -u ./code/renderer/tr_shader.c ./code/renderer/tr_shader.c
--- ./code/renderer/tr_shader.c 2011-12-25 20:06:49.000000000 +1100
+++ ./code/renderer/tr_shader.c 2012-05-30 20:54:17.000000000 +1000
@@ -4264,6 +4264,25 @@
ri.Printf (PRINT_ALL, "------------------\n");
}
+/* andrewj: added this */
+static char * GetHardwareName( void )
+{
+
+ // TODO: if (GLSL_enabled) return "glsl";
+
+ switch (glConfig.hardwareType)
+ {
+ case GLHW_3DFX_2D3D: return "voodoo";
+ case GLHW_RIVA128: return "riva128";
+ case GLHW_RAGEPRO: return "ragepro";
+ case GLHW_PERMEDIA2: return "permedia2";
+
+ // TODO: case GLHW_POWERVR: return "powervr";
+
+ default: return NULL;
+ }
+}
+
/*
====================
ScanAndLoadShaderFiles
@@ -4273,20 +4292,44 @@
=====================
*/
#define MAX_SHADER_FILES 4096
+#define MAX_HW_SHADER_FILES 1024
static void ScanAndLoadShaderFiles( void )
{
char **shaderFiles;
- char *buffers[MAX_SHADER_FILES];
+ char *buffers[MAX_SHADER_FILES + MAX_HW_SHADER_FILES];
char *p;
int numShaderFiles;
int i;
char *oldp, *token, *hashMem, *textEnd;
+ char *hw_name;
+ char ** hwShaderFiles;
+ int numHWShaderFiles;
int shaderTextHashTableSizes[MAX_SHADERTEXT_HASH], hash, size;
long sum = 0, summand;
// scan for shader files
shaderFiles = ri.FS_ListFiles( "scripts", ".shader", &numShaderFiles );
+ // andrewj: add hardware-specific shaders
+ hw_name = GetHardwareName();
+
+ if ( hw_name && hw_name[0] )
+ {
+ char hw_directory[128];
+ Com_sprintf( hw_directory, sizeof( hw_directory ), "hardware/%s/scripts", hw_name );
+
+ hwShaderFiles = ri.FS_ListFiles( hw_directory, ".shader", &numHWShaderFiles );
+
+ if ( numHWShaderFiles > MAX_HW_SHADER_FILES ) {
+ numHWShaderFiles = MAX_HW_SHADER_FILES;
+ }
+ }
+ else
+ {
+ hwShaderFiles = NULL;
+ numHWShaderFiles = 0;
+ }
+
if ( !shaderFiles || !numShaderFiles )
{
ri.Printf( PRINT_WARNING, "WARNING: no shader files found\n" );
@@ -4298,14 +4341,18 @@
}
// load and parse shader files
- for ( i = 0; i < numShaderFiles; i++ )
+ for ( i = 0; i < numShaderFiles + numHWShaderFiles; i++ )
{
char filename[MAX_QPATH];
- Com_sprintf( filename, sizeof( filename ), "scripts/%s", shaderFiles[i] );
+ if (i < numHWShaderFiles)
+ Com_sprintf( filename, sizeof( filename ), "hardware/%s/scripts/%s", hw_name, hwShaderFiles[i] );
+ else
+ Com_sprintf( filename, sizeof( filename ), "scripts/%s", shaderFiles[i - numHWShaderFiles] );
+
ri.Printf( PRINT_DEVELOPER, "...loading '%s'\n", filename );
summand = ri.FS_ReadFile( filename, (void **)&buffers[i] );
-
+
if ( !buffers[i] )
ri.Error( ERR_DROP, "Couldn't load %s", filename );
@@ -4338,28 +4385,39 @@
sum += summand;
}
+ numShaderFiles += numHWShaderFiles;
+
// build single large buffer
s_shaderText = ri.Hunk_Alloc( sum + numShaderFiles*2, h_low );
s_shaderText[ 0 ] = '\0';
textEnd = s_shaderText;
- // free in reverse order, so the temp files are all dumped
- for ( i = numShaderFiles - 1; i >= 0 ; i-- )
+ // andrewj: changed this to append in forward order, which means that individual
+ // shaders defined in later paks can properly override earlier ones.
+ for ( i = 0 ; i < numShaderFiles ; i++ )
{
- if ( !buffers[i] )
- continue;
+ if ( buffers[i] )
+ {
+ strcat( textEnd, buffers[i] );
+ strcat( textEnd, "\n" );
- strcat( textEnd, buffers[i] );
- strcat( textEnd, "\n" );
- textEnd += strlen( textEnd );
- ri.FS_FreeFile( buffers[i] );
+ textEnd += strlen( textEnd );
+ }
}
+ // free in reverse order, so the temp files are all dumped
+ for ( i = numShaderFiles - 1; i >= 0 ; i-- )
+ if ( buffers[i] )
+ ri.FS_FreeFile( buffers[i] );
+
COM_Compress( s_shaderText );
// free up memory
ri.FS_FreeFileList( shaderFiles );
+ if ( hwShaderFiles )
+ ri.FS_FreeFileList( hwShaderFiles );
+
Com_Memset(shaderTextHashTableSizes, 0, sizeof(shaderTextHashTableSizes));
size = 0;