mirror of
https://github.com/nzp-team/fteqw.git
synced 2024-11-25 13:21:36 +00:00
Fix potentially serious vulkan performance issue.
Stripped obsolete vk_nv_dedicated_allocation extension. Misc fixes for warnings. Linux now defaults to using ~/.local/share/fte instead of ~/.fte for greater consistency. Other misc linux tweaks. git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@5267 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
parent
6766b8af55
commit
b7784f41d9
51 changed files with 736 additions and 596 deletions
|
@ -890,8 +890,12 @@ GLB_DIR=gl_$(FTE_FULLTARGET)
|
|||
GLCL_DIR=glcl_$(FTE_FULLTARGET)
|
||||
SV_DIR?=sv_$(FTE_FULLTARGET)
|
||||
|
||||
VKCL_OBJS=$(VKQUAKE_OBJS) $(BOTLIB_OBJS) snd_sdl.o cd_sdl.o sys_sdl.o in_sdl.o snd_directx.o $(D3DGL_OBJS) $(LTO_END)
|
||||
VKCL_OBJS=$(VKQUAKE_OBJS) $(D3DGL_OBJS) gl_bloom.o $(BOTLIB_OBJS) gl_vidsdl.o snd_sdl.o cd_sdl.o sys_sdl.o in_sdl.o
|
||||
VK_CFLAGS=-DFTE_SDL $(VKCFLAGS) `$(SDLCONFIG) --cflags`
|
||||
VKB_DIR=vk_$(FTE_FULLTARGET)
|
||||
VKCL_DIR=vk_$(FTE_FULLTARGET)
|
||||
VK_EXE_NAME=../$(EXE_NAME)-vk$(FTE_FULLTARGET)
|
||||
VKCL_EXE_NAME=../$(EXE_NAME)-vkcl$(FTE_FULLTARGET)
|
||||
|
||||
SV_OBJS=$(COMMON_OBJS) $(SERVER_OBJS) $(PROGS_OBJS) $(SERVERONLY_OBJS) $(BOTLIB_OBJS)
|
||||
SV_EXE_NAME=../$(EXE_NAME)-sv$(FTE_FULLTARGET)
|
||||
|
|
|
@ -1863,10 +1863,9 @@ void CL_SendCmd (double frametime, qboolean mainloop)
|
|||
|
||||
#ifndef CLIENTONLY
|
||||
if (sv.state && cls.state != ca_active)
|
||||
{
|
||||
fullsend = -1;
|
||||
{ //HACK: if we're also the server, spam like a crazy person until we're on the server, for faster apparent load times.
|
||||
fullsend = -1; //send no movement command.
|
||||
msecstouse = usetime = msecs;
|
||||
msecs = 0;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
|
|
|
@ -1619,7 +1619,7 @@ void CL_ClearState (void)
|
|||
#ifdef Q2CLIENT
|
||||
for (i = 0; i < countof(cl.configstring_general); i++)
|
||||
{
|
||||
if (cl.configstring_general)
|
||||
if (cl.configstring_general[i])
|
||||
Z_Free(cl.configstring_general[i]);
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -4242,7 +4242,7 @@ static void CLQ2_ParseConfigString (void)
|
|||
return;
|
||||
}
|
||||
|
||||
if (i < 0 || i >= Q2MAX_CONFIGSTRINGS)
|
||||
if ((unsigned int)i >= Q2MAX_CONFIGSTRINGS)
|
||||
Host_EndGame ("configstring > Q2MAX_CONFIGSTRINGS");
|
||||
|
||||
// strncpy (olds, cl.configstrings[i], sizeof(olds));
|
||||
|
@ -7937,7 +7937,7 @@ void CLNQ_ParseServerMessage (void)
|
|||
break;
|
||||
case svcdp_updatestatbyte:
|
||||
//case svcneh_fog:
|
||||
if (CPNQ_IS_BJP || cls.protocol_nq == PROTOCOL_VERSION_NEHD)
|
||||
if (CPNQ_IS_BJP || cls.protocol_nq == CPNQ_NEHAHRA)
|
||||
{
|
||||
CL_ResetFog(0);
|
||||
if (MSG_ReadByte())
|
||||
|
|
|
@ -1085,9 +1085,9 @@ static void CLQ2_DeltaEntity (q2frame_t *frame, int newnum, entity_state_t *old,
|
|||
|| state->modelindex2 != ent->current.modelindex2
|
||||
|| state->u.q2.modelindex3 != ent->current.u.q2.modelindex3
|
||||
|| state->u.q2.modelindex4 != ent->current.u.q2.modelindex4
|
||||
|| abs(state->origin[0] - ent->current.origin[0]) > 512
|
||||
|| abs(state->origin[1] - ent->current.origin[1]) > 512
|
||||
|| abs(state->origin[2] - ent->current.origin[2]) > 512
|
||||
|| fabs(state->origin[0] - ent->current.origin[0]) > 512
|
||||
|| fabs(state->origin[1] - ent->current.origin[1]) > 512
|
||||
|| fabs(state->origin[2] - ent->current.origin[2]) > 512
|
||||
|| state->u.q2.event == Q2EV_PLAYER_TELEPORT
|
||||
|| state->u.q2.event == Q2EV_OTHER_TELEPORT
|
||||
)
|
||||
|
@ -2442,7 +2442,7 @@ void CLQ2_CalcViewValues (int seat)
|
|||
ops = &oldframe->playerstate[seat];
|
||||
|
||||
// see if the player entity was teleported this frame
|
||||
if ( fabs(ops->pmove.origin[0] - ps->pmove.origin[0]) > 256*8
|
||||
if ( abs(ops->pmove.origin[0] - ps->pmove.origin[0]) > 256*8
|
||||
|| abs(ops->pmove.origin[1] - ps->pmove.origin[1]) > 256*8
|
||||
|| abs(ops->pmove.origin[2] - ps->pmove.origin[2]) > 256*8)
|
||||
ops = ps; // don't interpolate
|
||||
|
|
|
@ -2197,7 +2197,8 @@ static qbyte *ReadRawBMPFile(qbyte *buf, int length, int *width, int *height, si
|
|||
data32[i] = pal[buf[x]];
|
||||
i++;
|
||||
}
|
||||
buf += h.Width;
|
||||
//BMP rows are 32-bit aligned.
|
||||
buf += (h.Width+3)&~3;
|
||||
}
|
||||
|
||||
if (!OffsetofBMPBits)
|
||||
|
|
|
@ -3128,7 +3128,7 @@ int CL_ReadServerInfo(char *msg, enum masterprotocol_e prototype, qboolean favor
|
|||
info->maxplayers = bound(0, ping, 255);
|
||||
|
||||
ping = atoi(Info_ValueForKey(msg, "timelimit"));
|
||||
info->tl = bound(-327678, ping, 32767);
|
||||
info->tl = bound(-32768, ping, 32767);
|
||||
ping = atoi(Info_ValueForKey(msg, "fraglimit"));
|
||||
info->fl = bound(-32768, ping, 32767);
|
||||
|
||||
|
|
|
@ -1188,7 +1188,8 @@ int menuentsize;
|
|||
// cvars
|
||||
#define MENUPROGSGROUP "Menu progs control"
|
||||
cvar_t forceqmenu = CVAR("forceqmenu", "0");
|
||||
cvar_t pr_menuqc_coreonerror = CVAR("pr_menuqc_coreonerror", "1");
|
||||
cvar_t pr_menu_coreonerror = CVAR("pr_menu_coreonerror", "1");
|
||||
cvar_t pr_menu_memsize = CVAR("pr_menu_memsize", "64m");
|
||||
|
||||
|
||||
//new generic functions.
|
||||
|
@ -2447,7 +2448,7 @@ void VARGS Menu_Abort (char *format, ...)
|
|||
|
||||
Con_Printf("Menu_Abort: %s\nShutting down menu.dat\n", string);
|
||||
|
||||
if (pr_menuqc_coreonerror.value)
|
||||
if (pr_menu_coreonerror.value)
|
||||
{
|
||||
char *buffer;
|
||||
size_t size = 1024*1024*8;
|
||||
|
@ -2585,7 +2586,7 @@ qboolean MP_Init (void)
|
|||
int mprogs;
|
||||
Con_DPrintf("Initializing menu.dat\n");
|
||||
menu_world.progs = InitProgs(&menuprogparms);
|
||||
PR_Configure(menu_world.progs, 64*1024*1024, 1, pr_enable_profiling.ival);
|
||||
PR_Configure(menu_world.progs, PR_ReadBytesString(pr_menu_memsize.string), 1, pr_enable_profiling.ival);
|
||||
mprogs = PR_LoadProgs(menu_world.progs, "menu.dat");
|
||||
if (mprogs < 0) //no per-progs builtins.
|
||||
{
|
||||
|
@ -2746,7 +2747,8 @@ void MP_RegisterCvarsAndCmds(void)
|
|||
|
||||
|
||||
Cvar_Register(&forceqmenu, MENUPROGSGROUP);
|
||||
Cvar_Register(&pr_menuqc_coreonerror, MENUPROGSGROUP);
|
||||
Cvar_Register(&pr_menu_coreonerror, MENUPROGSGROUP);
|
||||
Cvar_Register(&pr_menu_memsize, MENUPROGSGROUP);
|
||||
|
||||
if (COM_CheckParm("-qmenu"))
|
||||
Cvar_Set(&forceqmenu, "1");
|
||||
|
|
|
@ -463,15 +463,16 @@ cvar_t gl_screenangle = CVAR("gl_screenangle", "0");
|
|||
#ifdef VKQUAKE
|
||||
cvar_t vk_stagingbuffers = CVARD ("vk_stagingbuffers", "", "Configures which dynamic buffers are copied into gpu memory for rendering, instead of reading from shared memory. Empty for default settings.\nAccepted chars are u, e, v, 0.");
|
||||
cvar_t vk_submissionthread = CVARD ("vk_submissionthread", "", "Execute submits+presents on a thread dedicated to executing them. This may be a significant speedup on certain drivers.");
|
||||
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_debug = CVARFD("vk_debug", "0", CVAR_VIDEOLATCH, "Register a debug handler to display driver/layer messages. 2 enables the standard validation layers.");
|
||||
cvar_t vk_dualqueue = CVARFD("vk_dualqueue", "", CVAR_VIDEOLATCH, "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.");
|
||||
cvar_t vk_khr_push_descriptor = CVARD ("vk_khr_push_descriptor", "", "Enables better descriptor streaming.");
|
||||
cvar_t vk_amd_rasterization_order = CVARD ("vk_amd_rasterization_order", "", "Enables the use of relaxed rasterization ordering, for a small speedup at the minor risk of a little zfighting.");
|
||||
cvar_t vk_usememorypools = CVARFD("vk_usememorypools", "", CVAR_VIDEOLATCH, "Allocates memory pools for sub allocations. Vulkan has a limit to the number of memory allocations allowed so this should always be enabled, however at this time FTE is unable to reclaim pool memory, and would require periodic vid_restarts to flush them.");
|
||||
cvar_t vk_nv_glsl_shader = CVARFD("vk_loadglsl", "", CVAR_VIDEOLATCH, "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_khr_get_memory_requirements2 = CVARFD("vk_khr_get_memory_requirements2", "", CVAR_VIDEOLATCH, "Enable extended memory info querires");
|
||||
cvar_t vk_khr_dedicated_allocation = CVARFD("vk_khr_dedicated_allocation", "", CVAR_VIDEOLATCH, "Flag vulkan memory allocations as dedicated, where applicable.");
|
||||
cvar_t vk_khr_push_descriptor = CVARFD("vk_khr_push_descriptor", "", CVAR_VIDEOLATCH, "Enables better descriptor streaming.");
|
||||
cvar_t vk_amd_rasterization_order = CVARFD("vk_amd_rasterization_order", "", CVAR_VIDEOLATCH, "Enables the use of relaxed rasterization ordering, for a small speedup at the minor risk of a little zfighting.");
|
||||
#endif
|
||||
|
||||
#ifdef D3D9QUAKE
|
||||
|
@ -1011,9 +1012,10 @@ void Renderer_Init(void)
|
|||
Cvar_Register (&vk_dualqueue, VKRENDEREROPTIONS);
|
||||
Cvar_Register (&vk_busywait, VKRENDEREROPTIONS);
|
||||
Cvar_Register (&vk_waitfence, VKRENDEREROPTIONS);
|
||||
Cvar_Register (&vk_usememorypools, VKRENDEREROPTIONS);
|
||||
|
||||
Cvar_Register (&vk_nv_glsl_shader, VKRENDEREROPTIONS);
|
||||
Cvar_Register (&vk_nv_dedicated_allocation, VKRENDEREROPTIONS);
|
||||
Cvar_Register (&vk_khr_get_memory_requirements2,VKRENDEREROPTIONS);
|
||||
Cvar_Register (&vk_khr_dedicated_allocation,VKRENDEREROPTIONS);
|
||||
Cvar_Register (&vk_khr_push_descriptor, VKRENDEREROPTIONS);
|
||||
Cvar_Register (&vk_amd_rasterization_order, VKRENDEREROPTIONS);
|
||||
|
@ -1944,6 +1946,7 @@ qboolean R_BuildRenderstate(rendererstate_t *newr, char *rendererstring)
|
|||
}
|
||||
else
|
||||
{
|
||||
int bestpri = -2, pri;
|
||||
for (i = 0; i < sizeof(rendererinfo)/sizeof(rendererinfo[0]); i++)
|
||||
{
|
||||
if (!rendererinfo[i] || !rendererinfo[i]->description)
|
||||
|
@ -1954,8 +1957,21 @@ qboolean R_BuildRenderstate(rendererstate_t *newr, char *rendererstring)
|
|||
continue;
|
||||
if (!stricmp(rendererinfo[i]->name[j], com_token))
|
||||
{
|
||||
newr->renderer = rendererinfo[i];
|
||||
break;
|
||||
if (rendererinfo[i]->VID_GetPriority)
|
||||
pri = rendererinfo[i]->VID_GetPriority();
|
||||
else if (rendererinfo[i]->rtype == QR_HEADLESS)
|
||||
pri = -1; //headless renderers are a really poor choice, and will make the user think it buggy.
|
||||
else if (rendererinfo[i]->rtype == QR_NONE)
|
||||
pri = 0; //dedicated servers are possible, but we really don't want to use them unless we have no other choice.
|
||||
else
|
||||
pri = 1;
|
||||
|
||||
if (pri > bestpri)
|
||||
{
|
||||
bestpri = pri;
|
||||
newr->renderer = rendererinfo[i];
|
||||
}
|
||||
break; //try the next renderer now.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -236,7 +236,7 @@ void S_PaintChannels(soundcardinfo_t *sc, int endtime)
|
|||
{ //hit eof, loop it or stop it
|
||||
if (s->loopstart != -1) /*some wavs contain a loop offset directly in the sound file, such samples loop even if a non-looping builtin was used*/
|
||||
{
|
||||
ch->pos &= ~((-1)<<PITCHSHIFT); /*clear out all but the subsample offset*/
|
||||
ch->pos &= ~((~0u)<<PITCHSHIFT); /*clear out all but the subsample offset*/
|
||||
ch->pos += s->loopstart<<PITCHSHIFT; //ignore the offset if its off the end of the file
|
||||
}
|
||||
else if (ch->flags & CF_FORCELOOP) /*(static)channels which are explicitly looping always loop from the start*/
|
||||
|
|
|
@ -452,7 +452,7 @@ int Sys_FileTime (char *path)
|
|||
|
||||
void Sys_mkdir (const char *path)
|
||||
{
|
||||
mkdir (path, 0777);
|
||||
mkdir (path, 0760);
|
||||
}
|
||||
qboolean Sys_rmdir (const char *path)
|
||||
{
|
||||
|
@ -464,7 +464,10 @@ qboolean Sys_rmdir (const char *path)
|
|||
}
|
||||
qboolean Sys_remove (const char *path)
|
||||
{
|
||||
return system(va("rm \"%s\"", path));
|
||||
//remove is part of c89.
|
||||
if (remove(path) == -1)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
qboolean Sys_Rename (const char *oldfname, const char *newfname)
|
||||
{
|
||||
|
@ -1003,7 +1006,8 @@ int main (int c, const char **v)
|
|||
sleeptime = Host_Frame(time);
|
||||
oldtime = newtime;
|
||||
|
||||
Sys_Sleep(sleeptime);
|
||||
if (sleeptime)
|
||||
Sys_Sleep(sleeptime);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -373,42 +373,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
#undef WAYLANDQUAKE
|
||||
#endif
|
||||
|
||||
#ifdef NO_MULTITHREAD
|
||||
#undef MULTITHREAD
|
||||
#endif
|
||||
#ifdef NO_LIBRARIES //catch-all...
|
||||
#define NO_DIRECTX
|
||||
#define NO_PNG
|
||||
#define NO_JPEG
|
||||
#define NO_ZLIB
|
||||
#define NO_OGG
|
||||
#define NO_FREETYPE
|
||||
#endif
|
||||
#ifdef NO_OPENAL
|
||||
#undef AVAIL_OPENAL
|
||||
#endif
|
||||
#ifdef NO_PNG
|
||||
#undef AVAIL_PNGLIB
|
||||
#endif
|
||||
#ifdef NO_JPEG
|
||||
#undef AVAIL_JPEGLIB
|
||||
#endif
|
||||
#ifdef NO_OGG
|
||||
#undef AVAIL_OGGVORBIS
|
||||
#endif
|
||||
#ifdef NO_FREETYPE
|
||||
#undef AVAIL_FREETYPE
|
||||
#endif
|
||||
#ifdef NO_ZLIB
|
||||
#undef AVAIL_ZLIB
|
||||
#undef AVAIL_PNGLIB
|
||||
#undef AVAIL_XZDEC
|
||||
#undef AVAIL_GZDEC
|
||||
#endif
|
||||
#if (defined(_MSC_VER) && (_MSC_VER < 1500)) || defined(FTE_SDL)
|
||||
#undef AVAIL_WASAPI //wasapi is available in the vista sdk, while that's compatible with earlier versions, its not really expected until 2008
|
||||
#endif
|
||||
|
||||
//include a file to update the various configurations for game-specific configs (hopefully just names)
|
||||
#ifdef BRANDING_INC
|
||||
#include STRINGIFY(BRANDING_INC)
|
||||
|
@ -580,6 +544,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
#ifdef ANDROID
|
||||
#define GLESONLY //should reduce the conditions a little
|
||||
// #undef HEADLESSQUAKE
|
||||
#define NO_FREETYPE
|
||||
#define NO_OPENAL
|
||||
#endif
|
||||
#if defined(NACL)
|
||||
//stuff is sandboxed.
|
||||
|
@ -599,12 +565,47 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
#undef HEADLESSQUAKE
|
||||
#define NO_FREETYPE
|
||||
#endif
|
||||
#if (defined(_MSC_VER) && (_MSC_VER < 1500)) || defined(FTE_SDL)
|
||||
#undef AVAIL_WASAPI //wasapi is available in the vista sdk, while that's compatible with earlier versions, its not really expected until 2008
|
||||
#endif
|
||||
|
||||
#ifdef NO_MULTITHREAD
|
||||
#undef MULTITHREAD
|
||||
#endif
|
||||
#ifndef MULTITHREAD
|
||||
//database code requires threads to do stuff async.
|
||||
#undef USE_SQLITE
|
||||
#undef USE_MYSQL
|
||||
#endif
|
||||
#ifdef NO_LIBRARIES //catch-all...
|
||||
#define NO_DIRECTX
|
||||
#define NO_PNG
|
||||
#define NO_JPEG
|
||||
#define NO_ZLIB
|
||||
#define NO_OGG
|
||||
#define NO_FREETYPE
|
||||
#endif
|
||||
#ifdef NO_OPENAL
|
||||
#undef AVAIL_OPENAL
|
||||
#endif
|
||||
#ifdef NO_PNG
|
||||
#undef AVAIL_PNGLIB
|
||||
#endif
|
||||
#ifdef NO_JPEG
|
||||
#undef AVAIL_JPEGLIB
|
||||
#endif
|
||||
#ifdef NO_OGG
|
||||
#undef AVAIL_OGGVORBIS
|
||||
#endif
|
||||
#ifdef NO_FREETYPE
|
||||
#undef AVAIL_FREETYPE
|
||||
#endif
|
||||
#ifdef NO_ZLIB
|
||||
#undef AVAIL_ZLIB
|
||||
#undef AVAIL_PNGLIB
|
||||
#undef AVAIL_XZDEC
|
||||
#undef AVAIL_GZDEC
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_WINSSPI) || defined(HAVE_GNUTLS)
|
||||
#define HAVE_SSL
|
||||
|
|
|
@ -6052,9 +6052,9 @@ qboolean QDECL Mod_LoadPSKModel(model_t *mod, void *buffer, size_t fsize)
|
|||
group[j].boneofs = animmatrix + 12*num_boneinfo*frameinfo[j].firstpose;
|
||||
group[j].numposes = frameinfo[j].posecount;
|
||||
if (*frameinfo[j].name)
|
||||
snprintf(group[j].name, sizeof(group[j].name), "%s", frameinfo[j].name);
|
||||
Q_snprintfz(group[j].name, sizeof(group[j].name), "%s", frameinfo[j].name);
|
||||
else
|
||||
snprintf(group[j].name, sizeof(group[j].name), "frame_%i", j);
|
||||
Q_snprintfz(group[j].name, sizeof(group[j].name), "frame_%i", j);
|
||||
group[j].loop = frameinfo[j].loop;
|
||||
group[j].rate = frameinfo[j].fps;
|
||||
group[j].skeltype = SKEL_RELATIVE;
|
||||
|
@ -6077,7 +6077,7 @@ qboolean QDECL Mod_LoadPSKModel(model_t *mod, void *buffer, size_t fsize)
|
|||
{
|
||||
group[iframe].boneofs = animmatrix + 12*num_boneinfo*(animinfo[j].firstframe+i);
|
||||
group[iframe].numposes = 1;
|
||||
snprintf(group[iframe].name, sizeof(group[iframe].name), "%s_%i", animinfo[j].name, i);
|
||||
Q_snprintfz(group[iframe].name, sizeof(group[iframe].name), "%s_%i", animinfo[j].name, i);
|
||||
group[iframe].loop = true;
|
||||
group[iframe].rate = animinfo[j].fps;
|
||||
group[iframe].skeltype = SKEL_RELATIVE;
|
||||
|
|
|
@ -3119,8 +3119,8 @@ const gamemode_info_t gamemode_info[] = {
|
|||
#ifndef NOLEGACY
|
||||
//cmdline switch exename protocol name(dpmaster) identifying file exec dir1 dir2 dir3 dir(fte) full name
|
||||
//two quakes - one without extra game dirs which should avoid fuckups from nquake's configs (which screw over cvars that every nq progs.dat depends upon but which the ezquake id1-only less-compatible gamecode ignores).
|
||||
{"-quake", "qw", "FTE-Quake DarkPlaces-Quake", {"id1/pak0.pak", "id1/quake.rc"},QCFG, {"id1", "qw", "*fte"}, "Quake", "https://fte.triptohell.info/downloadables.php" /*,"id1/pak0.pak|http://quakeservers.nquake.com/qsw106.zip|http://nquake.localghost.net/qsw106.zip|http://qw.quakephil.com/nquake/qsw106.zip|http://fnu.nquake.com/qsw106.zip"*/},
|
||||
{"-netquake", "q1", "FTE-Quake DarkPlaces-Quake", {"id1/pak0.pak", "id1/quake.rc"},QCFG, {"id1"}, "Quake", "https://fte.triptohell.info/downloadables.php" /*,"id1/pak0.pak|http://quakeservers.nquake.com/qsw106.zip|http://nquake.localghost.net/qsw106.zip|http://qw.quakephil.com/nquake/qsw106.zip|http://fnu.nquake.com/qsw106.zip"*/},
|
||||
{"-quake", "q1", "FTE-Quake DarkPlaces-Quake", {"id1/pak0.pak", "id1/quake.rc"},QCFG, {"id1", "qw", "*fte"}, "Quake", "https://fte.triptohell.info/downloadables.php" /*,"id1/pak0.pak|http://quakeservers.nquake.com/qsw106.zip|http://nquake.localghost.net/qsw106.zip|http://qw.quakephil.com/nquake/qsw106.zip|http://fnu.nquake.com/qsw106.zip"*/},
|
||||
{"-netquake", "nq", "FTE-Quake DarkPlaces-Quake", {"id1/pak0.pak", "id1/quake.rc"},QCFG, {"id1"}, "Quake", "https://fte.triptohell.info/downloadables.php" /*,"id1/pak0.pak|http://quakeservers.nquake.com/qsw106.zip|http://nquake.localghost.net/qsw106.zip|http://qw.quakephil.com/nquake/qsw106.zip|http://fnu.nquake.com/qsw106.zip"*/},
|
||||
//quake's mission packs should not be favoured over the base game nor autodetected
|
||||
//third part mods also tend to depend upon the mission packs for their huds, even if they don't use any other content.
|
||||
//and q2 also has a rogue/pak0.pak file that we don't want to find and cause quake2 to look like dissolution of eternity
|
||||
|
@ -6177,14 +6177,54 @@ void COM_InitFilesystem (void)
|
|||
#endif
|
||||
}
|
||||
#else
|
||||
//yay for unix!.
|
||||
ev = getenv("HOME");
|
||||
//on unix, we use environment settings.
|
||||
//if $HOME/.fte/ exists then we use that because of legacy reasons.
|
||||
//but if it doesn't exist then we use $XDG_DATA_HOME/.fte instead
|
||||
//we used to use $HOME/.#HOMESUBDIR/ but this is now only used if it actually exists AND the new path doesn't.
|
||||
//new installs use $XDG_DATA_HOME/#HOMESUBDIR/ instead
|
||||
|
||||
ev = getenv("FTEHOME");
|
||||
if (ev && *ev)
|
||||
{
|
||||
if (ev[strlen(ev)-1] == '/')
|
||||
Q_snprintfz(com_homepath, sizeof(com_homepath), "%s.fte/", ev);
|
||||
Q_strncpyz(com_homepath, ev, sizeof(com_homepath));
|
||||
else
|
||||
Q_snprintfz(com_homepath, sizeof(com_homepath), "%s/.fte/", ev);
|
||||
Q_snprintfz(com_homepath, sizeof(com_homepath), "%s/", ev);
|
||||
usehome = true; // always use home on unix unless told not to
|
||||
ev = NULL;
|
||||
}
|
||||
else
|
||||
ev = getenv("HOME");
|
||||
if (ev && *ev)
|
||||
{
|
||||
const char *xdghome;
|
||||
char oldhome[MAX_OSPATH];
|
||||
char newhome[MAX_OSPATH];
|
||||
struct stat s;
|
||||
|
||||
#ifdef GAME_SHORTNAME
|
||||
#define HOMESUBDIR GAME_SHORTNAME
|
||||
#else
|
||||
#define HOMESUBDIR "fte" //FIXME: this should come from the manifest, as fte_GAME or something
|
||||
#endif
|
||||
|
||||
if (ev[strlen(ev)-1] == '/')
|
||||
Q_snprintfz(oldhome, sizeof(oldhome), "%s."HOMESUBDIR"/", ev);
|
||||
else
|
||||
Q_snprintfz(oldhome, sizeof(oldhome), "%s/."HOMESUBDIR"/", ev);
|
||||
|
||||
xdghome = getenv("XDG_DATA_HOME");
|
||||
if (!xdghome || !*xdghome)
|
||||
xdghome = va("%s/.local/share", ev);
|
||||
if (xdghome[strlen(xdghome)-1] == '/')
|
||||
Q_snprintfz(newhome, sizeof(newhome), "%s"HOMESUBDIR"/", xdghome);
|
||||
else
|
||||
Q_snprintfz(newhome, sizeof(newhome), "%s/"HOMESUBDIR"/", xdghome);
|
||||
|
||||
if (stat(newhome, &s) == -1 && stat(oldhome, &s) != -1)
|
||||
Q_strncpyz(com_homepath, oldhome, sizeof(com_homepath));
|
||||
else
|
||||
Q_strncpyz(com_homepath, newhome, sizeof(com_homepath));
|
||||
usehome = true; // always use home on unix unless told not to
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -524,7 +524,7 @@ char *NET_AdrToString (char *s, int len, netadr_t *a)
|
|||
char *rs = s;
|
||||
char *prot = "";
|
||||
#ifdef IPPROTO_IPV6
|
||||
qboolean doneblank;
|
||||
int doneblank;
|
||||
#endif
|
||||
|
||||
switch(a->prot)
|
||||
|
@ -2228,7 +2228,7 @@ qboolean FTENET_NATPMP_GetPacket(struct ftenet_generic_connection_s *con)
|
|||
}
|
||||
neterr_t FTENET_NATPMP_SendPacket(struct ftenet_generic_connection_s *con, int length, const void *data, netadr_t *to)
|
||||
{
|
||||
return false;
|
||||
return NETERR_NOROUTE;
|
||||
}
|
||||
void FTENET_NATPMP_Close(struct ftenet_generic_connection_s *con)
|
||||
{
|
||||
|
|
|
@ -1073,7 +1073,7 @@ qintptr_t VARGS Plug_Net_SetTLSClient(void *offset, quintptr_t mask, const qintp
|
|||
{
|
||||
pluginstream_t *stream;
|
||||
unsigned int handle = VM_LONG(arg[0]);
|
||||
if (handle < 0 || handle >= pluginstreamarraylen || pluginstreamarray[handle].plugin != currentplug)
|
||||
if (handle >= pluginstreamarraylen || pluginstreamarray[handle].plugin != currentplug)
|
||||
{
|
||||
Con_Printf("Plug_Net_SetTLSClient: socket does not belong to you (or is invalid)\n");
|
||||
return -2;
|
||||
|
@ -1106,7 +1106,7 @@ qintptr_t VARGS Plug_Net_GetTLSBinding(void *offset, quintptr_t mask, const qint
|
|||
return -2;
|
||||
if (VM_OOB(arg[1], *bindsize))
|
||||
return -2;
|
||||
if (handle < 0 || handle >= pluginstreamarraylen || pluginstreamarray[handle].plugin != currentplug)
|
||||
if ((size_t)handle >= pluginstreamarraylen || pluginstreamarray[handle].plugin != currentplug)
|
||||
{
|
||||
Con_Printf("Plug_Net_GetTLSBinding: socket does not belong to you (or is invalid)\n");
|
||||
return -2;
|
||||
|
|
|
@ -100,14 +100,15 @@ void PF_Common_RegisterCvars(void)
|
|||
|
||||
qofs_t PR_ReadBytesString(char *str)
|
||||
{
|
||||
size_t u = strtoul(str, &str, 0);
|
||||
//use doubles, so we can cope with eg "5.3mb" or much larger values
|
||||
double d = strtod(str, &str);
|
||||
if (*str == 'g')
|
||||
u *= 1024*1024*1024;
|
||||
d *= 1024*1024*1024;
|
||||
if (*str == 'm')
|
||||
u *= 1024*1024;
|
||||
d *= 1024*1024;
|
||||
if (*str == 'k')
|
||||
u *= 1024;
|
||||
return u;
|
||||
d *= 1024;
|
||||
return d;
|
||||
}
|
||||
|
||||
//just prints out a warning with stack trace. so I can throttle spammy stack traces.
|
||||
|
|
|
@ -76,8 +76,8 @@ typedef unsigned int FT_Pixel_Mode; //for consistency even without freetype supp
|
|||
#ifndef FT_PIXEL_MODE_BGRA
|
||||
#define FT_PIXEL_MODE_BGRA 7 //added in FT 2.5
|
||||
#endif
|
||||
#define FT_PIXEL_MODE_RGBA_SA (~(FT_Pixel_Mode)0) //RGBA, straight alpha. not in freetype.
|
||||
#define FT_PIXEL_MODE_RGBA (~(FT_Pixel_Mode)1) //RGBA, premultiplied alpha. not in freetype.
|
||||
#define FT_PIXEL_MODE_RGBA_SA (100) //RGBA, straight alpha. not in freetype.
|
||||
#define FT_PIXEL_MODE_RGBA (101) //RGBA, premultiplied alpha. not in freetype.
|
||||
|
||||
static const char *imgs[] =
|
||||
{
|
||||
|
@ -672,7 +672,7 @@ static struct charcache_s *Font_LoadGlyphData(font_t *f, CHARIDXTYPE charidx, FT
|
|||
out += PLANEWIDTH*4;
|
||||
}
|
||||
}
|
||||
else if (pixelmode == FT_PIXEL_MODE_RGBA_SA)
|
||||
else if ((unsigned int)pixelmode == FT_PIXEL_MODE_RGBA_SA)
|
||||
{ //rgba font
|
||||
for (y = -pad; y < 0; y++)
|
||||
{
|
||||
|
@ -739,7 +739,7 @@ static struct charcache_s *Font_LoadGlyphData(font_t *f, CHARIDXTYPE charidx, FT
|
|||
out += PLANEWIDTH*4;
|
||||
}
|
||||
}
|
||||
else if (pixelmode == FT_PIXEL_MODE_RGBA)
|
||||
else if ((unsigned int)pixelmode == FT_PIXEL_MODE_RGBA)
|
||||
{ //bgra srgb font, already premultiplied
|
||||
for (y = -pad; y < 0; y++)
|
||||
{
|
||||
|
|
|
@ -6577,7 +6577,7 @@ static void *validateqcpointer(pubprogfuncs_t *prinst, size_t qcptr, size_t elem
|
|||
PR_BIError(prinst, "brush: elementcount %u is too large\n", (unsigned int)elementcount);
|
||||
return NULL;
|
||||
}
|
||||
if (qcptr < 0 || qcptr+(elementsize*elementcount) > prinst->stringtablesize)
|
||||
if (qcptr+(elementsize*elementcount) > (size_t)prinst->stringtablesize)
|
||||
{
|
||||
PR_BIError(prinst, "brush: invalid qc pointer\n");
|
||||
return NULL;
|
||||
|
@ -6803,7 +6803,7 @@ void QCBUILTIN PF_brush_selected(pubprogfuncs_t *prinst, struct globalvars_s *pr
|
|||
heightmap_t *hm = mod?mod->terrain:NULL;
|
||||
unsigned int brushid = G_INT(OFS_PARM1);
|
||||
// unsigned int faceid = G_INT(OFS_PARM2);
|
||||
unsigned int state = G_FLOAT(OFS_PARM3);
|
||||
int state = G_FLOAT(OFS_PARM3);
|
||||
unsigned int i;
|
||||
brushes_t *br;
|
||||
|
||||
|
@ -6842,17 +6842,17 @@ void QCBUILTIN PF_brush_selected(pubprogfuncs_t *prinst, struct globalvars_s *pr
|
|||
// {"brush_calcfacepoints",PF_brush_calcfacepoints,0,0, 0, 0, D("int(int faceid, brushface_t *in_faces, int numfaces, vector *points, int maxpoints)", "Determines the points of the specified face, if the specified brush were to actually be created.")},
|
||||
void QCBUILTIN PF_brush_calcfacepoints(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
|
||||
{
|
||||
unsigned int faceid = G_INT(OFS_PARM0);
|
||||
unsigned int numfaces = G_INT(OFS_PARM2);
|
||||
size_t faceid = G_INT(OFS_PARM0);
|
||||
size_t numfaces = G_INT(OFS_PARM2);
|
||||
qcbrushface_t *in_faces = validateqcpointer(prinst, G_INT(OFS_PARM1), sizeof(*in_faces), numfaces, false);
|
||||
unsigned int maxpoints = G_INT(OFS_PARM4);
|
||||
size_t maxpoints = G_INT(OFS_PARM4);
|
||||
vec3_t *out_verts = validateqcpointer(prinst, G_INT(OFS_PARM3), sizeof(*out_verts), maxpoints, false);
|
||||
vecV_t facepoints[256];
|
||||
vec4_t planes[256];
|
||||
unsigned int j, numpoints;
|
||||
|
||||
faceid--;
|
||||
if (faceid < 0 || faceid >= numfaces)
|
||||
if ((size_t)faceid >= numfaces)
|
||||
{
|
||||
G_INT(OFS_RETURN) = 0;
|
||||
return;
|
||||
|
|
|
@ -3153,7 +3153,7 @@ qboolean X11VID_Init (rendererstate_t *info, unsigned char *palette, int psl)
|
|||
#ifdef VKQUAKE
|
||||
case PSL_VULKAN:
|
||||
visinfo = &vinfodef;
|
||||
if (!x11.pXMatchVisualInfo(vid_dpy, scrnum, info->bpp?info->bpp:DefaultDepth(vid_dpy, scrnum), TrueColor, visinfo))
|
||||
if (!x11.pXMatchVisualInfo(vid_dpy, scrnum, min(24,info->bpp?info->bpp:DefaultDepth(vid_dpy, scrnum)), TrueColor, visinfo))
|
||||
{
|
||||
Sys_Error("Couldn't choose visual for vulkan\n");
|
||||
}
|
||||
|
|
|
@ -221,7 +221,7 @@ static qboolean SDLVID_Init (rendererstate_t *info, unsigned char *palette, r_qr
|
|||
sdlwindow = SDL_CreateWindow(FULLENGINENAME, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, info->width, info->height, flags);
|
||||
if (!sdlwindow)
|
||||
{
|
||||
Con_Printf("Couldn't set video mode: %s\n", SDL_GetError());
|
||||
Con_Printf("SDL_CreateWindow failed: %s\n", SDL_GetError());
|
||||
return false;
|
||||
}
|
||||
CL_UpdateWindowTitle();
|
||||
|
@ -379,7 +379,9 @@ void GLVID_DeInit (void)
|
|||
#endif
|
||||
|
||||
SDL_QuitSubSystem(SDL_INIT_VIDEO);
|
||||
#ifdef OPENGL_SDL
|
||||
GL_ForgetPointers();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -700,7 +700,20 @@ static void WL_SetCaption(const char *text)
|
|||
|
||||
static int WL_GetPriority(void)
|
||||
{
|
||||
char *dpyname = getenv("WAYLAND_DISPLAY");
|
||||
//2 = above x11, 0 = below x11.
|
||||
char *stype = getenv("XDG_SESSION_TYPE");
|
||||
char *dpyname;
|
||||
if (!strcmp(stype, "wayland"))
|
||||
return 2;
|
||||
if (!strcmp(stype, "x11"))
|
||||
return 0;
|
||||
if (!strcmp(stype, "tty")) //FIXME: support this!
|
||||
return 0;
|
||||
|
||||
//otherwise if both WAYLAND_DISPLAY and DISPLAY are defined, then we assume that we were started from xwayland wrapper thing, and that the native/preferred windowing system is wayland.
|
||||
//(lets just hope our wayland support is comparable)
|
||||
|
||||
dpyname = getenv("WAYLAND_DISPLAY");
|
||||
if (dpyname && *dpyname)
|
||||
return 2; //something above X11.
|
||||
return 0; //default.
|
||||
|
|
|
@ -1448,7 +1448,7 @@ qboolean DL_CreateThread(struct dl_download *dl, vfsfile_t *file, void (*NotifyF
|
|||
|
||||
dl->threadenable = true;
|
||||
#if defined(LOADERTHREAD) && !defined(NPFTE)
|
||||
if (dlthreads < 0)
|
||||
if (dlthreads < 4)
|
||||
#endif
|
||||
{
|
||||
dl->threadctx = Sys_CreateThread("download", DL_Thread_Work, dl, THREADP_NORMAL, 0);
|
||||
|
|
|
@ -205,7 +205,7 @@ static void PR_memvalidate (progfuncs_t *progfuncs)
|
|||
l = 0;
|
||||
while (b)
|
||||
{
|
||||
if (b < 0 || b >= prinst.addressableused)
|
||||
if ((size_t)b >= (size_t)prinst.addressableused)
|
||||
{
|
||||
printf("PF_memalloc: memory corruption\n");
|
||||
PR_StackTrace(&progfuncs->funcs, false);
|
||||
|
|
|
@ -310,7 +310,11 @@ typedef union QCC_eval_s
|
|||
{
|
||||
QCC_string_t string;
|
||||
float _float;
|
||||
float vector[1];
|
||||
#ifdef __GNUC__
|
||||
float vector[0]; //gnuc extension. I'm using it to mute clang warnings.
|
||||
#else
|
||||
float vector[1]; //should be 3, except that then eval_t would be too big.
|
||||
#endif
|
||||
func_t function;
|
||||
int _int;
|
||||
// union QCC_eval_s *ptr;
|
||||
|
|
|
@ -7360,7 +7360,7 @@ vectorarrayindex:
|
|||
i = tmp.sym->symboldata[tmp.ofs]._float;
|
||||
else
|
||||
i = -1;
|
||||
if (i < 0 || i >= 3)
|
||||
if ((unsigned)i >= 3u)
|
||||
QCC_PR_ParseErrorPrintSRef(0, r->base, "(vector) array index out of bounds");
|
||||
}
|
||||
else if (QCC_OPCodeValid(&pr_opcodes[OP_BOUNDCHECK]) && flag_boundchecks)
|
||||
|
@ -7382,7 +7382,7 @@ vectorarrayindex:
|
|||
i = tmp.sym->symboldata[tmp.ofs]._float;
|
||||
else
|
||||
i = -1;
|
||||
if (i < 0 || i >= 3)
|
||||
if ((unsigned)i >= 3u)
|
||||
QCC_PR_ParseErrorPrintSRef(0, r->base, "(vector) array index out of bounds");
|
||||
}
|
||||
else if (QCC_OPCodeValid(&pr_opcodes[OP_BOUNDCHECK]) && flag_boundchecks)
|
||||
|
@ -7405,7 +7405,7 @@ vectorarrayindex:
|
|||
i = tmp.sym->symboldata[tmp.ofs]._float;
|
||||
else
|
||||
i = -1;
|
||||
if (i < 0 || i >= arraysize)
|
||||
if ((unsigned)i >= (unsigned)arraysize)
|
||||
QCC_PR_ParseErrorPrintSRef(0, r->base, "(constant) array index out of bounds (0 <= %i < %i)", i, arraysize);
|
||||
}
|
||||
else
|
||||
|
|
|
@ -351,7 +351,7 @@ compiler_flag_t compiler_flag[] = {
|
|||
{&keyword_accumulate, nondefaultkeyword,"accumulate", "Keyword: accumulate", "Disables the 'accumulate' keyword."},
|
||||
|
||||
//options
|
||||
{&flag_acc, 0, "acc", "Reacc support", "Reacc is a pascall like compiler. It was released before the Quake source was released. This flag has a few effects. It sorts all qc files in the current directory into alphabetical order to compile them. It also allows Reacc global/field distinctions, as well as allows ¦ as EOF. Whilst case insensitivity and lax type checking are supported by reacc, they are seperate compiler flags in fteqcc."}, //reacc like behaviour of src files.
|
||||
{&flag_acc, 0, "acc", "Reacc support", "Reacc is a pascall like compiler. It was released before the Quake source was released. This flag has a few effects. It sorts all qc files in the current directory into alphabetical order to compile them. It also allows Reacc global/field distinctions, as well as allows | for linebreaks. Whilst case insensitivity and lax type checking are supported by reacc, they are seperate compiler flags in fteqcc."}, //reacc like behaviour of src files.
|
||||
{&flag_qccx, FLAG_MIDCOMPILE,"qccx", "QCCX syntax", "WARNING: This syntax makes mods inherantly engine specific.\nDo NOT use unless you know what you're doing.This is provided for compatibility only\nAny entity hacks will be unsupported in FTEQW, DP, and others, resulting in engine crashes if the code in question is executed."},
|
||||
{&keywords_coexist, FLAG_ASDEFAULT, "kce", "Keywords Coexist", "If you want keywords to NOT be disabled when they a variable by the same name is defined, check here."},
|
||||
{&output_parms, 0, "parms", "Define offset parms", "if PARM0 PARM1 etc should be defined by the compiler. These are useful if you make use of the asm keyword for function calls, or you wish to create your own variable arguments. This is an easy way to break decompilers."}, //controls weather to define PARMx for the parms (note - this can screw over some decompilers)
|
||||
|
@ -2050,18 +2050,9 @@ strofs = (strofs+3)&~3;
|
|||
|
||||
qtst[i].line = statements[i].linenum;
|
||||
qtst[i].op = PRLittleShort((unsigned short)statements[i].op);
|
||||
if (a < 0)
|
||||
qtst[i].a = PRLittleShort((short)a);
|
||||
else
|
||||
qtst[i].a = (unsigned short)PRLittleShort((unsigned short)a);
|
||||
if (b < 0)
|
||||
qtst[i].b = PRLittleShort((short)b);
|
||||
else
|
||||
qtst[i].b = (unsigned short)PRLittleShort((unsigned short)b);
|
||||
if (c < 0)
|
||||
qtst[i].c = PRLittleShort((short)c);
|
||||
else
|
||||
qtst[i].c = (unsigned short)PRLittleShort((unsigned short)c);
|
||||
qtst[i].a = (unsigned short)PRLittleShort((unsigned short)a);
|
||||
qtst[i].b = (unsigned short)PRLittleShort((unsigned short)b);
|
||||
qtst[i].c = (unsigned short)PRLittleShort((unsigned short)c);
|
||||
}
|
||||
|
||||
// no compression
|
||||
|
@ -2106,18 +2097,10 @@ strofs = (strofs+3)&~3;
|
|||
if (((signed)a >= (signed)numpr_globals && statements[i].a.sym) || ((signed)b >= (signed)numpr_globals && statements[i].b.sym) || ((signed)c >= (signed)numpr_globals && statements[i].c.sym))
|
||||
printf("invalid offset on %s instruction\n", pr_opcodes[statements[i].op].opname);
|
||||
#endif
|
||||
if (a < 0)
|
||||
statements16[i].a = PRLittleShort(a);
|
||||
else
|
||||
statements16[i].a = (unsigned short)PRLittleShort(a);
|
||||
if (b < 0)
|
||||
statements16[i].b = PRLittleShort((short)b);
|
||||
else
|
||||
statements16[i].b = (unsigned short)PRLittleShort((unsigned short)b);
|
||||
if (c < 0)
|
||||
statements16[i].c = PRLittleShort((short)c);
|
||||
else
|
||||
statements16[i].c = (unsigned short)PRLittleShort((unsigned short)c);
|
||||
//truncate to 16bit. should probably warn if the high bits are not 0x0000 or 0xffff
|
||||
statements16[i].a = (unsigned short)PRLittleShort((unsigned short)a);
|
||||
statements16[i].b = (unsigned short)PRLittleShort((unsigned short)b);
|
||||
statements16[i].c = (unsigned short)PRLittleShort((unsigned short)c);
|
||||
}
|
||||
|
||||
if (progs.blockscompressed&1)
|
||||
|
|
|
@ -2265,7 +2265,7 @@ qboolean PR_LoadQ1QVM(void)
|
|||
q1qvmprogfuncs.edicttable_length = sv.world.max_edicts;
|
||||
|
||||
limit = VM_MemoryMask(q1qvm);
|
||||
if (gd.sizeofent < 0 || gd.sizeofent > 0xffffffff / gd.maxedicts)
|
||||
if (gd.sizeofent > 0xffffffff / gd.maxedicts)
|
||||
gd.sizeofent = 0xffffffff / gd.maxedicts;
|
||||
if ((quintptr_t)gd.ents+(gd.sizeofent*gd.maxedicts) < (quintptr_t)gd.ents || (quintptr_t)gd.ents > (quintptr_t)limit)
|
||||
gd.ents = 0;
|
||||
|
|
|
@ -104,6 +104,7 @@ cvar_t sv_listen_dp = CVARD("sv_listen_dp", "0", "Allows the server to respond
|
|||
#ifdef QWOVERQ3
|
||||
cvar_t sv_listen_q3 = CVAR("sv_listen_q3", "0");
|
||||
#endif
|
||||
cvar_t sv_reconnectlimit = CVARD("sv_reconnectlimit", "0", "Blocks dupe connection within the specified length of time .");
|
||||
extern cvar_t net_enable_dtls;
|
||||
cvar_t sv_reportheartbeats = CVARD("sv_reportheartbeats", "2", "Print a notice each time a heartbeat is sent to a master server. When set to 2, the message will be displayed once.");
|
||||
cvar_t sv_highchars = CVAR("sv_highchars", "1");
|
||||
|
@ -2782,6 +2783,12 @@ client_t *SVC_DirectConnect(void)
|
|||
if (NET_CompareBaseAdr (&adr, &cl->netchan.remote_address)
|
||||
&& ((protocol == SCP_QUAKEWORLD && cl->netchan.qport == qport) || adr.port == cl->netchan.remote_address.port ))
|
||||
{
|
||||
if (realtime - cl->connection_started < sv_reconnectlimit.value)
|
||||
{
|
||||
Con_Printf ("%s:reconnect rejected: too soon\n", NET_AdrToString (adrbuf, sizeof(adrbuf), &adr));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (cl->state == cs_connected)
|
||||
{
|
||||
if (cl->protocol != protocol)
|
||||
|
@ -5141,6 +5148,7 @@ void SV_InitLocal (void)
|
|||
Cvar_Register (&sv_listen_q3, cvargroup_servercontrol);
|
||||
#endif
|
||||
sv_listen_qw.restriction = RESTRICT_MAX; //no disabling this over rcon.
|
||||
Cvar_Register (&sv_reconnectlimit, cvargroup_servercontrol);
|
||||
Cvar_Register (&fraglog_public, cvargroup_servercontrol);
|
||||
|
||||
SVNET_RegisterCvars();
|
||||
|
|
|
@ -1208,7 +1208,7 @@ void SQL_ServerCycle (void)
|
|||
qreq->results = qres;
|
||||
|
||||
if (developer.ival)
|
||||
if (qres->error)
|
||||
if (*qres->error)
|
||||
Con_Printf("%s\n", qres->error);
|
||||
if (qreq->state == SR_ABORTED)
|
||||
{
|
||||
|
|
|
@ -775,6 +775,22 @@ static int Sys_CheckChRoot(void)
|
|||
//SSL_InitGlobal(true); //make sure we load our public cert from outside the sandbox. an exploit might still be able to find it in memory though. FIXME: disabled in case this reads from somewhere bad - we're still root.
|
||||
#endif
|
||||
|
||||
{ //this protects against stray setuid programs like su reading passwords from /etc/passwd et al
|
||||
//there shouldn't be anyway so really this is pure paranoia.
|
||||
//(the length thing is to avoid overflows inside va giving false negatives.)
|
||||
struct stat s;
|
||||
if (strlen(newroot) > 4096 || lstat(va("%s/etc/", newroot), &s) != -1)
|
||||
{
|
||||
printf("refusing to chroot to %s - contains an /etc directory\n", newroot);
|
||||
return -1;
|
||||
}
|
||||
if (strlen(newroot) > 4096 || lstat(va("%s/proc/", newroot), &s) != -1)
|
||||
{
|
||||
printf("refusing to chroot to %s - contains a /proc directory\n", newroot);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
printf("Changing root dir to \"%s\"\n", newroot);
|
||||
if (chroot(newroot))
|
||||
{
|
||||
|
@ -783,10 +799,16 @@ static int Sys_CheckChRoot(void)
|
|||
}
|
||||
chdir("/"); //chroot does NOT change the working directory, so we need to make sure that happens otherwise still a way out.
|
||||
|
||||
//signal to the fs.c code to use an explicit base home dir.
|
||||
if (newhome)
|
||||
setenv("HOME", va("/user/%s", newhome), true);
|
||||
setenv("FTEHOME", va("/user/%s", newhome), true);
|
||||
else
|
||||
setenv("HOME", va("/user/%i", ruid), true);
|
||||
setenv("FTEHOME", va("/user/%i", ruid), true);
|
||||
|
||||
//these paths are no longer valid.
|
||||
setenv("HOME", "", true);
|
||||
setenv("XDG_DATA_HOME", "", true);
|
||||
|
||||
setenv("PWD", "/", true);
|
||||
|
||||
ret = true;
|
||||
|
|
|
@ -802,14 +802,7 @@ void SVQ2_ConfigStrings_f (void)
|
|||
return;
|
||||
}
|
||||
|
||||
start = atoi(Cmd_Argv(2));
|
||||
|
||||
if (start < 0)
|
||||
{
|
||||
Con_Printf ("SV_Configstrings_f: %s tried crashing us\n", host_client->name);
|
||||
host_client->drop = true;
|
||||
return;
|
||||
}
|
||||
start = strtoul(Cmd_Argv(2), NULL, 0);
|
||||
|
||||
// write a packet full of data
|
||||
|
||||
|
@ -820,7 +813,7 @@ void SVQ2_ConfigStrings_f (void)
|
|||
if (str && *str)
|
||||
{
|
||||
MSG_WriteByte (&host_client->netchan.message, svcq2_configstring);
|
||||
MSG_WriteShort (&host_client->netchan.message, start);
|
||||
MSG_WriteShort (&host_client->netchan.message, (unsigned short)start);
|
||||
MSG_WriteString (&host_client->netchan.message, str);
|
||||
}
|
||||
start++;
|
||||
|
@ -7898,7 +7891,7 @@ void SV_ExecuteClientMessage (client_t *cl)
|
|||
#ifdef Q2SERVER
|
||||
void SVQ2_ExecuteClientMessage (client_t *cl)
|
||||
{
|
||||
enum clcq2_ops_e c;
|
||||
int c;
|
||||
char *s;
|
||||
usercmd_t oldest, oldcmd, newcmd;
|
||||
q2client_frame_t *frame;
|
||||
|
@ -7978,7 +7971,7 @@ void SVQ2_ExecuteClientMessage (client_t *cl)
|
|||
if (c == -1)
|
||||
break;
|
||||
|
||||
switch (c)
|
||||
switch ((enum clcq2_ops_e)c)
|
||||
{
|
||||
default:
|
||||
Con_Printf ("SVQ2_ReadClientMessage: unknown command char %i\n", c);
|
||||
|
|
|
@ -1,4 +1,8 @@
|
|||
CC=i686-pc-mingw32-gcc
|
||||
|
||||
#NOTE: if you're on windows, you might want to use CC=i686-pc-mingw32-gcc
|
||||
|
||||
CC ?= gcc
|
||||
VKSDKPATH ?= ~/VulkanSDK/1.1.73.0/x86_64/bin/
|
||||
|
||||
all:
|
||||
|
||||
|
@ -22,12 +26,12 @@ makevulkanblob: makevulkanblob.c
|
|||
$(CC) $< -o $@
|
||||
|
||||
vulkanblobs/%.fvb: vulkan/%.glsl makevulkanblob vulkan/sys/defs.h vulkan/sys/fog.h vulkan/sys/offsetmapping.h vulkan/sys/skeletal.h
|
||||
./makevulkanblob $< $@
|
||||
@echo Making $<
|
||||
@PATH=$(PATH):$(VKSDKPATH) ./makevulkanblob $< $@
|
||||
|
||||
#vulkanblobs/%.fvb: glsl/%.glsl makevulkanblob vulkan/sys/defs.h vulkan/sys/fog.h vulkan/sys/offsetmapping.h vulkan/sys/skeletal.h
|
||||
# ./makevulkanblob $< $@
|
||||
|
||||
|
||||
all: generatebuiltinsl $(ALLNAMES)
|
||||
which glslangValidator
|
||||
./generatebuiltinsl
|
|
@ -108,8 +108,13 @@ int generatevulkanblobs(struct blobheader *blob, size_t maxblobsize, const char
|
|||
|
||||
FILE *glsl = fopen(glslname, "rt");
|
||||
if (!glsl)
|
||||
{
|
||||
printf("Unable to read %s\n", glslname);
|
||||
return 0;
|
||||
}
|
||||
FILE *temp = fopen(tempname, "wt");
|
||||
if (!temp)
|
||||
printf("Unable to write %s\n", tempname);
|
||||
while(fgets(command, sizeof(command), glsl))
|
||||
{
|
||||
if (inheader && !strncmp(command, "!!", 2))
|
||||
|
@ -130,14 +135,14 @@ int generatevulkanblobs(struct blobheader *blob, size_t maxblobsize, const char
|
|||
{
|
||||
type = command[5] == 'i' || command[5] == 'f' || command[5] == 'b';
|
||||
size = type?1:(command[5]-'0');
|
||||
arg = strtok(command+7, " ,=\n");
|
||||
arg = strtok(command+7, " ,=\r\n");
|
||||
type = command[6-type] - 'a' + 'A';
|
||||
}
|
||||
else
|
||||
{
|
||||
type = command[6] == 'i' || command[6] == 'f' || command[6] == 'b';
|
||||
size = type?1:(command[6]-'0');
|
||||
arg = strtok(command+8, " ,=\n");
|
||||
arg = strtok(command+8, " ,=\r\n");
|
||||
type = command[7-type];
|
||||
}
|
||||
|
||||
|
@ -154,8 +159,13 @@ int generatevulkanblobs(struct blobheader *blob, size_t maxblobsize, const char
|
|||
{
|
||||
if (arg)
|
||||
{
|
||||
arg = strtok(NULL, " ,=\n");
|
||||
if (type == 'f' || type == 'F')
|
||||
arg = strtok(NULL, " ,=\r\n");
|
||||
if (!arg)
|
||||
{
|
||||
printf("%s has no default value. Assuming 0\n", cb+4);
|
||||
u[i].u = 0; //0 either way.
|
||||
}
|
||||
else if (type == 'f' || type == 'F')
|
||||
u[i].f = atof(arg);
|
||||
else
|
||||
u[i].u = atoi(arg);
|
||||
|
@ -172,7 +182,7 @@ int generatevulkanblobs(struct blobheader *blob, size_t maxblobsize, const char
|
|||
}
|
||||
else if (!strncmp(command, "!!permu", 7))
|
||||
{
|
||||
char *arg = strtok(command+7, " ,\n");
|
||||
char *arg = strtok(command+7, " ,\r\n");
|
||||
for (i = 0; permutationnames[i]; i++)
|
||||
{
|
||||
if (!strcmp(arg, permutationnames[i]))
|
||||
|
@ -191,7 +201,7 @@ int generatevulkanblobs(struct blobheader *blob, size_t maxblobsize, const char
|
|||
}
|
||||
else if (!strncmp(command, "!!samps", 7))
|
||||
{
|
||||
char *arg = strtok(command+7, " ,\n");
|
||||
char *arg = strtok(command+7, " ,\r\n");
|
||||
do
|
||||
{
|
||||
//light
|
||||
|
@ -235,7 +245,7 @@ int generatevulkanblobs(struct blobheader *blob, size_t maxblobsize, const char
|
|||
blob->numtextures = atoi(arg);
|
||||
else
|
||||
printf("Unknown texture: \"%s\"\n", arg);
|
||||
} while((arg = strtok(NULL, " ,\n")));
|
||||
} while((arg = strtok(NULL, " ,\r\n")));
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
@ -397,26 +407,34 @@ int generatevulkanblobs(struct blobheader *blob, size_t maxblobsize, const char
|
|||
|
||||
snprintf(command, sizeof(command),
|
||||
/*preprocess the vertex shader*/
|
||||
#ifdef _WIN32
|
||||
"echo #version 450 core > %s && "
|
||||
#else
|
||||
"echo \"#version 450 core\" > %s && "
|
||||
#endif
|
||||
"cpp %s -DVULKAN -DVERTEX_SHADER -P >> %s && "
|
||||
|
||||
/*preprocess the fragment shader*/
|
||||
#ifdef _WIN32
|
||||
"echo #version 450 core > %s && "
|
||||
#else
|
||||
"echo \"#version 450 core\" > %s && "
|
||||
#endif
|
||||
"cpp %s -DVULKAN -DFRAGMENT_SHADER -P >> %s && "
|
||||
|
||||
/*convert to spir-v (annoyingly we have no control over the output file names*/
|
||||
"glslangValidator -V -l -d %s %s"
|
||||
|
||||
/*strip stuff out, so drivers don't glitch out from stuff that we don't use*/
|
||||
" && spirv-remap -i vert.spv frag.spv -o vulkan/remap"
|
||||
// " && spirv-remap -i vert.spv frag.spv -o vulkan/remap"
|
||||
|
||||
,tempvert, tempname, tempvert, tempfrag, tempname, tempfrag, tempvert, tempfrag);
|
||||
|
||||
system(command);
|
||||
|
||||
unlink(tempname);
|
||||
unlink(tempvert);
|
||||
unlink(tempfrag);
|
||||
remove(tempname);
|
||||
remove(tempvert);
|
||||
remove(tempfrag);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
@ -451,12 +469,20 @@ int main(int argc, const char **argv)
|
|||
fclose(o);
|
||||
r = 0;
|
||||
}
|
||||
else
|
||||
printf("Unable to write blob %s\n", blobname);
|
||||
}
|
||||
}
|
||||
fclose(f);
|
||||
fclose(v);
|
||||
unlink("vert.spv");
|
||||
unlink("frag.spv");
|
||||
if (f)
|
||||
fclose(f);
|
||||
else
|
||||
printf("Unable to read frag.spv\n");
|
||||
if (v)
|
||||
fclose(v);
|
||||
else
|
||||
printf("Unable to read vert.spv\n");
|
||||
remove("vert.spv");
|
||||
remove("frag.spv");
|
||||
|
||||
return r;
|
||||
}
|
|
@ -2,7 +2,7 @@
|
|||
#include "sys/defs.h"
|
||||
//apply gaussian filter
|
||||
|
||||
varying vec2 tc;
|
||||
layout(location=0) varying vec2 tc;
|
||||
|
||||
#ifdef VERTEX_SHADER
|
||||
void main ()
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
//the bloom filter
|
||||
//filter out any texels which are not to bloom
|
||||
|
||||
varying vec2 tc;
|
||||
layout(location=0) varying vec2 tc;
|
||||
|
||||
#ifdef VERTEX_SHADER
|
||||
void main ()
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
//add them together
|
||||
//optionally apply tonemapping
|
||||
|
||||
varying vec2 tc;
|
||||
layout(location=0) varying vec2 tc;
|
||||
|
||||
#ifdef VERTEX_SHADER
|
||||
void main ()
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
#include "sys/defs.h"
|
||||
|
||||
#ifdef VERTEX_SHADER
|
||||
varying vec4 vc;
|
||||
layout(location=0) varying vec4 vc;
|
||||
|
||||
#ifdef VERTEX_SHADER
|
||||
void main ()
|
||||
{
|
||||
vc = v_colour;
|
||||
|
@ -11,7 +11,6 @@ void main ()
|
|||
#endif
|
||||
|
||||
#ifdef FRAGMENT_SHADER
|
||||
varying vec4 vc;
|
||||
void main ()
|
||||
{
|
||||
gl_FragColor = vc;
|
||||
|
|
|
@ -8,8 +8,9 @@
|
|||
//regular sky shader for scrolling q1 skies
|
||||
//the sky surfaces are thrown through this as-is.
|
||||
|
||||
layout(location=0) varying vec3 pos;
|
||||
|
||||
#ifdef VERTEX_SHADER
|
||||
varying vec3 pos;
|
||||
void main ()
|
||||
{
|
||||
pos = v_position.xyz;
|
||||
|
@ -17,7 +18,6 @@ void main ()
|
|||
}
|
||||
#endif
|
||||
#ifdef FRAGMENT_SHADER
|
||||
varying vec3 pos;
|
||||
void main ()
|
||||
{
|
||||
vec2 tccoord;
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
//simple shader for simple skyboxes.
|
||||
|
||||
varying vec3 pos;
|
||||
layout(location=0) varying vec3 pos;
|
||||
#ifdef VERTEX_SHADER
|
||||
void main ()
|
||||
{
|
||||
|
|
|
@ -8,9 +8,11 @@
|
|||
|
||||
#include "sys/defs.h"
|
||||
#include "sys/fog.h"
|
||||
|
||||
layout(location=0) varying vec2 tc;
|
||||
layout(location=1) varying vec4 vc;
|
||||
|
||||
#ifdef VERTEX_SHADER
|
||||
varying vec2 tc;
|
||||
varying vec4 vc;
|
||||
void main ()
|
||||
{
|
||||
tc = v_texcoord;
|
||||
|
@ -19,8 +21,6 @@ void main ()
|
|||
}
|
||||
#endif
|
||||
#ifdef FRAGMENT_SHADER
|
||||
varying vec2 tc;
|
||||
varying vec4 vc;
|
||||
void main ()
|
||||
{
|
||||
vec4 col = texture2D(s_t0, tc);
|
||||
|
|
|
@ -10,7 +10,8 @@
|
|||
//this is expected to be moderately fast.
|
||||
|
||||
#include "sys/fog.h"
|
||||
varying vec2 tc;
|
||||
layout(location=0) varying vec2 tc;
|
||||
|
||||
#ifdef VERTEX_SHADER
|
||||
void main ()
|
||||
{
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
!!permu FOG
|
||||
!!cvar3f r_floorcolor
|
||||
!!cvar3f r_wallcolor
|
||||
!!cvar3f r_floorcolor=0.5,0.5,0.5
|
||||
!!cvar3f r_wallcolor=0.25,0.25,0.5
|
||||
!!cvarb r_fog_exp2=true
|
||||
!!samps 1
|
||||
#include "sys/defs.h"
|
||||
|
@ -8,14 +8,10 @@
|
|||
//this is for the '286' preset walls, and just draws lightmaps coloured based upon surface normals.
|
||||
|
||||
#include "sys/fog.h"
|
||||
varying vec4 col;
|
||||
layout(location=0) varying vec4 col;
|
||||
layout(location=1) varying vec2 lm;
|
||||
|
||||
#ifdef VERTEX_SHADER
|
||||
//attribute vec3 v_normal;
|
||||
//attribute vec2 v_lmcoord;
|
||||
varying vec2 lm;
|
||||
//uniform vec3 cvar_r_wallcolor;
|
||||
//uniform vec3 cvar_r_floorcolor;
|
||||
//uniform vec4 e_lmscale;
|
||||
void main ()
|
||||
{
|
||||
col = vec4(e_lmscale.rgb/255.0 * ((v_normal.z < 0.73)?cvar_r_wallcolor:cvar_r_floorcolor), e_lmscale.a);
|
||||
|
@ -24,8 +20,6 @@ void main ()
|
|||
}
|
||||
#endif
|
||||
#ifdef FRAGMENT_SHADER
|
||||
//uniform sampler2D s_t0;
|
||||
varying vec2 lm;
|
||||
void main ()
|
||||
{
|
||||
gl_FragColor = fog4(col * texture2D(s_t0, lm));
|
||||
|
|
|
@ -4,8 +4,8 @@
|
|||
//This shader implements super-sampled anti-aliasing.
|
||||
//
|
||||
|
||||
varying vec2 texcoord;
|
||||
varying vec2 e_sourcesize;
|
||||
layout(location=0) varying vec2 texcoord;
|
||||
layout(location=1) varying vec2 e_sourcesize;
|
||||
|
||||
#ifdef VERTEX_SHADER
|
||||
void main()
|
||||
|
|
|
@ -5,8 +5,8 @@
|
|||
|
||||
//fisheye view rendering, for silly fovs that are still playable.
|
||||
|
||||
layout(location=0) varying vec2 texcoord;
|
||||
#ifdef VERTEX_SHADER
|
||||
varying vec2 texcoord;
|
||||
void main()
|
||||
{
|
||||
texcoord = v_texcoord.xy;
|
||||
|
@ -14,8 +14,6 @@ void main()
|
|||
}
|
||||
#endif
|
||||
#ifdef FRAGMENT_SHADER
|
||||
varying vec2 texcoord;
|
||||
//uniform float cvar_ffov;
|
||||
void main()
|
||||
{
|
||||
vec3 tc;
|
||||
|
|
|
@ -4,8 +4,8 @@
|
|||
|
||||
//panoramic view rendering, for promo map shots or whatever.
|
||||
|
||||
layout(location=0) varying vec2 texcoord;
|
||||
#ifdef VERTEX_SHADER
|
||||
varying vec2 texcoord;
|
||||
void main()
|
||||
{
|
||||
texcoord = v_texcoord.xy;
|
||||
|
@ -13,7 +13,6 @@ void main()
|
|||
}
|
||||
#endif
|
||||
#ifdef FRAGMENT_SHADER
|
||||
varying vec2 texcoord;
|
||||
void main()
|
||||
{
|
||||
vec3 tc;
|
||||
|
|
|
@ -4,8 +4,8 @@
|
|||
|
||||
//stereographic view rendering, for high fovs that are still playable.
|
||||
|
||||
layout(location=0) varying vec2 texcoord;
|
||||
#ifdef VERTEX_SHADER
|
||||
varying vec2 texcoord;
|
||||
//uniform float cvar_ffov;
|
||||
void main()
|
||||
{
|
||||
|
@ -18,7 +18,6 @@ void main()
|
|||
}
|
||||
#endif
|
||||
#ifdef FRAGMENT_SHADER
|
||||
varying vec2 texcoord;
|
||||
void main()
|
||||
{
|
||||
vec3 tc;
|
||||
|
|
|
@ -6,9 +6,9 @@
|
|||
//this is a post processing shader that is drawn fullscreen whenever the view is underwater.
|
||||
//its generally expected to warp the view a little.
|
||||
|
||||
varying vec2 v_stc;
|
||||
varying vec2 v_warp;
|
||||
varying vec2 v_edge;
|
||||
layout(location=0) varying vec2 v_stc;
|
||||
layout(location=1) varying vec2 v_warp;
|
||||
layout(location=2) varying vec2 v_edge;
|
||||
|
||||
#ifdef VERTEX_SHADER
|
||||
void main ()
|
||||
|
|
|
@ -247,7 +247,7 @@ typedef struct
|
|||
vec4_t lightinfo; //org+radius
|
||||
|
||||
VkBuffer staticbuf; //holds fallback vertex info so we don't crash from it
|
||||
VkDeviceMemory staticbufmem;
|
||||
vk_poolmem_t staticbufmem;
|
||||
|
||||
texid_t tex_currentrender;
|
||||
|
||||
|
@ -1647,7 +1647,7 @@ void VKBE_Shutdown(void)
|
|||
shaderstate.wbatches = NULL;
|
||||
|
||||
vkDestroyBuffer(vk.device, shaderstate.staticbuf, vkallocationcb);
|
||||
vkFreeMemory(vk.device, shaderstate.staticbufmem, vkallocationcb);
|
||||
VK_ReleasePoolMemory(&shaderstate.staticbufmem);
|
||||
}
|
||||
|
||||
static texid_t SelectPassTexture(const shaderpass_t *pass)
|
||||
|
@ -2849,7 +2849,7 @@ static void BE_CreatePipeline(program_t *p, unsigned int shaderflags, unsigned i
|
|||
((blendflags&SBITS_MASK_BLUE)?0:VK_COLOR_COMPONENT_B_BIT) |
|
||||
((blendflags&SBITS_MASK_ALPHA)?0:VK_COLOR_COMPONENT_A_BIT);
|
||||
|
||||
if (blendflags & SBITS_BLEND_BITS)
|
||||
if ((blendflags & SBITS_BLEND_BITS) && (blendflags & SBITS_BLEND_BITS)!=(SBITS_SRCBLEND_ONE|SBITS_DSTBLEND_ZERO))
|
||||
{
|
||||
switch(blendflags & SBITS_SRCBLEND_BITS)
|
||||
{
|
||||
|
@ -3017,7 +3017,7 @@ static void BE_CreatePipeline(program_t *p, unsigned int shaderflags, unsigned i
|
|||
pipeCreateInfo.basePipelineHandle = VK_NULL_HANDLE;
|
||||
pipeCreateInfo.basePipelineIndex = -1; //used to create derivatives for pipelines created in the same call.
|
||||
|
||||
// pipeCreateInfo.flags = VK_PIPELINE_CREATE_ALLOW_DERIVATIVES_BIT;
|
||||
// pipeCreateInfo.flags = VK_PIPELINE_CREATE_ALLOW_DERIVATIVES_BIT;
|
||||
|
||||
err = vkCreateGraphicsPipelines(vk.device, vk.pipelinecache, 1, &pipeCreateInfo, vkallocationcb, &pipe->pipeline);
|
||||
|
||||
|
@ -3776,7 +3776,7 @@ void VKBE_SelectEntity(entity_t *ent)
|
|||
BE_RotateForEntity(ent, ent->model);
|
||||
}
|
||||
|
||||
//fixme: create allocations within larger buffers, use separate staging.
|
||||
//fixme: create allocations within larger ring buffers, use separate staging.
|
||||
void *VKBE_CreateStagingBuffer(struct stagingbuf *n, size_t size, VkBufferUsageFlags usage)
|
||||
{
|
||||
void *ptr;
|
||||
|
@ -3784,6 +3784,8 @@ void *VKBE_CreateStagingBuffer(struct stagingbuf *n, size_t size, VkBufferUsageF
|
|||
VkMemoryRequirements mem_reqs;
|
||||
VkMemoryAllocateInfo memAllocInfo = {VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO};
|
||||
|
||||
memset(&n->mem, 0, sizeof(n->mem));
|
||||
|
||||
n->retbuf = VK_NULL_HANDLE;
|
||||
n->usage = usage | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
|
||||
bufinf.flags = 0;
|
||||
|
@ -3801,9 +3803,9 @@ void *VKBE_CreateStagingBuffer(struct stagingbuf *n, size_t size, VkBufferUsageF
|
|||
if (memAllocInfo.memoryTypeIndex == ~0)
|
||||
Sys_Error("Unable to allocate buffer memory");
|
||||
|
||||
VkAssert(vkAllocateMemory(vk.device, &memAllocInfo, vkallocationcb, &n->memory));
|
||||
VkAssert(vkBindBufferMemory(vk.device, n->buf, n->memory, 0));
|
||||
VkAssert(vkMapMemory(vk.device, n->memory, 0, n->size, 0, &ptr));
|
||||
VkAssert(vkAllocateMemory(vk.device, &memAllocInfo, vkallocationcb, &n->mem.memory));
|
||||
VkAssert(vkBindBufferMemory(vk.device, n->buf, n->mem.memory, n->mem.offset));
|
||||
VkAssert(vkMapMemory(vk.device, n->mem.memory, 0, n->size, 0, &ptr));
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
@ -3813,21 +3815,21 @@ struct fencedbufferwork
|
|||
struct vk_fencework fw;
|
||||
|
||||
VkBuffer buf;
|
||||
VkDeviceMemory mem;
|
||||
vk_poolmem_t mem;
|
||||
};
|
||||
static void VKBE_DoneBufferStaging(void *staging)
|
||||
{
|
||||
struct fencedbufferwork *n = staging;
|
||||
vkDestroyBuffer(vk.device, n->buf, vkallocationcb);
|
||||
vkFreeMemory(vk.device, n->mem, vkallocationcb);
|
||||
VK_ReleasePoolMemory(&n->mem);
|
||||
}
|
||||
VkBuffer VKBE_FinishStaging(struct stagingbuf *n, VkDeviceMemory *memptr)
|
||||
VkBuffer VKBE_FinishStaging(struct stagingbuf *n, vk_poolmem_t *mem)
|
||||
{
|
||||
struct fencedbufferwork *fence;
|
||||
VkBuffer retbuf;
|
||||
|
||||
//caller filled the staging buffer, and now wants to copy stuff to the gpu.
|
||||
vkUnmapMemory(vk.device, n->memory);
|
||||
vkUnmapMemory(vk.device, n->mem.memory);
|
||||
|
||||
//create the hardware buffer
|
||||
if (n->retbuf)
|
||||
|
@ -3848,20 +3850,38 @@ VkBuffer VKBE_FinishStaging(struct stagingbuf *n, VkDeviceMemory *memptr)
|
|||
//sort out its memory
|
||||
{
|
||||
VkMemoryRequirements mem_reqs;
|
||||
VkMemoryAllocateInfo memAllocInfo = {VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO};
|
||||
vkGetBufferMemoryRequirements(vk.device, retbuf, &mem_reqs);
|
||||
memAllocInfo.allocationSize = mem_reqs.size;
|
||||
memAllocInfo.memoryTypeIndex = vk_find_memory_require(mem_reqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
|
||||
if (memAllocInfo.memoryTypeIndex == ~0)
|
||||
Sys_Error("Unable to allocate buffer memory");
|
||||
VkAssert(vkAllocateMemory(vk.device, &memAllocInfo, vkallocationcb, memptr));
|
||||
VkAssert(vkBindBufferMemory(vk.device, retbuf, *memptr, 0));
|
||||
if (!VK_AllocatePoolMemory(vk_find_memory_require(mem_reqs.memoryTypeBits, 0), mem_reqs.size, mem_reqs.alignment, mem))
|
||||
{
|
||||
VkMemoryAllocateInfo memAllocInfo = {VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO};
|
||||
VkMemoryDedicatedAllocateInfoKHR khr_mdai = {VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO_KHR};
|
||||
|
||||
//shouldn't really happen, but just in case...
|
||||
mem_reqs.size = max(1,mem_reqs.size);
|
||||
|
||||
memAllocInfo.allocationSize = mem_reqs.size;
|
||||
memAllocInfo.memoryTypeIndex = vk_find_memory_require(mem_reqs.memoryTypeBits, 0);
|
||||
if (vk.khr_dedicated_allocation)
|
||||
{
|
||||
khr_mdai.buffer = retbuf;
|
||||
khr_mdai.pNext = memAllocInfo.pNext;
|
||||
memAllocInfo.pNext = &khr_mdai;
|
||||
}
|
||||
|
||||
mem->pool = NULL;
|
||||
mem->offset = 0;
|
||||
mem->size = mem_reqs.size;
|
||||
mem->memory = VK_NULL_HANDLE;
|
||||
|
||||
VkAssert(vkAllocateMemory(vk.device, &memAllocInfo, vkallocationcb, &mem->memory));
|
||||
}
|
||||
VkAssert(vkBindBufferMemory(vk.device, retbuf, mem->memory, mem->offset));
|
||||
}
|
||||
|
||||
|
||||
fence = VK_FencedBegin(VKBE_DoneBufferStaging, sizeof(*fence));
|
||||
fence->buf = n->buf;
|
||||
fence->mem = n->memory;
|
||||
fence->mem = n->mem;
|
||||
|
||||
//FIXME: barrier?
|
||||
|
||||
|
@ -3893,7 +3913,7 @@ void VKBE_GenBatchVBOs(vbo_t **vbochain, batch_t *firstbatch, batch_t *stopbatch
|
|||
index_t *vboedata;
|
||||
qbyte *vbovdatastart, *vbovdata;
|
||||
struct stagingbuf vbuf, ebuf;
|
||||
VkDeviceMemory *retarded;
|
||||
vk_poolmem_t *poolmem;
|
||||
|
||||
vbo = Z_Malloc(sizeof(*vbo));
|
||||
|
||||
|
@ -3960,17 +3980,17 @@ void VKBE_GenBatchVBOs(vbo_t **vbochain, batch_t *firstbatch, batch_t *stopbatch
|
|||
}
|
||||
}
|
||||
|
||||
vbo->vbomem = retarded = Z_Malloc(sizeof(*retarded));
|
||||
vbo->vbomem = poolmem = Z_Malloc(sizeof(*poolmem));
|
||||
vbo->coord.vk.buff =
|
||||
vbo->texcoord.vk.buff =
|
||||
vbo->lmcoord[0].vk.buff =
|
||||
vbo->normals.vk.buff =
|
||||
vbo->svector.vk.buff =
|
||||
vbo->tvector.vk.buff =
|
||||
vbo->colours[0].vk.buff = VKBE_FinishStaging(&vbuf, retarded);
|
||||
vbo->colours[0].vk.buff = VKBE_FinishStaging(&vbuf, poolmem);
|
||||
|
||||
vbo->ebomem = retarded = Z_Malloc(sizeof(*retarded));
|
||||
vbo->indicies.vk.buff = VKBE_FinishStaging(&ebuf, retarded);
|
||||
vbo->ebomem = poolmem = Z_Malloc(sizeof(*poolmem));
|
||||
vbo->indicies.vk.buff = VKBE_FinishStaging(&ebuf, poolmem);
|
||||
vbo->indicies.vk.offs = 0;
|
||||
|
||||
vbo->indexcount = maxvboelements;
|
||||
|
@ -4022,22 +4042,19 @@ struct vkbe_clearvbo
|
|||
static void VKBE_SafeClearVBO(void *vboptr)
|
||||
{
|
||||
vbo_t *vbo = *(vbo_t**)vboptr;
|
||||
VkDeviceMemory *retarded;
|
||||
|
||||
if (vbo->indicies.vk.buff)
|
||||
{
|
||||
vkDestroyBuffer(vk.device, vbo->indicies.vk.buff, vkallocationcb);
|
||||
retarded = vbo->ebomem;
|
||||
vkFreeMemory(vk.device, *retarded, vkallocationcb);
|
||||
BZ_Free(retarded);
|
||||
VK_ReleasePoolMemory(vbo->ebomem);
|
||||
BZ_Free(vbo->ebomem);
|
||||
}
|
||||
|
||||
if (vbo->coord.vk.buff)
|
||||
{
|
||||
vkDestroyBuffer(vk.device, vbo->coord.vk.buff, vkallocationcb);
|
||||
retarded = vbo->vbomem;
|
||||
vkFreeMemory(vk.device, *retarded, vkallocationcb);
|
||||
BZ_Free(retarded);
|
||||
VK_ReleasePoolMemory(vbo->vbomem);
|
||||
BZ_Free(vbo->vbomem);
|
||||
}
|
||||
|
||||
BZ_Free(vbo);
|
||||
|
@ -4678,26 +4695,8 @@ void VKBE_RT_Gen(struct vk_rendertarg *targ, uint32_t width, uint32_t height, qb
|
|||
depth_imginfo.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT|VK_IMAGE_USAGE_SAMPLED_BIT;
|
||||
VkAssert(vkCreateImage(vk.device, &depth_imginfo, vkallocationcb, &targ->depth.image));
|
||||
|
||||
|
||||
{
|
||||
VkMemoryRequirements mem_reqs;
|
||||
VkMemoryAllocateInfo memAllocInfo = {VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO};
|
||||
vkGetImageMemoryRequirements(vk.device, targ->colour.image, &mem_reqs);
|
||||
memAllocInfo.allocationSize = mem_reqs.size;
|
||||
memAllocInfo.memoryTypeIndex = vk_find_memory_require(mem_reqs.memoryTypeBits, 0);
|
||||
VkAssert(vkAllocateMemory(vk.device, &memAllocInfo, vkallocationcb, &targ->colour.memory));
|
||||
VkAssert(vkBindImageMemory(vk.device, targ->colour.image, targ->colour.memory, 0));
|
||||
}
|
||||
|
||||
{
|
||||
VkMemoryRequirements mem_reqs;
|
||||
VkMemoryAllocateInfo memAllocInfo = {VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO};
|
||||
vkGetImageMemoryRequirements(vk.device, targ->depth.image, &mem_reqs);
|
||||
memAllocInfo.allocationSize = mem_reqs.size;
|
||||
memAllocInfo.memoryTypeIndex = vk_find_memory_require(mem_reqs.memoryTypeBits, 0);
|
||||
VkAssert(vkAllocateMemory(vk.device, &memAllocInfo, vkallocationcb, &targ->depth.memory));
|
||||
VkAssert(vkBindImageMemory(vk.device, targ->depth.image, targ->depth.memory, 0));
|
||||
}
|
||||
VK_AllocateBindImageMemory(&targ->colour, true);
|
||||
VK_AllocateBindImageMemory(&targ->depth, true);
|
||||
|
||||
// set_image_layout(vk.frame->cbuf, targ->colour.image, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
|
||||
// set_image_layout(vk.frame->cbuf, targ->depth.image, VK_IMAGE_ASPECT_DEPTH_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
|
||||
|
@ -4867,26 +4866,8 @@ void VKBE_RT_Gen_Cube(struct vk_rendertarg_cube *targ, uint32_t size, qboolean c
|
|||
depth_imginfo.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT|VK_IMAGE_USAGE_SAMPLED_BIT;
|
||||
VkAssert(vkCreateImage(vk.device, &depth_imginfo, vkallocationcb, &targ->depth.image));
|
||||
|
||||
|
||||
{
|
||||
VkMemoryRequirements mem_reqs;
|
||||
VkMemoryAllocateInfo memAllocInfo = {VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO};
|
||||
vkGetImageMemoryRequirements(vk.device, targ->colour.image, &mem_reqs);
|
||||
memAllocInfo.allocationSize = mem_reqs.size;
|
||||
memAllocInfo.memoryTypeIndex = vk_find_memory_require(mem_reqs.memoryTypeBits, 0);
|
||||
VkAssert(vkAllocateMemory(vk.device, &memAllocInfo, vkallocationcb, &targ->colour.memory));
|
||||
VkAssert(vkBindImageMemory(vk.device, targ->colour.image, targ->colour.memory, 0));
|
||||
}
|
||||
|
||||
{
|
||||
VkMemoryRequirements mem_reqs;
|
||||
VkMemoryAllocateInfo memAllocInfo = {VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO};
|
||||
vkGetImageMemoryRequirements(vk.device, targ->depth.image, &mem_reqs);
|
||||
memAllocInfo.allocationSize = mem_reqs.size;
|
||||
memAllocInfo.memoryTypeIndex = vk_find_memory_require(mem_reqs.memoryTypeBits, 0);
|
||||
VkAssert(vkAllocateMemory(vk.device, &memAllocInfo, vkallocationcb, &targ->depth.memory));
|
||||
VkAssert(vkBindImageMemory(vk.device, targ->depth.image, targ->depth.memory, 0));
|
||||
}
|
||||
VK_AllocateBindImageMemory(&targ->colour, true);
|
||||
VK_AllocateBindImageMemory(&targ->depth, true);
|
||||
|
||||
// set_image_layout(vk.frame->cbuf, targ->colour.image, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
|
||||
// set_image_layout(vk.frame->cbuf, targ->depth.image, VK_IMAGE_ASPECT_DEPTH_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
|
||||
|
@ -5809,12 +5790,12 @@ struct vk_shadowbuffer
|
|||
|
||||
VkBuffer vbuffer;
|
||||
VkDeviceSize voffset;
|
||||
VkDeviceMemory vmemory;
|
||||
vk_poolmem_t vmemory;
|
||||
unsigned int numverts;
|
||||
|
||||
VkBuffer ibuffer;
|
||||
VkDeviceSize ioffset;
|
||||
VkDeviceMemory imemory;
|
||||
vk_poolmem_t imemory;
|
||||
unsigned int numindicies;
|
||||
};
|
||||
//FIXME: needs context for threading
|
||||
|
@ -5830,12 +5811,10 @@ struct vk_shadowbuffer *VKBE_GenerateShadowBuffer(vecV_t *verts, int numverts, i
|
|||
|
||||
map = VKBE_AllocateBufferSpace(DB_VBO, sizeof(*verts)*numverts, &buf->vbuffer, &buf->voffset);
|
||||
memcpy(map, verts, sizeof(*verts)*numverts);
|
||||
buf->vmemory = VK_NULL_HANDLE;
|
||||
buf->numverts = numverts;
|
||||
|
||||
map = VKBE_AllocateBufferSpace(DB_EBO, sizeof(*indicies)*numindicies, &buf->ibuffer, &buf->ioffset);
|
||||
memcpy(map, indicies, sizeof(*indicies)*numindicies);
|
||||
buf->imemory = VK_NULL_HANDLE;
|
||||
buf->numindicies = numindicies;
|
||||
return buf;
|
||||
}
|
||||
|
@ -5866,8 +5845,8 @@ static void VKBE_DestroyShadowBuffer_Delayed(void *ctx)
|
|||
struct vk_shadowbuffer *buf = ctx;
|
||||
vkDestroyBuffer(vk.device, buf->vbuffer, vkallocationcb);
|
||||
vkDestroyBuffer(vk.device, buf->ibuffer, vkallocationcb);
|
||||
vkFreeMemory(vk.device, buf->vmemory, vkallocationcb);
|
||||
vkFreeMemory(vk.device, buf->imemory, vkallocationcb);
|
||||
VK_ReleasePoolMemory(&buf->vmemory);
|
||||
VK_ReleasePoolMemory(&buf->imemory);
|
||||
}
|
||||
void VKBE_DestroyShadowBuffer(struct vk_shadowbuffer *buf)
|
||||
{
|
||||
|
@ -6359,33 +6338,33 @@ void VKBE_VBO_Finish(vbobctx_t *ctx, void *edata, size_t esize, vboarray_t *earr
|
|||
{
|
||||
struct stagingbuf *n;
|
||||
struct stagingbuf ebo;
|
||||
VkDeviceMemory *retarded;
|
||||
vk_poolmem_t *poolmem;
|
||||
index_t *map = VKBE_CreateStagingBuffer(&ebo, esize, VK_BUFFER_USAGE_INDEX_BUFFER_BIT);
|
||||
memcpy(map, edata, esize);
|
||||
*ebomem = retarded = Z_Malloc(sizeof(*retarded));
|
||||
earray->vk.buff = VKBE_FinishStaging(&ebo, retarded);
|
||||
*ebomem = poolmem = Z_Malloc(sizeof(*poolmem));
|
||||
earray->vk.buff = VKBE_FinishStaging(&ebo, poolmem);
|
||||
earray->vk.offs = 0;
|
||||
|
||||
if (ctx)
|
||||
{
|
||||
n = ctx->vboptr[0];
|
||||
*vbomem = retarded = Z_Malloc(sizeof(*retarded));
|
||||
VKBE_FinishStaging(n, retarded);
|
||||
*vbomem = poolmem = Z_Malloc(sizeof(*poolmem));
|
||||
/*buffer was pre-created*/VKBE_FinishStaging(n, poolmem);
|
||||
Z_Free(n);
|
||||
}
|
||||
}
|
||||
void VKBE_VBO_Destroy(vboarray_t *vearray, void *mem)
|
||||
{
|
||||
VkDeviceMemory *retarded = mem;
|
||||
vk_poolmem_t *poolmem = mem;
|
||||
struct fencedbufferwork *fence;
|
||||
if (!vearray->vk.buff)
|
||||
return; //not actually allocated...
|
||||
|
||||
fence = VK_AtFrameEnd(VKBE_DoneBufferStaging, NULL, sizeof(*fence));
|
||||
fence->buf = vearray->vk.buff;
|
||||
fence->mem = *retarded;
|
||||
fence->mem = *poolmem;
|
||||
|
||||
Z_Free(retarded);
|
||||
Z_Free(poolmem);
|
||||
}
|
||||
|
||||
void VKBE_Scissor(srect_t *rect)
|
||||
|
|
|
@ -12,10 +12,11 @@ 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_get_memory_requirements2;
|
||||
extern cvar_t vk_khr_dedicated_allocation;
|
||||
extern cvar_t vk_khr_push_descriptor;
|
||||
extern cvar_t vk_amd_rasterization_order;
|
||||
extern cvar_t vk_usememorypools;
|
||||
extern cvar_t vid_srgb, vid_vsync, vid_triplebuffer, r_stereo_method, vid_multisample, vid_bpp;
|
||||
void R2D_Console_Resize(void);
|
||||
|
||||
|
@ -182,8 +183,7 @@ void VK_DestroyVkTexture(vk_image_t *img)
|
|||
vkDestroyImageView(vk.device, img->view, vkallocationcb);
|
||||
if (img->image)
|
||||
vkDestroyImage(vk.device, img->image, vkallocationcb);
|
||||
if (img->memory)
|
||||
vkFreeMemory(vk.device, img->memory, vkallocationcb);
|
||||
VK_ReleasePoolMemory(&img->mem);
|
||||
}
|
||||
static void VK_DestroyVkTexture_Delayed(void *w)
|
||||
{
|
||||
|
@ -303,7 +303,7 @@ static qboolean VK_CreateSwapChain(void)
|
|||
VkPresentModeKHR *presentmode;
|
||||
VkSurfaceCapabilitiesKHR surfcaps;
|
||||
VkSwapchainCreateInfoKHR swapinfo = {VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR};
|
||||
uint32_t i, curpri;
|
||||
uint32_t i, curpri, preaquirecount;
|
||||
VkSwapchainKHR newvkswapchain;
|
||||
VkImage *images;
|
||||
VkDeviceMemory *memories;
|
||||
|
@ -369,9 +369,7 @@ static qboolean VK_CreateSwapChain(void)
|
|||
VkMemoryRequirements mem_reqs;
|
||||
VkMemoryAllocateInfo memAllocInfo = {VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO};
|
||||
VkMemoryDedicatedAllocateInfoKHR khr_mdai = {VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO_KHR};
|
||||
VkDedicatedAllocationMemoryAllocateInfoNV nv_damai = {VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_MEMORY_ALLOCATE_INFO_NV};
|
||||
VkImageCreateInfo ici = {VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO};
|
||||
VkDedicatedAllocationImageCreateInfoNV nv_daici = {VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_IMAGE_CREATE_INFO_NV};
|
||||
|
||||
ici.flags = 0;
|
||||
ici.imageType = VK_IMAGE_TYPE_2D;
|
||||
|
@ -389,13 +387,6 @@ static qboolean VK_CreateSwapChain(void)
|
|||
ici.pQueueFamilyIndices = NULL;
|
||||
ici.initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
||||
|
||||
if (vk.nv_dedicated_allocation)
|
||||
{ //render targets should always have dedicated allocations, supposedly. and we're doing it anyway.
|
||||
nv_daici.dedicatedAllocation = true;
|
||||
nv_daici.pNext = ici.pNext;
|
||||
ici.pNext = &nv_daici;
|
||||
}
|
||||
|
||||
VkAssert(vkCreateImage(vk.device, &ici, vkallocationcb, &images[i]));
|
||||
|
||||
vkGetImageMemoryRequirements(vk.device, images[i], &mem_reqs);
|
||||
|
@ -409,12 +400,6 @@ static qboolean VK_CreateSwapChain(void)
|
|||
if (memAllocInfo.memoryTypeIndex == ~0)
|
||||
memAllocInfo.memoryTypeIndex = vk_find_memory_require(mem_reqs.memoryTypeBits, 0);
|
||||
|
||||
if (vk.nv_dedicated_allocation)
|
||||
{ //annoying, but hey.
|
||||
nv_damai.pNext = memAllocInfo.pNext;
|
||||
nv_damai.image = images[i];
|
||||
memAllocInfo.pNext = &nv_damai;
|
||||
}
|
||||
if (vk.khr_dedicated_allocation)
|
||||
{
|
||||
khr_mdai.pNext = memAllocInfo.pNext;
|
||||
|
@ -478,11 +463,20 @@ static qboolean VK_CreateSwapChain(void)
|
|||
if (surfcaps.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR)
|
||||
swapinfo.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
|
||||
else if (surfcaps.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR)
|
||||
{
|
||||
swapinfo.compositeAlpha = VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR;
|
||||
Con_Printf(CON_WARNING"Vulkan swapchain using composite alpha premultiplied\n");
|
||||
}
|
||||
else if (surfcaps.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_POST_MULTIPLIED_BIT_KHR)
|
||||
{
|
||||
swapinfo.compositeAlpha = VK_COMPOSITE_ALPHA_POST_MULTIPLIED_BIT_KHR;
|
||||
Con_Printf(CON_WARNING"Vulkan swapchain using composite alpha postmultiplied\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
swapinfo.compositeAlpha = VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR; //erk?
|
||||
Con_Printf(CON_WARNING"composite alpha inherit\n");
|
||||
}
|
||||
swapinfo.imageArrayLayers = /*(r_stereo_method.ival==1)?2:*/1;
|
||||
swapinfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
||||
swapinfo.queueFamilyIndexCount = 0;
|
||||
|
@ -663,7 +657,7 @@ static qboolean VK_CreateSwapChain(void)
|
|||
vk.aquirelast = vk.aquirenext = 0;
|
||||
for (i = 0; i < ACQUIRELIMIT; i++)
|
||||
{
|
||||
if (vk_waitfence.ival)
|
||||
if (vk_waitfence.ival || !*vk_waitfence.string)
|
||||
{
|
||||
VkFenceCreateInfo fci = {VK_STRUCTURE_TYPE_FENCE_CREATE_INFO};
|
||||
VkAssert(vkCreateFence(vk.device,&fci,vkallocationcb,&vk.acquirefences[i]));
|
||||
|
@ -676,8 +670,12 @@ static qboolean VK_CreateSwapChain(void)
|
|||
vk.acquirefences[i] = VK_NULL_HANDLE;
|
||||
}
|
||||
}
|
||||
if (!vk_submissionthread.value && *vk_submissionthread.string)
|
||||
preaquirecount = 1;
|
||||
else
|
||||
preaquirecount = vk.backbuf_count;
|
||||
/*-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 < preaquirecount && vk.aquirelast <= vk.backbuf_count-surfcaps.minImageCount)
|
||||
{
|
||||
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++;
|
||||
|
@ -733,10 +731,10 @@ static qboolean VK_CreateSwapChain(void)
|
|||
{
|
||||
VkImageViewCreateInfo ivci = {VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO};
|
||||
ivci.format = vk.backbufformat;
|
||||
ivci.components.r = VK_COMPONENT_SWIZZLE_R;
|
||||
ivci.components.g = VK_COMPONENT_SWIZZLE_G;
|
||||
ivci.components.b = VK_COMPONENT_SWIZZLE_B;
|
||||
ivci.components.a = VK_COMPONENT_SWIZZLE_A;
|
||||
// ivci.components.r = VK_COMPONENT_SWIZZLE_R;
|
||||
// ivci.components.g = VK_COMPONENT_SWIZZLE_G;
|
||||
// ivci.components.b = VK_COMPONENT_SWIZZLE_B;
|
||||
// ivci.components.a = VK_COMPONENT_SWIZZLE_A;
|
||||
ivci.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
ivci.subresourceRange.baseMipLevel = 0;
|
||||
ivci.subresourceRange.levelCount = 1;
|
||||
|
@ -747,7 +745,7 @@ static qboolean VK_CreateSwapChain(void)
|
|||
ivci.image = images[i];
|
||||
vk.backbufs[i].colour.image = images[i];
|
||||
if (memories)
|
||||
vk.backbufs[i].colour.memory = memories[i];
|
||||
vk.backbufs[i].colour.mem.memory = memories[i];
|
||||
vk.backbufs[i].colour.width = swapinfo.imageExtent.width;
|
||||
vk.backbufs[i].colour.height = swapinfo.imageExtent.height;
|
||||
VkAssert(vkCreateImageView(vk.device, &ivci, vkallocationcb, &vk.backbufs[i].colour.view));
|
||||
|
@ -759,7 +757,6 @@ static qboolean VK_CreateSwapChain(void)
|
|||
//depth image
|
||||
{
|
||||
VkImageCreateInfo depthinfo = {VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO};
|
||||
VkDedicatedAllocationImageCreateInfoNV nv_daici = {VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_IMAGE_CREATE_INFO_NV};
|
||||
depthinfo.flags = 0;
|
||||
depthinfo.imageType = VK_IMAGE_TYPE_2D;
|
||||
depthinfo.format = vk.depthformat;
|
||||
|
@ -775,39 +772,11 @@ static qboolean VK_CreateSwapChain(void)
|
|||
depthinfo.queueFamilyIndexCount = 0;
|
||||
depthinfo.pQueueFamilyIndices = NULL;
|
||||
depthinfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
if (vk.nv_dedicated_allocation)
|
||||
{
|
||||
nv_daici.dedicatedAllocation = true;
|
||||
nv_daici.pNext = depthinfo.pNext;
|
||||
depthinfo.pNext = &nv_daici;
|
||||
}
|
||||
VkAssert(vkCreateImage(vk.device, &depthinfo, vkallocationcb, &vk.backbufs[i].depth.image));
|
||||
}
|
||||
|
||||
//depth memory
|
||||
{
|
||||
VkMemoryRequirements mem_reqs;
|
||||
VkMemoryAllocateInfo memAllocInfo = {VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO};
|
||||
VkMemoryDedicatedAllocateInfoKHR khr_mdai = {VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO_KHR};
|
||||
VkDedicatedAllocationMemoryAllocateInfoNV nv_damai = {VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_MEMORY_ALLOCATE_INFO_NV};
|
||||
vkGetImageMemoryRequirements(vk.device, vk.backbufs[i].depth.image, &mem_reqs);
|
||||
memAllocInfo.allocationSize = mem_reqs.size;
|
||||
memAllocInfo.memoryTypeIndex = vk_find_memory_require(mem_reqs.memoryTypeBits, 0);
|
||||
if (vk.nv_dedicated_allocation)
|
||||
{
|
||||
nv_damai.image = vk.backbufs[i].depth.image;
|
||||
nv_damai.pNext = memAllocInfo.pNext;
|
||||
memAllocInfo.pNext = &nv_damai;
|
||||
}
|
||||
if (vk.khr_dedicated_allocation)
|
||||
{
|
||||
khr_mdai.image = vk.backbufs[i].depth.image;
|
||||
khr_mdai.pNext = memAllocInfo.pNext;
|
||||
memAllocInfo.pNext = &khr_mdai;
|
||||
}
|
||||
VkAssert(vkAllocateMemory(vk.device, &memAllocInfo, vkallocationcb, &vk.backbufs[i].depth.memory));
|
||||
VkAssert(vkBindImageMemory(vk.device, vk.backbufs[i].depth.image, vk.backbufs[i].depth.memory, 0));
|
||||
}
|
||||
VK_AllocateBindImageMemory(&vk.backbufs[i].depth, true);
|
||||
|
||||
//depth view
|
||||
{
|
||||
|
@ -836,7 +805,6 @@ static qboolean VK_CreateSwapChain(void)
|
|||
//mscolour image
|
||||
{
|
||||
VkImageCreateInfo mscolourinfo = {VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO};
|
||||
VkDedicatedAllocationImageCreateInfoNV nv_daici = {VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_IMAGE_CREATE_INFO_NV};
|
||||
mscolourinfo.flags = 0;
|
||||
mscolourinfo.imageType = VK_IMAGE_TYPE_2D;
|
||||
mscolourinfo.format = vk.backbufformat;
|
||||
|
@ -852,40 +820,11 @@ static qboolean VK_CreateSwapChain(void)
|
|||
mscolourinfo.queueFamilyIndexCount = 0;
|
||||
mscolourinfo.pQueueFamilyIndices = NULL;
|
||||
mscolourinfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
if (vk.nv_dedicated_allocation)
|
||||
{
|
||||
nv_daici.dedicatedAllocation = true;
|
||||
nv_daici.pNext = mscolourinfo.pNext;
|
||||
mscolourinfo.pNext = &nv_daici;
|
||||
}
|
||||
VkAssert(vkCreateImage(vk.device, &mscolourinfo, vkallocationcb, &vk.backbufs[i].mscolour.image));
|
||||
}
|
||||
|
||||
//mscolour memory
|
||||
{
|
||||
VkMemoryRequirements mem_reqs;
|
||||
VkMemoryAllocateInfo memAllocInfo = {VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO};
|
||||
VkMemoryDedicatedAllocateInfoKHR khr_mdai = {VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO_KHR};
|
||||
VkDedicatedAllocationMemoryAllocateInfoNV nv_damai = {VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_MEMORY_ALLOCATE_INFO_NV};
|
||||
vkGetImageMemoryRequirements(vk.device, vk.backbufs[i].mscolour.image, &mem_reqs);
|
||||
memAllocInfo.allocationSize = mem_reqs.size;
|
||||
memAllocInfo.memoryTypeIndex = vk_find_memory_require(mem_reqs.memoryTypeBits, 0);
|
||||
if (vk.nv_dedicated_allocation)
|
||||
{
|
||||
nv_damai.image = vk.backbufs[i].mscolour.image;
|
||||
nv_damai.pNext = memAllocInfo.pNext;
|
||||
memAllocInfo.pNext = &nv_damai;
|
||||
}
|
||||
if (vk.khr_dedicated_allocation)
|
||||
{
|
||||
khr_mdai.image = vk.backbufs[i].mscolour.image;
|
||||
khr_mdai.pNext = memAllocInfo.pNext;
|
||||
memAllocInfo.pNext = &khr_mdai;
|
||||
}
|
||||
|
||||
VkAssert(vkAllocateMemory(vk.device, &memAllocInfo, vkallocationcb, &vk.backbufs[i].mscolour.memory));
|
||||
VkAssert(vkBindImageMemory(vk.device, vk.backbufs[i].mscolour.image, vk.backbufs[i].mscolour.memory, 0));
|
||||
}
|
||||
VK_AllocateBindImageMemory(&vk.backbufs[i].mscolour, true);
|
||||
|
||||
//mscolour view
|
||||
{
|
||||
|
@ -1020,21 +959,133 @@ void VK_UpdateFiltering(image_t *imagelist, int filtermip[3], int filterpic[3],
|
|||
}
|
||||
}
|
||||
|
||||
qboolean VK_AllocatePoolMemory(uint32_t pooltype, VkDeviceSize memsize, VkDeviceSize poolalignment, vk_poolmem_t *mem)
|
||||
{
|
||||
struct vk_mempool_s *p;
|
||||
VkDeviceSize pad;
|
||||
|
||||
if (!vk_usememorypools.ival)
|
||||
return false;
|
||||
|
||||
if (memsize > 1024*1024*4)
|
||||
return false;
|
||||
for (p = vk.mempools; p; p = p->next)
|
||||
{
|
||||
if (p->memtype == pooltype)
|
||||
{
|
||||
if (p->memoryoffset + poolalignment + memsize < p->memorysize)
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!p)
|
||||
{
|
||||
VkMemoryAllocateInfo poolai = {VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO};
|
||||
p = Z_Malloc(sizeof(*p));
|
||||
p->memorysize = poolai.allocationSize = 512*1024*1024; //lets just allocate big...
|
||||
p->memtype = poolai.memoryTypeIndex = pooltype;
|
||||
|
||||
if (VK_SUCCESS != vkAllocateMemory(vk.device, &poolai, vkallocationcb, &p->memory))
|
||||
{ //out of memory? oh well, a smaller dedicated allocation might still work.
|
||||
Z_Free(p);
|
||||
return false;
|
||||
}
|
||||
p->next = vk.mempools;
|
||||
vk.mempools = p;
|
||||
}
|
||||
pad = ((p->memoryoffset+poolalignment-1)&~(poolalignment-1)) - p->memoryoffset;
|
||||
p->memoryoffset = (p->memoryoffset+poolalignment-1)&~(poolalignment-1);
|
||||
p->gaps += pad;
|
||||
mem->offset = p->memoryoffset;
|
||||
mem->size = memsize; //FIXME: we have no way to deal with gaps due to alignment
|
||||
mem->memory = p->memory;
|
||||
mem->pool = p;
|
||||
|
||||
p->memoryoffset += memsize;
|
||||
return true;
|
||||
}
|
||||
void VK_ReleasePoolMemory(vk_poolmem_t *mem)
|
||||
{
|
||||
if (mem->pool)
|
||||
{
|
||||
//FIXME: track power-of-two holes?
|
||||
mem->pool->gaps += mem->size;
|
||||
mem->pool = NULL;
|
||||
mem->memory = VK_NULL_HANDLE;
|
||||
}
|
||||
else if (mem->memory)
|
||||
{
|
||||
vkFreeMemory(vk.device, mem->memory, vkallocationcb);
|
||||
mem->memory = VK_NULL_HANDLE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//does NOT bind.
|
||||
//image memory is NOT expected to be host-visible. you'll get what vulkan gives you.
|
||||
qboolean VK_AllocateImageMemory(VkImage image, qboolean dedicated, vk_poolmem_t *mem)
|
||||
{
|
||||
uint32_t pooltype;
|
||||
VkMemoryRequirements2KHR mem_reqs2 = {VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2_KHR};
|
||||
|
||||
if (!dedicated && vk.khr_get_memory_requirements2)
|
||||
{
|
||||
VkImageMemoryRequirementsInfo2KHR imri = {VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2_KHR};
|
||||
VkMemoryDedicatedRequirementsKHR mdr = {VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS_KHR};
|
||||
imri.image = image;
|
||||
if (vk.khr_dedicated_allocation)
|
||||
mem_reqs2.pNext = &mdr; //chain the result struct
|
||||
vkGetImageMemoryRequirements2KHR(vk.device, &imri, &mem_reqs2);
|
||||
|
||||
//and now we know if it should be dedicated or not.
|
||||
dedicated |= mdr.prefersDedicatedAllocation || mdr.requiresDedicatedAllocation;
|
||||
}
|
||||
else
|
||||
vkGetImageMemoryRequirements(vk.device, image, &mem_reqs2.memoryRequirements);
|
||||
|
||||
pooltype = vk_find_memory_try(mem_reqs2.memoryRequirements.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
|
||||
if (pooltype == ~0)
|
||||
pooltype = vk_find_memory_require(mem_reqs2.memoryRequirements.memoryTypeBits, 0);
|
||||
|
||||
if (!dedicated && VK_AllocatePoolMemory(pooltype, mem_reqs2.memoryRequirements.size, mem_reqs2.memoryRequirements.alignment, mem))
|
||||
return true; //got a shared allocation.
|
||||
else
|
||||
{ //make it dedicated one way or another.
|
||||
VkMemoryAllocateInfo memAllocInfo = {VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO};
|
||||
VkMemoryDedicatedAllocateInfoKHR khr_mdai = {VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO_KHR};
|
||||
|
||||
//shouldn't really happen, but just in case...
|
||||
mem_reqs2.memoryRequirements.size = max(1,mem_reqs2.memoryRequirements.size);
|
||||
|
||||
memAllocInfo.allocationSize = mem_reqs2.memoryRequirements.size;
|
||||
memAllocInfo.memoryTypeIndex = pooltype;
|
||||
if (vk.khr_dedicated_allocation)
|
||||
{
|
||||
khr_mdai.image = image;
|
||||
khr_mdai.pNext = memAllocInfo.pNext;
|
||||
memAllocInfo.pNext = &khr_mdai;
|
||||
}
|
||||
|
||||
mem->pool = NULL;
|
||||
mem->offset = 0;
|
||||
mem->size = mem_reqs2.memoryRequirements.size;
|
||||
mem->memory = VK_NULL_HANDLE;
|
||||
|
||||
VkAssert(vkAllocateMemory(vk.device, &memAllocInfo, vkallocationcb, &mem->memory));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
void VK_AllocateBindImageMemory(vk_image_t *image, qboolean dedicated)
|
||||
{
|
||||
if (VK_AllocateImageMemory(image->image, dedicated, &image->mem))
|
||||
VkAssert(vkBindImageMemory(vk.device, image->image, image->mem.memory, image->mem.offset));
|
||||
}
|
||||
|
||||
|
||||
vk_image_t VK_CreateTexture2DArray(uint32_t width, uint32_t height, uint32_t layers, uint32_t mips, uploadfmt_t encoding, unsigned int type, qboolean rendertarget)
|
||||
{
|
||||
vk_image_t ret;
|
||||
#ifdef USE_STAGING_BUFFERS
|
||||
qboolean staging = layers == 0;
|
||||
#else
|
||||
const qboolean staging = false;
|
||||
#endif
|
||||
VkMemoryRequirements mem_reqs;
|
||||
VkMemoryAllocateInfo memAllocInfo = {VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO};
|
||||
VkMemoryDedicatedAllocateInfoKHR khr_mdai = {VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO_KHR};
|
||||
VkDedicatedAllocationMemoryAllocateInfoNV nv_damai = {VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_MEMORY_ALLOCATE_INFO_NV};
|
||||
|
||||
VkImageViewCreateInfo viewInfo = {VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO};
|
||||
VkImageCreateInfo ici = {VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO};
|
||||
VkDedicatedAllocationImageCreateInfoNV nv_daici = {VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_IMAGE_CREATE_INFO_NV};
|
||||
VkFormat format = VK_FORMAT_UNDEFINED;;
|
||||
|
||||
ret.width = width;
|
||||
|
@ -1043,7 +1094,7 @@ vk_image_t VK_CreateTexture2DArray(uint32_t width, uint32_t height, uint32_t lay
|
|||
ret.mipcount = mips;
|
||||
ret.encoding = encoding;
|
||||
ret.type = type;
|
||||
ret.layout = staging?VK_IMAGE_LAYOUT_PREINITIALIZED:VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
ret.layout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
|
||||
//vulkan expresses packed formats in terms of native endian (if big-endian, then everything makes sense), non-packed formats are expressed in byte order (consistent with big-endian).
|
||||
//PTI formats are less well-defined...
|
||||
|
@ -1165,102 +1216,67 @@ vk_image_t VK_CreateTexture2DArray(uint32_t width, uint32_t height, uint32_t lay
|
|||
ici.extent.height = height;
|
||||
ici.extent.depth = 1;
|
||||
ici.mipLevels = mips;
|
||||
ici.arrayLayers = staging?1:layers;
|
||||
ici.arrayLayers = layers;
|
||||
ici.samples = VK_SAMPLE_COUNT_1_BIT;
|
||||
ici.tiling = staging?VK_IMAGE_TILING_LINEAR:VK_IMAGE_TILING_OPTIMAL;
|
||||
ici.usage = staging?VK_IMAGE_USAGE_TRANSFER_SRC_BIT:(VK_IMAGE_USAGE_SAMPLED_BIT|VK_IMAGE_USAGE_TRANSFER_DST_BIT);
|
||||
ici.tiling = VK_IMAGE_TILING_OPTIMAL;
|
||||
ici.usage = VK_IMAGE_USAGE_SAMPLED_BIT|(rendertarget?0:VK_IMAGE_USAGE_TRANSFER_DST_BIT);
|
||||
ici.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
||||
ici.queueFamilyIndexCount = 0;
|
||||
ici.pQueueFamilyIndices = NULL;
|
||||
ici.initialLayout = ret.layout;
|
||||
if (vk.nv_dedicated_allocation/* && (size > foo || rendertarget)*/) //FIXME: should only really be used for rendertargets or large images, other stuff should be merged. however, as we don't support any memory suballocations, we're going to just flag everything for now.
|
||||
{
|
||||
nv_daici.dedicatedAllocation = true;
|
||||
nv_daici.pNext = ici.pNext;
|
||||
ici.pNext = &nv_daici;
|
||||
}
|
||||
|
||||
VkAssert(vkCreateImage(vk.device, &ici, vkallocationcb, &ret.image));
|
||||
|
||||
vkGetImageMemoryRequirements(vk.device, ret.image, &mem_reqs);
|
||||
|
||||
memAllocInfo.allocationSize = mem_reqs.size;
|
||||
if (staging)
|
||||
memAllocInfo.memoryTypeIndex = vk_find_memory_require(mem_reqs.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
|
||||
else
|
||||
{
|
||||
memAllocInfo.memoryTypeIndex = vk_find_memory_try(mem_reqs.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT|VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
|
||||
if (memAllocInfo.memoryTypeIndex == ~0)
|
||||
memAllocInfo.memoryTypeIndex = vk_find_memory_try(mem_reqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
|
||||
if (memAllocInfo.memoryTypeIndex == ~0)
|
||||
memAllocInfo.memoryTypeIndex = vk_find_memory_try(mem_reqs.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
|
||||
if (memAllocInfo.memoryTypeIndex == ~0)
|
||||
memAllocInfo.memoryTypeIndex = vk_find_memory_require(mem_reqs.memoryTypeBits, 0);
|
||||
}
|
||||
if (nv_daici.dedicatedAllocation)
|
||||
{
|
||||
nv_damai.image = ret.image;
|
||||
nv_damai.pNext = memAllocInfo.pNext;
|
||||
memAllocInfo.pNext = &nv_damai;
|
||||
}
|
||||
if (vk.khr_dedicated_allocation)
|
||||
{
|
||||
khr_mdai.image = ret.image;
|
||||
khr_mdai.pNext = memAllocInfo.pNext;
|
||||
memAllocInfo.pNext = &khr_mdai;
|
||||
}
|
||||
VkAssert(vkAllocateMemory(vk.device, &memAllocInfo, vkallocationcb, &ret.memory));
|
||||
VkAssert(vkBindImageMemory(vk.device, ret.image, ret.memory, 0));
|
||||
VK_AllocateBindImageMemory(&ret, false);
|
||||
|
||||
ret.view = VK_NULL_HANDLE;
|
||||
ret.sampler = VK_NULL_HANDLE;
|
||||
|
||||
if (!staging)
|
||||
|
||||
viewInfo.flags = 0;
|
||||
viewInfo.image = ret.image;
|
||||
viewInfo.viewType = (ret.type==PTI_CUBEMAP)?VK_IMAGE_VIEW_TYPE_CUBE:VK_IMAGE_VIEW_TYPE_2D;
|
||||
viewInfo.format = format;
|
||||
switch(encoding)
|
||||
{
|
||||
VkImageViewCreateInfo viewInfo = {VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO};
|
||||
viewInfo.flags = 0;
|
||||
viewInfo.image = ret.image;
|
||||
viewInfo.viewType = (ret.type==PTI_CUBEMAP)?VK_IMAGE_VIEW_TYPE_CUBE:VK_IMAGE_VIEW_TYPE_2D;
|
||||
viewInfo.format = format;
|
||||
switch(encoding)
|
||||
{
|
||||
//formats that explicitly drop the alpha
|
||||
case PTI_BC1_RGB:
|
||||
case PTI_BC1_RGB_SRGB:
|
||||
case PTI_RGBX8:
|
||||
case PTI_RGBX8_SRGB:
|
||||
case PTI_BGRX8:
|
||||
case PTI_BGRX8_SRGB:
|
||||
viewInfo.components.r = VK_COMPONENT_SWIZZLE_R;
|
||||
viewInfo.components.g = VK_COMPONENT_SWIZZLE_G;
|
||||
viewInfo.components.b = VK_COMPONENT_SWIZZLE_B;
|
||||
viewInfo.components.a = VK_COMPONENT_SWIZZLE_ONE;
|
||||
break;
|
||||
case PTI_L8: //must be an R8 texture
|
||||
viewInfo.components.r = VK_COMPONENT_SWIZZLE_R;
|
||||
viewInfo.components.g = VK_COMPONENT_SWIZZLE_R;
|
||||
viewInfo.components.b = VK_COMPONENT_SWIZZLE_R;
|
||||
viewInfo.components.a = VK_COMPONENT_SWIZZLE_ONE;
|
||||
break;
|
||||
case PTI_L8A8: //must be an RG8 texture
|
||||
viewInfo.components.r = VK_COMPONENT_SWIZZLE_R;
|
||||
viewInfo.components.g = VK_COMPONENT_SWIZZLE_R;
|
||||
viewInfo.components.b = VK_COMPONENT_SWIZZLE_R;
|
||||
viewInfo.components.a = VK_COMPONENT_SWIZZLE_G;
|
||||
break;
|
||||
default:
|
||||
viewInfo.components.r = VK_COMPONENT_SWIZZLE_IDENTITY;
|
||||
viewInfo.components.g = VK_COMPONENT_SWIZZLE_IDENTITY;
|
||||
viewInfo.components.b = VK_COMPONENT_SWIZZLE_IDENTITY;
|
||||
viewInfo.components.a = VK_COMPONENT_SWIZZLE_IDENTITY;
|
||||
break;
|
||||
}
|
||||
viewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
viewInfo.subresourceRange.baseMipLevel = 0;
|
||||
viewInfo.subresourceRange.levelCount = mips;
|
||||
viewInfo.subresourceRange.baseArrayLayer = 0;
|
||||
viewInfo.subresourceRange.layerCount = layers;
|
||||
VkAssert(vkCreateImageView(vk.device, &viewInfo, NULL, &ret.view));
|
||||
//formats that explicitly drop the alpha
|
||||
case PTI_BC1_RGB:
|
||||
case PTI_BC1_RGB_SRGB:
|
||||
case PTI_RGBX8:
|
||||
case PTI_RGBX8_SRGB:
|
||||
case PTI_BGRX8:
|
||||
case PTI_BGRX8_SRGB:
|
||||
viewInfo.components.r = VK_COMPONENT_SWIZZLE_R;
|
||||
viewInfo.components.g = VK_COMPONENT_SWIZZLE_G;
|
||||
viewInfo.components.b = VK_COMPONENT_SWIZZLE_B;
|
||||
viewInfo.components.a = VK_COMPONENT_SWIZZLE_ONE;
|
||||
break;
|
||||
case PTI_L8: //must be an R8 texture
|
||||
viewInfo.components.r = VK_COMPONENT_SWIZZLE_R;
|
||||
viewInfo.components.g = VK_COMPONENT_SWIZZLE_R;
|
||||
viewInfo.components.b = VK_COMPONENT_SWIZZLE_R;
|
||||
viewInfo.components.a = VK_COMPONENT_SWIZZLE_ONE;
|
||||
break;
|
||||
case PTI_L8A8: //must be an RG8 texture
|
||||
viewInfo.components.r = VK_COMPONENT_SWIZZLE_R;
|
||||
viewInfo.components.g = VK_COMPONENT_SWIZZLE_R;
|
||||
viewInfo.components.b = VK_COMPONENT_SWIZZLE_R;
|
||||
viewInfo.components.a = VK_COMPONENT_SWIZZLE_G;
|
||||
break;
|
||||
default:
|
||||
viewInfo.components.r = VK_COMPONENT_SWIZZLE_IDENTITY;
|
||||
viewInfo.components.g = VK_COMPONENT_SWIZZLE_IDENTITY;
|
||||
viewInfo.components.b = VK_COMPONENT_SWIZZLE_IDENTITY;
|
||||
viewInfo.components.a = VK_COMPONENT_SWIZZLE_IDENTITY;
|
||||
break;
|
||||
}
|
||||
viewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
viewInfo.subresourceRange.baseMipLevel = 0;
|
||||
viewInfo.subresourceRange.levelCount = mips;
|
||||
viewInfo.subresourceRange.baseArrayLayer = 0;
|
||||
viewInfo.subresourceRange.layerCount = layers;
|
||||
VkAssert(vkCreateImageView(vk.device, &viewInfo, NULL, &ret.view));
|
||||
|
||||
return ret;
|
||||
}
|
||||
void set_image_layout(VkCommandBuffer cmd, VkImage image, VkImageAspectFlags aspectMask,
|
||||
|
@ -1366,6 +1382,7 @@ void VK_FencedSubmit(void *work)
|
|||
//check if we can release anything yet.
|
||||
VK_FencedCheck();
|
||||
|
||||
//FIXME: this seems to be an excessively expensive function.
|
||||
vkCreateFence(vk.device, &fenceinfo, vkallocationcb, &w->fence);
|
||||
|
||||
VK_Submit_Work(w->cbuf, VK_NULL_HANDLE, 0, VK_NULL_HANDLE, w->fence, NULL, w);
|
||||
|
@ -1423,45 +1440,26 @@ void *VK_AtFrameEnd(void (*frameended)(void *work), void *workdata, size_t works
|
|||
return w+1;
|
||||
}
|
||||
|
||||
#define USE_STAGING_BUFFERS
|
||||
struct texturefence
|
||||
{
|
||||
struct vk_fencework w;
|
||||
|
||||
int mips;
|
||||
#ifdef USE_STAGING_BUFFERS
|
||||
VkBuffer stagingbuffer;
|
||||
VkDeviceMemory stagingmemory;
|
||||
#else
|
||||
vk_image_t staging[32];
|
||||
#endif
|
||||
};
|
||||
static void VK_TextureLoaded(void *ctx)
|
||||
{
|
||||
struct texturefence *w = ctx;
|
||||
#ifdef USE_STAGING_BUFFERS
|
||||
vkDestroyBuffer(vk.device, w->stagingbuffer, vkallocationcb);
|
||||
vkFreeMemory(vk.device, w->stagingmemory, vkallocationcb);
|
||||
#else
|
||||
unsigned int i;
|
||||
for (i = 0; i < w->mips; i++)
|
||||
if (w->staging[i].image != VK_NULL_HANDLE)
|
||||
{
|
||||
vkDestroyImage(vk.device, w->staging[i].image, vkallocationcb);
|
||||
vkFreeMemory(vk.device, w->staging[i].memory, vkallocationcb);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
qboolean VK_LoadTextureMips (texid_t tex, const struct pendingtextureinfo *mips)
|
||||
{
|
||||
#ifdef USE_STAGING_BUFFERS
|
||||
VkBufferCreateInfo bci = {VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO};
|
||||
VkMemoryRequirements mem_reqs;
|
||||
VkMemoryAllocateInfo memAllocInfo = {VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO};
|
||||
void *mapdata;
|
||||
#else
|
||||
uint32_t y;
|
||||
#endif
|
||||
|
||||
struct texturefence *fence;
|
||||
VkCommandBuffer vkloadcmd;
|
||||
|
@ -1571,7 +1569,6 @@ qboolean VK_LoadTextureMips (texid_t tex, const struct pendingtextureinfo *mips)
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef USE_STAGING_BUFFERS
|
||||
//figure out how big our staging buffer needs to be
|
||||
bci.size = 0;
|
||||
for (i = 0; i < mipcount; i++)
|
||||
|
@ -1636,63 +1633,6 @@ qboolean VK_LoadTextureMips (texid_t tex, const struct pendingtextureinfo *mips)
|
|||
bci.size += blockswidth*blocksheight*blockbytes;
|
||||
}
|
||||
vkUnmapMemory(vk.device, fence->stagingmemory);
|
||||
#else
|
||||
//create the staging images and fill them
|
||||
for (i = 0; i < mipcount; i++)
|
||||
{
|
||||
VkImageSubresource subres = {0};
|
||||
VkSubresourceLayout layout;
|
||||
void *mapdata;
|
||||
//figure out the number of 'blocks' in the image.
|
||||
//for non-compressed formats this is just the width directly.
|
||||
//for compressed formats (ie: s3tc/dxt) we need to round up to deal with npot.
|
||||
uint32_t blockswidth = (mips->mip[i].width+blockwidth-1) / blockwidth;
|
||||
uint32_t blocksheight = (mips->mip[i].height+blockheight-1) / blockheight;
|
||||
|
||||
fence->staging[i] = VK_CreateTexture2DArray(mips->mip[i].width, mips->mip[i].height, 0, 1, mips->encoding, PTI_2D);
|
||||
subres.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
subres.mipLevel = 0;
|
||||
subres.arrayLayer = 0;
|
||||
vkGetImageSubresourceLayout(vk.device, fence->staging[i].image, &subres, &layout);
|
||||
VkAssert(vkMapMemory(vk.device, fence->staging[i].memory, 0, layout.size, 0, &mapdata));
|
||||
if (mapdata)
|
||||
{
|
||||
for (y = 0; y < blockheight; y++)
|
||||
memcpy((char*)mapdata + layout.offset + y*layout.rowPitch, (char*)mips->mip[i].data + y*blockswidth*blockbytes, blockswidth*blockbytes);
|
||||
}
|
||||
else
|
||||
Sys_Error("Unable to map staging image\n");
|
||||
|
||||
vkUnmapMemory(vk.device, fence->staging[i].memory);
|
||||
|
||||
//queue up an image copy for this mip
|
||||
{
|
||||
VkImageCopy region;
|
||||
region.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
region.srcSubresource.mipLevel = 0;
|
||||
region.srcSubresource.baseArrayLayer = 0;
|
||||
region.srcSubresource.layerCount = 1;
|
||||
region.srcOffset.x = 0;
|
||||
region.srcOffset.y = 0;
|
||||
region.srcOffset.z = 0;
|
||||
region.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
region.dstSubresource.mipLevel = i%(mipcount/layers);
|
||||
region.dstSubresource.baseArrayLayer = i/(mipcount/layers);
|
||||
region.dstSubresource.layerCount = 1;
|
||||
region.dstOffset.x = 0;
|
||||
region.dstOffset.y = 0;
|
||||
region.dstOffset.z = 0;
|
||||
region.extent.width = mips->mip[i].width;
|
||||
region.extent.height = mips->mip[i].height;
|
||||
region.extent.depth = 1;
|
||||
|
||||
set_image_layout(vkloadcmd, fence->staging[i].image, VK_IMAGE_ASPECT_COLOR_BIT,
|
||||
VK_IMAGE_LAYOUT_PREINITIALIZED, VK_ACCESS_HOST_WRITE_BIT,
|
||||
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_ACCESS_TRANSFER_READ_BIT);
|
||||
vkCmdCopyImage(vkloadcmd, fence->staging[i].image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, target.image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
//layouts are annoying. and weird.
|
||||
{
|
||||
|
@ -3079,7 +3019,7 @@ qboolean VK_SCR_GrabBackBuffer(void)
|
|||
imgbarrier.pNext = NULL;
|
||||
imgbarrier.srcAccessMask = 0;//VK_ACCESS_MEMORY_READ_BIT;
|
||||
imgbarrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
|
||||
imgbarrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;//vk.rendertarg->colour.layout; //'Alternately, oldLayout can be VK_IMAGE_LAYOUT_UNDEFINED, if the image’s contents need not be preserved.'
|
||||
imgbarrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;//vk.rendertarg->colour.layout; //'Alternately, oldLayout can be VK_IMAGE_LAYOUT_UNDEFINED, if the image's contents need not be preserved.'
|
||||
imgbarrier.newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
||||
imgbarrier.image = vk.frame->backbuf->colour.image;
|
||||
imgbarrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
|
@ -3216,7 +3156,7 @@ void VK_DebugFramerate(void)
|
|||
|
||||
qboolean VK_SCR_UpdateScreen (void)
|
||||
{
|
||||
uint32_t fblayout;
|
||||
VkImageLayout fblayout;
|
||||
|
||||
VK_FencedCheck();
|
||||
|
||||
|
@ -3519,7 +3459,12 @@ void VK_DoPresent(struct vkframe *theframe)
|
|||
RSpeedMark();
|
||||
if (err)
|
||||
{
|
||||
Con_Printf("ERROR: vkQueuePresentKHR: %x\n", err);
|
||||
if (err == VK_SUBOPTIMAL_KHR)
|
||||
Con_DPrintf("vkQueuePresentKHR: VK_SUBOPTIMAL_KHR\n");
|
||||
else if (err == VK_ERROR_OUT_OF_DATE_KHR)
|
||||
Con_DPrintf("vkQueuePresentKHR: VK_ERROR_OUT_OF_DATE_KHR\n");
|
||||
else
|
||||
Con_Printf("ERROR: vkQueuePresentKHR: %i\n", err);
|
||||
vk.neednewswapchain = true;
|
||||
}
|
||||
else
|
||||
|
@ -3527,7 +3472,7 @@ void VK_DoPresent(struct vkframe *theframe)
|
|||
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);
|
||||
Con_Printf("ERROR: vkAcquireNextImageKHR: %i\n", err);
|
||||
vk.neednewswapchain = true;
|
||||
vk.devicelost |= (err == VK_ERROR_DEVICE_LOST);
|
||||
}
|
||||
|
@ -3657,7 +3602,12 @@ void VK_Submit_Work(VkCommandBuffer cmdbuf, VkSemaphore semwait, VkPipelineStage
|
|||
*link = work;
|
||||
|
||||
#ifdef MULTITHREAD
|
||||
if (vk.submitthread && !vk.neednewswapchain)
|
||||
if (vk.neednewswapchain && vk.submitthread)
|
||||
{ //if we're trying to kill the submission thread, don't post work to it - instead wait for it to die cleanly then do it ourselves.
|
||||
Sys_WaitOnThread(vk.submitthread);
|
||||
vk.submitthread = NULL;
|
||||
}
|
||||
if (vk.submitthread)
|
||||
Sys_ConditionSignal(vk.submitcondition);
|
||||
else
|
||||
#endif
|
||||
|
@ -3796,6 +3746,7 @@ qboolean VK_Init(rendererstate_t *info, const char **sysextnames, qboolean (*cre
|
|||
VkResult err;
|
||||
VkApplicationInfo app;
|
||||
VkInstanceCreateInfo inst_info;
|
||||
int gpuidx;
|
||||
const char *extensions[8];
|
||||
uint32_t extensions_count = 0;
|
||||
|
||||
|
@ -3812,12 +3763,12 @@ qboolean VK_Init(rendererstate_t *info, const char **sysextnames, qboolean (*cre
|
|||
qboolean supported;
|
||||
} knowndevexts[] =
|
||||
{
|
||||
{&vk.khr_swapchain, VK_KHR_SWAPCHAIN_EXTENSION_NAME, NULL, true, NULL, " Nothing will be drawn!"},
|
||||
{&vk.nv_glsl_shader, VK_NV_GLSL_SHADER_EXTENSION_NAME, &vk_nv_glsl_shader, false, NULL, " Direct use of glsl is not supported."},
|
||||
{&vk.nv_dedicated_allocation, VK_NV_DEDICATED_ALLOCATION_EXTENSION_NAME, &vk_nv_dedicated_allocation, true, &vk.khr_dedicated_allocation, NULL},
|
||||
{&vk.khr_dedicated_allocation, VK_KHR_DEDICATED_ALLOCATION_EXTENSION_NAME, &vk_khr_dedicated_allocation, true, NULL, NULL},
|
||||
{&vk.khr_push_descriptor, VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME, &vk_khr_push_descriptor, true, NULL, NULL},
|
||||
{&vk.amd_rasterization_order, VK_AMD_RASTERIZATION_ORDER_EXTENSION_NAME, &vk_amd_rasterization_order, false, NULL, NULL},
|
||||
{&vk.khr_swapchain, VK_KHR_SWAPCHAIN_EXTENSION_NAME, NULL, true, NULL, " Nothing will be drawn!"},
|
||||
{&vk.nv_glsl_shader, VK_NV_GLSL_SHADER_EXTENSION_NAME, &vk_nv_glsl_shader, false, NULL, " Direct use of glsl is not supported."},
|
||||
{&vk.khr_get_memory_requirements2, VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME,&vk_khr_get_memory_requirements2,true, NULL, NULL},
|
||||
{&vk.khr_dedicated_allocation, VK_KHR_DEDICATED_ALLOCATION_EXTENSION_NAME, &vk_khr_dedicated_allocation, true, NULL, NULL},
|
||||
{&vk.khr_push_descriptor, VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME, &vk_khr_push_descriptor, true, NULL, NULL},
|
||||
{&vk.amd_rasterization_order, VK_AMD_RASTERIZATION_ORDER_EXTENSION_NAME, &vk_amd_rasterization_order, false, NULL, NULL},
|
||||
};
|
||||
size_t e;
|
||||
|
||||
|
@ -3959,6 +3910,17 @@ qboolean VK_Init(rendererstate_t *info, const char **sysextnames, qboolean (*cre
|
|||
uint32_t gpucount = 0, i;
|
||||
uint32_t bestpri = ~0u, pri;
|
||||
VkPhysicalDevice *devs;
|
||||
char *s = info->subrenderer;
|
||||
int wantdev = -1;
|
||||
if (*s)
|
||||
{
|
||||
if (!Q_strncasecmp(s, "GPU", 3))
|
||||
s += 3;
|
||||
wantdev = strtoul(s, &s, 0);
|
||||
if (*s) //its a named device.
|
||||
wantdev = -1;
|
||||
}
|
||||
|
||||
vkEnumeratePhysicalDevices(vk.instance, &gpucount, NULL);
|
||||
if (!gpucount)
|
||||
{
|
||||
|
@ -3993,7 +3955,10 @@ qboolean VK_Init(rendererstate_t *info, const char **sysextnames, qboolean (*cre
|
|||
Con_DPrintf("Found Vulkan Device \"%s\"\n", props.deviceName);
|
||||
|
||||
if (!vk.gpu)
|
||||
{
|
||||
gpuidx = i;
|
||||
vk.gpu = devs[i];
|
||||
}
|
||||
switch(props.deviceType)
|
||||
{
|
||||
default:
|
||||
|
@ -4013,17 +3978,27 @@ qboolean VK_Init(rendererstate_t *info, const char **sysextnames, qboolean (*cre
|
|||
pri = 4;
|
||||
break;
|
||||
}
|
||||
if (!Q_strcasecmp(props.deviceName, info->subrenderer))
|
||||
pri = 0;
|
||||
if (wantdev >= 0)
|
||||
{
|
||||
if (wantdev == i)
|
||||
pri = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!Q_strcasecmp(props.deviceName, info->subrenderer))
|
||||
pri = 0;
|
||||
}
|
||||
|
||||
if (pri < bestpri)
|
||||
{
|
||||
vk.gpu = devs[i];
|
||||
gpuidx = i;
|
||||
vk.gpu = devs[gpuidx];
|
||||
bestpri = pri;
|
||||
}
|
||||
}
|
||||
free(devs);
|
||||
|
||||
if (bestpri == ~0u)
|
||||
if (!vk.gpu)
|
||||
{
|
||||
Con_Printf("vulkan: unable to pick a usable device\n");
|
||||
return false;
|
||||
|
@ -4037,7 +4012,7 @@ qboolean VK_Init(rendererstate_t *info, const char **sysextnames, qboolean (*cre
|
|||
|
||||
switch(props.vendorID)
|
||||
{
|
||||
//explicit vendors
|
||||
//explicit registered vendors
|
||||
case 0x10001: vendor = "Vivante"; break;
|
||||
case 0x10002: vendor = "VeriSilicon"; break;
|
||||
|
||||
|
@ -4053,6 +4028,7 @@ qboolean VK_Init(rendererstate_t *info, const char **sysextnames, qboolean (*cre
|
|||
case 0x1AEE: vendor = "Imagination";break;
|
||||
case 0x1957: vendor = "Freescale"; break;
|
||||
|
||||
//I really have no idea who makes mobile gpus nowadays, but lets make some guesses.
|
||||
case 0x1AE0: vendor = "Google"; break;
|
||||
case 0x5333: vendor = "S3"; break;
|
||||
case 0xA200: vendor = "NEC"; break;
|
||||
|
@ -4076,8 +4052,8 @@ qboolean VK_Init(rendererstate_t *info, const char **sysextnames, qboolean (*cre
|
|||
case VK_PHYSICAL_DEVICE_TYPE_CPU: type = "software"; break;
|
||||
}
|
||||
|
||||
Con_Printf("Vulkan %u.%u.%u: %s %s %s (%u.%u.%u)\n", VK_VERSION_MAJOR(props.apiVersion), VK_VERSION_MINOR(props.apiVersion), VK_VERSION_PATCH(props.apiVersion),
|
||||
type, vendor, props.deviceName,
|
||||
Con_Printf("Vulkan %u.%u.%u: GPU%i %s %s %s (%u.%u.%u)\n", VK_VERSION_MAJOR(props.apiVersion), VK_VERSION_MINOR(props.apiVersion), VK_VERSION_PATCH(props.apiVersion),
|
||||
gpuidx, type, vendor, props.deviceName,
|
||||
VK_VERSION_MAJOR(props.driverVersion), VK_VERSION_MINOR(props.driverVersion), VK_VERSION_PATCH(props.driverVersion)
|
||||
);
|
||||
}
|
||||
|
@ -4205,7 +4181,7 @@ qboolean VK_Init(rendererstate_t *info, const char **sysextnames, qboolean (*cre
|
|||
Con_DPrintf("Using %s.\n", knowndevexts[e].name);
|
||||
devextensions[numdevextensions++] = knowndevexts[e].name;
|
||||
}
|
||||
else if (knowndevexts[e].var->ival)
|
||||
else if (knowndevexts[e].var && knowndevexts[e].var->ival)
|
||||
Con_Printf("unable to enable %s extension.%s\n", knowndevexts[e].name, knowndevexts[e].warningtext?knowndevexts[e].warningtext:"");
|
||||
else if (knowndevexts[e].supported)
|
||||
Con_DPrintf("Ignoring %s.\n", knowndevexts[e].name);
|
||||
|
@ -4255,7 +4231,43 @@ qboolean VK_Init(rendererstate_t *info, const char **sysextnames, qboolean (*cre
|
|||
devinf.ppEnabledExtensionNames = devextensions;
|
||||
devinf.pEnabledFeatures = &features;
|
||||
|
||||
err = vkCreateDevice(vk.gpu, &devinf, NULL, &vk.device);
|
||||
#if 0
|
||||
if (vkEnumeratePhysicalDeviceGroupsKHR && vk_afr.ival)
|
||||
{
|
||||
//'Every physical device must be in exactly one device group'. So we can just use the first group that lists it and automatically get AFR.
|
||||
uint32_t gpugroups = 0;
|
||||
VkDeviceGroupDeviceCreateInfoKHX dgdci = {VK_STRUCTURE_TYPE_DEVICE_GROUP_DEVICE_CREATE_INFO_KHR};
|
||||
|
||||
VkPhysicalDeviceGroupPropertiesKHR *groups;
|
||||
vkEnumeratePhysicalDeviceGroupsKHR(vk.instance, &gpugroups, NULL);
|
||||
groups = malloc(sizeof(*groups)*gpugroups);
|
||||
vkEnumeratePhysicalDeviceGroupsKHR(vk.instance, &gpugroups, groups);
|
||||
for (i = 0; i < gpugroups; i++)
|
||||
{
|
||||
for (j = 0; j < groups[i].physicalDeviceCount; j++)
|
||||
if (groups[i].physicalDevices[j] == vk.gpu)
|
||||
{
|
||||
dgdci.physicalDeviceCount = groups[i].physicalDeviceCount;
|
||||
dgdci.pPhysicalDevices = groups[i].physicalDevices;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (dgdci.physicalDeviceCount > 1)
|
||||
{
|
||||
vk.subdevices = dgdci.physicalDeviceCount;
|
||||
dgdci.pNext = devinf.pNext;
|
||||
devinf.pNext = &dgdci;
|
||||
}
|
||||
|
||||
err = vkCreateDevice(vk.gpu, &devinf, NULL, &vk.device);
|
||||
|
||||
free(groups);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
err = vkCreateDevice(vk.gpu, &devinf, NULL, &vk.device);
|
||||
|
||||
switch(err)
|
||||
{
|
||||
case VK_ERROR_INCOMPATIBLE_DRIVER:
|
||||
|
@ -4396,6 +4408,15 @@ void VK_Shutdown(void)
|
|||
vkDestroyPipelineCache(vk.device, vk.pipelinecache, vkallocationcb);
|
||||
}
|
||||
|
||||
while(vk.mempools)
|
||||
{
|
||||
void *l;
|
||||
vkFreeMemory(vk.device, vk.mempools->memory, vkallocationcb);
|
||||
l = vk.mempools;
|
||||
vk.mempools = vk.mempools->next;
|
||||
Z_Free(l);
|
||||
}
|
||||
|
||||
if (vk.device)
|
||||
vkDestroyDevice(vk.device, vkallocationcb);
|
||||
if (vk_debugcallback)
|
||||
|
|
|
@ -58,6 +58,7 @@
|
|||
//funcs specific to an instance
|
||||
#define VKInst2Funcs \
|
||||
VKFunc(EnumeratePhysicalDevices) \
|
||||
VKFunc(EnumeratePhysicalDeviceGroupsKHX) \
|
||||
VKFunc(EnumerateDeviceExtensionProperties) \
|
||||
VKFunc(GetPhysicalDeviceProperties) \
|
||||
VKFunc(GetPhysicalDeviceQueueFamilyProperties) \
|
||||
|
@ -126,6 +127,7 @@
|
|||
VKFunc(GetDeviceQueue) \
|
||||
VKFunc(GetBufferMemoryRequirements) \
|
||||
VKFunc(GetImageMemoryRequirements) \
|
||||
VKFunc(GetImageMemoryRequirements2KHR) \
|
||||
VKFunc(GetImageSubresourceLayout) \
|
||||
VKFunc(CreateFramebuffer) \
|
||||
VKFunc(DestroyFramebuffer) \
|
||||
|
@ -193,10 +195,18 @@
|
|||
#define VkWarnAssert(f) f
|
||||
#endif
|
||||
|
||||
typedef struct
|
||||
{
|
||||
struct vk_mempool_s *pool;
|
||||
VkDeviceMemory memory;
|
||||
size_t size;
|
||||
size_t offset;
|
||||
} vk_poolmem_t;
|
||||
|
||||
typedef struct vk_image_s
|
||||
{
|
||||
VkImage image;
|
||||
VkDeviceMemory memory;
|
||||
vk_poolmem_t mem;
|
||||
VkImageView view;
|
||||
VkSampler sampler;
|
||||
VkImageLayout layout;
|
||||
|
@ -256,12 +266,12 @@ extern struct vulkaninfo_s
|
|||
qboolean vsync;
|
||||
qboolean allowsubmissionthread;
|
||||
|
||||
qboolean khr_swapchain; //aka: not headless. we're actually rendering stuff!
|
||||
qboolean nv_glsl_shader; //we can load glsl shaders. probably missing lots of reflection info though, so this is probably too limited.
|
||||
qboolean nv_dedicated_allocation; //nvidia-specific extension that provides hints that there's no memory aliasing going on.
|
||||
qboolean khr_dedicated_allocation; //standardised version of the above where the driver decides whether a resource is worth a dedicated allocation.
|
||||
qboolean khr_push_descriptor; //more efficient descriptor streaming
|
||||
qboolean amd_rasterization_order; //allows primitives to draw in any order
|
||||
qboolean khr_swapchain; //aka: not headless. we're actually rendering stuff!
|
||||
qboolean nv_glsl_shader; //we can load glsl shaders. probably missing lots of reflection info though, so this is probably too limited.
|
||||
qboolean khr_get_memory_requirements2; //slightly richer info
|
||||
qboolean khr_dedicated_allocation; //standardised version of the above where the driver decides whether a resource is worth a dedicated allocation.
|
||||
qboolean khr_push_descriptor; //more efficient descriptor streaming
|
||||
qboolean amd_rasterization_order; //allows primitives to draw in any order
|
||||
|
||||
VkInstance instance;
|
||||
VkDevice device;
|
||||
|
@ -299,6 +309,19 @@ extern struct vulkaninfo_s
|
|||
float max_anistophy;
|
||||
float max_anistophy_limit;
|
||||
|
||||
struct vk_mempool_s
|
||||
{
|
||||
struct vk_mempool_s *next;
|
||||
|
||||
uint32_t memtype;
|
||||
VkDeviceMemory memory;
|
||||
|
||||
//FIXME: replace with an ordered list of free blocks.
|
||||
VkDeviceSize gaps;
|
||||
VkDeviceSize memoryoffset;
|
||||
VkDeviceSize memorysize;
|
||||
} *mempools;
|
||||
|
||||
struct descpool
|
||||
{
|
||||
VkDescriptorPool pool;
|
||||
|
@ -450,11 +473,15 @@ void VKBE_RT_End(struct vk_rendertarg *targ);
|
|||
void VKBE_RT_Destroy(struct vk_rendertarg *targ);
|
||||
|
||||
|
||||
qboolean VK_AllocatePoolMemory(uint32_t pooltype, VkDeviceSize memsize, VkDeviceSize poolalignment, vk_poolmem_t *mem);
|
||||
void VK_ReleasePoolMemory(vk_poolmem_t *mem);
|
||||
qboolean VK_AllocateImageMemory(VkImage image, qboolean dedicated, vk_poolmem_t *mem); //dedicated should normally be TRUE for render targets
|
||||
void VK_AllocateBindImageMemory(vk_image_t *image, qboolean dedicated); //dedicated should normally be TRUE for render targets
|
||||
struct stagingbuf
|
||||
{
|
||||
VkBuffer buf;
|
||||
VkBuffer retbuf;
|
||||
VkDeviceMemory memory;
|
||||
vk_poolmem_t mem;
|
||||
size_t size;
|
||||
VkBufferUsageFlags usage;
|
||||
};
|
||||
|
@ -462,7 +489,7 @@ vk_image_t VK_CreateTexture2DArray(uint32_t width, uint32_t height, uint32_t lay
|
|||
void set_image_layout(VkCommandBuffer cmd, VkImage image, VkImageAspectFlags aspectMask, VkImageLayout old_image_layout, VkAccessFlags srcaccess, VkPipelineStageFlagBits srcstagemask, VkImageLayout new_image_layout, VkAccessFlags dstaccess, VkPipelineStageFlagBits dststagemask);
|
||||
void VK_CreateSampler(unsigned int flags, vk_image_t *img);
|
||||
void *VKBE_CreateStagingBuffer(struct stagingbuf *n, size_t size, VkBufferUsageFlags usage);
|
||||
VkBuffer VKBE_FinishStaging(struct stagingbuf *n, VkDeviceMemory *memptr);
|
||||
VkBuffer VKBE_FinishStaging(struct stagingbuf *n, vk_poolmem_t *memptr);
|
||||
void *VK_FencedBegin(void (*passed)(void *work), size_t worksize);
|
||||
void VK_FencedSubmit(void *work);
|
||||
void VK_FencedCheck(void);
|
||||
|
|
Loading…
Reference in a new issue