-#ifdef SUPPORTD3D
-
-#ifdef SUPPORTD3D
-#include <d3d9.h>
-extern LPDIRECT3DDEVICE9 vid_d3d9dev;
-extern D3DCAPS9 vid_d3d9caps;
-#endif
-
-struct r_hlsl_permutation_s;
-typedef struct r_hlsl_permutation_s
-{
- /// hash lookup data
- struct r_hlsl_permutation_s *hashnext;
- unsigned int mode;
- unsigned int permutation;
-
- /// indicates if we have tried compiling this permutation already
- qboolean compiled;
- /// NULL if compilation failed
- IDirect3DVertexShader9 *vertexshader;
- IDirect3DPixelShader9 *pixelshader;
-}
-r_hlsl_permutation_t;
-
-typedef enum D3DVSREGISTER_e
-{
- D3DVSREGISTER_TexMatrix = 0, // float4x4
- D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
- D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
- D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
- D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
- D3DVSREGISTER_ModelToLight = 20, // float4x4
- D3DVSREGISTER_EyePosition = 24,
- D3DVSREGISTER_FogPlane = 25,
- D3DVSREGISTER_LightDir = 26,
- D3DVSREGISTER_LightPosition = 27,
-}
-D3DVSREGISTER_t;
-
-typedef enum D3DPSREGISTER_e
-{
- D3DPSREGISTER_Alpha = 0,
- D3DPSREGISTER_BloomBlur_Parameters = 1,
- D3DPSREGISTER_ClientTime = 2,
- D3DPSREGISTER_Color_Ambient = 3,
- D3DPSREGISTER_Color_Diffuse = 4,
- D3DPSREGISTER_Color_Specular = 5,
- D3DPSREGISTER_Color_Glow = 6,
- D3DPSREGISTER_Color_Pants = 7,
- D3DPSREGISTER_Color_Shirt = 8,
- D3DPSREGISTER_DeferredColor_Ambient = 9,
- D3DPSREGISTER_DeferredColor_Diffuse = 10,
- D3DPSREGISTER_DeferredColor_Specular = 11,
- D3DPSREGISTER_DeferredMod_Diffuse = 12,
- D3DPSREGISTER_DeferredMod_Specular = 13,
- D3DPSREGISTER_DistortScaleRefractReflect = 14,
- D3DPSREGISTER_EyePosition = 15, // unused
- D3DPSREGISTER_FogColor = 16,
- D3DPSREGISTER_FogHeightFade = 17,
- D3DPSREGISTER_FogPlane = 18,
- D3DPSREGISTER_FogPlaneViewDist = 19,
- D3DPSREGISTER_FogRangeRecip = 20,
- D3DPSREGISTER_LightColor = 21,
- D3DPSREGISTER_LightDir = 22, // unused
- D3DPSREGISTER_LightPosition = 23,
- D3DPSREGISTER_OffsetMapping_Scale = 24,
- D3DPSREGISTER_PixelSize = 25,
- D3DPSREGISTER_ReflectColor = 26,
- D3DPSREGISTER_ReflectFactor = 27,
- D3DPSREGISTER_ReflectOffset = 28,
- D3DPSREGISTER_RefractColor = 29,
- D3DPSREGISTER_Saturation = 30,
- D3DPSREGISTER_ScreenCenterRefractReflect = 31,
- D3DPSREGISTER_ScreenScaleRefractReflect = 32,
- D3DPSREGISTER_ScreenToDepth = 33,
- D3DPSREGISTER_ShadowMap_Parameters = 34,
- D3DPSREGISTER_ShadowMap_TextureScale = 35,
- D3DPSREGISTER_SpecularPower = 36,
- D3DPSREGISTER_UserVec1 = 37,
- D3DPSREGISTER_UserVec2 = 38,
- D3DPSREGISTER_UserVec3 = 39,
- D3DPSREGISTER_UserVec4 = 40,
- D3DPSREGISTER_ViewTintColor = 41,
- D3DPSREGISTER_PixelToScreenTexCoord = 42,
- D3DPSREGISTER_BloomColorSubtract = 43,
- D3DPSREGISTER_ViewToLight = 44, // float4x4
- D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
- // next at 52
-}
-D3DPSREGISTER_t;
-
-/// information about each possible shader permutation
-r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
-/// currently selected permutation
-r_hlsl_permutation_t *r_hlsl_permutation;
-/// storage for permutations linked in the hash table
-memexpandablearray_t r_hlsl_permutationarray;
-
-static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
-{
- //unsigned int hashdepth = 0;
- unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
- r_hlsl_permutation_t *p;
- for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
- {
- if (p->mode == mode && p->permutation == permutation)
- {
- //if (hashdepth > 10)
- // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
- return p;
- }
- //hashdepth++;
- }
- p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
- p->mode = mode;
- p->permutation = permutation;
- p->hashnext = r_hlsl_permutationhash[mode][hashindex];
- r_hlsl_permutationhash[mode][hashindex] = p;
- //if (hashdepth > 10)
- // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
- return p;
-}
-
-static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
-{
- char *shaderstring;
- if (!filename || !filename[0])
- return NULL;
- if (!strcmp(filename, "hlsl/default.hlsl"))
- {
- if (!hlslshaderstring)
- {
- hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
- if (hlslshaderstring)
- Con_DPrintf("Loading shaders from file %s...\n", filename);
- else
- hlslshaderstring = (char *)builtincgshaderstring;
- }
- shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
- memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
- return shaderstring;
- }
- shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
- if (shaderstring)
- {
- if (printfromdisknotice)
- Con_DPrintf("from disk %s... ", filename);
- return shaderstring;
- }
- return shaderstring;
-}
-
-#include <d3dx9.h>
-#include <d3dx9mesh.h>
-#pragma comment(lib, "d3dx9.lib")
-
-static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
-{
- DWORD *vsbin = NULL;
- DWORD *psbin = NULL;
- fs_offset_t vsbinsize;
- fs_offset_t psbinsize;
-// IDirect3DVertexShader9 *vs = NULL;
-// IDirect3DPixelShader9 *ps = NULL;
- ID3DXBuffer *vslog = NULL;
- ID3DXBuffer *vsbuffer = NULL;
- ID3DXConstantTable *vsconstanttable = NULL;
- ID3DXBuffer *pslog = NULL;
- ID3DXBuffer *psbuffer = NULL;
- ID3DXConstantTable *psconstanttable = NULL;
- int vsresult = 0;
- int psresult = 0;
- char temp[MAX_INPUTLINE];
- const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
- if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
- if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
- vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
- psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
- if ((!vsbin && vertstring) || (!psbin && fragstring))
- {
- vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
- psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
- if (vertstring && vertstring[0])
- {
- vsresult = D3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, 0, &vsbuffer, &vslog, &vsconstanttable);
- if (vsbuffer)
- {
- vsbinsize = vsbuffer->GetBufferSize();
- vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
- memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
- vsbuffer->Release();
- }
- if (vslog)
- {
- strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
- Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
- vslog->Release();
- }
- }
- if (fragstring && fragstring[0])
- {
- psresult = D3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, 0, &psbuffer, &pslog, &psconstanttable);
- if (psbuffer)
- {
- psbinsize = psbuffer->GetBufferSize();
- psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
- memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
- psbuffer->Release();
- }
- if (pslog)
- {
- strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
- Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
- pslog->Release();
- }
- }
- }
- if (vsbin)
- {
- vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
- if (FAILED(vsresult))
- Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
- }
- if (psbin)
- {
- psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
- if (FAILED(psresult))
- Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
- }
- // free the shader data
- vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
- psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
-}
-
-static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
-{
- int i;
- shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
- int vertstrings_count = 0, vertstring_length = 0;
- int geomstrings_count = 0, geomstring_length = 0;
- int fragstrings_count = 0, fragstring_length = 0;
- char *t;
- char *vertexstring, *geometrystring, *fragmentstring;
- char *vertstring, *geomstring, *fragstring;
- const char *vertstrings_list[32+3];
- const char *geomstrings_list[32+3];
- const char *fragstrings_list[32+3];
- char permutationname[256];
- char cachename[256];
-
- if (p->compiled)
- return;
- p->compiled = true;
- p->vertexshader = NULL;
- p->pixelshader = NULL;
-
- permutationname[0] = 0;
- cachename[0] = 0;
- vertexstring = R_HLSL_GetText(modeinfo->vertexfilename, true);
- geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
- fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
-
- strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
- strlcat(cachename, "hlsl/", sizeof(cachename));
-
- // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
- vertstrings_list[vertstrings_count++] = "#define HLSL\n";
- geomstrings_list[geomstrings_count++] = "#define HLSL\n";
- fragstrings_list[fragstrings_count++] = "#define HLSL\n";
-
- // the first pretext is which type of shader to compile as
- // (later these will all be bound together as a program object)
- vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
- geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
- fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
-
- // the second pretext is the mode (for example a light source)
- vertstrings_list[vertstrings_count++] = modeinfo->pretext;
- geomstrings_list[geomstrings_count++] = modeinfo->pretext;
- fragstrings_list[fragstrings_count++] = modeinfo->pretext;
- strlcat(permutationname, modeinfo->name, sizeof(permutationname));
- strlcat(cachename, modeinfo->name, sizeof(cachename));
-
- // now add all the permutation pretexts
- for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
- {
- if (permutation & (1<<i))
- {
- vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
- geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
- fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
- strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
- strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
- }
- else
- {
- // keep line numbers correct
- vertstrings_list[vertstrings_count++] = "\n";
- geomstrings_list[geomstrings_count++] = "\n";
- fragstrings_list[fragstrings_count++] = "\n";
- }
- }
-
- // replace spaces in the cachename with _ characters
- for (i = 0;cachename[i];i++)
- if (cachename[i] == ' ')
- cachename[i] = '_';
-
- // now append the shader text itself
- vertstrings_list[vertstrings_count++] = vertexstring;
- geomstrings_list[geomstrings_count++] = geometrystring;
- fragstrings_list[fragstrings_count++] = fragmentstring;
-
- // if any sources were NULL, clear the respective list
- if (!vertexstring)
- vertstrings_count = 0;
- if (!geometrystring)
- geomstrings_count = 0;
- if (!fragmentstring)
- fragstrings_count = 0;
-
- vertstring_length = 0;
- for (i = 0;i < vertstrings_count;i++)
- vertstring_length += strlen(vertstrings_list[i]);
- vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
- for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
- memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
-
- geomstring_length = 0;
- for (i = 0;i < geomstrings_count;i++)
- geomstring_length += strlen(geomstrings_list[i]);
- geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
- for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
- memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
-
- fragstring_length = 0;
- for (i = 0;i < fragstrings_count;i++)
- fragstring_length += strlen(fragstrings_list[i]);
- fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
- for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
- memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
-
- // try to load the cached shader, or generate one
- R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
-
- if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
- Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
- else
- Con_Printf("^1HLSL shader %s failed! some features may not work properly.\n", permutationname);
-
- // free the strings
- if (vertstring)
- Mem_Free(vertstring);
- if (geomstring)
- Mem_Free(geomstring);
- if (fragstring)
- Mem_Free(fragstring);
- if (vertexstring)
- Mem_Free(vertexstring);
- if (geometrystring)
- Mem_Free(geometrystring);
- if (fragmentstring)
- Mem_Free(fragmentstring);
-}
-
-static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
-static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
-static inline void hlslVSSetParameter4f(D3DVSREGISTER_t r, float x, float y, float z, float w) {float temp[4];Vector4Set(temp, x, y, z, w);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
-static inline void hlslVSSetParameter3f(D3DVSREGISTER_t r, float x, float y, float z) {float temp[4];Vector4Set(temp, x, y, z, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
-static inline void hlslVSSetParameter2f(D3DVSREGISTER_t r, float x, float y) {float temp[4];Vector4Set(temp, x, y, 0, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
-static inline void hlslVSSetParameter1f(D3DVSREGISTER_t r, float x) {float temp[4];Vector4Set(temp, x, 0, 0, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
-
-static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
-static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
-static inline void hlslPSSetParameter4f(D3DPSREGISTER_t r, float x, float y, float z, float w) {float temp[4];Vector4Set(temp, x, y, z, w);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
-static inline void hlslPSSetParameter3f(D3DPSREGISTER_t r, float x, float y, float z) {float temp[4];Vector4Set(temp, x, y, z, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
-static inline void hlslPSSetParameter2f(D3DPSREGISTER_t r, float x, float y) {float temp[4];Vector4Set(temp, x, y, 0, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
-static inline void hlslPSSetParameter1f(D3DPSREGISTER_t r, float x) {float temp[4];Vector4Set(temp, x, 0, 0, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
-
-void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
-{
- r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
- if (r_hlsl_permutation != perm)
- {
- r_hlsl_permutation = perm;
- if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
- {
- if (!r_hlsl_permutation->compiled)
- R_HLSL_CompilePermutation(perm, mode, permutation);
- if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
- {
- // remove features until we find a valid permutation
- int i;
- for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
- {
- // reduce i more quickly whenever it would not remove any bits
- int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
- if (!(permutation & j))
- continue;
- permutation -= j;
- r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
- if (!r_hlsl_permutation->compiled)
- R_HLSL_CompilePermutation(perm, mode, permutation);
- if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
- break;
- }
- if (i >= SHADERPERMUTATION_COUNT)
- {
- //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
- r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
- return; // no bit left to clear, entire mode is broken
- }
- }
- }
- IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
- IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
- }
- hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
- hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
- hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
-}
-#endif
-