small vulkan perf tweak.

fix capturedemo over vid reloads.
fix playfilm letterboxing issue.
con_printf will now create consoles as needed.
fix .skin compose line.
fix a couple of q3bsp issues
core gl contexts will no longer be given pre-core glsl shaders, is the theory.
qcc now warns about unused fields. use the __used keyword to mark those fields as actually needed. use __unused to allow the qcc to potentially silently strip them.

git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@5166 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
Spoike 2017-11-14 14:37:04 +00:00
parent ceae6e2a6b
commit c7d5695e5e
35 changed files with 418 additions and 220 deletions

View File

@ -1802,7 +1802,6 @@ downloadlist_t *CL_DownloadFailed(const char *name, qdownload_t *qdl)
}
#ifdef PEXT_CHUNKEDDOWNLOADS
#define DLBLOCKSIZE 1024
int CL_DownloadRate(void)
{

View File

@ -3092,7 +3092,12 @@ static qboolean Image_ReadBLPFile(texid_t tex, unsigned int flags, char *fname,
mips->mipcount = miplevel;
}
COM_AddWork(WG_MAIN, Image_LoadTextureMips, tex, mips, 0, 0);
tex->width = w;
tex->height = h;
if (flags & IF_NOWORKER)
Image_LoadTextureMips(tex, mips, 0, 0);
else
COM_AddWork(WG_MAIN, Image_LoadTextureMips, tex, mips, 0, 0);
return true;
}

View File

@ -2623,8 +2623,11 @@ void Key_Event (unsigned int devid, int key, unsigned int unicode, qboolean down
if (Key_Dest_Has(kdm_emenu))
{
M_Keydown (key, unicode);
return;
if (key < K_F1 || key > K_F15)
{ //function keys don't get intercepted by the menu...
M_Keydown (key, unicode);
return;
}
}
#ifdef MENU_DAT
if (Key_Dest_Has(kdm_gmenu))

View File

@ -2585,7 +2585,7 @@ qboolean Media_ShowFilm(void)
ch = 3;
}
R2D_Letterbox(0, 0, vid.pixelwidth, vid.pixelheight, videoshader, cw, ch);
R2D_Letterbox(0, 0, vid.fbvwidth, vid.fbvheight, videoshader, cw, ch);
SCR_SetUpToDrawConsole();
if (scr_con_current)
@ -3778,9 +3778,8 @@ void Media_InitFakeSoundDevice (int speed, int channels, int samplebits)
S_DefaultSpeakerConfiguration(sc);
}
void Media_StopRecordFilm_f (void)
//stops capturing and destroys everything.
static void Media_FlushCapture(void)
{
#ifdef GLQUAKE_PBOS
if (offscreen_format && qrenderer == QR_OPENGL)
@ -3835,6 +3834,20 @@ void Media_StopRecordFilm_f (void)
}
#endif
#ifdef GLQUAKE
if (capturingfbo && qrenderer == QR_OPENGL)
{
GLBE_FBO_Pop(captureoldfbo);
GLBE_FBO_Destroy(&capturefbo);
vid.framebuffer = NULL;
}
#endif
}
void Media_StopRecordFilm_f (void)
{
Media_FlushCapture();
capturingfbo = false;
if (capture_fakesounddevice)
S_ShutdownCard(capture_fakesounddevice);
@ -3850,18 +3863,32 @@ void Media_StopRecordFilm_f (void)
currentcapture_ctx = NULL;
currentcapture_funcs = NULL;
#ifdef GLQUAKE
if (capturingfbo && qrenderer == QR_OPENGL)
{
GLBE_FBO_Pop(captureoldfbo);
GLBE_FBO_Destroy(&capturefbo);
}
#endif
vid.framebuffer = NULL;
capturingfbo = false;
Cvar_ForceCallback(&vid_conautoscale);
}
void Media_VideoRestarting(void)
{
Media_FlushCapture();
}
void Media_VideoRestarted(void)
{
#ifdef GLQUAKE
if (capturingfbo && qrenderer == QR_OPENGL && gl_config.ext_framebuffer_objects)
{ //restore it how it was, if we can.
int w = capturefbo.rb_size[0], h = capturefbo.rb_size[1];
capturingfbo = true;
capturetexture = R2D_RT_Configure("$democapture", w, h, TF_BGRA32, RT_IMAGEFLAGS);
captureoldfbo = GLBE_FBO_Update(&capturefbo, FBO_RB_DEPTH|(Sh_StencilShadowsActive()?FBO_RB_STENCIL:0), &capturetexture, 1, r_nulltex, capturetexture->width, capturetexture->height, 0);
vid.fbpwidth = capturetexture->width;
vid.fbpheight = capturetexture->height;
vid.framebuffer = capturetexture;
}
else
#endif
capturingfbo = false;
if (capturingfbo)
Cvar_ForceCallback(&vid_conautoscale);
}
static void Media_RecordFilm (char *recordingname, qboolean demo)
{
int sndkhz, sndchannels, sndbits;
@ -4067,6 +4094,8 @@ void Media_CaptureDemoEnd(void) {}
qboolean Media_PausedDemo(qboolean fortiming) {return false;}
double Media_TweekCaptureFrameTime(double oldtime, double time) { return oldtime+time ; }
void Media_RecordFrame (void) {}
void Media_VideoRestarting(void) {}
void Media_VideoRestarted(void) {}
#endif

View File

@ -373,6 +373,11 @@ typedef union vboarray_s
unsigned int offs;
} vk;
#endif
struct
{ //matches the biggest version. currently vulkan. this ensures that plugins can allocate model data without caring about renderers.
qint64_t buff;
unsigned int offs;
} pad;
} vboarray_t;
//scissor rects

View File

@ -1070,7 +1070,11 @@ void QCBUILTIN PF_SubConPrintf (pubprogfuncs_t *prinst, struct globalvars_s *pr_
const char *fmt = PR_GetStringOfs(prinst, OFS_PARM1);
console_t *con = Con_FindConsole(conname);
if (!con)
return;
{
con = Con_Create(conname, 0);
if (!con)
return;
}
PF_sprintf_internal(prinst, pr_globals, fmt, 2, outbuf, sizeof(outbuf));
Con_PrintCon(con, outbuf, con->parseflags);
}

View File

