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);
#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*/
typedef enum
typedef enum wgroup_e
{
WG_MAIN = 0,
WG_LOADER = 1,

View file

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

View file

@ -149,12 +149,16 @@ qboolean Sys_ConditionSignal(void *condv); //lock first
qboolean Sys_ConditionBroadcast(void *condv); //lock first
void Sys_DestroyConditional(void *condv);
enum wgroup_e;
typedef struct
{
void *(QDECL *CreateMutex)(void);
qboolean (QDECL *LockMutex)(void *mutex);
qboolean (QDECL *UnlockMutex)(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"
} 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 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)
@ -2048,13 +2085,7 @@ typedef struct sgeneric_s
qboolean failed;
} sgeneric_t;
static sgeneric_t *sgenerics;
struct sbuiltin_s
{
int qrtype;
int apiver;
char name[MAX_QPATH];
char *body;
} sbuiltins[] =
static struct sbuiltin_s sbuiltins[] =
{
#include "r_bishaders.h"
{QR_NONE}
@ -2155,23 +2186,35 @@ static void Shader_LoadGeneric(sgeneric_t *g, int qrtype)
else
{
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))
{
ver = sbuiltins[i].apiver;
if (l == materialloader_count)
progs = sbuiltins;
else if (materialloader[l].funcs && materialloader[l].funcs->builtinshaders)
progs = materialloader[l].funcs->builtinshaders;
else
continue;
if (ver < sh_config.minver || ver > sh_config.maxver)
if (!(qrenderer==QR_OPENGL&&ver==110))
for (i = 0; *progs[i].name; i++)
{
if (progs[i].qrtype == qrtype && !strcmp(progs[i].name, basicname))
{
ver = progs[i].apiver;
if (ver < sh_config.minver || ver > sh_config.maxver)
if (!(qrenderer==QR_OPENGL&&ver==110))
continue;
TRACE(("Loading Embedded %s\n", g->name));
g->failed = !Shader_LoadPermutations(g->name, &g->prog, progs[i].body, qrtype, ver, blobname);
if (g->failed)
continue;
TRACE(("Loading Embedded %s\n", g->name));
g->failed = !Shader_LoadPermutations(g->name, &g->prog, sbuiltins[i].body, qrtype, ver, blobname);
if (g->failed)
continue;
return;
return;
}
}
}
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);
}
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)
{
char *token = Shader_ParseSensString(ptr);
@ -2847,7 +2901,7 @@ static shaderkey_t shaderkeys[] =
{"glslprogram", Shader_GLSLProgramName, "fte"}, //for renderers that accept embedded glsl
{"hlslprogram", Shader_HLSL9ProgramName, "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).
//dp compat
@ -4353,8 +4407,9 @@ static const char *Shader_Skip(const char *file, const char *shadername, const c
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;
char name[MAX_QPATH];
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)
{
Shader_Reset(ps->s);
Shader_Reset(ps);
if (!strcmp(shortname, "textures/common/clip") || !strcmp(shortname, "textures/common/nodraw") || !strcmp(shortname, "common/nodraw"))
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)
{
size_t offset = 0, length;
@ -7294,8 +7355,15 @@ static qboolean Shader_ParseShader(parsestate_t *ps, const char *parsename)
if (!strcmp(token, ".mat") || !*token)
{
char shaderfile[MAX_QPATH];
size_t i;
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);
file = COM_LoadTempMoreFile(shaderfile, &length);
}
@ -7303,7 +7371,7 @@ static qboolean Shader_ParseShader(parsestate_t *ps, const char *parsename)
file = COM_LoadTempMoreFile(parsename, &length);
if (file)
{
Shader_Reset(ps->s);
Shader_Reset(ps);
token = COM_ParseExt (&file, true, false); //we need to skip over the leading {.
if (*token != '{')
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;
}
Shader_Reset(ps->s);
Shader_Reset(ps);
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_maxshaders;
extern shader_t **r_shaders;

View file

@ -109,7 +109,7 @@ void dumpprogblob(FILE *out, FILE *src)
fprintf(out, "\"");
}
struct shadertype_s
static struct shadertype_s
{
char *abrv;
char *filepattern;
@ -126,12 +126,48 @@ struct shadertype_s
};
//tbh we should precompile the d3d shaders.
int main(void)
static void dumpprogram(FILE *c, const char *progname)
{
FILE *s;
char line[1024];
int a;
printf("%25s: ", progname);
for (a = 0; a < sizeof(shadertype)/sizeof(shadertype[0]); a++)
{
sprintf(line, shadertype[a].filepattern, progname);
if (shadertype[a].apiversion == -1)
s = fopen(line, "rb");
else
s = fopen(line, "rt");
if (!s)
{
printf("%4s", "");
continue;
}
fprintf(c, "#ifdef %s\n", shadertype[a].preprocessor);
fprintf(c, "{%s, %i, \"%s\",\n", shadertype[a].rendererapi, shadertype[a].apiversion, progname);
if (shadertype[a].apiversion == -1)
dumpprogblob(c,s);
else
dumpprogstring(c, s);
fputs("},\n", c);
fprintf(c, "#endif\n");
fclose(s);
fflush(c);
printf("%4s", shadertype[a].abrv);
}
printf("\n");
}
int main(int argc, const char **argv)
{
FILE *c, *s;
char line[1024];
int i, j, a;
c = fopen("../gl/r_bishaders.h", "wt");
const char *outname = ((argc>1)?argv[1]:"../gl/r_bishaders.h");
c = fopen(outname, "wt");
if (!c)
{
@ -141,35 +177,15 @@ int main(void)
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++)
{
sprintf(line, shadertype[a].filepattern, shaders[i]);
if (shadertype[a].apiversion == -1)
s = fopen(line, "rb");
else
s = fopen(line, "rt");
if (!s)
{
printf("%4s", "");
continue;
}
fprintf(c, "#ifdef %s\n", shadertype[a].preprocessor);
fprintf(c, "{%s, %i, \"%s\",\n", shadertype[a].rendererapi, shadertype[a].apiversion, shaders[i]);
if (shadertype[a].apiversion == -1)
dumpprogblob(c,s);
else
dumpprogstring(c, s);
fputs("},\n", c);
fprintf(c, "#endif\n");
fclose(s);
fflush(c);
printf("%4s", shadertype[a].abrv);
}
printf("\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);

View file

@ -349,6 +349,8 @@ typedef struct //for plugins that need to read/write files...
//helpers
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(unsigned int,BlockChecksum,(const void *buffer, int length)); //mostly for pack hashes.
F(qbyte*, LoadFile, (const char *fname, size_t *fsize)); //plugfuncs->Free