1
0
Fork 0
forked from fte/fteqw

Allow plugins to provide material interpreters.

git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@6105 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
Spoike 2021-11-03 20:31:41 +00:00
parent 022e42c6c7
commit a9a4e3c358
7 changed files with 176 additions and 60 deletions

View file

@ -364,7 +364,7 @@ extern cvar_t worker_flush;
qboolean COM_DoWork(int thread, qboolean leavelocked); qboolean COM_DoWork(int thread, qboolean leavelocked);
#define COM_MainThreadWork() while (COM_DoWork(0, false) && worker_flush.ival) /*called each frame to do any gl uploads or whatever*/ #define COM_MainThreadWork() while (COM_DoWork(0, false) && worker_flush.ival) /*called each frame to do any gl uploads or whatever*/
#define COM_MainThreadFlush() while (COM_DoWork(0, false)) /*make sure the main thread has done ALL work pending*/ #define COM_MainThreadFlush() while (COM_DoWork(0, false)) /*make sure the main thread has done ALL work pending*/
typedef enum typedef enum wgroup_e
{ {
WG_MAIN = 0, WG_MAIN = 0,
WG_LOADER = 1, WG_LOADER = 1,

View file

@ -408,6 +408,8 @@ static qboolean QDECL PlugBI_ExportInterface(const char *name, void *interfacept
return R_RegisterVRDriver(currentplug, interfaceptr); return R_RegisterVRDriver(currentplug, interfaceptr);
if (!strcmp(name, plugimageloaderfuncs_name)) if (!strcmp(name, plugimageloaderfuncs_name))
return Image_RegisterLoader(currentplug, interfaceptr); return Image_RegisterLoader(currentplug, interfaceptr);
if (!strcmp(name, plugmaterialloaderfuncs_name))
return Material_RegisterLoader(currentplug, interfaceptr);
#endif #endif
#ifdef PACKAGEMANAGER #ifdef PACKAGEMANAGER
if (!strcmp(name, plugupdatesourcefuncs_name)) if (!strcmp(name, plugupdatesourcefuncs_name))
@ -1536,6 +1538,7 @@ void Plug_Close(plugin_t *plug)
#ifdef HAVE_CLIENT #ifdef HAVE_CLIENT
S_UnregisterSoundInputModule(plug); S_UnregisterSoundInputModule(plug);
Image_RegisterLoader(plug, NULL); Image_RegisterLoader(plug, NULL);
Material_RegisterLoader(plug, NULL);
#endif #endif
NET_RegisterCrypto(plug, NULL); NET_RegisterCrypto(plug, NULL);
#ifdef PACKAGEMANAGER #ifdef PACKAGEMANAGER
@ -1869,6 +1872,8 @@ static void *QDECL PlugBI_GetEngineInterface(const char *interfacename, size_t s
COM_EnumerateFiles, COM_EnumerateFiles,
wildcmp, wildcmp,
COM_GetFileExtension,
COM_FileBase,
COM_CleanUpPath, COM_CleanUpPath,
Com_BlockChecksum, Com_BlockChecksum,
FS_LoadMallocFile, FS_LoadMallocFile,
@ -2044,7 +2049,10 @@ static void *QDECL PlugBI_GetEngineInterface(const char *interfacename, size_t s
Sys_CreateMutex, Sys_CreateMutex,
Sys_LockMutex, Sys_LockMutex,
Sys_UnlockMutex, Sys_UnlockMutex,
Sys_DestroyMutex Sys_DestroyMutex,
COM_AddWork,
COM_WorkerPartialSync,
}; };
if (structsize == sizeof(funcs)) if (structsize == sizeof(funcs))

View file

@ -149,12 +149,16 @@ qboolean Sys_ConditionSignal(void *condv); //lock first
qboolean Sys_ConditionBroadcast(void *condv); //lock first qboolean Sys_ConditionBroadcast(void *condv); //lock first
void Sys_DestroyConditional(void *condv); void Sys_DestroyConditional(void *condv);
enum wgroup_e;
typedef struct typedef struct
{ {
void *(QDECL *CreateMutex)(void); void *(QDECL *CreateMutex)(void);
qboolean (QDECL *LockMutex)(void *mutex); qboolean (QDECL *LockMutex)(void *mutex);
qboolean (QDECL *UnlockMutex)(void *mutex); qboolean (QDECL *UnlockMutex)(void *mutex);
void (QDECL *DestroyMutex)(void *mutex); void (QDECL *DestroyMutex)(void *mutex);
void (*AddWork)(enum wgroup_e thread, void(*func)(void *ctx, void *data, size_t a, size_t b), void *ctx, void *data, size_t a, size_t b); //low priority
void (*WaitForCompletion)(void *priorityctx, int *address, int sleepwhilevalue);
#define plugthreadfuncs_name "Threading" #define plugthreadfuncs_name "Threading"
} plugthreadfuncs_t; } plugthreadfuncs_t;

View file

@ -297,6 +297,43 @@ static qboolean Shader_LocateSource(const char *name, const char **buf, size_t *
static void Shader_ReadShader(parsestate_t *ps, const char *shadersource, shadercachefile_t *sourcefile); static void Shader_ReadShader(parsestate_t *ps, const char *shadersource, shadercachefile_t *sourcefile);
static qboolean Shader_ParseShader(parsestate_t *ps, const char *parsename); static qboolean Shader_ParseShader(parsestate_t *ps, const char *parsename);
static struct
{
void *module;
plugmaterialloaderfuncs_t *funcs;
} *materialloader;
static size_t materialloader_count;
qboolean Material_RegisterLoader(void *module, plugmaterialloaderfuncs_t *driver)
{
int i;
if (!driver)
{
for (i = 0; i < materialloader_count; )
{
if (materialloader[i].module == module)
{
memmove(&materialloader[i], &materialloader[i+1], materialloader_count-(i+1));
materialloader_count--;
}
else
i++;
}
return true;
}
else
{
void *n = BZ_Malloc(sizeof(*materialloader)*(materialloader_count+1));
memcpy(n, materialloader, sizeof(*materialloader)*materialloader_count);
Z_Free(materialloader);
materialloader = n;
materialloader[materialloader_count].module = module;
materialloader[materialloader_count].funcs = driver;
materialloader_count++;
return true;
}
}
//=========================================================================== //===========================================================================
static qboolean Shader_EvaluateCondition(shader_t *shader, const char **ptr) static qboolean Shader_EvaluateCondition(shader_t *shader, const char **ptr)
@ -2048,13 +2085,7 @@ typedef struct sgeneric_s
qboolean failed; qboolean failed;
} sgeneric_t; } sgeneric_t;
static sgeneric_t *sgenerics; static sgeneric_t *sgenerics;
struct sbuiltin_s static struct sbuiltin_s sbuiltins[] =
{
int qrtype;
int apiver;
char name[MAX_QPATH];
char *body;
} sbuiltins[] =
{ {
#include "r_bishaders.h" #include "r_bishaders.h"
{QR_NONE} {QR_NONE}
@ -2155,18 +2186,29 @@ static void Shader_LoadGeneric(sgeneric_t *g, int qrtype)
else else
{ {
int ver; int ver;
for (i = 0; *sbuiltins[i].name; i++) const struct sbuiltin_s *progs;
unsigned int l;
for (l = 0; l <= materialloader_count; l++)
{ {
if (sbuiltins[i].qrtype == qrtype && !strcmp(sbuiltins[i].name, basicname)) if (l == materialloader_count)
progs = sbuiltins;
else if (materialloader[l].funcs && materialloader[l].funcs->builtinshaders)
progs = materialloader[l].funcs->builtinshaders;
else
continue;
for (i = 0; *progs[i].name; i++)
{ {
ver = sbuiltins[i].apiver; if (progs[i].qrtype == qrtype && !strcmp(progs[i].name, basicname))
{
ver = progs[i].apiver;
if (ver < sh_config.minver || ver > sh_config.maxver) if (ver < sh_config.minver || ver > sh_config.maxver)
if (!(qrenderer==QR_OPENGL&&ver==110)) if (!(qrenderer==QR_OPENGL&&ver==110))
continue; continue;
TRACE(("Loading Embedded %s\n", g->name)); TRACE(("Loading Embedded %s\n", g->name));
g->failed = !Shader_LoadPermutations(g->name, &g->prog, sbuiltins[i].body, qrtype, ver, blobname); g->failed = !Shader_LoadPermutations(g->name, &g->prog, progs[i].body, qrtype, ver, blobname);
if (g->failed) if (g->failed)
continue; continue;
@ -2174,6 +2216,7 @@ static void Shader_LoadGeneric(sgeneric_t *g, int qrtype)
return; return;
} }
} }
}
TRACE(("Program unloadable %s\n", g->name)); TRACE(("Program unloadable %s\n", g->name));
} }
} }
@ -2489,6 +2532,17 @@ static void Shader_HLSL11ProgramName (parsestate_t *ps, const char **ptr)
Shader_SLProgramName(shader,pass,ptr,QR_DIRECT3D11); Shader_SLProgramName(shader,pass,ptr,QR_DIRECT3D11);
} }
static void Shaderpass_BlendFunc (parsestate_t *ps, const char **ptr);
static void Shader_ProgBlendFunc (parsestate_t *ps, const char **ptr)
{
if (ps->s->prog)
{
ps->pass = ps->s->passes;
Shaderpass_BlendFunc(ps, ptr);
ps->pass = NULL;
}
}
static void Shader_ReflectCube(parsestate_t *ps, const char **ptr) static void Shader_ReflectCube(parsestate_t *ps, const char **ptr)
{ {
char *token = Shader_ParseSensString(ptr); char *token = Shader_ParseSensString(ptr);
@ -2847,7 +2901,7 @@ static shaderkey_t shaderkeys[] =
{"glslprogram", Shader_GLSLProgramName, "fte"}, //for renderers that accept embedded glsl {"glslprogram", Shader_GLSLProgramName, "fte"}, //for renderers that accept embedded glsl
{"hlslprogram", Shader_HLSL9ProgramName, "fte"}, //for d3d with embedded hlsl {"hlslprogram", Shader_HLSL9ProgramName, "fte"}, //for d3d with embedded hlsl
{"hlsl11program", Shader_HLSL11ProgramName, "fte"}, //for d3d with embedded hlsl {"hlsl11program", Shader_HLSL11ProgramName, "fte"}, //for d3d with embedded hlsl
// {"progblendfunc", Shader_ProgBlendFunc, "fte"}, //specifies the blend mode (actually just overrides the first subpasses' blendmode. {"progblendfunc", Shader_ProgBlendFunc, "fte"}, //specifies the blend mode (actually just overrides the first subpasses' blendmode.
// {"progmap", Shader_ProgMap, "fte"}, //avoids needing extra subpasses (actually just inserts an extra pass). // {"progmap", Shader_ProgMap, "fte"}, //avoids needing extra subpasses (actually just inserts an extra pass).
//dp compat //dp compat
@ -4353,8 +4407,9 @@ static const char *Shader_Skip(const char *file, const char *shadername, const c
return ptr; return ptr;
} }
static void Shader_Reset(shader_t *s) static void Shader_Reset(parsestate_t *ps)
{ {
shader_t *s = ps->s;
extern cvar_t r_refractreflect_scale; extern cvar_t r_refractreflect_scale;
char name[MAX_QPATH]; char name[MAX_QPATH];
int id = s->id; int id = s->id;
@ -4393,7 +4448,7 @@ static void Shader_Reset(shader_t *s)
static void Shader_Regenerate(parsestate_t *ps, const char *shortname) static void Shader_Regenerate(parsestate_t *ps, const char *shortname)
{ {
Shader_Reset(ps->s); Shader_Reset(ps);
if (!strcmp(shortname, "textures/common/clip") || !strcmp(shortname, "textures/common/nodraw") || !strcmp(shortname, "common/nodraw")) if (!strcmp(shortname, "textures/common/clip") || !strcmp(shortname, "textures/common/nodraw") || !strcmp(shortname, "common/nodraw"))
Shader_DefaultScript(ps, shortname, Shader_DefaultScript(ps, shortname,
@ -7279,6 +7334,12 @@ static void Shader_ReadShader(parsestate_t *ps, const char *shadersource, shader
} }
} }
static void Shader_LoadMaterialString(parsestate_t *ps, const char *shadertext)
{ //callback for our external material loaders.
Shader_Reset(ps);
Shader_ReadShader(ps, shadertext, NULL);
}
static qboolean Shader_ParseShader(parsestate_t *ps, const char *parsename) static qboolean Shader_ParseShader(parsestate_t *ps, const char *parsename)
{ {
size_t offset = 0, length; size_t offset = 0, length;
@ -7294,8 +7355,15 @@ static qboolean Shader_ParseShader(parsestate_t *ps, const char *parsename)
if (!strcmp(token, ".mat") || !*token) if (!strcmp(token, ".mat") || !*token)
{ {
char shaderfile[MAX_QPATH]; char shaderfile[MAX_QPATH];
size_t i;
if (!*token) if (!*token)
{ {
for (i = 0; i < materialloader_count; i++)
{
if (materialloader[i].funcs->ReadMaterial(ps, parsename, Shader_LoadMaterialString))
return true;
}
Q_snprintfz(shaderfile, sizeof(shaderfile), "%s.mat", parsename); Q_snprintfz(shaderfile, sizeof(shaderfile), "%s.mat", parsename);
file = COM_LoadTempMoreFile(shaderfile, &length); file = COM_LoadTempMoreFile(shaderfile, &length);
} }
@ -7303,7 +7371,7 @@ static qboolean Shader_ParseShader(parsestate_t *ps, const char *parsename)
file = COM_LoadTempMoreFile(parsename, &length); file = COM_LoadTempMoreFile(parsename, &length);
if (file) if (file)
{ {
Shader_Reset(ps->s); Shader_Reset(ps);
token = COM_ParseExt (&file, true, false); //we need to skip over the leading {. token = COM_ParseExt (&file, true, false); //we need to skip over the leading {.
if (*token != '{') if (*token != '{')
token = COM_ParseExt (&file, true, false); //try again, in case we found some legacy name. token = COM_ParseExt (&file, true, false); //try again, in case we found some legacy name.
@ -7331,7 +7399,7 @@ static qboolean Shader_ParseShader(parsestate_t *ps, const char *parsename)
return false; return false;
} }
Shader_Reset(ps->s); Shader_Reset(ps);
Shader_ReadShader(ps, file, sourcefile); Shader_ReadShader(ps, file, sourcefile);

View file

@ -710,6 +710,24 @@ struct shader_s
*/ */
}; };
struct shaderparsestate_s;
struct sbuiltin_s
{
int qrtype;
int apiver;
char name[MAX_QPATH];
char *body;
};
typedef struct
{
const char *loadername;
qboolean (*ReadMaterial)(struct shaderparsestate_s *ps, const char *filename, void (*LoadMaterialString)(struct shaderparsestate_s *ps, const char *script));
struct sbuiltin_s *builtinshaders;
#define plugmaterialloaderfuncs_name "MaterialLoader"
} plugmaterialloaderfuncs_t;
qboolean Material_RegisterLoader(void *module, plugmaterialloaderfuncs_t *loader);
extern unsigned int r_numshaders; extern unsigned int r_numshaders;
extern unsigned int r_maxshaders; extern unsigned int r_maxshaders;
extern shader_t **r_shaders; extern shader_t **r_shaders;

View file

@ -109,7 +109,7 @@ void dumpprogblob(FILE *out, FILE *src)
fprintf(out, "\""); fprintf(out, "\"");
} }
struct shadertype_s static struct shadertype_s
{ {
char *abrv; char *abrv;
char *filepattern; char *filepattern;
@ -126,27 +126,15 @@ struct shadertype_s
}; };
//tbh we should precompile the d3d shaders. //tbh we should precompile the d3d shaders.
int main(void) static void dumpprogram(FILE *c, const char *progname)
{ {
FILE *c, *s; FILE *s;
char line[1024]; char line[1024];
int i, j, a; int a;
c = fopen("../gl/r_bishaders.h", "wt"); printf("%25s: ", progname);
if (!c)
{
printf("unable to open a file\n");
return 0;
}
fprintf(c, "/*\nWARNING: THIS FILE IS GENERATED BY '"__FILE__"'.\nYOU SHOULD NOT EDIT THIS FILE BY HAND\n*/\n\n");
for (i = 0; *shaders[i]; i++)
{
printf("%25s: ", shaders[i]);
for (a = 0; a < sizeof(shadertype)/sizeof(shadertype[0]); a++) for (a = 0; a < sizeof(shadertype)/sizeof(shadertype[0]); a++)
{ {
sprintf(line, shadertype[a].filepattern, shaders[i]); sprintf(line, shadertype[a].filepattern, progname);
if (shadertype[a].apiversion == -1) if (shadertype[a].apiversion == -1)
s = fopen(line, "rb"); s = fopen(line, "rb");
else else
@ -157,7 +145,7 @@ int main(void)
continue; continue;
} }
fprintf(c, "#ifdef %s\n", shadertype[a].preprocessor); fprintf(c, "#ifdef %s\n", shadertype[a].preprocessor);
fprintf(c, "{%s, %i, \"%s\",\n", shadertype[a].rendererapi, shadertype[a].apiversion, shaders[i]); fprintf(c, "{%s, %i, \"%s\",\n", shadertype[a].rendererapi, shadertype[a].apiversion, progname);
if (shadertype[a].apiversion == -1) if (shadertype[a].apiversion == -1)
dumpprogblob(c,s); dumpprogblob(c,s);
else else
@ -172,6 +160,34 @@ int main(void)
printf("\n"); printf("\n");
} }
int main(int argc, const char **argv)
{
FILE *c, *s;
int i, j, a;
const char *outname = ((argc>1)?argv[1]:"../gl/r_bishaders.h");
c = fopen(outname, "wt");
if (!c)
{
printf("unable to open a file\n");
return 0;
}
fprintf(c, "/*\nWARNING: THIS FILE IS GENERATED BY '"__FILE__"'.\nYOU SHOULD NOT EDIT THIS FILE BY HAND\n*/\n\n");
if (argc>2)
{ //if we're passed a file list on the commandline then just use that (generally for plugins).
for (i = 2; i < argc; i++)
dumpprogram(c, argv[i]);
}
else
{ //use our built in list.
for (i = 0; *shaders[i]; i++)
dumpprogram(c, shaders[i]);
}
fclose(c); fclose(c);
return 0; return 0;

View file

@ -349,6 +349,8 @@ typedef struct //for plugins that need to read/write files...
//helpers //helpers
F(int, WildCmp, (const char *wild, const char *string)); F(int, WildCmp, (const char *wild, const char *string));
F(const char *,GetExtension,(const char *filename, const char *ignoreext));
F(void, FileBase, (const char *in, char *out, int outlen));
F(void, CleanUpPath, (char *str)); F(void, CleanUpPath, (char *str));
F(unsigned int,BlockChecksum,(const void *buffer, int length)); //mostly for pack hashes. F(unsigned int,BlockChecksum,(const void *buffer, int length)); //mostly for pack hashes.
F(qbyte*, LoadFile, (const char *fname, size_t *fsize)); //plugfuncs->Free F(qbyte*, LoadFile, (const char *fname, size_t *fsize)); //plugfuncs->Free