@ -1664,7 +1664,7 @@ texid_t R2D_RT_GetTexture(const char *id, unsigned int *width, unsigned int *hei
if (!strcmp(id, "-"))
{
tid = internalrt;
internalrt = r_nulltex;
// internalrt = r_nulltex;
}
else
tid = Image_FindTexture(id, NULL, RT_IMAGEFLAGS);

View File

@ -542,6 +542,8 @@ qboolean Media_PausedDemo (qboolean fortiming);
int Media_Capturing (void);
double Media_TweekCaptureFrameTime(double oldtime, double time);
void Media_WriteCurrentTrack(sizebuf_t *buf);
void Media_VideoRestarting(void);
void Media_VideoRestarted(void);
void MYgluPerspective(double fovx, double fovy, double zNear, double zFar);

View File

@ -455,6 +455,7 @@ cvar_t vk_submissionthread = CVARD ("vk_submissionthread", "", "Execute su
cvar_t vk_debug = CVARD ("vk_debug", "0", "Register a debug handler to display driver/layer messages. 2 enables the standard validation layers.");
cvar_t vk_dualqueue = CVARD ("vk_dualqueue", "", "Attempt to use a separate queue for presentation. Blank for default.");
cvar_t vk_busywait = CVARD ("vk_busywait", "", "Force busy waiting until the GPU finishes doing its thing.");
cvar_t vk_waitfence = CVARD ("vk_waitfence", "", "Waits on fences, instead of semaphores. This is more likely to result in gpu stalls while the cpu waits.");
cvar_t vk_nv_glsl_shader = CVARD ("vk_loadglsl", "", "Enable direct loading of glsl, where supported by drivers. Do not use in combination with vk_debug 2 (vk_debug should be 1 if you want to see any glsl compile errors). Don't forget to do a vid_restart after.");
cvar_t vk_nv_dedicated_allocation = CVARD ("vk_nv_dedicated_allocation", "", "Flag vulkan memory allocations as dedicated, where applicable.");
//cvar_t vk_khr_dedicated_allocation = CVARD ("vk_khr_dedicated_allocation", "", "Flag vulkan memory allocations as dedicated, where applicable.");
@ -981,6 +982,7 @@ void Renderer_Init(void)
Cvar_Register (&vk_debug, VKRENDEREROPTIONS);
Cvar_Register (&vk_dualqueue, VKRENDEREROPTIONS);
Cvar_Register (&vk_busywait, VKRENDEREROPTIONS);
Cvar_Register (&vk_waitfence, VKRENDEREROPTIONS);
Cvar_Register (&vk_nv_glsl_shader, VKRENDEREROPTIONS);
Cvar_Register (&vk_nv_dedicated_allocation, VKRENDEREROPTIONS);
@ -1257,6 +1259,8 @@ void R_ShutdownRenderer(qboolean devicetoo)
IN_Shutdown();
Media_VideoRestarting();
if (R_DeInit)
{
TRACE(("dbg: R_ApplyRenderer: R_DeInit\n"));
@ -1466,6 +1470,7 @@ TRACE(("dbg: R_ApplyRenderer: screen inited\n"));
Sbar_Flush();
IN_ReInit();
Media_VideoRestarted();
Cvar_ForceCallback(&v_gamma);
}

View File

@ -158,7 +158,7 @@ cvar_t snd_voip_showmeter = CVARAFD("cl_voip_showmeter", "1", NULL, CVAR_ARCHIV
cvar_t snd_voip_play = CVARAFCD("cl_voip_play", "1", NULL, CVAR_ARCHIVE, S_Voip_Play_Callback, "Enables voip playback. Value is a volume scaler.");
cvar_t snd_voip_ducking = CVARAFD("cl_voip_ducking", "0.5", NULL, CVAR_ARCHIVE, "Scales game audio by this much when someone is talking to you. Does not affect your speaker volume when you speak (minimum of cl_voip_capturingvol and cl_voip_ducking is used).");
cvar_t snd_voip_micamp = CVARAFD("cl_voip_micamp", "2", NULL, CVAR_ARCHIVE, "Amplifies your microphone when using voip.");
cvar_t snd_voip_codec = CVARAFD("cl_voip_codec", "", NULL, CVAR_ARCHIVE, "0: speex(@11khz). 1: raw. 2: opus. 3: speex(@8khz). 4: speex(@16). 5:speex(@32).");
cvar_t snd_voip_codec = CVARAFD("cl_voip_codec", "", NULL, CVAR_ARCHIVE, "0: speex(@11khz). 1: raw. 2: opus. 3: speex(@8khz). 4: speex(@16). 5:speex(@32). 6: pcma. 7: pcmu.");
cvar_t snd_voip_noisefilter = CVARAFD("cl_voip_noisefilter", "1", NULL, CVAR_ARCHIVE, "Enable the use of the noise cancelation filter.");
cvar_t snd_voip_autogain = CVARAFD("cl_voip_autogain", "0", NULL, CVAR_ARCHIVE, "Attempts to normalize your voice levels to a standard level. Useful for lazy people, but interferes with voice activation levels.");
cvar_t snd_voip_opus_bitrate = CVARAFD("cl_voip_opus_bitrate", "3000", NULL, CVAR_ARCHIVE, "For codecs with non-specific bitrates, this specifies the target bitrate to use.");
@ -1349,6 +1349,7 @@ void S_Voip_Transmit(unsigned char clc, sizebuf_t *buf)
switch(s_voip.enccodec)
{
case VOIP_SPEEX_OLD:
//this is from before I understood speex properly.
level += S_Voip_Preprocess(start, s_voip.encframesize, micamp);
qspeex_bits_reset(&s_voip.speex.encbits);
qspeex_encode_int(s_voip.encoder, start, &s_voip.speex.encbits);
@ -1364,6 +1365,7 @@ void S_Voip_Transmit(unsigned char clc, sizebuf_t *buf)
case VOIP_SPEEX_NARROW:
case VOIP_SPEEX_WIDE:
case VOIP_SPEEX_ULTRAWIDE:
//write multiple speex frames into a single merged frame
qspeex_bits_reset(&s_voip.speex.encbits);
for (; encpos+s_voip.encframesize*2 <= s_voip.capturepos; )
{
@ -1394,6 +1396,7 @@ void S_Voip_Transmit(unsigned char clc, sizebuf_t *buf)
break;
case VOIP_PCMA:
case VOIP_PCMU:
//FIXME: what's with this /2? these are just 8-bit mono (logarithmic) pcm...
len = s_voip.capturepos-encpos; //amount of data to be eaten in this frame
len = min(len, sizeof(outbuf)-outpos);
len = min(len, s_voip.encframesize*2);
@ -1463,6 +1466,8 @@ void S_Voip_Transmit(unsigned char clc, sizebuf_t *buf)
break;
}
//opus has no way to detect the end properly.
//standard rtp favours many small packets.
if (rtpstream || s_voip.enccodec == VOIP_OPUS)
break;
}
@ -1503,10 +1508,20 @@ void S_Voip_Transmit(unsigned char clc, sizebuf_t *buf)
{
if (buf->maxsize - buf->cursize >= 5+outpos)
{
qbyte cgen = ((s_voip.enccodec&0x7)<<4) | (s_voip.generation & 0x0f);
if (s_voip.enccodec >= 8 || 0)
cgen |= 0x80;
MSG_WriteByte(buf, clc);
MSG_WriteByte(buf, (s_voip.enccodec<<4) | (s_voip.generation & 0x0f)); /*gonna leave that nibble clear here... in this version, the client will ignore packets with those bits set. can use them for codec or something*/
MSG_WriteByte(buf, cgen);
MSG_WriteByte(buf, initseq&0xff);
MSG_WriteShort(buf, outpos);
/*if (cgen & 0x80)
{
MSG_WriteShort(buf, 1+outpos);
MSG_WriteByte(buf, s_voip.enccodec>>3);
}
else*/
MSG_WriteShort(buf, outpos); //even with codecs where the size is easy to determine, this is still useful for servers (which are unaware of the actual codec)
SZ_Write(buf, outbuf, outpos);
}
else

View File

@ -776,7 +776,7 @@ qboolean Wad_NextDownload (void)
{
k = wads[i];
wads[i] = 0;
strcpy(wadname+9, &wads[j]);
Q_strncpyz(wadname+9, &wads[j], sizeof(wadname)-9);
if (wadname[9])
{
if (COM_FCheckExists(wadname+9))

View File

@ -488,40 +488,40 @@ typedef struct
// a given brush can contribute multiple content bits
// multiple brushes can be in a single leaf
#define FTECONTENTS_EMPTY 0x00000000
#define FTECONTENTS_SOLID 0x00000001
//q2window 0x00000002
//q2aux 0x00000004
#define FTECONTENTS_LAVA 0x00000008
#define FTECONTENTS_SLIME 0x00000010
#define FTECONTENTS_WATER 0x00000020
#define FTECONTENTS_FLUID (FTECONTENTS_WATER|FTECONTENTS_SLIME|FTECONTENTS_LAVA|FTECONTENTS_SKY) //sky is a fluid for q1 code.
//q2mist 0x00000040
//q3notteam1 0x00000080
//q3notteam2 0x00000100
//q3nobotclip 0x00000200
// 0x00000400
// 0x00000800
// 0x00001000
// 0x00002000
#define FTECONTENTS_LADDER 0x00004000
//q2areaportal,q3areaportal 0x00008000
#define FTECONTENTS_PLAYERCLIP 0x00010000
#define FTECONTENTS_MONSTERCLIP 0x00020000
//q2current0,q3teleporter 0x00040000
//q2current90,q3jumppad 0x00080000
//q2current180,q3clusterportal 0x00100000
//q2current270,q3donotenter 0x00200000
//q2currentup,q3botclip 0x00400000
//q2currentdown,q3mover 0x00800000
//q2origin,q3origin 0x01000000
#define FTECONTENTS_BODY 0x02000000
#define FTECONTENTS_CORPSE 0x04000000
//q2detail,q3detail 0x08000000
//q2translucent,q3structual 0x10000000
//q2ladder,q3translucent 0x20000000
//q3trigger 0x40000000
#define FTECONTENTS_SKY 0x80000000
#define FTECONTENTS_EMPTY 0x00000000
#define FTECONTENTS_SOLID 0x00000001
//q2window 0x00000002
//q2aux 0x00000004
#define FTECONTENTS_LAVA 0x00000008
#define FTECONTENTS_SLIME 0x00000010
#define FTECONTENTS_WATER 0x00000020
#define FTECONTENTS_FLUID (FTECONTENTS_WATER|FTECONTENTS_SLIME|FTECONTENTS_LAVA|FTECONTENTS_SKY) //sky is a fluid for q1 code.
//q2mist 0x00000040
//q3notteam1 0x00000080
//q3notteam2 0x00000100
//q3nobotclip 0x00000200
// 0x00000400
// 0x00000800
// 0x00001000
// 0x00002000
#define FTECONTENTS_LADDER 0x00004000
//q2areaportal,q3areaportal 0x00008000
#define FTECONTENTS_PLAYERCLIP 0x00010000
#define FTECONTENTS_MONSTERCLIP 0x00020000
//q2current0,q3teleporter 0x00040000
//q2current90,q3jumppad 0x00080000
//q2current180,q3clusterportal 0x00100000
//q2current270,q3donotenter 0x00200000
//q2currentup,q3botclip 0x00400000
//q2currentdown,q3mover 0x00800000
//q2origin,q3origin 0x01000000 //could define, but normally removed by compiler, so why?
#define FTECONTENTS_BODY 0x02000000
#define FTECONTENTS_CORPSE 0x04000000
//q2detail,q3detail 0x08000000 //not very useful to us
//q2translucent,q3structual 0x10000000
//q2ladder,q3translucent 0x20000000
//q3trigger 0x40000000
#define FTECONTENTS_SKY/*q3nodrop*/ 0x80000000
// lower bits are stronger, and will eat weaker brushes completely
#define Q2CONTENTS_SOLID FTECONTENTS_SOLID //0x00000001

View File

@ -2805,60 +2805,14 @@ int Mod_CountSkinFiles(model_t *mod)
return i;
}
//support for foo.md3_0.skin
shader_t *Mod_ShaderFromQ3SkinFile(galiasinfo_t *surf, model_t *mod, int skinnum)
{
shader_t *result = NULL;
skinid_t skinid;
skinfile_t *skinfile;
int i;
char *filedata;
char skinfilename[MAX_QPATH];
char *modelname = mod->name;
if (qrenderer == QR_NONE)
return NULL;
Q_snprintfz(skinfilename, sizeof(skinfilename), "%s_%i.skin", modelname, skinnum);
filedata = FS_LoadMallocFile(skinfilename, NULL);
if (!filedata)
{
COM_StripExtension(modelname, skinfilename, sizeof(skinfilename));
Q_snprintfz(skinfilename+strlen(skinfilename), sizeof(skinfilename)-strlen(skinfilename), "_%i.skin", skinnum);
filedata = FS_LoadMallocFile(skinfilename, NULL);
}
if (filedata)
{
skinid = Mod_ReadSkinFile(skinfilename, filedata);
Z_Free(filedata);
skinfile = Mod_LookupSkin(skinid);
if (skinfile)
{
//check if this skinfile has a mapping.
for (i = 0; i < skinfile->nummappings; i++)
{
if (!strcmp(surf->surfacename, skinfile->mappings[i].surface))
{
skinfile->mappings[i].shader->uses++; //so it doesn't blow up when the skin gets freed.
result = skinfile->mappings[i].shader;
break;
}
}
Mod_WipeSkin(skinid);
}
}
return result;
}
void Mod_LoadAliasShaders(model_t *mod)
{
qbyte *mipdata[4];
galiasinfo_t *ai = mod->meshinfo;
galiasskin_t *s;
skinframe_t *f;
int i, j;
int i, j, k;
int numskins;
unsigned int loadflags;
unsigned int imageflags;
@ -2906,15 +2860,64 @@ void Mod_LoadAliasShaders(model_t *mod)
for (ai = mod->meshinfo; ai; ai = ai->nextsurf)
for (ai = mod->meshinfo, numskins = 0; ai; ai = ai->nextsurf)
{
if (numskins < ai->numskins)
numskins = ai->numskins;
Mod_GenerateMeshVBO(ai); //FIXME: shares verts
for (i = 0, s = ai->ofsskins; i < ai->numskins; i++, s++)
}
for (i = 0; i < numskins; i++)
{
shader_t *result = NULL;
skinid_t skinid;
skinfile_t *skinfile;
char *filedata;
char skinfilename[MAX_QPATH];
char *modelname = mod->name;
skinid = 0;
skinfile = NULL;
if (qrenderer != QR_NONE)
{
Q_snprintfz(skinfilename, sizeof(skinfilename), "%s_%i.skin", modelname, i);
filedata = FS_LoadMallocFile(skinfilename, NULL);
if (!filedata)
{
COM_StripExtension(modelname, skinfilename, sizeof(skinfilename));
Q_snprintfz(skinfilename+strlen(skinfilename), sizeof(skinfilename)-strlen(skinfilename), "_%i.skin", i);
filedata = FS_LoadMallocFile(skinfilename, NULL);
}
if (filedata)
{
skinid = Mod_ReadSkinFile(skinfilename, filedata);
Z_Free(filedata);
skinfile = Mod_LookupSkin(skinid);
}
}
for (ai = mod->meshinfo; ai; ai = ai->nextsurf)
{
if (i >= ai->numskins)
continue;
s = ai->ofsskins+i;
for (j = 0, f = s->frame; j < s->numframes; j++, f++)
{
if (j == 0)
f->shader = Mod_ShaderFromQ3SkinFile(ai, mod, i);
if (j == 0 && skinfile)
{
//check if this skinfile has a mapping.
for (k = 0; k < skinfile->nummappings; k++)
{
if (!strcmp(ai->surfacename, skinfile->mappings[k].surface))
{
skinfile->mappings[k].shader->uses++; //so it doesn't blow up when the skin gets freed.
f->shader = skinfile->mappings[k].shader;
f->texnums = skinfile->mappings[k].texnums;
skinfile->mappings[k].needsfree = 0; //don't free any composed texture. it'll live on as part of the model.
break;
}
}
}
else
f->shader = NULL;
if (!f->shader)
@ -2944,6 +2947,7 @@ void Mod_LoadAliasShaders(model_t *mod)
R_BuildDefaultTexnums(&f->texnums, f->shader);
}
}
Mod_WipeSkin(skinid);
}
}
#endif

View File

@ -168,6 +168,7 @@ typedef struct console_s
conchar_t defaultcharbits;
int commandcompletion; //allows tab completion of quake console commands
//WARNING: note that links do NOT represent any sort of security. text can be inserted from anywhere. Its fine to use such things for context, but don't treat them as sescure.
int (*linebuffered) (struct console_s *con, char *line); //if present, called on enter, causes the standard console input to appear. return 2 to not save the line in history.
qboolean (*redirect) (struct console_s *con, unsigned int unicode, int key); //if present, called every character.
qboolean (*mouseover)(struct console_s *con, char **out_tiptext, shader_t **out_shader);

View File

@ -6111,6 +6111,7 @@ void FS_RegisterDefaultFileSystems(void)
FS_RegisterFileSystemType(NULL, "pk4", FSZIP_LoadArchive, true);
FS_RegisterFileSystemType(NULL, "apk", FSZIP_LoadArchive, false);
FS_RegisterFileSystemType(NULL, "zip", FSZIP_LoadArchive, false);
FS_RegisterFileSystemType(NULL, "exe", FSZIP_LoadArchive, false); //for self-extracting zips.
#endif
#ifdef PACKAGE_DOOMWAD
FS_RegisterFileSystemType(NULL, "wad", FSDWD_LoadArchive, true);

View File

@ -3439,13 +3439,20 @@ static qboolean CModQ3_LoadVisibility (model_t *mod, qbyte *mod_base, lump_t *l)
if (l->filelen == 0)
{
int i;
#if 0
//the 'correct' code
numclusters = 0;
for (i = 0; i < mod->numleafs; i++)
if (numclusters <= mod->leafs[i].cluster)
if (numclusters < mod->leafs[i].cluster+1)
numclusters = mod->leafs[i].cluster+1;
numclusters++;
#else
//but its much faster to merge all leafs into a single pvs cluster. no vis is no vis.
numclusters = 2;
for (i = 0; i < mod->numleafs; i++)
mod->leafs[i].cluster = !!mod->leafs[i].cluster;
#endif
prv->q3pvs = ZG_Malloc(&mod->memgroup, sizeof(*prv->q3pvs) + (numclusters+7)/8 * numclusters);
memset (prv->q3pvs, 0xff, sizeof(*prv->q3pvs) + (numclusters+7)/8 * numclusters);
prv->q3pvs->numclusters = numclusters;
@ -3564,7 +3571,7 @@ static void CModQ3_LoadLighting (model_t *loadmodel, qbyte *mod_base, lump_t *l)
}
}
}
for (; m%loadmodel->lightmaps.merge; m++)
/*for (; m%loadmodel->lightmaps.merge; m++)
{
out = loadmodel->lightdata;
//figure out which merged lightmap we're putting it into
@ -3578,7 +3585,7 @@ static void CModQ3_LoadLighting (model_t *loadmodel, qbyte *mod_base, lump_t *l)
out[s+1] = 255;
out[s+2] = 0;
}
}
}*/
}
static qboolean CModQ3_LoadLightgrid (model_t *loadmodel, qbyte *mod_base, lump_t *l)
@ -4199,7 +4206,8 @@ static cmodel_t *CM_LoadMap (model_t *mod, qbyte *filein, size_t filelen, qboole
CModQ3_LoadLighting (mod, mod_base, &header.lumps[Q3LUMP_LIGHTMAPS]); //fixme: duplicated loading.
}
#endif
noerrors = noerrors && CModQ3_LoadMarksurfaces (mod, mod_base, &header.lumps[Q3LUMP_LEAFSURFACES]); noerrors = noerrors && CModQ3_LoadLeafs (mod, mod_base, &header.lumps[Q3LUMP_LEAFS]);
noerrors = noerrors && CModQ3_LoadMarksurfaces (mod, mod_base, &header.lumps[Q3LUMP_LEAFSURFACES]);
noerrors = noerrors && CModQ3_LoadLeafs (mod, mod_base, &header.lumps[Q3LUMP_LEAFS]);
noerrors = noerrors && CModQ3_LoadNodes (mod, mod_base, &header.lumps[Q3LUMP_NODES]);
noerrors = noerrors && CModQ3_LoadSubmodels (mod, mod_base, &header.lumps[Q3LUMP_MODELS]);
noerrors = noerrors && CModQ3_LoadVisibility (mod, mod_base, &header.lumps[Q3LUMP_VISIBILITY]);

View File

@ -472,6 +472,8 @@ enum {
#define DLERR_REDIRECTPACK -5 //client should download the specified package instead.
#define DLERR_PACKAGE -6 //not networked. packages require special file access.
#define DLBLOCKSIZE 1024 //chunked downloads use fixed-size chunks (which I somewhat regret, but too late now I guess, really ought to use ranges.).
//these flags are sent as part of the svc_precache index, for any-time precaches. using the upper two bits means we still have 16k available models/sounds/etc
#define PC_TYPE 0xc000
#define PC_MODEL 0x0000

View File

@ -1080,6 +1080,7 @@
AdditionalIncludeDirectories="../libs/speex;..\client;../libs/freetype2/include;../common;../server;../gl;../sw;../qclib;../libs;../libs/dxsdk9/include;../libs/dxsdk7/include"
PreprocessorDefinitions="NDEBUG;WIN32;_WINDOWS;GLQUAKE;D3D9QUAKE;D3D11QUAKE;SWQUAKE;VKQUAKE;USE_EGL"
StringPooling="true"
ExceptionHandling="0"
RuntimeLibrary="0"
EnableFunctionLevelLinking="true"
FloatingPointModel="2"
@ -1102,6 +1103,7 @@
/>
<Tool
Name="VCLinkerTool"
AdditionalOptions="/DYNAMICBASE /NXCOMPAT"
AdditionalDependencies="comctl32.lib wsock32.lib odbc32.lib odbccp32.lib winmm.lib"
OutputFile="../../fteqw.exe"
LinkIncremental="1"
@ -1517,6 +1519,7 @@
/>
<Tool
Name="VCLinkerTool"
AdditionalOptions="/DYNAMICBASE /NXCOMPAT"
AdditionalDependencies="comctl32.lib wsock32.lib odbc32.lib odbccp32.lib winmm.lib"
OutputFile="../../fteqw_dbg.exe"
LinkIncremental="2"
@ -1527,6 +1530,7 @@
GenerateDebugInformation="true"
GenerateMapFile="true"
SubSystem="2"
LargeAddressAware="2"
TargetMachine="1"
/>
<Tool

View File

@ -85,7 +85,10 @@ void Mod_WipeSkin(skinid_t id)
for (i = 0; i < sk->nummappings; i++)
{
if (sk->mappings[i].needsfree)
{
Image_UnloadTexture(sk->mappings[i].texnums.base);
sk->mappings[i].texnums.base = r_nulltex;
}
R_UnloadShader(sk->mappings[i].shader);
}
Z_Free(registeredskins[id]);
@ -115,16 +118,18 @@ skinfile_t *Mod_LookupSkin(skinid_t id)
return registeredskins[id];
return NULL;
}
static void Mod_ComposeSkin(char *texture, struct cctx_s *cctx)
struct composeline_s
{
shader_t *sourceimg;
vec2_t pos, size;
vec4_t tc;
vec4_t rgba;
};
static void Mod_ParseComposeLine(char *texture, struct composeline_s *line)
{
float x=0, y=0;
float w, h;
int iw=0, ih=0;
float s1 = 0, t1 = 0, s2 = 1, t2 = 1;
float r=1,g=1,b=1,a=1;
int l;
char *s, tname[MAX_QPATH];
shader_t *sourceimg;
for (s = texture; *s; s++)
{
if (*s == '@' || *s == ':' || *s == '?' || *s == '*')
@ -138,59 +143,55 @@ static void Mod_ComposeSkin(char *texture, struct cctx_s *cctx)
tname[l] = 0;
//load the image and set some default sizes, etc.
sourceimg = R2D_SafeCachePic(tname);
if (!sourceimg || R_GetShaderSizes(sourceimg, &iw, &ih, true) != 1) //no shader? no point in doing anything.
{
w = 0;
h = 0;
sourceimg = NULL;
}
if (*tname)
line->sourceimg = R2D_SafeCachePic(tname);
else
{
w = iw;
h = ih;
}
line->sourceimg = NULL;
Vector2Set(line->pos, 0, 0);
Vector2Set(line->size, -1, -1);
Vector4Set(line->tc, 0, 0, 1, 1);
Vector4Set(line->rgba, 1, 1, 1, 1);
while(*s)
{
switch(*s)
{
case '@':
x = strtod(s+1, &s);
line->pos[0] = strtod(s+1, &s);
if (*s == ',')
s++;
y = strtod(s, &s);
line->pos[1] = strtod(s, &s);
break;
case ':':
w = strtod(s+1, &s);
line->size[0] = strtod(s+1, &s);
if (*s == ',')
s++;
h = strtod(s, &s);
line->size[1] = strtod(s, &s);
break;
case '$':
s1 = strtod(s+1, &s);
line->tc[0] = strtod(s+1, &s);
if (*s == ',')
s++;
t1 = strtod(s, &s);
line->tc[1] = strtod(s, &s);
if (*s == ',')
s++;
s2 = strtod(s, &s);
line->tc[2] = strtod(s, &s);
if (*s == ',')
s++;
t2 = strtod(s, &s);
line->tc[3] = strtod(s, &s);
break;
case '?':
r = strtod(s+1, &s);
line->rgba[0] = strtod(s+1, &s);
if (*s == ',')
s++;
g = strtod(s, &s);
line->rgba[1] = strtod(s, &s);
if (*s == ',')
s++;
b = strtod(s, &s);
line->rgba[2] = strtod(s, &s);
if (*s == ',')
s++;
a = strtod(s, &s);
line->rgba[3] = strtod(s, &s);
break;
// case '*':
// break;
@ -199,26 +200,46 @@ static void Mod_ComposeSkin(char *texture, struct cctx_s *cctx)
break;
}
}
}
static void Mod_ComposeSkin(char *texture, struct cctx_s *cctx, struct composeline_s *line)
{
int iw=0, ih=0;
if (!w || !h)
return;
//create a render target if one is not already selected
if (!TEXVALID(cctx->diffuse))
if (!line->sourceimg || R_GetShaderSizes(line->sourceimg, &iw, &ih, false) != 1) //no shader? no point in doing anything.
{
strcpy(r_refdef.rt_destcolour[0].texname, "-");
cctx->width = x+w;
cctx->height = y+h;
cctx->diffuse = R2D_RT_Configure(r_refdef.rt_destcolour[0].texname, cctx->width, cctx->height, TF_RGBA32, RT_IMAGEFLAGS);
BE_RenderToTextureUpdate2d(true);
iw = ih = 0;
line->sourceimg = NULL;
}
if (line->size[0] < 0)
line->size[0] = iw;
if (line->size[1] < 0)
line->size[1] = ih;
if (line->size[0]>0 && line->size[1]>0)
{
//create a render target if one is not already selected
if (!TEXVALID(cctx->diffuse))
{
if (R2D_Flush)
R2D_Flush();
strcpy(r_refdef.rt_destcolour[0].texname, "-");
cctx->width = line->pos[0]+line->size[0];
cctx->height = line->pos[1]+line->size[1];
cctx->diffuse = R2D_RT_Configure(r_refdef.rt_destcolour[0].texname, cctx->width, cctx->height, TF_RGBA32, RT_IMAGEFLAGS);
BE_RenderToTextureUpdate2d(true);
}
if (line->sourceimg)
{
R2D_ImageColours(line->rgba[0],line->rgba[1],line->rgba[2],line->rgba[3]);
R2D_Image(line->pos[0], line->pos[1], line->size[0], line->size[1], line->tc[0], line->tc[1], line->tc[2], line->tc[3], line->sourceimg);
}
}
if (!sourceimg)
return;
R2D_ImageColours(r,g,b,a);
R2D_Image(x, cctx->height-(y+h), w, h, s1, t2, s2, t1, sourceimg);
R_UnloadShader(sourceimg); //we're done with it now
if (R2D_Flush)
R2D_Flush();
R_UnloadShader(line->sourceimg); //we're done with it now
}
//create a new skin with explicit name and text. even if its already loaded. this means you can free it safely.
skinid_t Mod_ReadSkinFile(const char *skinname, const char *skintext)
@ -279,6 +300,8 @@ skinid_t Mod_ReadSkinFile(const char *skinname, const char *skintext)
//body
if (com_tokentype != TTP_LINEENDING)
{
size_t l,lines;
struct composeline_s line[64];
//fixme: this blocks waiting for the textures to load.
struct cctx_s cctx;
memset(&cctx, 0, sizeof(cctx));
@ -290,7 +313,8 @@ skinid_t Mod_ReadSkinFile(const char *skinname, const char *skintext)
R_BuildDefaultTexnums(NULL, skin->mappings[skin->nummappings].shader);
skin->mappings[skin->nummappings].texnums = *skin->mappings[skin->nummappings].shader->defaulttextures;
for(;;)
//parse the lines, and start to load the various shaders.
for(lines = 0;lines<countof(line);)
{
while(*skintext == ' ' || *skintext == '\t')
skintext++;
@ -299,15 +323,20 @@ skinid_t Mod_ReadSkinFile(const char *skinname, const char *skintext)
else
break;
skintext = COM_Parse(skintext);
Mod_ComposeSkin(com_token, &cctx);
Mod_ParseComposeLine(com_token, &line[lines++]);
}
//all the textures should be loading now... block while waiting for them (sucks)
for (l = 0; l < lines; l++)
R_GetShaderSizes(line[l].sourceimg, NULL, NULL, true);
//okay, they're loaded, do the compose now.
for (l = 0; l < lines; l++)
Mod_ComposeSkin(com_token, &cctx, &line[l]);
*r_refdef.rt_destcolour[0].texname = 0;
BE_RenderToTextureUpdate2d(true);
skin->mappings[skin->nummappings].needsfree = 1;
skin->mappings[skin->nummappings].texnums.base = cctx.diffuse;
skin->nummappings++;
*r_refdef.rt_destcolour[0].texname = 0;
BE_RenderToTextureUpdate2d(true);
}
}
else if (!strcmp(com_token, "geomset"))

View File

@ -3705,7 +3705,7 @@ void GLBE_SelectMode(backendmode_t mode)
if (!shaderstate.allblackshader.glsl.handle)
{
const char *defs[] = {NULL};
shaderstate.allblackshader = GLSlang_CreateProgram(NULL, "allblackprogram", gl_config_gles?100:110, defs, "#include \"sys/skeletal.h\"\nvoid main(){gl_Position = skeletaltransform();}", NULL, NULL, NULL, "void main(){gl_FragColor=vec4(0.0,0.0,0.0,1.0);}", false, NULL);
shaderstate.allblackshader = GLSlang_CreateProgram(NULL, "allblackprogram", sh_config.minver, defs, "#include \"sys/skeletal.h\"\nvoid main(){gl_Position = skeletaltransform();}", NULL, NULL, NULL, "void main(){gl_FragColor=vec4(0.0,0.0,0.0,1.0);}", false, NULL);
shaderstate.allblack_mvp = qglGetUniformLocationARB(shaderstate.allblackshader.glsl.handle, "m_modelviewprojection");
}
/*BEM_DEPTHONLY does support mesh writing, but its not the only way its used... FIXME!*/
@ -3734,7 +3734,7 @@ void GLBE_SelectMode(backendmode_t mode)
if (gl_config_nofixedfunc && !shaderstate.allblackshader.glsl.handle)
{
const char *defs[] = {NULL};
shaderstate.allblackshader = GLSlang_CreateProgram(NULL, "allblackprogram", gl_config_gles?100:110, defs, "#include \"sys/skeletal.h\"\nvoid main(){gl_Position = skeletaltransform();}", NULL, NULL, NULL, "void main(){gl_FragColor=vec4(0.0,0.0,0.0,1.0);}", false, NULL);
shaderstate.allblackshader = GLSlang_CreateProgram(NULL, "allblackprogram", sh_config.minver, defs, "#include \"sys/skeletal.h\"\nvoid main(){gl_Position = skeletaltransform();}", NULL, NULL, NULL, "void main(){gl_FragColor=vec4(0.0,0.0,0.0,1.0);}", false, NULL);
shaderstate.allblack_mvp = qglGetUniformLocationARB(shaderstate.allblackshader.glsl.handle, "m_modelviewprojection");
}
@ -4303,7 +4303,7 @@ static void DrawMeshes(void)
if (!shaderstate.allblackshader.glsl.handle)
{
const char *defs[] = {NULL};
shaderstate.allblackshader = GLSlang_CreateProgram(NULL, "allblackprogram", gl_config_gles?100:110, defs, "#include \"sys/skeletal.h\"\nvoid main(){gl_Position = skeletaltransform();}", NULL, NULL, NULL, "void main(){gl_FragColor=vec4(0.0,0.0,0.0,1.0);}", false, NULL);
shaderstate.allblackshader = GLSlang_CreateProgram(NULL, "allblackprogram", sh_config.minver, defs, "#include \"sys/skeletal.h\"\nvoid main(){gl_Position = skeletaltransform();}", NULL, NULL, NULL, "void main(){gl_FragColor=vec4(0.0,0.0,0.0,1.0);}", false, NULL);
shaderstate.allblack_mvp = qglGetUniformLocationARB(shaderstate.allblackshader.glsl.handle, "m_modelviewprojection");
}

View File

@ -1797,7 +1797,7 @@ static void Shader_LoadGeneric(sgeneric_t *g, int qrtype)
ver = sbuiltins[i].apiver;
if (ver < sh_config.minver || ver > sh_config.maxver)
if (!(qrenderer==QR_OPENGL&&ver==110&&sh_config.maxver==100))
if (!(qrenderer==QR_OPENGL&&ver==110))
continue;
g->failed = !Shader_LoadPermutations(g->name, &g->prog, sbuiltins[i].body, qrtype, ver, blobname);

View File

@ -2997,8 +2997,23 @@ qboolean GL_Init(rendererstate_t *info, void *(*getglfunction) (char *name))
if (GL_CheckExtension("GL_EXT_packed_depth_stencil"))
sh_config.texfmt[PTI_DEPTH24_8] = true;
sh_config.minver = gl_config.arb_shader_objects?110:0;
sh_config.maxver = gl_config.arb_shader_objects?gl_config.maxglslversion:0;
if (gl_config.nofixedfunc)
{ //core contexts don't normally support glsl < 140 (such glsl versions have lots of compat syntax still, which will not function on core. drivers might accept it anyway, but yeah, lots of crap that shouldn't work)
//FIXME: GL_NUM_SHADING_LANGUAGE_VERSIONS and GL_SHADING_LANGUAGE_VERSION might allow for earlier versions.
sh_config.minver = 140;
sh_config.maxver = gl_config.maxglslversion;
}
else if (gl_config.arb_shader_objects)
{
//FIXME: we could accept 100 here, but that gets messy when gles is considered, and old drivers suck anyway.
sh_config.minver = 110;
sh_config.maxver = gl_config.maxglslversion;
}
else
{
sh_config.minver = 0;
sh_config.maxver = 0;
}
sh_config.blobpath = "glsl/%s.blob";
sh_config.progpath = "glsl/%s.glsl";
sh_config.shadernamefmt = "%s_glsl";

View File

@ -5,6 +5,8 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
#ifdef GLQUAKE
{QR_OPENGL, 110, "fixedemu",
"!!ver 100-450\n"
//this shader is present for support for gles/gl3core contexts
//it is single-texture-with-vertex-colours, and doesn't do anything special.
//beware that a few things use this, including apparently fonts and bloom rescaling.
@ -2418,6 +2420,8 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
#endif
#ifdef GLQUAKE
{QR_OPENGL, 110, "default2d",
"!!ver 100-450\n"
//this shader is present for support for gles/gl3core contexts
//it is single-texture-with-vertex-colours, and doesn't do anything special.
//beware that a few things use this, including apparently fonts and bloom rescaling.
@ -4964,6 +4968,8 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
#endif
#ifdef GLQUAKE
{QR_OPENGL, 110, "defaultfill",
"!!ver 100-450\n"
"#ifdef VERTEX_SHADER\n"
"attribute vec4 v_colour;\n"
"varying vec4 vc;\n"
@ -7392,6 +7398,7 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
#endif
#ifdef GLQUAKE
{QR_OPENGL, 110, "defaultgammacb",
"!!ver 100-450\n"
//this shader is applies gamma/contrast/brightness to the source image, and dumps it out.
"varying vec2 tc;\n"

View File

@ -731,6 +731,7 @@ enum {
WARN_READNOTWRITTEN,
WARN_NOTREFERENCED,
WARN_NOTREFERENCEDCONST,
WARN_NOTREFERENCEDFIELD,
WARN_CONFLICTINGRETURNS,
WARN_TOOFEWPARAMS,
WARN_TOOMANYPARAMS,

View File

@ -10145,8 +10145,9 @@ void QCC_PR_ParseStatement (void)
{
PR_GenerateReturnOuts();
if (pr_scope->type->aux_type->type != ev_void)
{
QCC_PR_ParseWarning(WARN_MISSINGRETURNVALUE, "\'%s\' returned nothing, expected %s", pr_scope->name, pr_scope->type->aux_type->name);
{ //accumulated functions are not required to return anything, on the assumption that a previous 'part' of the function did so
if (!pr_scope->def || !pr_scope->def->accumulate || !pr_scope->returndef.cast)
QCC_PR_ParseWarning(WARN_MISSINGRETURNVALUE, "\'%s\' returned nothing, expected %s", pr_scope->name, pr_scope->type->aux_type->name);
//this should not normally happen
if (!pr_scope->returndef.cast)
{ //but if it does, allocate a local that can be return=foo; before the return. depend upon qc's null initialisation rules for the default value.
@ -11849,6 +11850,8 @@ pbool QCC_CheckUninitialised(int firststatement, int laststatement)
{
if (local->constant)
continue; //will get some other warning, so we don't care.
if (local->isstatic)
continue; //not a real local, so will be properly initialised.
if (local->symbolheader != local)
continue; //ignore slave symbols, cos they're not interesting and should have been checked as part of the parent.
if (local->ofs < paramend)
@ -11878,13 +11881,13 @@ void QCC_Marshal_Locals(int firststatement, int laststatement)
if (qccwarningaction[WARN_UNINITIALIZED])
QCC_CheckUninitialised(firststatement, laststatement); //still need to call it for warnings, but if those warnings are off we can skip the cost
}
else if (!pr_scope->def->accumulate && !opt_locals_overlapping)
else if (!opt_locals_overlapping)
{
if (qccwarningaction[WARN_UNINITIALIZED])
QCC_CheckUninitialised(firststatement, laststatement); //still need to call it for warnings, but if those warnings are off we can skip the cost
error = true; //always use the legacy behaviour
}
else if (QCC_CheckUninitialised(firststatement, laststatement) && !pr_scope->def->accumulate)
else if (QCC_CheckUninitialised(firststatement, laststatement))
{
error = true;
// QCC_PR_Note(ERR_INTERNAL, strings+s_file, pr_source_line, "Not overlapping locals from %s due to uninitialised locals", pr_scope->name);
@ -13884,7 +13887,7 @@ pbool QCC_PR_ParseInitializerType(int arraysize, QCC_def_t *basedef, QCC_sref_t
//generate a goto statement around the nested function, so that nothing is hurt.
patch = QCC_Generate_OP_GOTO();
f = QCC_PR_ParseImmediateStatements (NULL, type, flags&PIF_WRAP);
f = QCC_PR_ParseImmediateStatements (def.sym->isstatic?def.sym:NULL, type, flags&PIF_WRAP);
patch->a.ofs = &statements[numstatements] - patch;
if (patch->a.ofs == 1)
numstatements--; //never mind then.

View File

@ -218,6 +218,7 @@ struct {
{" F322", WARN_IFSTRING_USED},
{" F323", WARN_UNREACHABLECODE},
{" F207", WARN_NOTREFERENCEDFIELD},
{" F208", WARN_NOTREFERENCEDCONST},
{" F209", WARN_EXTRAPRECACHE},
{" F210", WARN_NOTPRECACHED},
@ -962,7 +963,7 @@ void QCC_DetermineNeededSymbols(QCC_def_t *endsyssym)
}
}
//non-system fields should maybe be present too.
for (; sym; sym = sym->next)
/* for (; sym; sym = sym->next)
{
if (sym->constant && sym->type->type == ev_field && !opt_stripunusedfields)
{
@ -977,6 +978,7 @@ void QCC_DetermineNeededSymbols(QCC_def_t *endsyssym)
// sym->symbolheader->used = true;
// }
}
*/
for (i=0 ; i<numstatements ; i++)
{
@ -1007,12 +1009,15 @@ void QCC_FinaliseDef(QCC_def_t *def)
return; //was already finalised.
if (def->symbolheader != def)
{
QCC_FinaliseDef(def->symbolheader);
def->referenced = true;
}
if (def->symbolheader == def && def->deftail)
{
//for head symbols, we go through and touch all of their children
QCC_def_t *prev, *sub;
if (!def->referenced)
if (def->used && !def->referenced)
{
pbool ignoreone = true;
//touch all but one child
@ -1022,18 +1027,16 @@ void QCC_FinaliseDef(QCC_def_t *def)
def->referenced=true; //if one child is referenced, the composite is referenced
else if (!sub->referenced && ignoreone)
ignoreone = false; //this is the one we're going to warn about
else
sub->referenced |= def->referenced;
}
if (!def->referenced) //no child defs were referenced at all. if we're going to be warning about this then at least mute warnings for any other fields
for (prev = def, sub = prev->next; prev != def->deftail; sub = (prev=sub)->next)
sub->referenced = true;
// if (def->referenced) //no child defs were referenced at all. if we're going to be warning about this then at least mute warnings for any other fields
// for (prev = def, sub = prev->next; prev != def->deftail; sub = (prev=sub)->next)
// sub->referenced = true;
}
else
{
//touch children
//touch children to silence annoying warnings.
for (prev = def, sub = prev->next; prev != def->deftail; sub = (prev=sub)->next)
sub->referenced |= def->referenced;
sub->referenced |= true;
}
#ifdef TODO_READWRITETRACK
@ -1698,9 +1701,11 @@ pbool QCC_WriteData (int crc)
QCC_PR_Warning(WARN_WRITTENNOTREAD, def->filen, def->s_line, "%s %s = %s written, but not read.", TypeName(def->type, typestr, sizeof(typestr)), def->name, QCC_VarAtOffset(sr));
}
#endif
if (!def->symbolheader->read && !def->symbolheader->written && !def->symbolheader->referenced)
if (!def->symbolheader->read && !def->symbolheader->written && !def->referenced)
{
int wt = def->constant?WARN_NOTREFERENCEDCONST:WARN_NOTREFERENCED;
if (def->type->type == ev_field && def->constant)
wt = WARN_NOTREFERENCEDFIELD;
pr_scope = def->scope;
if (!strncmp(def->name, "spawnfunc_", 10))
; //no warnings from unreferenced entry points.

View File

@ -588,8 +588,10 @@ extern qboolean ssqc_deprecated_warned;
#define svc_setfrags 14
#define svc_updatecolors 17
#ifdef HEXEN2
#define svch2_clearviewflags 41 //hexen2.
#define svch2_setangles_lerp 50
#endif
//these are present in the darkplaces engine.
//I wanna knick their mods.
@ -706,9 +708,9 @@ void NPP_NQFlush(void)
{
client_t *cl;
int i;
#ifdef HEXEN2
char *h2finale = NULL;
char *h2title = NULL;
#ifdef HEXEN2
if (progstype == PROG_H2)
{
/*FIXME: hexen2 intermission+finale includes the viewheight. NQ does not, and QW has explicit position with scores but no finale*/
@ -728,6 +730,7 @@ void NPP_NQFlush(void)
{
if (cl->state == cs_spawned && ISQWCLIENT(cl))
{
#ifdef HEXEN2
if (h2finale)
{
ClientReliableCheckBlock(cl, 6 + strlen(h2title) + 3 + strlen(h2finale) + 1);
@ -747,7 +750,9 @@ void NPP_NQFlush(void)
ClientReliableWrite_String(cl, h2finale);
}
else if (cl->fteprotocolextensions2 & PEXT2_REPLACEMENTDELTAS)
else
#endif
if (cl->fteprotocolextensions2 & PEXT2_REPLACEMENTDELTAS)
{ //special intermission mode to leave the view attached to the viewentity (as required for nq - especially rogue's finale) instead of hacking it to some specific point
ClientReliableCheckBlock(cl, 5);
ClientReliableWrite_Byte(cl, svc_finale);

View File

@ -2904,7 +2904,7 @@ void SV_MemInfo_f(void)
}
void SV_Download_f (void)
{
{ //command for dedicated servers. apparently.
#ifdef WEBCLIENT
char *url = Cmd_Argv(1);
char *localname = Cmd_Argv(2);

View File

@ -5233,7 +5233,7 @@ void SV_FixupName(char *in, char *out, unsigned int outlen)
s = out;
while(iswhite(*in) || isinvalid(*in) || *in == '\1' || *in == '\2') //1 and 2 are to stop clients from printing the entire line as chat. only do that for the leading charater.
in++;
while(*in && len > 0)
while(*in && len > 1)
{
if (isinvalid(*in))
{

View File

@ -1,3 +1,5 @@
!!ver 100-450
//this shader is present for support for gles/gl3core contexts
//it is single-texture-with-vertex-colours, and doesn't do anything special.
//beware that a few things use this, including apparently fonts and bloom rescaling.

View File

@ -1,3 +1,5 @@
!!ver 100-450
#ifdef VERTEX_SHADER
attribute vec4 v_colour;
varying vec4 vc;

View File

@ -1,3 +1,4 @@
!!ver 100-450
//this shader is applies gamma/contrast/brightness to the source image, and dumps it out.
varying vec2 tc;

View File

@ -1,3 +1,5 @@
!!ver 100-450
//this shader is present for support for gles/gl3core contexts
//it is single-texture-with-vertex-colours, and doesn't do anything special.
//beware that a few things use this, including apparently fonts and bloom rescaling.

View File

@ -10,6 +10,7 @@ extern cvar_t vk_submissionthread;
extern cvar_t vk_debug;
extern cvar_t vk_dualqueue;
extern cvar_t vk_busywait;
extern cvar_t vk_waitfence;
extern cvar_t vk_nv_glsl_shader;
extern cvar_t vk_nv_dedicated_allocation;
extern cvar_t vk_khr_dedicated_allocation;
@ -220,7 +221,8 @@ static void VK_DestroySwapChain(void)
vk.dopresent(NULL);
while (vk.aquirenext < vk.aquirelast)
{
VkWarnAssert(vkWaitForFences(vk.device, 1, &vk.acquirefences[vk.aquirenext%ACQUIRELIMIT], VK_FALSE, UINT64_MAX));
if (vk.acquirefences[vk.aquirenext%ACQUIRELIMIT])
VkWarnAssert(vkWaitForFences(vk.device, 1, &vk.acquirefences[vk.aquirenext%ACQUIRELIMIT], VK_FALSE, UINT64_MAX));
vk.aquirenext++;
}
if (vk.device)
@ -281,6 +283,7 @@ static qboolean VK_CreateSwapChain(void)
vid_triplebuffer.modified = false;
vid_srgb.modified = false;
vk_submissionthread.modified = false;
vk_waitfence.modified = false;
vid_multisample.modified = false;
vk.triplebuffer = vid_triplebuffer.ival;
@ -305,9 +308,19 @@ static qboolean VK_CreateSwapChain(void)
vk.aquirelast = vk.aquirenext = 0;
for (i = 0; i < ACQUIRELIMIT; i++)
{
VkFenceCreateInfo fci = {VK_STRUCTURE_TYPE_FENCE_CREATE_INFO};
fci.flags = VK_FENCE_CREATE_SIGNALED_BIT;
VkAssert(vkCreateFence(vk.device,&fci,vkallocationcb,&vk.acquirefences[i]));
if (1)
{
VkFenceCreateInfo fci = {VK_STRUCTURE_TYPE_FENCE_CREATE_INFO};
fci.flags = VK_FENCE_CREATE_SIGNALED_BIT;
VkAssert(vkCreateFence(vk.device,&fci,vkallocationcb,&vk.acquirefences[i]));
vk.acquiresemaphores[i] = VK_NULL_HANDLE;
}
else
{
VkSemaphoreCreateInfo sci = {VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO};
VkAssert(vkCreateSemaphore(vk.device, &sci, vkallocationcb, &vk.acquiresemaphores[i]));
vk.acquirefences[i] = VK_NULL_HANDLE;
}
vk.acquirebufferidx[vk.aquirelast%ACQUIRELIMIT] = vk.aquirelast%vk.backbuf_count;
vk.aquirelast++;
@ -411,8 +424,12 @@ static qboolean VK_CreateSwapChain(void)
uint32_t priority = 0;
switch(presentmode[i])
{
default://ignore it.
default://ignore it if we don't know it.
break;
//this is awkward. normally we use vsync<0 to allow tearing-with-vsync, but that leaves us with a problem as far as what 0 should signify - tearing or not.
//if we're using mailbox then we could instead discard the command buffers and skip rendering of the actual scenes.
//we could have our submission thread wait some time period after the last vswap (ie: before the next) before submitting the command.
//this could reduce gpu load at higher resolutions without lying too much about cpu usage...
case VK_PRESENT_MODE_IMMEDIATE_KHR:
priority = (vk.vsync?0:2) + 2; //for most quake players, latency trumps tearing.
break;
@ -434,7 +451,7 @@ static qboolean VK_CreateSwapChain(void)
}
if (!vk.vsync && swapinfo.presentMode != VK_PRESENT_MODE_IMMEDIATE_KHR)
Con_Printf("Warning: vulkan graphics driver does not fully support disabling vsync.\n");
Con_Printf("Warning: vulkan graphics driver does not support VK_PRESENT_MODE_IMMEDIATE_KHR.\n");
vk.srgbcapable = false;
swapinfo.imageColorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR;
@ -499,13 +516,23 @@ static qboolean VK_CreateSwapChain(void)
vk.aquirelast = vk.aquirenext = 0;
for (i = 0; i < ACQUIRELIMIT; i++)
{
VkFenceCreateInfo fci = {VK_STRUCTURE_TYPE_FENCE_CREATE_INFO};
VkAssert(vkCreateFence(vk.device,&fci,vkallocationcb,&vk.acquirefences[i]));
if (vk_waitfence.ival)
{
VkFenceCreateInfo fci = {VK_STRUCTURE_TYPE_FENCE_CREATE_INFO};
VkAssert(vkCreateFence(vk.device,&fci,vkallocationcb,&vk.acquirefences[i]));
vk.acquiresemaphores[i] = VK_NULL_HANDLE;
}
else
{
VkSemaphoreCreateInfo sci = {VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO};
VkAssert(vkCreateSemaphore(vk.device, &sci, vkallocationcb, &vk.acquiresemaphores[i]));
vk.acquirefences[i] = VK_NULL_HANDLE;
}
}
/*-1 to hide any weird thread issues*/
while (vk.aquirelast < ACQUIRELIMIT-1 && vk.aquirelast < vk.backbuf_count && vk.aquirelast <= vk.backbuf_count-surfcaps.minImageCount)
{
VkAssert(vkAcquireNextImageKHR(vk.device, vk.swapchain, UINT64_MAX, VK_NULL_HANDLE, vk.acquirefences[vk.aquirelast%ACQUIRELIMIT], &vk.acquirebufferidx[vk.aquirelast%ACQUIRELIMIT]));
VkAssert(vkAcquireNextImageKHR(vk.device, vk.swapchain, UINT64_MAX, vk.acquiresemaphores[vk.aquirelast%ACQUIRELIMIT], vk.acquirefences[vk.aquirelast%ACQUIRELIMIT], &vk.acquirebufferidx[vk.aquirelast%ACQUIRELIMIT]));
vk.aquirelast++;
}
}
@ -1074,7 +1101,8 @@ void *VK_FencedBegin(void (*passed)(void *work), size_t worksize)
return w;
}
//end+submit a commandbuffer, and set up a fence so we know when its complete
//end+submit a commandbuffer, and set up a fence so we know when its complete. this is not within the context of any frame, so make sure any textures are safe to rewrite early...
//completion can be signalled before the current frame finishes, so watch out for that too.
void VK_FencedSubmit(void *work)
{
struct vk_fencework *w = work;
@ -2623,6 +2651,7 @@ VkCommandBuffer VK_AllocFrameCBuf(void)
qboolean VK_SCR_GrabBackBuffer(void)
{
VkSemaphore sem;
RSpeedLocals();
if (vk.frame) //erk, we already have one...
@ -2643,31 +2672,37 @@ qboolean VK_SCR_GrabBackBuffer(void)
while (vk.aquirenext == vk.aquirelast)
{ //we're still waiting for the render thread to increment acquirelast.
//shouldn't really happen, but can if the gpu is slow.
Sys_Sleep(0); //o.O
#ifdef _WIN32
Sys_SendKeyEvents();
#endif
}
//wait for the queued acquire to actually finish
if (vk_busywait.ival)
{ //busy wait, to try to get the highest fps possible
while (VK_TIMEOUT == vkGetFenceStatus(vk.device, vk.acquirefences[vk.aquirenext%ACQUIRELIMIT]))
;
}
else
if (vk.acquirefences[vk.aquirenext%ACQUIRELIMIT] != VK_NULL_HANDLE)
{
//friendly wait
VkResult err = vkWaitForFences(vk.device, 1, &vk.acquirefences[vk.aquirenext%ACQUIRELIMIT], VK_FALSE, UINT64_MAX);
if (err)
{
if (err == VK_ERROR_DEVICE_LOST)
Sys_Error("Vulkan device lost");
return false;
//wait for the queued acquire to actually finish
if (vk_busywait.ival)
{ //busy wait, to try to get the highest fps possible
while (VK_TIMEOUT == vkGetFenceStatus(vk.device, vk.acquirefences[vk.aquirenext%ACQUIRELIMIT]))
;
}
else
{
//friendly wait
VkResult err = vkWaitForFences(vk.device, 1, &vk.acquirefences[vk.aquirenext%ACQUIRELIMIT], VK_FALSE, UINT64_MAX);
if (err)
{
if (err == VK_ERROR_DEVICE_LOST)
Sys_Error("Vulkan device lost");
return false;
}
}
VkAssert(vkResetFences(vk.device, 1, &vk.acquirefences[vk.aquirenext%ACQUIRELIMIT]));
}
vk.bufferidx = vk.acquirebufferidx[vk.aquirenext%ACQUIRELIMIT];
VkAssert(vkResetFences(vk.device, 1, &vk.acquirefences[vk.aquirenext%ACQUIRELIMIT]));
sem = vk.acquiresemaphores[vk.aquirenext%ACQUIRELIMIT];
vk.aquirenext++;
//grab the first unused
@ -2684,6 +2719,7 @@ qboolean VK_SCR_GrabBackBuffer(void)
vk.frame->numcbufs = 0;
vk.rendertarg->cbuf = VK_AllocFrameCBuf();
vk.frame->acquiresemaphore = sem;
RSpeedEnd(RSPEED_SETUP);
@ -2859,7 +2895,7 @@ qboolean VK_SCR_UpdateScreen (void)
VK_FencedCheck();
//a few cvars need some extra work if they're changed
if ((vk.allowsubmissionthread && vk_submissionthread.modified) || vid_vsync.modified || vid_triplebuffer.modified || vid_srgb.modified || vid_multisample.modified)
if ((vk.allowsubmissionthread && vk_submissionthread.modified) || vid_vsync.modified || vk_waitfence.modified || vid_triplebuffer.modified || vid_srgb.modified || vid_multisample.modified)
vk.neednewswapchain = true;
if (vk.devicelost)
@ -2989,7 +3025,7 @@ qboolean VK_SCR_UpdateScreen (void)
vk.frame->frameendjobs = vk.frameendjobs;
vk.frameendjobs = NULL;
VK_Submit_Work(vk.rendertarg->cbuf, VK_NULL_HANDLE, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, vk.frame->backbuf->presentsemaphore, vk.frame->finishedfence, vk.frame, &fw->fw);
VK_Submit_Work(vk.rendertarg->cbuf, vk.frame->acquiresemaphore, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, vk.frame->backbuf->presentsemaphore, vk.frame->finishedfence, vk.frame, &fw->fw);
}
//now would be a good time to do any compute work or lightmap updates...
@ -3161,7 +3197,7 @@ void VK_DoPresent(struct vkframe *theframe)
}
else
{
err = vkAcquireNextImageKHR(vk.device, vk.swapchain, 0, VK_NULL_HANDLE, vk.acquirefences[vk.aquirelast%ACQUIRELIMIT], &vk.acquirebufferidx[vk.aquirelast%ACQUIRELIMIT]);
err = vkAcquireNextImageKHR(vk.device, vk.swapchain, 0, vk.acquiresemaphores[vk.aquirelast%ACQUIRELIMIT], vk.acquirefences[vk.aquirelast%ACQUIRELIMIT], &vk.acquirebufferidx[vk.aquirelast%ACQUIRELIMIT]);
if (err)
{
Con_Printf("ERROR: vkAcquireNextImageKHR: %x\n", err);

View File

@ -208,6 +208,7 @@ enum dynbuf_e
};
struct vk_rendertarg
{
VkCommandBuffer cbuf; //cbuf allocated for this render target.
VkFramebuffer framebuffer;
vk_image_t colour, depth, mscolour;
@ -265,6 +266,7 @@ extern struct vulkaninfo_s
VkPhysicalDeviceLimits limits;
#define ACQUIRELIMIT 8
VkSemaphore acquiresemaphores[ACQUIRELIMIT];
VkFence acquirefences[ACQUIRELIMIT];
uint32_t acquirebufferidx[ACQUIRELIMIT];
unsigned int aquirenext;
@ -315,6 +317,7 @@ extern struct vulkaninfo_s
struct vkframe *next;
struct dynbuffer *dynbufs[DB_MAX];
struct descpool *descpools;
VkSemaphore acquiresemaphore;
VkCommandBuffer *cbufs;
size_t numcbufs;
size_t maxcbufs;