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:
parent
ceae6e2a6b
commit
c7d5695e5e
35 changed files with 418 additions and 220 deletions
|
@ -1802,7 +1802,6 @@ downloadlist_t *CL_DownloadFailed(const char *name, qdownload_t *qdl)
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef PEXT_CHUNKEDDOWNLOADS
|
#ifdef PEXT_CHUNKEDDOWNLOADS
|
||||||
#define DLBLOCKSIZE 1024
|
|
||||||
|
|
||||||
int CL_DownloadRate(void)
|
int CL_DownloadRate(void)
|
||||||
{
|
{
|
||||||
|
|
|
@ -3092,7 +3092,12 @@ static qboolean Image_ReadBLPFile(texid_t tex, unsigned int flags, char *fname,
|
||||||
mips->mipcount = miplevel;
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2623,8 +2623,11 @@ void Key_Event (unsigned int devid, int key, unsigned int unicode, qboolean down
|
||||||
|
|
||||||
if (Key_Dest_Has(kdm_emenu))
|
if (Key_Dest_Has(kdm_emenu))
|
||||||
{
|
{
|
||||||
M_Keydown (key, unicode);
|
if (key < K_F1 || key > K_F15)
|
||||||
return;
|
{ //function keys don't get intercepted by the menu...
|
||||||
|
M_Keydown (key, unicode);
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#ifdef MENU_DAT
|
#ifdef MENU_DAT
|
||||||
if (Key_Dest_Has(kdm_gmenu))
|
if (Key_Dest_Has(kdm_gmenu))
|
||||||
|
|
|
@ -2585,7 +2585,7 @@ qboolean Media_ShowFilm(void)
|
||||||
ch = 3;
|
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();
|
SCR_SetUpToDrawConsole();
|
||||||
if (scr_con_current)
|
if (scr_con_current)
|
||||||
|
@ -3778,9 +3778,8 @@ void Media_InitFakeSoundDevice (int speed, int channels, int samplebits)
|
||||||
S_DefaultSpeakerConfiguration(sc);
|
S_DefaultSpeakerConfiguration(sc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//stops capturing and destroys everything.
|
||||||
|
static void Media_FlushCapture(void)
|
||||||
void Media_StopRecordFilm_f (void)
|
|
||||||
{
|
{
|
||||||
#ifdef GLQUAKE_PBOS
|
#ifdef GLQUAKE_PBOS
|
||||||
if (offscreen_format && qrenderer == QR_OPENGL)
|
if (offscreen_format && qrenderer == QR_OPENGL)
|
||||||
|
@ -3835,6 +3834,20 @@ void Media_StopRecordFilm_f (void)
|
||||||
}
|
}
|
||||||
#endif
|
#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)
|
if (capture_fakesounddevice)
|
||||||
S_ShutdownCard(capture_fakesounddevice);
|
S_ShutdownCard(capture_fakesounddevice);
|
||||||
|
@ -3850,18 +3863,32 @@ void Media_StopRecordFilm_f (void)
|
||||||
currentcapture_ctx = NULL;
|
currentcapture_ctx = NULL;
|
||||||
currentcapture_funcs = 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);
|
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)
|
static void Media_RecordFilm (char *recordingname, qboolean demo)
|
||||||
{
|
{
|
||||||
int sndkhz, sndchannels, sndbits;
|
int sndkhz, sndchannels, sndbits;
|
||||||
|
@ -4067,6 +4094,8 @@ void Media_CaptureDemoEnd(void) {}
|
||||||
qboolean Media_PausedDemo(qboolean fortiming) {return false;}
|
qboolean Media_PausedDemo(qboolean fortiming) {return false;}
|
||||||
double Media_TweekCaptureFrameTime(double oldtime, double time) { return oldtime+time ; }
|
double Media_TweekCaptureFrameTime(double oldtime, double time) { return oldtime+time ; }
|
||||||
void Media_RecordFrame (void) {}
|
void Media_RecordFrame (void) {}
|
||||||
|
void Media_VideoRestarting(void) {}
|
||||||
|
void Media_VideoRestarted(void) {}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -373,6 +373,11 @@ typedef union vboarray_s
|
||||||
unsigned int offs;
|
unsigned int offs;
|
||||||
} vk;
|
} vk;
|
||||||
#endif
|
#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;
|
} vboarray_t;
|
||||||
|
|
||||||
//scissor rects
|
//scissor rects
|
||||||
|
|
|
@ -1070,7 +1070,11 @@ void QCBUILTIN PF_SubConPrintf (pubprogfuncs_t *prinst, struct globalvars_s *pr_
|
||||||
const char *fmt = PR_GetStringOfs(prinst, OFS_PARM1);
|
const char *fmt = PR_GetStringOfs(prinst, OFS_PARM1);
|
||||||
console_t *con = Con_FindConsole(conname);
|
console_t *con = Con_FindConsole(conname);
|
||||||
if (!con)
|
if (!con)
|
||||||
return;
|
{
|
||||||
|
con = Con_Create(conname, 0);
|
||||||
|
if (!con)
|
||||||
|
return;
|
||||||
|
}
|
||||||
PF_sprintf_internal(prinst, pr_globals, fmt, 2, outbuf, sizeof(outbuf));
|
PF_sprintf_internal(prinst, pr_globals, fmt, 2, outbuf, sizeof(outbuf));
|
||||||
Con_PrintCon(con, outbuf, con->parseflags);
|
Con_PrintCon(con, outbuf, con->parseflags);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1664,7 +1664,7 @@ texid_t R2D_RT_GetTexture(const char *id, unsigned int *width, unsigned int *hei
|
||||||
if (!strcmp(id, "-"))
|
if (!strcmp(id, "-"))
|
||||||
{
|
{
|
||||||
tid = internalrt;
|
tid = internalrt;
|
||||||
internalrt = r_nulltex;
|
// internalrt = r_nulltex;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
tid = Image_FindTexture(id, NULL, RT_IMAGEFLAGS);
|
tid = Image_FindTexture(id, NULL, RT_IMAGEFLAGS);
|
||||||
|
|
|
@ -542,6 +542,8 @@ qboolean Media_PausedDemo (qboolean fortiming);
|
||||||
int Media_Capturing (void);
|
int Media_Capturing (void);
|
||||||
double Media_TweekCaptureFrameTime(double oldtime, double time);
|
double Media_TweekCaptureFrameTime(double oldtime, double time);
|
||||||
void Media_WriteCurrentTrack(sizebuf_t *buf);
|
void Media_WriteCurrentTrack(sizebuf_t *buf);
|
||||||
|
void Media_VideoRestarting(void);
|
||||||
|
void Media_VideoRestarted(void);
|
||||||
|
|
||||||
void MYgluPerspective(double fovx, double fovy, double zNear, double zFar);
|
void MYgluPerspective(double fovx, double fovy, double zNear, double zFar);
|
||||||
|
|
||||||
|
|
|
@ -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_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_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_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_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_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.");
|
//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_debug, VKRENDEREROPTIONS);
|
||||||
Cvar_Register (&vk_dualqueue, VKRENDEREROPTIONS);
|
Cvar_Register (&vk_dualqueue, VKRENDEREROPTIONS);
|
||||||
Cvar_Register (&vk_busywait, VKRENDEREROPTIONS);
|
Cvar_Register (&vk_busywait, VKRENDEREROPTIONS);
|
||||||
|
Cvar_Register (&vk_waitfence, VKRENDEREROPTIONS);
|
||||||
|
|
||||||
Cvar_Register (&vk_nv_glsl_shader, VKRENDEREROPTIONS);
|
Cvar_Register (&vk_nv_glsl_shader, VKRENDEREROPTIONS);
|
||||||
Cvar_Register (&vk_nv_dedicated_allocation, VKRENDEREROPTIONS);
|
Cvar_Register (&vk_nv_dedicated_allocation, VKRENDEREROPTIONS);
|
||||||
|
@ -1257,6 +1259,8 @@ void R_ShutdownRenderer(qboolean devicetoo)
|
||||||
|
|
||||||
IN_Shutdown();
|
IN_Shutdown();
|
||||||
|
|
||||||
|
Media_VideoRestarting();
|
||||||
|
|
||||||
if (R_DeInit)
|
if (R_DeInit)
|
||||||
{
|
{
|
||||||
TRACE(("dbg: R_ApplyRenderer: R_DeInit\n"));
|
TRACE(("dbg: R_ApplyRenderer: R_DeInit\n"));
|
||||||
|
@ -1466,6 +1470,7 @@ TRACE(("dbg: R_ApplyRenderer: screen inited\n"));
|
||||||
Sbar_Flush();
|
Sbar_Flush();
|
||||||
|
|
||||||
IN_ReInit();
|
IN_ReInit();
|
||||||
|
Media_VideoRestarted();
|
||||||
|
|
||||||
Cvar_ForceCallback(&v_gamma);
|
Cvar_ForceCallback(&v_gamma);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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_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_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_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_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_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.");
|
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)
|
switch(s_voip.enccodec)
|
||||||
{
|
{
|
||||||
case VOIP_SPEEX_OLD:
|
case VOIP_SPEEX_OLD:
|
||||||
|
//this is from before I understood speex properly.
|
||||||
level += S_Voip_Preprocess(start, s_voip.encframesize, micamp);
|
level += S_Voip_Preprocess(start, s_voip.encframesize, micamp);
|
||||||
qspeex_bits_reset(&s_voip.speex.encbits);
|
qspeex_bits_reset(&s_voip.speex.encbits);
|
||||||
qspeex_encode_int(s_voip.encoder, start, &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_NARROW:
|
||||||
case VOIP_SPEEX_WIDE:
|
case VOIP_SPEEX_WIDE:
|
||||||
case VOIP_SPEEX_ULTRAWIDE:
|
case VOIP_SPEEX_ULTRAWIDE:
|
||||||
|
//write multiple speex frames into a single merged frame
|
||||||
qspeex_bits_reset(&s_voip.speex.encbits);
|
qspeex_bits_reset(&s_voip.speex.encbits);
|
||||||
for (; encpos+s_voip.encframesize*2 <= s_voip.capturepos; )
|
for (; encpos+s_voip.encframesize*2 <= s_voip.capturepos; )
|
||||||
{
|
{
|
||||||
|
@ -1394,6 +1396,7 @@ void S_Voip_Transmit(unsigned char clc, sizebuf_t *buf)
|
||||||
break;
|
break;
|
||||||
case VOIP_PCMA:
|
case VOIP_PCMA:
|
||||||
case VOIP_PCMU:
|
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 = s_voip.capturepos-encpos; //amount of data to be eaten in this frame
|
||||||
len = min(len, sizeof(outbuf)-outpos);
|
len = min(len, sizeof(outbuf)-outpos);
|
||||||
len = min(len, s_voip.encframesize*2);
|
len = min(len, s_voip.encframesize*2);
|
||||||
|
@ -1463,6 +1466,8 @@ void S_Voip_Transmit(unsigned char clc, sizebuf_t *buf)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//opus has no way to detect the end properly.
|
||||||
|
//standard rtp favours many small packets.
|
||||||
if (rtpstream || s_voip.enccodec == VOIP_OPUS)
|
if (rtpstream || s_voip.enccodec == VOIP_OPUS)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1503,10 +1508,20 @@ void S_Voip_Transmit(unsigned char clc, sizebuf_t *buf)
|
||||||
{
|
{
|
||||||
if (buf->maxsize - buf->cursize >= 5+outpos)
|
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, 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_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);
|
SZ_Write(buf, outbuf, outpos);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
@ -776,7 +776,7 @@ qboolean Wad_NextDownload (void)
|
||||||
{
|
{
|
||||||
k = wads[i];
|
k = wads[i];
|
||||||
wads[i] = 0;
|
wads[i] = 0;
|
||||||
strcpy(wadname+9, &wads[j]);
|
Q_strncpyz(wadname+9, &wads[j], sizeof(wadname)-9);
|
||||||
if (wadname[9])
|
if (wadname[9])
|
||||||
{
|
{
|
||||||
if (COM_FCheckExists(wadname+9))
|
if (COM_FCheckExists(wadname+9))
|
||||||
|
|
|
@ -488,40 +488,40 @@ typedef struct
|
||||||
// a given brush can contribute multiple content bits
|
// a given brush can contribute multiple content bits
|
||||||
// multiple brushes can be in a single leaf
|
// multiple brushes can be in a single leaf
|
||||||
|
|
||||||
#define FTECONTENTS_EMPTY 0x00000000
|
#define FTECONTENTS_EMPTY 0x00000000
|
||||||
#define FTECONTENTS_SOLID 0x00000001
|
#define FTECONTENTS_SOLID 0x00000001
|
||||||
//q2window 0x00000002
|
//q2window 0x00000002
|
||||||
//q2aux 0x00000004
|
//q2aux 0x00000004
|
||||||
#define FTECONTENTS_LAVA 0x00000008
|
#define FTECONTENTS_LAVA 0x00000008
|
||||||
#define FTECONTENTS_SLIME 0x00000010
|
#define FTECONTENTS_SLIME 0x00000010
|
||||||
#define FTECONTENTS_WATER 0x00000020
|
#define FTECONTENTS_WATER 0x00000020
|
||||||
#define FTECONTENTS_FLUID (FTECONTENTS_WATER|FTECONTENTS_SLIME|FTECONTENTS_LAVA|FTECONTENTS_SKY) //sky is a fluid for q1 code.
|
#define FTECONTENTS_FLUID (FTECONTENTS_WATER|FTECONTENTS_SLIME|FTECONTENTS_LAVA|FTECONTENTS_SKY) //sky is a fluid for q1 code.
|
||||||
//q2mist 0x00000040
|
//q2mist 0x00000040
|
||||||
//q3notteam1 0x00000080
|
//q3notteam1 0x00000080
|
||||||
//q3notteam2 0x00000100
|
//q3notteam2 0x00000100
|
||||||
//q3nobotclip 0x00000200
|
//q3nobotclip 0x00000200
|
||||||
// 0x00000400
|
// 0x00000400
|
||||||
// 0x00000800
|
// 0x00000800
|
||||||
// 0x00001000
|
// 0x00001000
|
||||||
// 0x00002000
|
// 0x00002000
|
||||||
#define FTECONTENTS_LADDER 0x00004000
|
#define FTECONTENTS_LADDER 0x00004000
|
||||||
//q2areaportal,q3areaportal 0x00008000
|
//q2areaportal,q3areaportal 0x00008000
|
||||||
#define FTECONTENTS_PLAYERCLIP 0x00010000
|
#define FTECONTENTS_PLAYERCLIP 0x00010000
|
||||||
#define FTECONTENTS_MONSTERCLIP 0x00020000
|
#define FTECONTENTS_MONSTERCLIP 0x00020000
|
||||||
//q2current0,q3teleporter 0x00040000
|
//q2current0,q3teleporter 0x00040000
|
||||||
//q2current90,q3jumppad 0x00080000
|
//q2current90,q3jumppad 0x00080000
|
||||||
//q2current180,q3clusterportal 0x00100000
|
//q2current180,q3clusterportal 0x00100000
|
||||||
//q2current270,q3donotenter 0x00200000
|
//q2current270,q3donotenter 0x00200000
|
||||||
//q2currentup,q3botclip 0x00400000
|
//q2currentup,q3botclip 0x00400000
|
||||||
//q2currentdown,q3mover 0x00800000
|
//q2currentdown,q3mover 0x00800000
|
||||||
//q2origin,q3origin 0x01000000
|
//q2origin,q3origin 0x01000000 //could define, but normally removed by compiler, so why?
|
||||||
#define FTECONTENTS_BODY 0x02000000
|
#define FTECONTENTS_BODY 0x02000000
|
||||||
#define FTECONTENTS_CORPSE 0x04000000
|
#define FTECONTENTS_CORPSE 0x04000000
|
||||||
//q2detail,q3detail 0x08000000
|
//q2detail,q3detail 0x08000000 //not very useful to us
|
||||||
//q2translucent,q3structual 0x10000000
|
//q2translucent,q3structual 0x10000000
|
||||||
//q2ladder,q3translucent 0x20000000
|
//q2ladder,q3translucent 0x20000000
|
||||||
//q3trigger 0x40000000
|
//q3trigger 0x40000000
|
||||||
#define FTECONTENTS_SKY 0x80000000
|
#define FTECONTENTS_SKY/*q3nodrop*/ 0x80000000
|
||||||
|
|
||||||
// lower bits are stronger, and will eat weaker brushes completely
|
// lower bits are stronger, and will eat weaker brushes completely
|
||||||
#define Q2CONTENTS_SOLID FTECONTENTS_SOLID //0x00000001
|
#define Q2CONTENTS_SOLID FTECONTENTS_SOLID //0x00000001
|
||||||
|
|
|
@ -2805,60 +2805,14 @@ int Mod_CountSkinFiles(model_t *mod)
|
||||||
return i;
|
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)
|
void Mod_LoadAliasShaders(model_t *mod)
|
||||||
{
|
{
|
||||||
qbyte *mipdata[4];
|
qbyte *mipdata[4];
|
||||||
galiasinfo_t *ai = mod->meshinfo;
|
galiasinfo_t *ai = mod->meshinfo;
|
||||||
galiasskin_t *s;
|
galiasskin_t *s;
|
||||||
skinframe_t *f;
|
skinframe_t *f;
|
||||||
int i, j;
|
int i, j, k;
|
||||||
|
int numskins;
|
||||||
|
|
||||||
unsigned int loadflags;
|
unsigned int loadflags;
|
||||||
unsigned int imageflags;
|
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
|
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++)
|
for (j = 0, f = s->frame; j < s->numframes; j++, f++)
|
||||||
{
|
{
|
||||||
if (j == 0)
|
if (j == 0 && skinfile)
|
||||||
f->shader = Mod_ShaderFromQ3SkinFile(ai, mod, i);
|
{
|
||||||
|
//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
|
else
|
||||||
f->shader = NULL;
|
f->shader = NULL;
|
||||||
if (!f->shader)
|
if (!f->shader)
|
||||||
|
@ -2944,6 +2947,7 @@ void Mod_LoadAliasShaders(model_t *mod)
|
||||||
R_BuildDefaultTexnums(&f->texnums, f->shader);
|
R_BuildDefaultTexnums(&f->texnums, f->shader);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Mod_WipeSkin(skinid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -168,6 +168,7 @@ typedef struct console_s
|
||||||
conchar_t defaultcharbits;
|
conchar_t defaultcharbits;
|
||||||
int commandcompletion; //allows tab completion of quake console commands
|
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.
|
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 (*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);
|
qboolean (*mouseover)(struct console_s *con, char **out_tiptext, shader_t **out_shader);
|
||||||
|
|
|
@ -6111,6 +6111,7 @@ void FS_RegisterDefaultFileSystems(void)
|
||||||
FS_RegisterFileSystemType(NULL, "pk4", FSZIP_LoadArchive, true);
|
FS_RegisterFileSystemType(NULL, "pk4", FSZIP_LoadArchive, true);
|
||||||
FS_RegisterFileSystemType(NULL, "apk", FSZIP_LoadArchive, false);
|
FS_RegisterFileSystemType(NULL, "apk", FSZIP_LoadArchive, false);
|
||||||
FS_RegisterFileSystemType(NULL, "zip", FSZIP_LoadArchive, false);
|
FS_RegisterFileSystemType(NULL, "zip", FSZIP_LoadArchive, false);
|
||||||
|
FS_RegisterFileSystemType(NULL, "exe", FSZIP_LoadArchive, false); //for self-extracting zips.
|
||||||
#endif
|
#endif
|
||||||
#ifdef PACKAGE_DOOMWAD
|
#ifdef PACKAGE_DOOMWAD
|
||||||
FS_RegisterFileSystemType(NULL, "wad", FSDWD_LoadArchive, true);
|
FS_RegisterFileSystemType(NULL, "wad", FSDWD_LoadArchive, true);
|
||||||
|
|
|
@ -3439,13 +3439,20 @@ static qboolean CModQ3_LoadVisibility (model_t *mod, qbyte *mod_base, lump_t *l)
|
||||||
if (l->filelen == 0)
|
if (l->filelen == 0)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
#if 0
|
||||||
|
//the 'correct' code
|
||||||
numclusters = 0;
|
numclusters = 0;
|
||||||
for (i = 0; i < mod->numleafs; i++)
|
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 = mod->leafs[i].cluster+1;
|
||||||
|
|
||||||
numclusters++;
|
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);
|
prv->q3pvs = ZG_Malloc(&mod->memgroup, sizeof(*prv->q3pvs) + (numclusters+7)/8 * numclusters);
|
||||||
memset (prv->q3pvs, 0xff, sizeof(*prv->q3pvs) + (numclusters+7)/8 * numclusters);
|
memset (prv->q3pvs, 0xff, sizeof(*prv->q3pvs) + (numclusters+7)/8 * numclusters);
|
||||||
prv->q3pvs->numclusters = 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;
|
out = loadmodel->lightdata;
|
||||||
//figure out which merged lightmap we're putting it into
|
//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+1] = 255;
|
||||||
out[s+2] = 0;
|
out[s+2] = 0;
|
||||||
}
|
}
|
||||||
}
|
}*/
|
||||||
}
|
}
|
||||||
|
|
||||||
static qboolean CModQ3_LoadLightgrid (model_t *loadmodel, qbyte *mod_base, lump_t *l)
|
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.
|
CModQ3_LoadLighting (mod, mod_base, &header.lumps[Q3LUMP_LIGHTMAPS]); //fixme: duplicated loading.
|
||||||
}
|
}
|
||||||
#endif
|
#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_LoadNodes (mod, mod_base, &header.lumps[Q3LUMP_NODES]);
|
||||||
noerrors = noerrors && CModQ3_LoadSubmodels (mod, mod_base, &header.lumps[Q3LUMP_MODELS]);
|
noerrors = noerrors && CModQ3_LoadSubmodels (mod, mod_base, &header.lumps[Q3LUMP_MODELS]);
|
||||||
noerrors = noerrors && CModQ3_LoadVisibility (mod, mod_base, &header.lumps[Q3LUMP_VISIBILITY]);
|
noerrors = noerrors && CModQ3_LoadVisibility (mod, mod_base, &header.lumps[Q3LUMP_VISIBILITY]);
|
||||||
|
|
|
@ -472,6 +472,8 @@ enum {
|
||||||
#define DLERR_REDIRECTPACK -5 //client should download the specified package instead.
|
#define DLERR_REDIRECTPACK -5 //client should download the specified package instead.
|
||||||
#define DLERR_PACKAGE -6 //not networked. packages require special file access.
|
#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
|
//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_TYPE 0xc000
|
||||||
#define PC_MODEL 0x0000
|
#define PC_MODEL 0x0000
|
||||||
|
|
|
@ -1080,6 +1080,7 @@
|
||||||
AdditionalIncludeDirectories="../libs/speex;..\client;../libs/freetype2/include;../common;../server;../gl;../sw;../qclib;../libs;../libs/dxsdk9/include;../libs/dxsdk7/include"
|
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"
|
PreprocessorDefinitions="NDEBUG;WIN32;_WINDOWS;GLQUAKE;D3D9QUAKE;D3D11QUAKE;SWQUAKE;VKQUAKE;USE_EGL"
|
||||||
StringPooling="true"
|
StringPooling="true"
|
||||||
|
ExceptionHandling="0"
|
||||||
RuntimeLibrary="0"
|
RuntimeLibrary="0"
|
||||||
EnableFunctionLevelLinking="true"
|
EnableFunctionLevelLinking="true"
|
||||||
FloatingPointModel="2"
|
FloatingPointModel="2"
|
||||||
|
@ -1102,6 +1103,7 @@
|
||||||
/>
|
/>
|
||||||
<Tool
|
<Tool
|
||||||
Name="VCLinkerTool"
|
Name="VCLinkerTool"
|
||||||
|
AdditionalOptions="/DYNAMICBASE /NXCOMPAT"
|
||||||
AdditionalDependencies="comctl32.lib wsock32.lib odbc32.lib odbccp32.lib winmm.lib"
|
AdditionalDependencies="comctl32.lib wsock32.lib odbc32.lib odbccp32.lib winmm.lib"
|
||||||
OutputFile="../../fteqw.exe"
|
OutputFile="../../fteqw.exe"
|
||||||
LinkIncremental="1"
|
LinkIncremental="1"
|
||||||
|
@ -1517,6 +1519,7 @@
|
||||||
/>
|
/>
|
||||||
<Tool
|
<Tool
|
||||||
Name="VCLinkerTool"
|
Name="VCLinkerTool"
|
||||||
|
AdditionalOptions="/DYNAMICBASE /NXCOMPAT"
|
||||||
AdditionalDependencies="comctl32.lib wsock32.lib odbc32.lib odbccp32.lib winmm.lib"
|
AdditionalDependencies="comctl32.lib wsock32.lib odbc32.lib odbccp32.lib winmm.lib"
|
||||||
OutputFile="../../fteqw_dbg.exe"
|
OutputFile="../../fteqw_dbg.exe"
|
||||||
LinkIncremental="2"
|
LinkIncremental="2"
|
||||||
|
@ -1527,6 +1530,7 @@
|
||||||
GenerateDebugInformation="true"
|
GenerateDebugInformation="true"
|
||||||
GenerateMapFile="true"
|
GenerateMapFile="true"
|
||||||
SubSystem="2"
|
SubSystem="2"
|
||||||
|
LargeAddressAware="2"
|
||||||
TargetMachine="1"
|
TargetMachine="1"
|
||||||
/>
|
/>
|
||||||
<Tool
|
<Tool
|
||||||
|
|
|
@ -85,7 +85,10 @@ void Mod_WipeSkin(skinid_t id)
|
||||||
for (i = 0; i < sk->nummappings; i++)
|
for (i = 0; i < sk->nummappings; i++)
|
||||||
{
|
{
|
||||||
if (sk->mappings[i].needsfree)
|
if (sk->mappings[i].needsfree)
|
||||||
|
{
|
||||||
Image_UnloadTexture(sk->mappings[i].texnums.base);
|
Image_UnloadTexture(sk->mappings[i].texnums.base);
|
||||||
|
sk->mappings[i].texnums.base = r_nulltex;
|
||||||
|
}
|
||||||
R_UnloadShader(sk->mappings[i].shader);
|
R_UnloadShader(sk->mappings[i].shader);
|
||||||
}
|
}
|
||||||
Z_Free(registeredskins[id]);
|
Z_Free(registeredskins[id]);
|
||||||
|
@ -115,16 +118,18 @@ skinfile_t *Mod_LookupSkin(skinid_t id)
|
||||||
return registeredskins[id];
|
return registeredskins[id];
|
||||||
return NULL;
|
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;
|
int l;
|
||||||
char *s, tname[MAX_QPATH];
|
char *s, tname[MAX_QPATH];
|
||||||
shader_t *sourceimg;
|
|
||||||
for (s = texture; *s; s++)
|
for (s = texture; *s; s++)
|
||||||
{
|
{
|
||||||
if (*s == '@' || *s == ':' || *s == '?' || *s == '*')
|
if (*s == '@' || *s == ':' || *s == '?' || *s == '*')
|
||||||
|
@ -138,59 +143,55 @@ static void Mod_ComposeSkin(char *texture, struct cctx_s *cctx)
|
||||||
tname[l] = 0;
|
tname[l] = 0;
|
||||||
|
|
||||||
//load the image and set some default sizes, etc.
|
//load the image and set some default sizes, etc.
|
||||||
sourceimg = R2D_SafeCachePic(tname);
|
if (*tname)
|
||||||
|
line->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;
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
line->sourceimg = NULL;
|
||||||
w = iw;
|
|
||||||
h = ih;
|
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)
|
while(*s)
|
||||||
{
|
{
|
||||||
switch(*s)
|
switch(*s)
|
||||||
{
|
{
|
||||||
case '@':
|
case '@':
|
||||||
x = strtod(s+1, &s);
|
line->pos[0] = strtod(s+1, &s);
|
||||||
if (*s == ',')
|
if (*s == ',')
|
||||||
s++;
|
s++;
|
||||||
y = strtod(s, &s);
|
line->pos[1] = strtod(s, &s);
|
||||||
break;
|
break;
|
||||||
case ':':
|
case ':':
|
||||||
w = strtod(s+1, &s);
|
line->size[0] = strtod(s+1, &s);
|
||||||
if (*s == ',')
|
if (*s == ',')
|
||||||
s++;
|
s++;
|
||||||
h = strtod(s, &s);
|
line->size[1] = strtod(s, &s);
|
||||||
break;
|
break;
|
||||||
case '$':
|
case '$':
|
||||||
s1 = strtod(s+1, &s);
|
line->tc[0] = strtod(s+1, &s);
|
||||||
if (*s == ',')
|
if (*s == ',')
|
||||||
s++;
|
s++;
|
||||||
t1 = strtod(s, &s);
|
line->tc[1] = strtod(s, &s);
|
||||||
if (*s == ',')
|
if (*s == ',')
|
||||||
s++;
|
s++;
|
||||||
s2 = strtod(s, &s);
|
line->tc[2] = strtod(s, &s);
|
||||||
if (*s == ',')
|
if (*s == ',')
|
||||||
s++;
|
s++;
|
||||||
t2 = strtod(s, &s);
|
line->tc[3] = strtod(s, &s);
|
||||||
break;
|
break;
|
||||||
case '?':
|
case '?':
|
||||||
r = strtod(s+1, &s);
|
line->rgba[0] = strtod(s+1, &s);
|
||||||
if (*s == ',')
|
if (*s == ',')
|
||||||
s++;
|
s++;
|
||||||
g = strtod(s, &s);
|
line->rgba[1] = strtod(s, &s);
|
||||||
if (*s == ',')
|
if (*s == ',')
|
||||||
s++;
|
s++;
|
||||||
b = strtod(s, &s);
|
line->rgba[2] = strtod(s, &s);
|
||||||
if (*s == ',')
|
if (*s == ',')
|
||||||
s++;
|
s++;
|
||||||
a = strtod(s, &s);
|
line->rgba[3] = strtod(s, &s);
|
||||||
break;
|
break;
|
||||||
// case '*':
|
// case '*':
|
||||||
// break;
|
// break;
|
||||||
|
@ -199,26 +200,46 @@ static void Mod_ComposeSkin(char *texture, struct cctx_s *cctx)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
static void Mod_ComposeSkin(char *texture, struct cctx_s *cctx, struct composeline_s *line)
|
||||||
|
{
|
||||||
|
int iw=0, ih=0;
|
||||||
|
|
||||||
if (!w || !h)
|
if (!line->sourceimg || R_GetShaderSizes(line->sourceimg, &iw, &ih, false) != 1) //no shader? no point in doing anything.
|
||||||
return;
|
|
||||||
|
|
||||||
//create a render target if one is not already selected
|
|
||||||
if (!TEXVALID(cctx->diffuse))
|
|
||||||
{
|
{
|
||||||
strcpy(r_refdef.rt_destcolour[0].texname, "-");
|
iw = ih = 0;
|
||||||
cctx->width = x+w;
|
line->sourceimg = NULL;
|
||||||
cctx->height = y+h;
|
}
|
||||||
cctx->diffuse = R2D_RT_Configure(r_refdef.rt_destcolour[0].texname, cctx->width, cctx->height, TF_RGBA32, RT_IMAGEFLAGS);
|
if (line->size[0] < 0)
|
||||||
BE_RenderToTextureUpdate2d(true);
|
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)
|
if (R2D_Flush)
|
||||||
return;
|
R2D_Flush();
|
||||||
|
R_UnloadShader(line->sourceimg); //we're done with it now
|
||||||
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
|
|
||||||
}
|
}
|
||||||
//create a new skin with explicit name and text. even if its already loaded. this means you can free it safely.
|
//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)
|
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
|
//body
|
||||||
if (com_tokentype != TTP_LINEENDING)
|
if (com_tokentype != TTP_LINEENDING)
|
||||||
{
|
{
|
||||||
|
size_t l,lines;
|
||||||
|
struct composeline_s line[64];
|
||||||
//fixme: this blocks waiting for the textures to load.
|
//fixme: this blocks waiting for the textures to load.
|
||||||
struct cctx_s cctx;
|
struct cctx_s cctx;
|
||||||
memset(&cctx, 0, sizeof(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);
|
R_BuildDefaultTexnums(NULL, skin->mappings[skin->nummappings].shader);
|
||||||
skin->mappings[skin->nummappings].texnums = *skin->mappings[skin->nummappings].shader->defaulttextures;
|
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')
|
while(*skintext == ' ' || *skintext == '\t')
|
||||||
skintext++;
|
skintext++;
|
||||||
|
@ -299,15 +323,20 @@ skinid_t Mod_ReadSkinFile(const char *skinname, const char *skintext)
|
||||||
else
|
else
|
||||||
break;
|
break;
|
||||||
skintext = COM_Parse(skintext);
|
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].needsfree = 1;
|
||||||
skin->mappings[skin->nummappings].texnums.base = cctx.diffuse;
|
skin->mappings[skin->nummappings].texnums.base = cctx.diffuse;
|
||||||
skin->nummappings++;
|
skin->nummappings++;
|
||||||
|
|
||||||
*r_refdef.rt_destcolour[0].texname = 0;
|
|
||||||
BE_RenderToTextureUpdate2d(true);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (!strcmp(com_token, "geomset"))
|
else if (!strcmp(com_token, "geomset"))
|
||||||
|
|
|
@ -3705,7 +3705,7 @@ void GLBE_SelectMode(backendmode_t mode)
|
||||||
if (!shaderstate.allblackshader.glsl.handle)
|
if (!shaderstate.allblackshader.glsl.handle)
|
||||||
{
|
{
|
||||||
const char *defs[] = {NULL};
|
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");
|
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!*/
|
/*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)
|
if (gl_config_nofixedfunc && !shaderstate.allblackshader.glsl.handle)
|
||||||
{
|
{
|
||||||
const char *defs[] = {NULL};
|
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");
|
shaderstate.allblack_mvp = qglGetUniformLocationARB(shaderstate.allblackshader.glsl.handle, "m_modelviewprojection");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4303,7 +4303,7 @@ static void DrawMeshes(void)
|
||||||
if (!shaderstate.allblackshader.glsl.handle)
|
if (!shaderstate.allblackshader.glsl.handle)
|
||||||
{
|
{
|
||||||
const char *defs[] = {NULL};
|
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");
|
shaderstate.allblack_mvp = qglGetUniformLocationARB(shaderstate.allblackshader.glsl.handle, "m_modelviewprojection");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1797,7 +1797,7 @@ static void Shader_LoadGeneric(sgeneric_t *g, int qrtype)
|
||||||
ver = sbuiltins[i].apiver;
|
ver = sbuiltins[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&&sh_config.maxver==100))
|
if (!(qrenderer==QR_OPENGL&&ver==110))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
g->failed = !Shader_LoadPermutations(g->name, &g->prog, sbuiltins[i].body, qrtype, ver, blobname);
|
g->failed = !Shader_LoadPermutations(g->name, &g->prog, sbuiltins[i].body, qrtype, ver, blobname);
|
||||||
|
|
|
@ -2997,8 +2997,23 @@ qboolean GL_Init(rendererstate_t *info, void *(*getglfunction) (char *name))
|
||||||
if (GL_CheckExtension("GL_EXT_packed_depth_stencil"))
|
if (GL_CheckExtension("GL_EXT_packed_depth_stencil"))
|
||||||
sh_config.texfmt[PTI_DEPTH24_8] = true;
|
sh_config.texfmt[PTI_DEPTH24_8] = true;
|
||||||
|
|
||||||
sh_config.minver = gl_config.arb_shader_objects?110:0;
|
if (gl_config.nofixedfunc)
|
||||||
sh_config.maxver = gl_config.arb_shader_objects?gl_config.maxglslversion:0;
|
{ //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.blobpath = "glsl/%s.blob";
|
||||||
sh_config.progpath = "glsl/%s.glsl";
|
sh_config.progpath = "glsl/%s.glsl";
|
||||||
sh_config.shadernamefmt = "%s_glsl";
|
sh_config.shadernamefmt = "%s_glsl";
|
||||||
|
|
|
@ -5,6 +5,8 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
|
||||||
|
|
||||||
#ifdef GLQUAKE
|
#ifdef GLQUAKE
|
||||||
{QR_OPENGL, 110, "fixedemu",
|
{QR_OPENGL, 110, "fixedemu",
|
||||||
|
"!!ver 100-450\n"
|
||||||
|
|
||||||
//this shader is present for support for gles/gl3core contexts
|
//this shader is present for support for gles/gl3core contexts
|
||||||
//it is single-texture-with-vertex-colours, and doesn't do anything special.
|
//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.
|
//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
|
#endif
|
||||||
#ifdef GLQUAKE
|
#ifdef GLQUAKE
|
||||||
{QR_OPENGL, 110, "default2d",
|
{QR_OPENGL, 110, "default2d",
|
||||||
|
"!!ver 100-450\n"
|
||||||
|
|
||||||
//this shader is present for support for gles/gl3core contexts
|
//this shader is present for support for gles/gl3core contexts
|
||||||
//it is single-texture-with-vertex-colours, and doesn't do anything special.
|
//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.
|
//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
|
#endif
|
||||||
#ifdef GLQUAKE
|
#ifdef GLQUAKE
|
||||||
{QR_OPENGL, 110, "defaultfill",
|
{QR_OPENGL, 110, "defaultfill",
|
||||||
|
"!!ver 100-450\n"
|
||||||
|
|
||||||
"#ifdef VERTEX_SHADER\n"
|
"#ifdef VERTEX_SHADER\n"
|
||||||
"attribute vec4 v_colour;\n"
|
"attribute vec4 v_colour;\n"
|
||||||
"varying vec4 vc;\n"
|
"varying vec4 vc;\n"
|
||||||
|
@ -7392,6 +7398,7 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
|
||||||
#endif
|
#endif
|
||||||
#ifdef GLQUAKE
|
#ifdef GLQUAKE
|
||||||
{QR_OPENGL, 110, "defaultgammacb",
|
{QR_OPENGL, 110, "defaultgammacb",
|
||||||
|
"!!ver 100-450\n"
|
||||||
//this shader is applies gamma/contrast/brightness to the source image, and dumps it out.
|
//this shader is applies gamma/contrast/brightness to the source image, and dumps it out.
|
||||||
|
|
||||||
"varying vec2 tc;\n"
|
"varying vec2 tc;\n"
|
||||||
|
|
|
@ -731,6 +731,7 @@ enum {
|
||||||
WARN_READNOTWRITTEN,
|
WARN_READNOTWRITTEN,
|
||||||
WARN_NOTREFERENCED,
|
WARN_NOTREFERENCED,
|
||||||
WARN_NOTREFERENCEDCONST,
|
WARN_NOTREFERENCEDCONST,
|
||||||
|
WARN_NOTREFERENCEDFIELD,
|
||||||
WARN_CONFLICTINGRETURNS,
|
WARN_CONFLICTINGRETURNS,
|
||||||
WARN_TOOFEWPARAMS,
|
WARN_TOOFEWPARAMS,
|
||||||
WARN_TOOMANYPARAMS,
|
WARN_TOOMANYPARAMS,
|
||||||
|
|
|
@ -10145,8 +10145,9 @@ void QCC_PR_ParseStatement (void)
|
||||||
{
|
{
|
||||||
PR_GenerateReturnOuts();
|
PR_GenerateReturnOuts();
|
||||||
if (pr_scope->type->aux_type->type != ev_void)
|
if (pr_scope->type->aux_type->type != ev_void)
|
||||||
{
|
{ //accumulated functions are not required to return anything, on the assumption that a previous 'part' of the function did so
|
||||||
QCC_PR_ParseWarning(WARN_MISSINGRETURNVALUE, "\'%s\' returned nothing, expected %s", pr_scope->name, pr_scope->type->aux_type->name);
|
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
|
//this should not normally happen
|
||||||
if (!pr_scope->returndef.cast)
|
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.
|
{ //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)
|
if (local->constant)
|
||||||
continue; //will get some other warning, so we don't care.
|
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)
|
if (local->symbolheader != local)
|
||||||
continue; //ignore slave symbols, cos they're not interesting and should have been checked as part of the parent.
|
continue; //ignore slave symbols, cos they're not interesting and should have been checked as part of the parent.
|
||||||
if (local->ofs < paramend)
|
if (local->ofs < paramend)
|
||||||
|
@ -11878,13 +11881,13 @@ void QCC_Marshal_Locals(int firststatement, int laststatement)
|
||||||
if (qccwarningaction[WARN_UNINITIALIZED])
|
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
|
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])
|
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
|
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
|
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;
|
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);
|
// 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.
|
//generate a goto statement around the nested function, so that nothing is hurt.
|
||||||
patch = QCC_Generate_OP_GOTO();
|
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;
|
patch->a.ofs = &statements[numstatements] - patch;
|
||||||
if (patch->a.ofs == 1)
|
if (patch->a.ofs == 1)
|
||||||
numstatements--; //never mind then.
|
numstatements--; //never mind then.
|
||||||
|
|
|
@ -218,6 +218,7 @@ struct {
|
||||||
{" F322", WARN_IFSTRING_USED},
|
{" F322", WARN_IFSTRING_USED},
|
||||||
{" F323", WARN_UNREACHABLECODE},
|
{" F323", WARN_UNREACHABLECODE},
|
||||||
|
|
||||||
|
{" F207", WARN_NOTREFERENCEDFIELD},
|
||||||
{" F208", WARN_NOTREFERENCEDCONST},
|
{" F208", WARN_NOTREFERENCEDCONST},
|
||||||
{" F209", WARN_EXTRAPRECACHE},
|
{" F209", WARN_EXTRAPRECACHE},
|
||||||
{" F210", WARN_NOTPRECACHED},
|
{" F210", WARN_NOTPRECACHED},
|
||||||
|
@ -962,7 +963,7 @@ void QCC_DetermineNeededSymbols(QCC_def_t *endsyssym)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//non-system fields should maybe be present too.
|
//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)
|
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;
|
// sym->symbolheader->used = true;
|
||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
for (i=0 ; i<numstatements ; i++)
|
for (i=0 ; i<numstatements ; i++)
|
||||||
{
|
{
|
||||||
|
@ -1007,12 +1009,15 @@ void QCC_FinaliseDef(QCC_def_t *def)
|
||||||
return; //was already finalised.
|
return; //was already finalised.
|
||||||
|
|
||||||
if (def->symbolheader != def)
|
if (def->symbolheader != def)
|
||||||
|
{
|
||||||
QCC_FinaliseDef(def->symbolheader);
|
QCC_FinaliseDef(def->symbolheader);
|
||||||
|
def->referenced = true;
|
||||||
|
}
|
||||||
if (def->symbolheader == def && def->deftail)
|
if (def->symbolheader == def && def->deftail)
|
||||||
{
|
{
|
||||||
//for head symbols, we go through and touch all of their children
|
//for head symbols, we go through and touch all of their children
|
||||||
QCC_def_t *prev, *sub;
|
QCC_def_t *prev, *sub;
|
||||||
if (!def->referenced)
|
if (def->used && !def->referenced)
|
||||||
{
|
{
|
||||||
pbool ignoreone = true;
|
pbool ignoreone = true;
|
||||||
//touch all but one child
|
//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
|
def->referenced=true; //if one child is referenced, the composite is referenced
|
||||||
else if (!sub->referenced && ignoreone)
|
else if (!sub->referenced && ignoreone)
|
||||||
ignoreone = false; //this is the one we're going to warn about
|
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
|
// 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)
|
// for (prev = def, sub = prev->next; prev != def->deftail; sub = (prev=sub)->next)
|
||||||
sub->referenced = true;
|
// sub->referenced = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//touch children
|
//touch children to silence annoying warnings.
|
||||||
for (prev = def, sub = prev->next; prev != def->deftail; sub = (prev=sub)->next)
|
for (prev = def, sub = prev->next; prev != def->deftail; sub = (prev=sub)->next)
|
||||||
sub->referenced |= def->referenced;
|
sub->referenced |= true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef TODO_READWRITETRACK
|
#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));
|
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
|
#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;
|
int wt = def->constant?WARN_NOTREFERENCEDCONST:WARN_NOTREFERENCED;
|
||||||
|
if (def->type->type == ev_field && def->constant)
|
||||||
|
wt = WARN_NOTREFERENCEDFIELD;
|
||||||
pr_scope = def->scope;
|
pr_scope = def->scope;
|
||||||
if (!strncmp(def->name, "spawnfunc_", 10))
|
if (!strncmp(def->name, "spawnfunc_", 10))
|
||||||
; //no warnings from unreferenced entry points.
|
; //no warnings from unreferenced entry points.
|
||||||
|
|
|
@ -588,8 +588,10 @@ extern qboolean ssqc_deprecated_warned;
|
||||||
#define svc_setfrags 14
|
#define svc_setfrags 14
|
||||||
#define svc_updatecolors 17
|
#define svc_updatecolors 17
|
||||||
|
|
||||||
|
#ifdef HEXEN2
|
||||||
#define svch2_clearviewflags 41 //hexen2.
|
#define svch2_clearviewflags 41 //hexen2.
|
||||||
#define svch2_setangles_lerp 50
|
#define svch2_setangles_lerp 50
|
||||||
|
#endif
|
||||||
|
|
||||||
//these are present in the darkplaces engine.
|
//these are present in the darkplaces engine.
|
||||||
//I wanna knick their mods.
|
//I wanna knick their mods.
|
||||||
|
@ -706,9 +708,9 @@ void NPP_NQFlush(void)
|
||||||
{
|
{
|
||||||
client_t *cl;
|
client_t *cl;
|
||||||
int i;
|
int i;
|
||||||
|
#ifdef HEXEN2
|
||||||
char *h2finale = NULL;
|
char *h2finale = NULL;
|
||||||
char *h2title = NULL;
|
char *h2title = NULL;
|
||||||
#ifdef HEXEN2
|
|
||||||
if (progstype == PROG_H2)
|
if (progstype == PROG_H2)
|
||||||
{
|
{
|
||||||
/*FIXME: hexen2 intermission+finale includes the viewheight. NQ does not, and QW has explicit position with scores but no finale*/
|
/*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))
|
if (cl->state == cs_spawned && ISQWCLIENT(cl))
|
||||||
{
|
{
|
||||||
|
#ifdef HEXEN2
|
||||||
if (h2finale)
|
if (h2finale)
|
||||||
{
|
{
|
||||||
ClientReliableCheckBlock(cl, 6 + strlen(h2title) + 3 + strlen(h2finale) + 1);
|
ClientReliableCheckBlock(cl, 6 + strlen(h2title) + 3 + strlen(h2finale) + 1);
|
||||||
|
@ -747,7 +750,9 @@ void NPP_NQFlush(void)
|
||||||
|
|
||||||
ClientReliableWrite_String(cl, h2finale);
|
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
|
{ //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);
|
ClientReliableCheckBlock(cl, 5);
|
||||||
ClientReliableWrite_Byte(cl, svc_finale);
|
ClientReliableWrite_Byte(cl, svc_finale);
|
||||||
|
|
|
@ -2904,7 +2904,7 @@ void SV_MemInfo_f(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
void SV_Download_f (void)
|
void SV_Download_f (void)
|
||||||
{
|
{ //command for dedicated servers. apparently.
|
||||||
#ifdef WEBCLIENT
|
#ifdef WEBCLIENT
|
||||||
char *url = Cmd_Argv(1);
|
char *url = Cmd_Argv(1);
|
||||||
char *localname = Cmd_Argv(2);
|
char *localname = Cmd_Argv(2);
|
||||||
|
|
|
@ -5233,7 +5233,7 @@ void SV_FixupName(char *in, char *out, unsigned int outlen)
|
||||||
s = out;
|
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.
|
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++;
|
in++;
|
||||||
while(*in && len > 0)
|
while(*in && len > 1)
|
||||||
{
|
{
|
||||||
if (isinvalid(*in))
|
if (isinvalid(*in))
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
!!ver 100-450
|
||||||
|
|
||||||
//this shader is present for support for gles/gl3core contexts
|
//this shader is present for support for gles/gl3core contexts
|
||||||
//it is single-texture-with-vertex-colours, and doesn't do anything special.
|
//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.
|
//beware that a few things use this, including apparently fonts and bloom rescaling.
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
!!ver 100-450
|
||||||
|
|
||||||
#ifdef VERTEX_SHADER
|
#ifdef VERTEX_SHADER
|
||||||
attribute vec4 v_colour;
|
attribute vec4 v_colour;
|
||||||
varying vec4 vc;
|
varying vec4 vc;
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
!!ver 100-450
|
||||||
//this shader is applies gamma/contrast/brightness to the source image, and dumps it out.
|
//this shader is applies gamma/contrast/brightness to the source image, and dumps it out.
|
||||||
|
|
||||||
varying vec2 tc;
|
varying vec2 tc;
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
!!ver 100-450
|
||||||
|
|
||||||
//this shader is present for support for gles/gl3core contexts
|
//this shader is present for support for gles/gl3core contexts
|
||||||
//it is single-texture-with-vertex-colours, and doesn't do anything special.
|
//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.
|
//beware that a few things use this, including apparently fonts and bloom rescaling.
|
||||||
|
|
|
@ -10,6 +10,7 @@ extern cvar_t vk_submissionthread;
|
||||||
extern cvar_t vk_debug;
|
extern cvar_t vk_debug;
|
||||||
extern cvar_t vk_dualqueue;
|
extern cvar_t vk_dualqueue;
|
||||||
extern cvar_t vk_busywait;
|
extern cvar_t vk_busywait;
|
||||||
|
extern cvar_t vk_waitfence;
|
||||||
extern cvar_t vk_nv_glsl_shader;
|
extern cvar_t vk_nv_glsl_shader;
|
||||||
extern cvar_t vk_nv_dedicated_allocation;
|
extern cvar_t vk_nv_dedicated_allocation;
|
||||||
extern cvar_t vk_khr_dedicated_allocation;
|
extern cvar_t vk_khr_dedicated_allocation;
|
||||||
|
@ -220,7 +221,8 @@ static void VK_DestroySwapChain(void)
|
||||||
vk.dopresent(NULL);
|
vk.dopresent(NULL);
|
||||||
while (vk.aquirenext < vk.aquirelast)
|
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++;
|
vk.aquirenext++;
|
||||||
}
|
}
|
||||||
if (vk.device)
|
if (vk.device)
|
||||||
|
@ -281,6 +283,7 @@ static qboolean VK_CreateSwapChain(void)
|
||||||
vid_triplebuffer.modified = false;
|
vid_triplebuffer.modified = false;
|
||||||
vid_srgb.modified = false;
|
vid_srgb.modified = false;
|
||||||
vk_submissionthread.modified = false;
|
vk_submissionthread.modified = false;
|
||||||
|
vk_waitfence.modified = false;
|
||||||
vid_multisample.modified = false;
|
vid_multisample.modified = false;
|
||||||
|
|
||||||
vk.triplebuffer = vid_triplebuffer.ival;
|
vk.triplebuffer = vid_triplebuffer.ival;
|
||||||
|
@ -305,9 +308,19 @@ static qboolean VK_CreateSwapChain(void)
|
||||||
vk.aquirelast = vk.aquirenext = 0;
|
vk.aquirelast = vk.aquirenext = 0;
|
||||||
for (i = 0; i < ACQUIRELIMIT; i++)
|
for (i = 0; i < ACQUIRELIMIT; i++)
|
||||||
{
|
{
|
||||||
VkFenceCreateInfo fci = {VK_STRUCTURE_TYPE_FENCE_CREATE_INFO};
|
if (1)
|
||||||
fci.flags = VK_FENCE_CREATE_SIGNALED_BIT;
|
{
|
||||||
VkAssert(vkCreateFence(vk.device,&fci,vkallocationcb,&vk.acquirefences[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]));
|
||||||
|
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.acquirebufferidx[vk.aquirelast%ACQUIRELIMIT] = vk.aquirelast%vk.backbuf_count;
|
||||||
vk.aquirelast++;
|
vk.aquirelast++;
|
||||||
|
@ -411,8 +424,12 @@ static qboolean VK_CreateSwapChain(void)
|
||||||
uint32_t priority = 0;
|
uint32_t priority = 0;
|
||||||
switch(presentmode[i])
|
switch(presentmode[i])
|
||||||
{
|
{
|
||||||
default://ignore it.
|
default://ignore it if we don't know it.
|
||||||
break;
|
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:
|
case VK_PRESENT_MODE_IMMEDIATE_KHR:
|
||||||
priority = (vk.vsync?0:2) + 2; //for most quake players, latency trumps tearing.
|
priority = (vk.vsync?0:2) + 2; //for most quake players, latency trumps tearing.
|
||||||
break;
|
break;
|
||||||
|
@ -434,7 +451,7 @@ static qboolean VK_CreateSwapChain(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!vk.vsync && swapinfo.presentMode != VK_PRESENT_MODE_IMMEDIATE_KHR)
|
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;
|
vk.srgbcapable = false;
|
||||||
swapinfo.imageColorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR;
|
swapinfo.imageColorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR;
|
||||||
|
@ -499,13 +516,23 @@ static qboolean VK_CreateSwapChain(void)
|
||||||
vk.aquirelast = vk.aquirenext = 0;
|
vk.aquirelast = vk.aquirenext = 0;
|
||||||
for (i = 0; i < ACQUIRELIMIT; i++)
|
for (i = 0; i < ACQUIRELIMIT; i++)
|
||||||
{
|
{
|
||||||
VkFenceCreateInfo fci = {VK_STRUCTURE_TYPE_FENCE_CREATE_INFO};
|
if (vk_waitfence.ival)
|
||||||
VkAssert(vkCreateFence(vk.device,&fci,vkallocationcb,&vk.acquirefences[i]));
|
{
|
||||||
|
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*/
|
/*-1 to hide any weird thread issues*/
|
||||||
while (vk.aquirelast < ACQUIRELIMIT-1 && vk.aquirelast < vk.backbuf_count && vk.aquirelast <= vk.backbuf_count-surfcaps.minImageCount)
|
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++;
|
vk.aquirelast++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1074,7 +1101,8 @@ void *VK_FencedBegin(void (*passed)(void *work), size_t worksize)
|
||||||
|
|
||||||
return w;
|
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)
|
void VK_FencedSubmit(void *work)
|
||||||
{
|
{
|
||||||
struct vk_fencework *w = work;
|
struct vk_fencework *w = work;
|
||||||
|
@ -2623,6 +2651,7 @@ VkCommandBuffer VK_AllocFrameCBuf(void)
|
||||||
|
|
||||||
qboolean VK_SCR_GrabBackBuffer(void)
|
qboolean VK_SCR_GrabBackBuffer(void)
|
||||||
{
|
{
|
||||||
|
VkSemaphore sem;
|
||||||
RSpeedLocals();
|
RSpeedLocals();
|
||||||
|
|
||||||
if (vk.frame) //erk, we already have one...
|
if (vk.frame) //erk, we already have one...
|
||||||
|
@ -2643,31 +2672,37 @@ qboolean VK_SCR_GrabBackBuffer(void)
|
||||||
|
|
||||||
while (vk.aquirenext == vk.aquirelast)
|
while (vk.aquirenext == vk.aquirelast)
|
||||||
{ //we're still waiting for the render thread to increment acquirelast.
|
{ //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
|
Sys_Sleep(0); //o.O
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
Sys_SendKeyEvents();
|
Sys_SendKeyEvents();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
//wait for the queued acquire to actually finish
|
if (vk.acquirefences[vk.aquirenext%ACQUIRELIMIT] != VK_NULL_HANDLE)
|
||||||
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
|
//wait for the queued acquire to actually finish
|
||||||
VkResult err = vkWaitForFences(vk.device, 1, &vk.acquirefences[vk.aquirenext%ACQUIRELIMIT], VK_FALSE, UINT64_MAX);
|
if (vk_busywait.ival)
|
||||||
if (err)
|
{ //busy wait, to try to get the highest fps possible
|
||||||
{
|
while (VK_TIMEOUT == vkGetFenceStatus(vk.device, vk.acquirefences[vk.aquirenext%ACQUIRELIMIT]))
|
||||||
if (err == VK_ERROR_DEVICE_LOST)
|
;
|
||||||
Sys_Error("Vulkan device lost");
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
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];
|
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++;
|
vk.aquirenext++;
|
||||||
|
|
||||||
//grab the first unused
|
//grab the first unused
|
||||||
|
@ -2684,6 +2719,7 @@ qboolean VK_SCR_GrabBackBuffer(void)
|
||||||
|
|
||||||
vk.frame->numcbufs = 0;
|
vk.frame->numcbufs = 0;
|
||||||
vk.rendertarg->cbuf = VK_AllocFrameCBuf();
|
vk.rendertarg->cbuf = VK_AllocFrameCBuf();
|
||||||
|
vk.frame->acquiresemaphore = sem;
|
||||||
|
|
||||||
RSpeedEnd(RSPEED_SETUP);
|
RSpeedEnd(RSPEED_SETUP);
|
||||||
|
|
||||||
|
@ -2859,7 +2895,7 @@ qboolean VK_SCR_UpdateScreen (void)
|
||||||
VK_FencedCheck();
|
VK_FencedCheck();
|
||||||
|
|
||||||
//a few cvars need some extra work if they're changed
|
//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;
|
vk.neednewswapchain = true;
|
||||||
|
|
||||||
if (vk.devicelost)
|
if (vk.devicelost)
|
||||||
|
@ -2989,7 +3025,7 @@ qboolean VK_SCR_UpdateScreen (void)
|
||||||
vk.frame->frameendjobs = vk.frameendjobs;
|
vk.frame->frameendjobs = vk.frameendjobs;
|
||||||
vk.frameendjobs = NULL;
|
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...
|
//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
|
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)
|
if (err)
|
||||||
{
|
{
|
||||||
Con_Printf("ERROR: vkAcquireNextImageKHR: %x\n", err);
|
Con_Printf("ERROR: vkAcquireNextImageKHR: %x\n", err);
|
||||||
|
|
|
@ -208,6 +208,7 @@ enum dynbuf_e
|
||||||
};
|
};
|
||||||
struct vk_rendertarg
|
struct vk_rendertarg
|
||||||
{
|
{
|
||||||
|
|
||||||
VkCommandBuffer cbuf; //cbuf allocated for this render target.
|
VkCommandBuffer cbuf; //cbuf allocated for this render target.
|
||||||
VkFramebuffer framebuffer;
|
VkFramebuffer framebuffer;
|
||||||
vk_image_t colour, depth, mscolour;
|
vk_image_t colour, depth, mscolour;
|
||||||
|
@ -265,6 +266,7 @@ extern struct vulkaninfo_s
|
||||||
VkPhysicalDeviceLimits limits;
|
VkPhysicalDeviceLimits limits;
|
||||||
|
|
||||||
#define ACQUIRELIMIT 8
|
#define ACQUIRELIMIT 8
|
||||||
|
VkSemaphore acquiresemaphores[ACQUIRELIMIT];
|
||||||
VkFence acquirefences[ACQUIRELIMIT];
|
VkFence acquirefences[ACQUIRELIMIT];
|
||||||
uint32_t acquirebufferidx[ACQUIRELIMIT];
|
uint32_t acquirebufferidx[ACQUIRELIMIT];
|
||||||
unsigned int aquirenext;
|
unsigned int aquirenext;
|
||||||
|
@ -315,6 +317,7 @@ extern struct vulkaninfo_s
|
||||||
struct vkframe *next;
|
struct vkframe *next;
|
||||||
struct dynbuffer *dynbufs[DB_MAX];
|
struct dynbuffer *dynbufs[DB_MAX];
|
||||||
struct descpool *descpools;
|
struct descpool *descpools;
|
||||||
|
VkSemaphore acquiresemaphore;
|
||||||
VkCommandBuffer *cbufs;
|
VkCommandBuffer *cbufs;
|
||||||
size_t numcbufs;
|
size_t numcbufs;
|
||||||
size_t maxcbufs;
|
size_t maxcbufs;
|
||||||
|
|
Loading…
Reference in a new issue