d3d11: stripped the reflection stuff from the d3d11 renderer. we'll do that stuff explicitly instead of having to deal with microsoft's api. its just more reliable.

openal: doppler now applies to openal more consistently.
vulkan: vk_loadglsl cvar enables vk_nv_glsl_shader, with support for existing glsl shaders (still no permutations for now). needs !!samps stuff.
vulkan: r_renderscale now partly works. r_fxaa also works under specific circumstances. needs more work. still no bloom or projections stuff.
menu_download: got a few tweaks to improve it, including zips. I still want to handle engine updates with this stuff, but that can wait for later.

git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@5008 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
Spoike 2016-07-26 11:47:59 +00:00
parent ec623409ff
commit eccfe6b560
43 changed files with 6506 additions and 5335 deletions

View file

@ -173,6 +173,7 @@ cvar_t cl_countpendingpl = CVARD("cl_countpendingpl", "0", "If set to 1, packet
cvar_t cl_standardchat = CVARFD("cl_standardchat", "0", CVAR_ARCHIVE, "Disables auto colour coding in chat messages."); cvar_t cl_standardchat = CVARFD("cl_standardchat", "0", CVAR_ARCHIVE, "Disables auto colour coding in chat messages.");
cvar_t msg_filter = CVARD("msg_filter", "0", "Filter out chat messages: 0=neither. 1=broadcast chat. 2=team chat. 3=all chat."); cvar_t msg_filter = CVARD("msg_filter", "0", "Filter out chat messages: 0=neither. 1=broadcast chat. 2=team chat. 3=all chat.");
cvar_t msg_filter_frags = CVARD("msg_filter_frags", "0", "Prevents frag messages from appearing on the console."); cvar_t msg_filter_frags = CVARD("msg_filter_frags", "0", "Prevents frag messages from appearing on the console.");
cvar_t msg_filter_pickups = CVARD("msg_filter_pickups", "0", "Prevents pickup messages from appearing on the console. This would normally be filtered by 'msg 1', but nq servers cannot respect that (nor nq mods running in qw servers).");
cvar_t cl_standardmsg = CVARFD("cl_standardmsg", "0", CVAR_ARCHIVE, "Disables auto colour coding in console prints."); cvar_t cl_standardmsg = CVARFD("cl_standardmsg", "0", CVAR_ARCHIVE, "Disables auto colour coding in console prints.");
cvar_t cl_parsewhitetext = CVARD("cl_parsewhitetext", "1", "When parsing chat messages, enable support for messages like: red{white}red"); cvar_t cl_parsewhitetext = CVARD("cl_parsewhitetext", "1", "When parsing chat messages, enable support for messages like: red{white}red");

View file

@ -268,7 +268,7 @@ char *svc_nqstrings[] =
"NEW PROTOCOL(88)" //88 "NEW PROTOCOL(88)" //88
}; };
extern cvar_t requiredownloads, cl_standardchat, msg_filter, msg_filter_frags, cl_countpendingpl, cl_download_mapsrc; extern cvar_t requiredownloads, cl_standardchat, msg_filter, msg_filter_frags, msg_filter_pickups, cl_countpendingpl, cl_download_mapsrc;
int oldparsecountmod; int oldparsecountmod;
int parsecountmod; int parsecountmod;
double parsecounttime; double parsecounttime;
@ -5948,14 +5948,15 @@ void CL_ParsePrint(char *msg, int level)
} }
else else
{ {
#ifdef PLUGINS
if (Plug_ServerMessage(printtext, level))
#endif
#ifdef CSQC_DAT #ifdef CSQC_DAT
if (!CSQC_ParsePrint(printtext, level)) if (!CSQC_ParsePrint(printtext, level))
#endif #endif
if (!Stats_ParsePrintLine(printtext) || !msg_filter_frags.ival) #ifdef PLUGINS
CL_PrintStandardMessage(printtext, level); if (Plug_ServerMessage(printtext, level))
#endif
if (!Stats_ParsePickups(printtext) || !msg_filter_pickups.ival)
if (!Stats_ParsePrintLine(printtext) || !msg_filter_frags.ival)
CL_PrintStandardMessage(printtext, level);
} }
} }
@ -7293,7 +7294,10 @@ void CLNQ_ParseServerMessage (void)
s = MSG_ReadString (); s = MSG_ReadString ();
if (*s == 1 || *s == 2) if (*s == 1 || *s == 2)
{
//FIXME: should be using the first char of the line, not the first char of the last segment.
CL_ParsePrint(s+1, PRINT_CHAT); CL_ParsePrint(s+1, PRINT_CHAT);
}
else if (CLNQ_ParseNQPrints(s)) else if (CLNQ_ParseNQPrints(s))
break; break;
else else

View file

@ -1620,7 +1620,8 @@ qboolean Stats_HaveFlags(int mode);
qboolean Stats_HaveKills(void); qboolean Stats_HaveKills(void);
float Stats_GetLastOwnFrag(int seat, char *res, int reslen); float Stats_GetLastOwnFrag(int seat, char *res, int reslen);
void VARGS Stats_Message(char *msg, ...) LIKEPRINTF(1); void VARGS Stats_Message(char *msg, ...) LIKEPRINTF(1);
qboolean Stats_ParsePrintLine(char *line); qboolean Stats_ParsePrintLine(const char *line);
qboolean Stats_ParsePickups(const char *line);
void Stats_NewMap(void); void Stats_NewMap(void);
void Stats_Clear(void); void Stats_Clear(void);
void Stats_Init(void); void Stats_Init(void);

View file

@ -275,60 +275,76 @@ qboolean Con_NameForNum(int num, char *buffer, int buffersize)
} }
#ifdef QTERM #ifdef QTERM
void QT_Kill(qterm_t *qt, qboolean killconsole)
{
qterm_t **link;
qt->console->close = NULL;
qt->console->userdata = NULL;
qt->console->redirect = NULL;
if (killconsole)
Con_Destroy(qt->console);
//yes this loop will crash if you're not careful. it makes it easier to debug.
for (link = &qterms; ; link = &(*link)->next)
{
if (*link == qt)
{
*link = qt->next;
break;
}
}
CloseHandle(qt->pipein);
CloseHandle(qt->pipeout);
CloseHandle(qt->pipeinih);
CloseHandle(qt->pipeoutih);
CloseHandle(qt->process);
Z_Free(qt);
}
void QT_Update(void) void QT_Update(void)
{ {
char buffer[2048]; char buffer[2048];
DWORD ret; DWORD ret;
qterm_t *qt; qterm_t *qt, *n;
qterm_t *prev = NULL; for (qt = qterms; qt; )
for (qt = qterms; qt; qt = (prev=qt)->next)
{ {
if (!qt->running) if (qt->running)
{ {
if (Con_IsActive(qt->console)) if (WaitForSingleObject(qt->process, 0) == WAIT_TIMEOUT)
continue;
Con_Destroy(qt->console);
if (prev)
prev->next = qt->next;
else
qterms = qt->next;
CloseHandle(qt->pipein);
CloseHandle(qt->pipeout);
CloseHandle(qt->pipeinih);
CloseHandle(qt->pipeoutih);
CloseHandle(qt->process);
Z_Free(qt);
break; //be lazy.
}
if (WaitForSingleObject(qt->process, 0) == WAIT_TIMEOUT)
{
if ((ret=GetFileSize(qt->pipeout, NULL)))
{ {
if (ret!=INVALID_FILE_SIZE) if ((ret=GetFileSize(qt->pipeout, NULL)))
{ {
ReadFile(qt->pipeout, buffer, sizeof(buffer)-32, &ret, NULL); if (ret!=INVALID_FILE_SIZE)
buffer[ret] = '\0'; {
Con_PrintCon(qt->console, buffer); ReadFile(qt->pipeout, buffer, sizeof(buffer)-32, &ret, NULL);
buffer[ret] = '\0';
Con_PrintCon(qt->console, buffer, PFS_NOMARKUP);
}
} }
} }
else
{
Con_PrintCon(qt->console, "Process ended\n", PFS_NOMARKUP);
qt->running = false;
}
} }
else
n = qt->next;
if (!qt->running)
{ {
Con_PrintCon(qt->console, "Process ended\n"); if (!Con_IsActive(qt->console))
qt->running = false; QT_Kill(qt, true);
} }
qt = n;
} }
} }
void QT_KeyPress(void *user, int key) qboolean QT_KeyPress(console_t *con, unsigned int unicode, int key)
{ {
qbyte k[2]; qbyte k[2];
qterm_t *qt = user; qterm_t *qt = con->userdata;
DWORD send = key; //get around a gcc warning DWORD send = key; //get around a gcc warning
@ -341,16 +357,24 @@ void QT_KeyPress(void *user, int key)
{ {
// *k = '\r'; // *k = '\r';
// WriteFile(qt->pipein, k, 1, &key, NULL); // WriteFile(qt->pipein, k, 1, &key, NULL);
// Con_PrintCon(k, &qt->console); // Con_PrintCon(k, &qt->console, PFS_NOMARKUP);
*k = '\n'; *k = '\n';
} }
if (GetFileSize(qt->pipein, NULL)<512) // if (GetFileSize(qt->pipein, NULL)<512)
{ {
WriteFile(qt->pipein, k, 1, &send, NULL); WriteFile(qt->pipein, k, 1, &send, NULL);
Con_PrintCon(qt->console, k); Con_PrintCon(qt->console, k, PFS_NOMARKUP);
} }
} }
return; return true;
}
qboolean QT_Close(struct console_s *con, qboolean force)
{
qterm_t *qt = con->userdata;
QT_Kill(qt, false);
return true;
} }
void QT_Create(char *command) void QT_Create(char *command)
@ -419,8 +443,10 @@ void QT_Create(char *command)
qt->console = Con_Create("QTerm", 0); qt->console = Con_Create("QTerm", 0);
qt->console->redirect = QT_KeyPress; qt->console->redirect = QT_KeyPress;
Con_PrintCon(qt->console, "Started Process\n"); qt->console->close = QT_Close;
Con_SetVisible(qt->console); qt->console->userdata = qt;
Con_PrintCon(qt->console, "Started Process\n", PFS_NOMARKUP);
Con_SetActive(qt->console);
qt->next = qterms; qt->next = qterms;
qterms = activeqterm = qt; qterms = activeqterm = qt;

View file

@ -780,6 +780,22 @@ static int Stats_ExtractName(char **line)
return bm; return bm;
} }
qboolean Stats_ParsePickups(const char *line)
{
#ifndef NOLEGACY
//fixme: rework this to support custom strings, with custom pickup icons
if (!Q_strncmp(line, "You got the ", 12)) //weapons, ammo, keys, powerups
return true;
if (!Q_strncmp(line, "You got armor", 13)) //caaake...
return true;
if (!Q_strncmp(line, "You get ", 8)) //backpackets
return true;
if (!Q_strncmp(line, "You receive ", 12)) //%i health\n
return true;
#endif
return false;
}
qboolean Stats_ParsePrintLine(char *line) qboolean Stats_ParsePrintLine(char *line)
{ {
statmessage_t *ms; statmessage_t *ms;

File diff suppressed because it is too large Load diff

View file

@ -163,6 +163,7 @@ cvar_t r_stainfadetime = SCVAR ("r_stainfadetime", "1");
cvar_t r_stains = CVARFC("r_stains", IFMINIMAL("0","0.75"), cvar_t r_stains = CVARFC("r_stains", IFMINIMAL("0","0.75"),
CVAR_ARCHIVE, CVAR_ARCHIVE,
Cvar_Limiter_ZeroToOne_Callback); Cvar_Limiter_ZeroToOne_Callback);
cvar_t r_renderscale = CVARD("r_renderscale", "1", "Provides a way to enable subsampling or super-sampling");
cvar_t r_fxaa = CVARD("r_fxaa", "0", "Runs a post-procesing pass to strip the jaggies."); cvar_t r_fxaa = CVARD("r_fxaa", "0", "Runs a post-procesing pass to strip the jaggies.");
cvar_t r_postprocshader = CVARD("r_postprocshader", "", "Specifies a custom shader to use as a post-processing shader"); cvar_t r_postprocshader = CVARD("r_postprocshader", "", "Specifies a custom shader to use as a post-processing shader");
cvar_t r_wallcolour = CVARAF ("r_wallcolour", "128 128 128", cvar_t r_wallcolour = CVARAF ("r_wallcolour", "128 128 128",
@ -425,8 +426,9 @@ cvar_t r_fog_exp2 = CVARD ("r_fog_exp2", "1", "Expresses how fog fades wit
#ifdef VKQUAKE #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_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", "1", "Execute submits+presents on a thread dedicated to executing them. This may be a significant speedup on certain drivers."); 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_debug = CVARD ("vk_debug", "0", "Register a debug handler to display driver/layer messages. 2 enables the standard validation layers.");
cvar_t vk_loadglsl = 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 errors). Don't forget to do a vid_restart after.");
#endif #endif
extern cvar_t gl_dither; extern cvar_t gl_dither;
@ -461,9 +463,6 @@ void GLRenderer_Init(void)
Cvar_Register (&gl_finish, GLRENDEREROPTIONS); Cvar_Register (&gl_finish, GLRENDEREROPTIONS);
Cvar_Register (&gl_lateswap, GLRENDEREROPTIONS); Cvar_Register (&gl_lateswap, GLRENDEREROPTIONS);
Cvar_Register (&gl_lerpimages, GLRENDEREROPTIONS); Cvar_Register (&gl_lerpimages, GLRENDEREROPTIONS);
Cvar_Register (&r_postprocshader, GLRENDEREROPTIONS);
Cvar_Register (&r_fxaa, GLRENDEREROPTIONS);
Cvar_Register (&r_renderscale, GLRENDEREROPTIONS);
Cvar_Register (&dpcompat_psa_ungroup, GLRENDEREROPTIONS); Cvar_Register (&dpcompat_psa_ungroup, GLRENDEREROPTIONS);
Cvar_Register (&r_lerpmuzzlehack, GLRENDEREROPTIONS); Cvar_Register (&r_lerpmuzzlehack, GLRENDEREROPTIONS);
@ -742,6 +741,9 @@ void Renderer_Init(void)
Cvar_Register (&r_wireframe, GRAPHICALNICETIES); Cvar_Register (&r_wireframe, GRAPHICALNICETIES);
Cvar_Register (&r_wireframe_smooth, GRAPHICALNICETIES); Cvar_Register (&r_wireframe_smooth, GRAPHICALNICETIES);
Cvar_Register (&r_refract_fbo, GRAPHICALNICETIES); Cvar_Register (&r_refract_fbo, GRAPHICALNICETIES);
Cvar_Register (&r_postprocshader, GRAPHICALNICETIES);
Cvar_Register (&r_fxaa, GRAPHICALNICETIES);
Cvar_Register (&r_renderscale, GRAPHICALNICETIES);
Cvar_Register (&r_stereo_separation, GRAPHICALNICETIES); Cvar_Register (&r_stereo_separation, GRAPHICALNICETIES);
Cvar_Register (&r_stereo_convergence, GRAPHICALNICETIES); Cvar_Register (&r_stereo_convergence, GRAPHICALNICETIES);
Cvar_Register (&r_stereo_method, GRAPHICALNICETIES); Cvar_Register (&r_stereo_method, GRAPHICALNICETIES);
@ -855,6 +857,7 @@ void Renderer_Init(void)
Cvar_Register (&vk_stagingbuffers, VKRENDEREROPTIONS); Cvar_Register (&vk_stagingbuffers, VKRENDEREROPTIONS);
Cvar_Register (&vk_submissionthread, VKRENDEREROPTIONS); Cvar_Register (&vk_submissionthread, VKRENDEREROPTIONS);
Cvar_Register (&vk_debug, VKRENDEREROPTIONS); Cvar_Register (&vk_debug, VKRENDEREROPTIONS);
Cvar_Register (&vk_loadglsl, VKRENDEREROPTIONS);
#endif #endif
// misc // misc

View file

@ -311,7 +311,7 @@ static cvar_t s_al_debug = CVAR("s_al_debug", "0");
static cvar_t s_al_use_reverb = CVAR("s_al_use_reverb", "1"); static cvar_t s_al_use_reverb = CVAR("s_al_use_reverb", "1");
static cvar_t s_al_max_distance = CVARFC("s_al_max_distance", "1000",0,OnChangeALSettings); static cvar_t s_al_max_distance = CVARFC("s_al_max_distance", "1000",0,OnChangeALSettings);
static cvar_t s_al_speedofsound = CVARFC("s_al_speedofsound", "343.3",0,OnChangeALSettings); static cvar_t s_al_speedofsound = CVARFC("s_al_speedofsound", "343.3",0,OnChangeALSettings);
static cvar_t s_al_dopplerfactor = CVARFC("s_al_dopplerfactor", "3.0",0,OnChangeALSettings); static cvar_t s_al_dopplerfactor = CVARFC("s_al_dopplerfactor", "1.0",0,OnChangeALSettings);
static cvar_t s_al_distancemodel = CVARFC("s_al_distancemodel", "2",0,OnChangeALSettings); static cvar_t s_al_distancemodel = CVARFC("s_al_distancemodel", "2",0,OnChangeALSettings);
static cvar_t s_al_rolloff_factor = CVAR("s_al_rolloff_factor", "1"); static cvar_t s_al_rolloff_factor = CVAR("s_al_rolloff_factor", "1");
static cvar_t s_al_reference_distance = CVAR("s_al_reference_distance", "120"); static cvar_t s_al_reference_distance = CVAR("s_al_reference_distance", "120");
@ -504,7 +504,13 @@ static void OpenAL_ListenerUpdate(soundcardinfo_t *sc, int entnum, vec3_t origin
{ {
oalinfo_t *oali = sc->handle; oalinfo_t *oali = sc->handle;
VectorScale(velocity, (snd_doppler.value?snd_doppler.value:s_al_velocityscale.value)/35.0, oali->ListenVel); if (snd_doppler.modified)
{
snd_doppler.modified = false;
OnChangeALSettings(NULL,NULL);
}
VectorScale(velocity, s_al_velocityscale.value/35.0, oali->ListenVel);
VectorCopy(origin, oali->ListenPos); VectorCopy(origin, oali->ListenPos);
oali->ListenEnt = entnum; oali->ListenEnt = entnum;
@ -994,7 +1000,7 @@ static void QDECL OnChangeALSettings (cvar_t *var, char *value)
palSpeedOfSound(s_al_speedofsound.value); palSpeedOfSound(s_al_speedofsound.value);
if (palDopplerFactor) if (palDopplerFactor)
palDopplerFactor(s_al_dopplerfactor.value); palDopplerFactor(s_al_dopplerfactor.value * snd_doppler.value);
if (palDistanceModel) if (palDistanceModel)
{ {

View file

@ -120,7 +120,7 @@ cvar_t snd_doppler_min = CVARAFD( "s_doppler_min", "0.5",
"snd_doppler_min", CVAR_ARCHIVE, "snd_doppler_min", CVAR_ARCHIVE,
"Slowest allowed doppler scale."); "Slowest allowed doppler scale.");
cvar_t snd_doppler_max = CVARAFD( "s_doppler_max", "2", cvar_t snd_doppler_max = CVARAFD( "s_doppler_max", "2",
"snd_doppler", CVAR_ARCHIVE, "snd_doppler_max", CVAR_ARCHIVE,
"Highest allowed doppler scale, to avoid things getting too weird."); "Highest allowed doppler scale, to avoid things getting too weird.");
cvar_t snd_playbackrate = CVARFD( "snd_playbackrate", "1", CVAR_CHEAT, "Debugging cvar that changes the playback rate of all new sounds."); cvar_t snd_playbackrate = CVARFD( "snd_playbackrate", "1", CVAR_CHEAT, "Debugging cvar that changes the playback rate of all new sounds.");

View file

@ -76,10 +76,10 @@ typedef struct
qboolean isminimized; //can omit rendering as it won't be seen anyway. qboolean isminimized; //can omit rendering as it won't be seen anyway.
int fullbright; // index of first fullbright color int fullbright; // index of first fullbright color
unsigned fbvwidth; /*virtual 2d width*/ unsigned fbvwidth; /*virtual 2d width of the current framebuffer image*/
unsigned fbvheight; /*virtual 2d height*/ unsigned fbvheight; /*virtual 2d height*/
unsigned fbpwidth; /*virtual 2d width*/ unsigned fbpwidth; /*physical 2d width of the current framebuffer image*/
unsigned fbpheight; /*virtual 2d height*/ unsigned fbpheight; /*physical 2d height*/
struct image_s *framebuffer; /*the framebuffer fbo (set by democapture)*/ struct image_s *framebuffer; /*the framebuffer fbo (set by democapture)*/
unsigned width; /*virtual 2d screen width*/ unsigned width; /*virtual 2d screen width*/

View file

@ -531,15 +531,13 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#elif defined(NACL) #elif defined(NACL)
#define PLATFORM "Nacl" #define PLATFORM "Nacl"
#elif defined(_WIN32_WCE) #elif defined(_WIN32_WCE)
#define PLATFORM "WinCE" #define PLATFORM "WinCE"
#define ARCH_DL_POSTFIX ".dll" #define ARCH_DL_POSTFIX ".dll"
#elif defined(_WIN32) #elif defined(_WIN32)
#if defined(WINRT) #if defined(WINRT)
#define PLATFORM "WinRT" /*those poor poor souls. maybe just maybe I'll actually get the tools for a port, its just a shame that I won't be able to release said port*/ #define PLATFORM "WinRT" /*those poor poor souls. maybe just maybe I'll actually get the tools for a port, its just a shame that I won't be able to release said port*/
#elif defined(__amd64__)
#define PLATFORM "Win64"
#else #else
#define PLATFORM "Win32" #define PLATFORM "Win"
#endif #endif
#define ARCH_DL_POSTFIX ".dll" #define ARCH_DL_POSTFIX ".dll"
#elif defined(_WIN16) #elif defined(_WIN16)
@ -551,13 +549,9 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#elif defined(ANDROID) || defined(__ANDROID__) #elif defined(ANDROID) || defined(__ANDROID__)
#define PLATFORM "Android" /*technically also linux*/ #define PLATFORM "Android" /*technically also linux*/
#elif defined(__linux__) #elif defined(__linux__)
#if defined(__amd64__) #define PLATFORM "Linux"
#define PLATFORM "Linux64"
#else
#define PLATFORM "Linux"
#endif
#elif defined(__APPLE__) #elif defined(__APPLE__)
#include "TargetConditionals.h" #include "TargetConditionals.h"
#if TARGET_IPHONE_SIMULATOR #if TARGET_IPHONE_SIMULATOR
#define PLATFORM "iOSSim" #define PLATFORM "iOSSim"
#elif TARGET_OS_IPHONE #elif TARGET_OS_IPHONE
@ -602,6 +596,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#define ARCH_CPU_POSTFIX "x86" #define ARCH_CPU_POSTFIX "x86"
#elif defined(__powerpc__) || defined(__ppc__) #elif defined(__powerpc__) || defined(__ppc__)
#define ARCH_CPU_POSTFIX "ppc" #define ARCH_CPU_POSTFIX "ppc"
#elif defined(__aarch64__)
#define ARCH_CPU_POSTFIX "arm64"
#elif defined(__arm__) #elif defined(__arm__)
#define ARCH_CPU_POSTFIX "arm" #define ARCH_CPU_POSTFIX "arm"
#else #else

View file

@ -82,6 +82,7 @@ anyway, the actual interface is the same. the old version might be slower, but w
#include <features.h> /* for glibc version */ #include <features.h> /* for glibc version */
#if defined(__GLIBC__) && (__GLIBC__ == 2) && (__GLIBC_MINOR__ >= 14) #if defined(__GLIBC__) && (__GLIBC__ == 2) && (__GLIBC_MINOR__ >= 14)
__asm__(".symver memcpy,memcpy@GLIBC_2.2.5"); __asm__(".symver memcpy,memcpy@GLIBC_2.2.5");
__asm__(".symver memmove,memmove@GLIBC_2.2.5");
#endif #endif
#endif #endif
/*end glibc workaround*/ /*end glibc workaround*/

View file

@ -247,7 +247,6 @@ void Con_SetActive (console_t *con);
qboolean Con_NameForNum(int num, char *buffer, int buffersize); qboolean Con_NameForNum(int num, char *buffer, int buffersize);
console_t *Con_FindConsole(const char *name); console_t *Con_FindConsole(const char *name);
console_t *Con_Create(const char *name, unsigned int flags); console_t *Con_Create(const char *name, unsigned int flags);
void Con_SetVisible (console_t *con);
void Con_PrintCon (console_t *con, const char *txt, unsigned int parseflags); void Con_PrintCon (console_t *con, const char *txt, unsigned int parseflags);
qboolean Con_InsertConChars (console_t *con, conline_t *line, int offset, conchar_t *c, int len); qboolean Con_InsertConChars (console_t *con, conline_t *line, int offset, conchar_t *c, int len);
conline_t *Con_ResizeLineBuffer(console_t *con, conline_t *old, unsigned int length); conline_t *Con_ResizeLineBuffer(console_t *con, conline_t *old, unsigned int length);

View file

@ -2907,7 +2907,7 @@ const gamemode_info_t gamemode_info[] = {
//for quake, we also allow extracting all files from paks. some people think it loads faster that way or something. //for quake, we also allow extracting all files from paks. some people think it loads faster that way or something.
//cmdline switch exename protocol name(dpmaster) identifying file exec dir1 dir2 dir3 dir(fte) full name //cmdline switch exename protocol name(dpmaster) identifying file exec dir1 dir2 dir3 dir(fte) full name
{"-quake", "q1", MASTER_PREFIX"Quake", {"id1/pak0.pak", "id1/quake.rc"},QCFG, {"id1", "qw", "*fte"}, "Quake", "https://fte.triptohell.info/downloadables.txt" /*,"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", MASTER_PREFIX"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"*/},
//quake's mission packs should not be favoured over the base game nor autodetected //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. //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 //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

View file

@ -43,7 +43,7 @@ extern ID3D11Device *pD3DDev11;
STDMETHOD_(SIZE_T, GetBufferSize)(THIS) PURE; STDMETHOD_(SIZE_T, GetBufferSize)(THIS) PURE;
}; };
#undef INTERFACE #undef INTERFACE
/*
#define D3D11_SHADER_VARIABLE_DESC void #define D3D11_SHADER_VARIABLE_DESC void
typedef unsigned int D3D_SHADER_INPUT_TYPE; typedef unsigned int D3D_SHADER_INPUT_TYPE;
typedef unsigned int D3D_RESOURCE_RETURN_TYPE; typedef unsigned int D3D_RESOURCE_RETURN_TYPE;
@ -101,16 +101,17 @@ extern ID3D11Device *pD3DDev11;
}; };
#define ID3D11ShaderReflection_GetVariableByName(r,v) r->lpVtbl->GetVariableByName(r,v) #define ID3D11ShaderReflection_GetVariableByName(r,v) r->lpVtbl->GetVariableByName(r,v)
#undef INTERFACE #undef INTERFACE
*/
#else #else
#include <d3d11shader.h> #include <d3d11shader.h>
#endif #endif
//const GUID IID_ID3D11ShaderReflection = {0x8d536ca1, 0x0cca, 0x4956, {0xa8, 0x37, 0x78, 0x69, 0x63, 0x75, 0x55, 0x84}}; //const GUID IID_ID3D11ShaderReflection = {0x8d536ca1, 0x0cca, 0x4956, {0xa8, 0x37, 0x78, 0x69, 0x63, 0x75, 0x55, 0x84}};
const GUID IID_ID3D11ShaderReflection = {0x0a233719, 0x3960, 0x4578, {0x9d, 0x7c, 0x20, 0x3b, 0x8b, 0x1d, 0x9c, 0xc1}}; //const GUID IID_ID3D11ShaderReflection = {0x0a233719, 0x3960, 0x4578, {0x9d, 0x7c, 0x20, 0x3b, 0x8b, 0x1d, 0x9c, 0xc1}};
#define ID3DBlob_GetBufferPointer(b) b->lpVtbl->GetBufferPointer(b) #define ID3DBlob_GetBufferPointer(b) b->lpVtbl->GetBufferPointer(b)
#define ID3DBlob_Release(b) b->lpVtbl->Release(b) #define ID3DBlob_Release(b) b->lpVtbl->Release(b)
#define ID3DBlob_GetBufferSize(b) b->lpVtbl->GetBufferSize(b) #define ID3DBlob_GetBufferSize(b) b->lpVtbl->GetBufferSize(b)
#define ID3D11ShaderReflection_Release IUnknown_Release //#define ID3D11ShaderReflection_Release IUnknown_Release
HRESULT (WINAPI *pD3DCompile) ( HRESULT (WINAPI *pD3DCompile) (
LPCVOID pSrcData, LPCVOID pSrcData,
@ -126,13 +127,6 @@ HRESULT (WINAPI *pD3DCompile) (
ID3DBlob **ppErrorMsgs ID3DBlob **ppErrorMsgs
); );
HRESULT (WINAPI *pD3DReflect)(
LPCVOID pSrcData,
SIZE_T SrcDataSize,
REFIID pInterface,
void **ppReflector
);
static dllhandle_t *shaderlib; static dllhandle_t *shaderlib;
@ -148,7 +142,7 @@ HRESULT STDMETHODCALLTYPE d3dinclude_Open(ID3DInclude *this, D3D_INCLUDE_TYPE In
{ {
if (IncludeType == D3D_INCLUDE_SYSTEM) if (IncludeType == D3D_INCLUDE_SYSTEM)
{ {
if (!strcmp(pFileName, "ftedefs.h")) if (!strcmp(pFileName, "ftedefs.h") || !strcmp(pFileName, "sys/defs.h"))
{ {
static const char *defstruct = static const char *defstruct =
"cbuffer ftemodeldefs : register(b0)\n" "cbuffer ftemodeldefs : register(b0)\n"
@ -189,6 +183,7 @@ HRESULT STDMETHODCALLTYPE d3dinclude_Open(ID3DInclude *this, D3D_INCLUDE_TYPE In
*pBytes = strlen(*ppData); *pBytes = strlen(*ppData);
return S_OK; return S_OK;
} }
//fog
} }
else else
{ {
@ -406,31 +401,6 @@ static qboolean D3D11Shader_LoadBlob(program_t *prog, const char *name, unsigned
qboolean D3D11Shader_CreateProgram (program_t *prog, const char *name, unsigned int permu, int ver, const char **precompilerconstants, const char *vert, const char *hull, const char *domain, const char *geom, const char *frag, qboolean silenterrors, vfsfile_t *blobfile) qboolean D3D11Shader_CreateProgram (program_t *prog, const char *name, unsigned int permu, int ver, const char **precompilerconstants, const char *vert, const char *hull, const char *domain, const char *geom, const char *frag, qboolean silenterrors, vfsfile_t *blobfile)
{ {
static const char *defaultsamplers[] =
{
"s_shadowmap",
"s_projectionmap",
"s_diffuse",
"s_normalmap",
"s_specular",
"s_upper",
"s_lower",
"s_fullbright",
"s_paletted",
"s_reflectcube",
"s_reflectmask",
"s_lightmap",
"s_deluxmap"
#if MAXRLIGHTMAPS > 1
,"s_lightmap1"
,"s_lightmap2"
,"s_lightmap3"
,"s_deluxmap1"
,"s_deluxmap2"
,"s_deluxmap3"
#endif
};
char *vsformat; char *vsformat;
char *hsformat = NULL; char *hsformat = NULL;
char *dsformat = NULL; char *dsformat = NULL;
@ -439,8 +409,8 @@ qboolean D3D11Shader_CreateProgram (program_t *prog, const char *name, unsigned
D3D_SHADER_MACRO defines[64]; D3D_SHADER_MACRO defines[64];
ID3DBlob *vcode = NULL, *hcode = NULL, *dcode = NULL, *gcode = NULL, *fcode = NULL, *errors = NULL; ID3DBlob *vcode = NULL, *hcode = NULL, *dcode = NULL, *gcode = NULL, *fcode = NULL, *errors = NULL;
qboolean success = false; qboolean success = false;
ID3D11ShaderReflection *freflect; // ID3D11ShaderReflection *freflect;
int i; // int i;
if (d3dfeaturelevel >= D3D_FEATURE_LEVEL_11_0) //and 11.1 if (d3dfeaturelevel >= D3D_FEATURE_LEVEL_11_0) //and 11.1
{ {
@ -653,7 +623,7 @@ qboolean D3D11Shader_CreateProgram (program_t *prog, const char *name, unsigned
} }
if (fcode) /* if (fcode)
{ {
pD3DReflect(ID3DBlob_GetBufferPointer(fcode), ID3DBlob_GetBufferSize(fcode), &IID_ID3D11ShaderReflection, (void**)&freflect); pD3DReflect(ID3DBlob_GetBufferPointer(fcode), ID3DBlob_GetBufferSize(fcode), &IID_ID3D11ShaderReflection, (void**)&freflect);
if (freflect) if (freflect)
@ -667,11 +637,11 @@ qboolean D3D11Shader_CreateProgram (program_t *prog, const char *name, unsigned
} }
tmu = prog->numsamplers; tmu = prog->numsamplers;
for (i = 0; i < sizeof(defaultsamplers)/sizeof(defaultsamplers[0]); i++) for (i = 0; sh_defaultsamplers[i]; i++)
{ {
// if (prog->defaulttextures & (1u<<i)) // if (prog->defaulttextures & (1u<<i))
// continue; // continue;
if (SUCCEEDED(freflect->lpVtbl->GetResourceBindingDescByName(freflect, va("t%s", defaultsamplers[i]+1), &bdesc))) if (SUCCEEDED(freflect->lpVtbl->GetResourceBindingDescByName(freflect, va("t%s", sh_defaultsamplers[i]+1), &bdesc)))
prog->defaulttextures |= (1u<<i); prog->defaulttextures |= (1u<<i);
if (!(prog->defaulttextures & (1u<<i))) if (!(prog->defaulttextures & (1u<<i)))
continue; continue;
@ -682,7 +652,7 @@ qboolean D3D11Shader_CreateProgram (program_t *prog, const char *name, unsigned
else else
Con_Printf("%s: D3DReflect failed, unable to get reflection info\n", name); Con_Printf("%s: D3DReflect failed, unable to get reflection info\n", name);
} }
*/
if (vcode) if (vcode)
ID3DBlob_Release(vcode); ID3DBlob_Release(vcode);
if (hcode) if (hcode)
@ -704,13 +674,11 @@ qboolean D3D11Shader_Init(unsigned int flevel)
dllfunction_t funcsold[] = dllfunction_t funcsold[] =
{ {
{(void**)&pD3DCompile, "D3DCompileFromMemory"}, {(void**)&pD3DCompile, "D3DCompileFromMemory"},
{(void**)&pD3DReflect, "D3DReflect"},
{NULL,NULL} {NULL,NULL}
}; };
dllfunction_t funcsnew[] = dllfunction_t funcsnew[] =
{ {
{(void**)&pD3DCompile, "D3DCompile"}, {(void**)&pD3DCompile, "D3DCompile"},
{(void**)&pD3DReflect, "D3DReflect"},
{NULL,NULL} {NULL,NULL}
}; };

View file

@ -260,30 +260,6 @@ static void D3D9Shader_ProgAutoFields(program_t *prog, const char *progname, cva
unsigned int i, p; unsigned int i, p;
int uniformloc; int uniformloc;
static const char *defaultsamplers[] =
{
"s_shadowmap",
"s_projectionmap",
"s_diffuse",
"s_normalmap",
"s_specular",
"s_upper",
"s_lower",
"s_fullbright",
"s_paletted",
"s_reflectcube",
"s_reflectmask",
"s_lightmap",
"s_deluxmap"
#if MAXRLIGHTMAPS > 1
,"s_lightmap1"
,"s_lightmap2"
,"s_lightmap3"
,"s_deluxmap1"
,"s_deluxmap2"
,"s_deluxmap3"
#endif
};
#define ALTLIGHTMAPSAMP 13 #define ALTLIGHTMAPSAMP 13
#define ALTDELUXMAPSAMP 16 #define ALTDELUXMAPSAMP 16
@ -364,12 +340,12 @@ static void D3D9Shader_ProgAutoFields(program_t *prog, const char *progname, cva
} }
} }
for (i = 0; i < sizeof(defaultsamplers)/sizeof(defaultsamplers[0]); i++) for (i = 0; sh_defaultsamplers[i]; i++)
{ {
//figure out which ones are needed. //figure out which ones are needed.
if (prog->defaulttextures & (1u<<i)) if (prog->defaulttextures & (1u<<i))
continue; //don't spam continue; //don't spam
uniformloc = D3D9Shader_FindUniform(&pp->h, 2, defaultsamplers[i]); uniformloc = D3D9Shader_FindUniform(&pp->h, 2, sh_defaultsamplers[i]);
if (uniformloc != -1) if (uniformloc != -1)
prog->defaulttextures |= (1u<<i); prog->defaulttextures |= (1u<<i);
} }
@ -390,11 +366,11 @@ static void D3D9Shader_ProgAutoFields(program_t *prog, const char *progname, cva
if (!prog->permu[p].h.loaded) if (!prog->permu[p].h.loaded)
continue; continue;
sampnum = prog->numsamplers; sampnum = prog->numsamplers;
for (i = 0; i < sizeof(defaultsamplers)/sizeof(defaultsamplers[0]); i++) for (i = 0; sh_defaultsamplers[i]; i++)
{ {
if (prog->defaulttextures & (1u<<i)) if (prog->defaulttextures & (1u<<i))
{ {
uniformloc = D3D9Shader_FindUniform(&prog->permu[p].h, 2, defaultsamplers[i]); uniformloc = D3D9Shader_FindUniform(&prog->permu[p].h, 2, sh_defaultsamplers[i]);
if (uniformloc != -1) if (uniformloc != -1)
{ {
int v[4] = {sampnum}; int v[4] = {sampnum};

View file

@ -1237,6 +1237,8 @@ static qboolean (D3D11_SCR_UpdateScreen) (void)
scr_drawloading = true; scr_drawloading = true;
SCR_DrawLoading (true); SCR_DrawLoading (true);
scr_drawloading = false; scr_drawloading = false;
if (R2D_Flush)
R2D_Flush();
// IDirect3DDevice9_EndScene(pD3DDev9); // IDirect3DDevice9_EndScene(pD3DDev9);
D3D11_PresentOrCrash(); D3D11_PresentOrCrash();
return true; return true;

View file

@ -26,10 +26,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "httpserver", "..\http\https
EndProject EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ftequake", "ftequake.vcproj", "{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}" Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ftequake", "ftequake.vcproj", "{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}"
ProjectSection(ProjectDependencies) = postProject ProjectSection(ProjectDependencies) = postProject
{E6CDA919-628B-45BF-A5DB-FB55179D6443} = {E6CDA919-628B-45BF-A5DB-FB55179D6443}
{9767E236-8454-44E9-8999-CD5BDAFBE9BA} = {9767E236-8454-44E9-8999-CD5BDAFBE9BA}
{0018E098-B12A-4E4D-9B22-6772DA287080} = {0018E098-B12A-4E4D-9B22-6772DA287080} {0018E098-B12A-4E4D-9B22-6772DA287080} = {0018E098-B12A-4E4D-9B22-6772DA287080}
{6ABD62A3-C5A0-43E8-BA4F-84606057774F} = {6ABD62A3-C5A0-43E8-BA4F-84606057774F}
EndProjectSection EndProjectSection
EndProject EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "dedserver", "dedserver.vcproj", "{482A886A-5755-4DAE-AD5F-D7CD4A990F9E}" Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "dedserver", "dedserver.vcproj", "{482A886A-5755-4DAE-AD5F-D7CD4A990F9E}"
@ -43,8 +40,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "irc", "..\..\plugins\irc\ir
EndProject EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "private", "..\..\plugins\private\private.vcproj", "{74542CA7-48C1-4664-9007-66F751131EA3}" Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "private", "..\..\plugins\private\private.vcproj", "{74542CA7-48C1-4664-9007-66F751131EA3}"
ProjectSection(ProjectDependencies) = postProject ProjectSection(ProjectDependencies) = postProject
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364} = {88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}
{72269FEE-293D-40BC-A7AE-E429F4496869} = {72269FEE-293D-40BC-A7AE-E429F4496869} {72269FEE-293D-40BC-A7AE-E429F4496869} = {72269FEE-293D-40BC-A7AE-E429F4496869}
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364} = {88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}
EndProjectSection EndProjectSection
EndProject EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "targets", "targets", "{EB5DFF7C-C0A8-426C-BC66-524162350F1B}" Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "targets", "targets", "{EB5DFF7C-C0A8-426C-BC66-524162350F1B}"

View file

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

View file

@ -53,7 +53,6 @@ extern cvar_t gl_part_flame;
extern cvar_t r_bloom; extern cvar_t r_bloom;
extern cvar_t r_wireframe_smooth; extern cvar_t r_wireframe_smooth;
cvar_t r_renderscale = CVARD("r_renderscale", "1", "Provides a way to enable subsampling or super-sampling");
cvar_t gl_affinemodels = SCVAR("gl_affinemodels","0"); cvar_t gl_affinemodels = SCVAR("gl_affinemodels","0");
cvar_t gl_finish = SCVAR("gl_finish","0"); cvar_t gl_finish = SCVAR("gl_finish","0");
cvar_t gl_dither = SCVAR("gl_dither", "1"); cvar_t gl_dither = SCVAR("gl_dither", "1");

View file

@ -1028,6 +1028,32 @@ static qboolean Shader_ParseProgramCvar(char *script, cvar_t **cvarrefs, char **
} }
#endif #endif
const char *sh_defaultsamplers[] =
{
"s_shadowmap",
"s_projectionmap",
"s_diffuse",
"s_normalmap",
"s_specular",
"s_upper",
"s_lower",
"s_fullbright",
"s_paletted",
"s_reflectcube",
"s_reflectmask",
"s_lightmap",
"s_deluxmap",
#if MAXRLIGHTMAPS > 1
"s_lightmap1",
"s_lightmap2",
"s_lightmap3",
"s_deluxmap1",
"s_deluxmap2",
"s_deluxmap3",
#endif
NULL
};
/*program text is already loaded, this function parses the 'header' of it to see which permutations it provides, and how many times we need to recompile it*/ /*program text is already loaded, this function parses the 'header' of it to see which permutations it provides, and how many times we need to recompile it*/
static qboolean Shader_LoadPermutations(char *name, program_t *prog, char *script, int qrtype, int ver, char *blobfilename) static qboolean Shader_LoadPermutations(char *name, program_t *prog, char *script, int qrtype, int ver, char *blobfilename)
{ {
@ -1067,14 +1093,18 @@ static qboolean Shader_LoadPermutations(char *name, program_t *prog, char *scrip
extern cvar_t gl_specular; extern cvar_t gl_specular;
#endif #endif
#ifdef VKQUAKE
if (qrenderer == QR_VULKAN && (qrtype == QR_VULKAN || qrtype == QR_OPENGL))
{
if (qrtype == QR_VULKAN && VK_LoadBlob(prog, script, name))
return true;
}
else
#endif
if (qrenderer != qrtype) if (qrenderer != qrtype)
{ {
return false; return false;
} }
#ifdef VKQUAKE
if (qrenderer == QR_VULKAN)
return VK_LoadBlob(prog, script, name);
#endif
#if defined(GLQUAKE) || defined(D3DQUAKE) #if defined(GLQUAKE) || defined(D3DQUAKE)
ver = 0; ver = 0;
@ -1106,6 +1136,37 @@ static qboolean Shader_LoadPermutations(char *name, program_t *prog, char *scrip
tess = true; tess = true;
script += 6; script += 6;
} }
else if (!strncmp(script, "!!samps", 7))
{
script += 7;
while (*script != '\n' && *script != '\r')
{
int i;
char *start;
while (*script == ' ' || *script == '\t')
script++;
start = script;
while (*script != ' ' && *script != '\t' && *script != '\r' && *script != '\n')
script++;
for (i = 0; sh_defaultsamplers[i]; i++)
{
if (!strncmp(start, sh_defaultsamplers[i]+2, script-start) && sh_defaultsamplers[i][2+script-start] == 0)
{
prog->defaulttextures |= (1u<<i);
break;
}
}
if (!sh_defaultsamplers[i])
{
i = atoi(start);
if (i)
prog->numsamplers = i;
else
Con_Printf("Unknown texture name in %s\n", name);
}
}
}
else if (!strncmp(script, "!!cvardf", 8)) else if (!strncmp(script, "!!cvardf", 8))
{ {
script += 8; script += 8;
@ -1593,12 +1654,12 @@ static void Shader_LoadGeneric(sgeneric_t *g, int qrtype)
*h = '\0'; *h = '\0';
if (strchr(basicname, '/') || strchr(basicname, '.')) if (strchr(basicname, '/') || strchr(basicname, '.'))
{ { //explicit path
FS_LoadFile(basicname, &file); FS_LoadFile(basicname, &file);
*blobname = 0; *blobname = 0;
} }
else else
{ { //renderer-specific files
if (sh_config.progpath) if (sh_config.progpath)
{ {
Q_snprintfz(blobname, sizeof(blobname), sh_config.progpath, basicname); Q_snprintfz(blobname, sizeof(blobname), sh_config.progpath, basicname);
@ -4867,7 +4928,7 @@ void Shader_DefaultBSPLM(const char *shortname, shader_t *s, const void *args)
} }
} }
#endif #endif
if (!builtin && ((sh_config.progs_supported && qrenderer == QR_OPENGL) || sh_config.progs_required || qrenderer == QR_VULKAN)) if (!builtin && ((sh_config.progs_supported && qrenderer == QR_OPENGL) || sh_config.progs_required))
{ {
builtin = ( builtin = (
"{\n" "{\n"

View file

@ -1237,6 +1237,7 @@ static const char *glsl_hdrs[] =
"attribute vec4 v_colour4;\n" "attribute vec4 v_colour4;\n"
#endif #endif
"#endif\n" "#endif\n"
#ifndef NOLEGACY
"uniform sampler2D s_shadowmap;\n" "uniform sampler2D s_shadowmap;\n"
"uniform samplerCube s_projectionmap;\n" "uniform samplerCube s_projectionmap;\n"
"uniform sampler2D s_diffuse;\n" "uniform sampler2D s_diffuse;\n"
@ -1259,6 +1260,7 @@ static const char *glsl_hdrs[] =
"uniform sampler2D s_deluxmap1;\n" "uniform sampler2D s_deluxmap1;\n"
"uniform sampler2D s_deluxmap2;\n" "uniform sampler2D s_deluxmap2;\n"
"uniform sampler2D s_deluxmap3;\n" "uniform sampler2D s_deluxmap3;\n"
#endif
#endif #endif
"#ifdef USEUBOS\n" "#ifdef USEUBOS\n"
@ -1822,7 +1824,7 @@ qboolean GLSlang_GenerateIncludes(int maxstrings, int *strings, const GLchar *pr
// glslang helper api function definitions // glslang helper api function definitions
// type should be GL_FRAGMENT_SHADER_ARB or GL_VERTEX_SHADER_ARB // type should be GL_FRAGMENT_SHADER_ARB or GL_VERTEX_SHADER_ARB
//doesn't check to see if it was okay. use FinishShader for that. //doesn't check to see if it was okay. use FinishShader for that.
static GLhandleARB GLSlang_CreateShader (const char *name, int ver, const char **precompilerconstants, const char *shadersource, GLenum shadertype, qboolean silent) static GLhandleARB GLSlang_CreateShader (program_t *prog, const char *name, int ver, const char **precompilerconstants, const char *shadersource, GLenum shadertype, qboolean silent)
{ {
GLhandleARB shader; GLhandleARB shader;
int i; int i;
@ -1888,6 +1890,61 @@ static GLhandleARB GLSlang_CreateShader (const char *name, int ver, const char *
length[strings] = strlen(prstrings[strings]); length[strings] = strlen(prstrings[strings]);
strings++; strings++;
} }
if (prog)
{ //for compat with vulkan, that injects samplers...
const char *numberedsamplernames[] =
{
"uniform sampler2D s_t0;\n",
"uniform sampler2D s_t1;\n",
"uniform sampler2D s_t2;\n",
"uniform sampler2D s_t3;\n",
"uniform sampler2D s_t4;\n",
"uniform sampler2D s_t5;\n",
"uniform sampler2D s_t6;\n",
"uniform sampler2D s_t7;\n",
};
#ifdef NOLEGACY
const char *defaultsamplernames[] =
{
"uniform sampler2D s_shadowmap;\n",
"uniform samplerCube s_projectionmap;\n",
"uniform sampler2D s_diffuse;\n",
"uniform sampler2D s_normalmap;\n",
"uniform sampler2D s_specular;\n",
"uniform sampler2D s_upper;\n",
"uniform sampler2D s_lower;\n",
"uniform sampler2D s_fullbright;\n",
"uniform sampler2D s_paletted;\n",
"uniform samplerCube s_reflectcube;\n",
"uniform sampler2D s_reflectmask;\n",
"uniform sampler2D s_lightmap;\n#define s_lightmap0 s_lightmap\n",
"uniform sampler2D s_deluxmap;\n#define s_deluxmap0 s_deluxmap\n",
"uniform sampler2D s_lightmap1;\n",
"uniform sampler2D s_lightmap2;\n",
"uniform sampler2D s_lightmap3;\n",
"uniform sampler2D s_deluxmap1;\n",
"uniform sampler2D s_deluxmap2;\n",
"uniform sampler2D s_deluxmap3;\n",
};
for (i = 0; i < countof(defaultsamplernames); i++)
{
if (prog->defaulttextures & (1u<<i))
{
prstrings[strings] = defaultsamplernames[i];
length[strings] = strlen(prstrings[strings]);
strings++;
}
}
#endif
for (i = 0; i < prog->numsamplers && i < countof(numberedsamplernames); i++)
{
prstrings[strings] = numberedsamplernames[i];
length[strings] = strlen(prstrings[strings]);
strings++;
}
}
break; break;
case GL_GEOMETRY_SHADER_ARB: case GL_GEOMETRY_SHADER_ARB:
prstrings[strings] = "#define GEOMETRY_SHADER\n"; prstrings[strings] = "#define GEOMETRY_SHADER\n";
@ -2199,7 +2256,7 @@ qboolean GLSlang_ValidateProgram(union programhandle_u *h, const char *name, qbo
return true; return true;
} }
union programhandle_u GLSlang_CreateProgram(const char *name, int ver, const char **precompilerconstants, const char *vert, const char *cont, const char *eval, const char *geom, const char *frag, qboolean silent, vfsfile_t *blobfile) union programhandle_u GLSlang_CreateProgram(program_t *prog, const char *name, int ver, const char **precompilerconstants, const char *vert, const char *cont, const char *eval, const char *geom, const char *frag, qboolean silent, vfsfile_t *blobfile)
{ {
union programhandle_u ret; union programhandle_u ret;
GLhandleARB vs; GLhandleARB vs;
@ -2227,11 +2284,11 @@ union programhandle_u GLSlang_CreateProgram(const char *name, int ver, const cha
if (!precompilerconstants) if (!precompilerconstants)
precompilerconstants = &nullconstants; precompilerconstants = &nullconstants;
fs = GLSlang_CreateShader(name, ver, precompilerconstants, frag, GL_FRAGMENT_SHADER_ARB, silent); fs = GLSlang_CreateShader(prog, name, ver, precompilerconstants, frag, GL_FRAGMENT_SHADER_ARB, silent);
gs = GLSlang_CreateShader(name, ver, precompilerconstants, geom, GL_GEOMETRY_SHADER_ARB, silent); gs = GLSlang_CreateShader(prog, name, ver, precompilerconstants, geom, GL_GEOMETRY_SHADER_ARB, silent);
vs = GLSlang_CreateShader(name, ver, precompilerconstants, vert, GL_VERTEX_SHADER_ARB, silent); vs = GLSlang_CreateShader(prog, name, ver, precompilerconstants, vert, GL_VERTEX_SHADER_ARB, silent);
cs = GLSlang_CreateShader(name, ver, precompilerconstants, cont, GL_TESS_CONTROL_SHADER_ARB, silent); cs = GLSlang_CreateShader(prog, name, ver, precompilerconstants, cont, GL_TESS_CONTROL_SHADER_ARB, silent);
es = GLSlang_CreateShader(name, ver, precompilerconstants, eval, GL_TESS_EVALUATION_SHADER_ARB, silent); es = GLSlang_CreateShader(prog, name, ver, precompilerconstants, eval, GL_TESS_EVALUATION_SHADER_ARB, silent);
fs = GLSlang_FinishShader(fs, name, GL_FRAGMENT_SHADER_ARB, silent); fs = GLSlang_FinishShader(fs, name, GL_FRAGMENT_SHADER_ARB, silent);
gs = GLSlang_FinishShader(gs, name, GL_GEOMETRY_SHADER_ARB, silent); gs = GLSlang_FinishShader(gs, name, GL_GEOMETRY_SHADER_ARB, silent);
@ -2307,7 +2364,7 @@ qboolean GLSlang_CreateProgramPermu(program_t *prog, const char *name, unsigned
return false; //can happen in gles2 return false; //can happen in gles2
#endif #endif
prog->permu[permu].h = GLSlang_CreateProgram(name, ver, precompilerconstants, vert, tcs, tes, geom, frag, noerrors, blobfile); prog->permu[permu].h = GLSlang_CreateProgram(prog, name, ver, precompilerconstants, vert, tcs, tes, geom, frag, noerrors, blobfile);
if (prog->permu[permu].h.glsl.handle) if (prog->permu[permu].h.glsl.handle)
return true; return true;
return false; return false;
@ -2369,30 +2426,6 @@ static void GLSlang_DeleteProg(program_t *prog)
static void GLSlang_ProgAutoFields(program_t *prog, const char *progname, cvar_t **cvars, char **cvarnames, int *cvartypes) static void GLSlang_ProgAutoFields(program_t *prog, const char *progname, cvar_t **cvars, char **cvarnames, int *cvartypes)
{ {
static const char *defaultsamplers[] =
{
"s_shadowmap",
"s_projectionmap",
"s_diffuse",
"s_normalmap",
"s_specular",
"s_upper",
"s_lower",
"s_fullbright",
"s_paletted",
"s_reflectcube",
"s_reflectmask",
"s_lightmap",
"s_deluxmap"
#if MAXRLIGHTMAPS > 1
,"s_lightmap1"
,"s_lightmap2"
,"s_lightmap3"
,"s_deluxmap1"
,"s_deluxmap2"
,"s_deluxmap3"
#endif
};
#define ALTLIGHTMAPSAMP 13 #define ALTLIGHTMAPSAMP 13
#define ALTDELUXMAPSAMP 16 #define ALTDELUXMAPSAMP 16
@ -2485,12 +2518,12 @@ static void GLSlang_ProgAutoFields(program_t *prog, const char *progname, cvar_t
prog->numsamplers = i+1; prog->numsamplers = i+1;
} }
} }
for (i = 0; i < sizeof(defaultsamplers)/sizeof(defaultsamplers[0]); i++) for (i = 0; sh_defaultsamplers[i]; i++)
{ {
//figure out which ones are needed. //figure out which ones are needed.
if (prog->defaulttextures & (1u<<i)) if (prog->defaulttextures & (1u<<i))
continue; //don't spam continue; //don't spam
uniformloc = qglGetUniformLocationARB(pp->h.glsl.handle, defaultsamplers[i]); uniformloc = qglGetUniformLocationARB(pp->h.glsl.handle, sh_defaultsamplers[i]);
if (uniformloc != -1) if (uniformloc != -1)
prog->defaulttextures |= (1u<<i); prog->defaulttextures |= (1u<<i);
} }
@ -2512,11 +2545,11 @@ static void GLSlang_ProgAutoFields(program_t *prog, const char *progname, cvar_t
continue; continue;
sampnum = prog->numsamplers; sampnum = prog->numsamplers;
GLSlang_UseProgram(prog->permu[p].h.glsl.handle); GLSlang_UseProgram(prog->permu[p].h.glsl.handle);
for (i = 0; i < sizeof(defaultsamplers)/sizeof(defaultsamplers[0]); i++) for (i = 0; sh_defaultsamplers[i]; i++)
{ {
if (prog->defaulttextures & (1u<<i)) if (prog->defaulttextures & (1u<<i))
{ {
uniformloc = qglGetUniformLocationARB(prog->permu[p].h.glsl.handle, defaultsamplers[i]); uniformloc = qglGetUniformLocationARB(prog->permu[p].h.glsl.handle, sh_defaultsamplers[i]);
if (uniformloc != -1) if (uniformloc != -1)
qglUniform1iARB(uniformloc, sampnum); qglUniform1iARB(uniformloc, sampnum);
sampnum++; sampnum++;

View file

@ -1078,7 +1078,8 @@ extern void (APIENTRY *qglBindVertexArray)(GLuint vaoarray);
//glslang helper api //glslang helper api
union programhandle_u GLSlang_CreateProgram(const char *name, int ver, const char **precompilerconstants, const char *vert, const char *cont, const char *eval, const char *geom, const char *frag, qboolean silent, vfsfile_t *blobfile); struct programshared_s;
union programhandle_u GLSlang_CreateProgram(struct programshared_s *prog, const char *name, int ver, const char **precompilerconstants, const char *vert, const char *cont, const char *eval, const char *geom, const char *frag, qboolean silent, vfsfile_t *blobfile);
GLint GLSlang_GetUniformLocation (int prog, char *name); GLint GLSlang_GetUniformLocation (int prog, char *name);
void GL_SelectProgram(int program); void GL_SelectProgram(int program);
#define GLSlang_UseProgram(prog) GL_SelectProgram(prog) #define GLSlang_UseProgram(prog) GL_SelectProgram(prog)
@ -1087,7 +1088,7 @@ void GL_SelectProgram(int program);
#ifdef _DEBUG #ifdef _DEBUG
#ifdef __GNUC__ #if defined(__GNUC__) && !defined(NACL)
#define checkglerror() do {int i=qglGetError(); if (i) Sys_Printf("GL Error %i detected at line %s:%i (caller %p)\n", i, __FILE__, __LINE__, __builtin_return_address(0));}while(0) #define checkglerror() do {int i=qglGetError(); if (i) Sys_Printf("GL Error %i detected at line %s:%i (caller %p)\n", i, __FILE__, __LINE__, __builtin_return_address(0));}while(0)
#else #else
#define checkglerror() do {int i=qglGetError(); if (i) Con_Printf("GL Error %i detected at line %s:%i\n", i, __FILE__, __LINE__);}while(0) #define checkglerror() do {int i=qglGetError(); if (i) Con_Printf("GL Error %i detected at line %s:%i\n", i, __FILE__, __LINE__);}while(0)

File diff suppressed because it is too large Load diff

View file

@ -713,6 +713,7 @@ typedef struct
} sh_config_t; } sh_config_t;
extern sh_config_t sh_config; extern sh_config_t sh_config;
#endif #endif
extern const char *sh_defaultsamplers[];
#ifdef GLSLONLY #ifdef GLSLONLY
#define gl_config_nofixedfunc true #define gl_config_nofixedfunc true

View file

@ -1735,7 +1735,7 @@ void PDECL PR_ExecuteProgram (pubprogfuncs_t *ppf, func_t fnum)
{ {
// if (pr_global_struct->self) // if (pr_global_struct->self)
// ED_Print (PROG_TO_EDICT(pr_global_struct->self)); // ED_Print (PROG_TO_EDICT(pr_global_struct->self));
#if defined(__GNUC__) && !defined(FTE_TARGET_WEB) #if defined(__GNUC__) && !defined(FTE_TARGET_WEB) && !defined(NACL)
printf("PR_ExecuteProgram: NULL function from exe (address %p)\n", __builtin_return_address(0)); printf("PR_ExecuteProgram: NULL function from exe (address %p)\n", __builtin_return_address(0));
#else #else
printf("PR_ExecuteProgram: NULL function from exe\n"); printf("PR_ExecuteProgram: NULL function from exe\n");

View file

@ -11287,21 +11287,21 @@ void PR_DumpPlatform_f(void)
{"CONTENT_SKY", "const float", QW|NQ|CS, NULL, Q1CONTENTS_SKY}, {"CONTENT_SKY", "const float", QW|NQ|CS, NULL, Q1CONTENTS_SKY},
{"CONTENT_LADDER", "const float", QW|NQ|CS, "If this value is assigned to a solid_bsp's .skin field, the entity will become a ladder volume.", Q1CONTENTS_LADDER}, {"CONTENT_LADDER", "const float", QW|NQ|CS, "If this value is assigned to a solid_bsp's .skin field, the entity will become a ladder volume.", Q1CONTENTS_LADDER},
{"CONTENTBIT_NONE", "const int", QW|NQ|CS, NULL, FTECONTENTS_EMPTY}, {"CONTENTBIT_NONE", "const int", QW|NQ|CS, NULL, 0,STRINGIFY(FTECONTENTS_EMPTY)},
{"CONTENTBIT_SOLID", "const int", QW|NQ|CS, NULL, FTECONTENTS_SOLID}, {"CONTENTBIT_SOLID", "const int", QW|NQ|CS, NULL, 0,STRINGIFY(FTECONTENTS_SOLID)},
{"CONTENTBIT_LAVA", "const int", QW|NQ|CS, NULL, FTECONTENTS_LAVA}, {"CONTENTBIT_LAVA", "const int", QW|NQ|CS, NULL, 0,STRINGIFY(FTECONTENTS_LAVA)},
{"CONTENTBIT_SLIME", "const int", QW|NQ|CS, NULL, FTECONTENTS_SLIME}, {"CONTENTBIT_SLIME", "const int", QW|NQ|CS, NULL, 0,STRINGIFY(FTECONTENTS_SLIME)},
{"CONTENTBIT_WATER", "const int", QW|NQ|CS, NULL, FTECONTENTS_WATER}, {"CONTENTBIT_WATER", "const int", QW|NQ|CS, NULL, 0,STRINGIFY(FTECONTENTS_WATER)},
{"CONTENTBIT_FTELADDER", "const int", QW|NQ|CS, NULL, FTECONTENTS_LADDER}, {"CONTENTBIT_FTELADDER", "const int", QW|NQ|CS, NULL, 0,STRINGIFY(FTECONTENTS_LADDER)},
{"CONTENTBIT_PLAYERCLIP", "const int", QW|NQ|CS, NULL, FTECONTENTS_PLAYERCLIP}, {"CONTENTBIT_PLAYERCLIP", "const int", QW|NQ|CS, NULL, 0,STRINGIFY(FTECONTENTS_PLAYERCLIP)},
{"CONTENTBIT_MONSTERCLIP", "const int", QW|NQ|CS, NULL, FTECONTENTS_MONSTERCLIP}, {"CONTENTBIT_MONSTERCLIP", "const int", QW|NQ|CS, NULL, 0,STRINGIFY(FTECONTENTS_MONSTERCLIP)},
{"CONTENTBIT_BODY", "const int", QW|NQ|CS, NULL, FTECONTENTS_BODY}, {"CONTENTBIT_BODY", "const int", QW|NQ|CS, NULL, 0,STRINGIFY(FTECONTENTS_BODY)},
{"CONTENTBIT_CORPSE", "const int", QW|NQ|CS, NULL, FTECONTENTS_CORPSE}, {"CONTENTBIT_CORPSE", "const int", QW|NQ|CS, NULL, 0,STRINGIFY(FTECONTENTS_CORPSE)},
{"CONTENTBIT_Q2LADDER", "const int", QW|NQ|CS, NULL, Q2CONTENTS_LADDER}, {"CONTENTBIT_Q2LADDER", "const int", QW|NQ|CS, NULL, 0,STRINGIFY(Q2CONTENTS_LADDER)},
{"CONTENTBIT_SKY", "const int", QW|NQ|CS, NULL, FTECONTENTS_SKY}, {"CONTENTBIT_SKY", "const int", QW|NQ|CS, NULL, 0,STRINGIFY(FTECONTENTS_SKY)},
{"CONTENTBITS_POINTSOLID", "const int", QW|NQ|CS, NULL, MASK_POINTSOLID}, {"CONTENTBITS_POINTSOLID", "const int", QW|NQ|CS, NULL, 0,STRINGIFY(MASK_POINTSOLID)},
{"CONTENTBITS_BOXSOLID", "const int", QW|NQ|CS, NULL, MASK_BOXSOLID}, {"CONTENTBITS_BOXSOLID", "const int", QW|NQ|CS, NULL, 0,STRINGIFY(MASK_BOXSOLID)},
{"CONTENTBITS_FLUID", "const int", QW|NQ|CS, NULL, FTECONTENTS_FLUID}, {"CONTENTBITS_FLUID", "const int", QW|NQ|CS, NULL, 0,STRINGIFY(FTECONTENTS_FLUID)},
{"CHAN_AUTO", "const float", QW|NQ|CS, "The automatic channel, play as many sounds on this channel as you want, and they'll all play, however the other channels will replace each other.", CHAN_AUTO}, {"CHAN_AUTO", "const float", QW|NQ|CS, "The automatic channel, play as many sounds on this channel as you want, and they'll all play, however the other channels will replace each other.", CHAN_AUTO},
{"CHAN_WEAPON", "const float", QW|NQ|CS, NULL, CHAN_WEAPON}, {"CHAN_WEAPON", "const float", QW|NQ|CS, NULL, CHAN_WEAPON},

View file

@ -95,6 +95,7 @@ void dumpprogblob(FILE *out, unsigned char *buf, unsigned int size)
struct blobheader struct blobheader
{ {
unsigned char blobmagic[4]; //\xffSPV
unsigned int blobversion; unsigned int blobversion;
unsigned int defaulttextures; //s_diffuse etc flags unsigned int defaulttextures; //s_diffuse etc flags
unsigned int numtextures; //s_t0 count unsigned int numtextures; //s_t0 count
@ -164,6 +165,7 @@ int generatevulkanblobs(struct blobheader *blob, size_t maxblobsize, char *fname
// snprintf(vertname, sizeof(vertname), "vulkan/%s.vert", fname); // snprintf(vertname, sizeof(vertname), "vulkan/%s.vert", fname);
// snprintf(fragname, sizeof(fragname), "vulkan/%s.frag", fname); // snprintf(fragname, sizeof(fragname), "vulkan/%s.frag", fname);
memcpy(blob->blobmagic, "\xffSPV", 4);
blob->blobversion = 1; blob->blobversion = 1;
blob->defaulttextures = 0; blob->defaulttextures = 0;
blob->numtextures = 0; blob->numtextures = 0;
@ -332,7 +334,6 @@ int generatevulkanblobs(struct blobheader *blob, size_t maxblobsize, char *fname
}; };
int binding = 2; int binding = 2;
inheader = 0; inheader = 0;
printf("%s %u+%#x samplers\n", fname, blob->numtextures, blob->defaulttextures);
fprintf(temp, "#define OFFSETMAPPING (cvar_r_glsl_offsetmapping>0)\n"); fprintf(temp, "#define OFFSETMAPPING (cvar_r_glsl_offsetmapping>0)\n");
fprintf(temp, "#define SPECULAR (cvar_gl_specular>0)\n"); fprintf(temp, "#define SPECULAR (cvar_gl_specular>0)\n");
fprintf(temp, "#ifdef FRAGMENT_SHADER\n"); fprintf(temp, "#ifdef FRAGMENT_SHADER\n");

View file

@ -1,3 +1,5 @@
!!samps 1
struct a2v struct a2v
{ {
float4 pos: POSITION; float4 pos: POSITION;

View file

@ -1,3 +1,5 @@
!!samps diffuse upper lower fullbright
struct a2v struct a2v
{ {
float4 pos: POSITION; float4 pos: POSITION;

View file

@ -1,3 +1,5 @@
!!samps diffuse fullbright
//regular sky shader for scrolling q1 skies //regular sky shader for scrolling q1 skies
//the sky surfaces are thrown through this as-is. //the sky surfaces are thrown through this as-is.

View file

@ -1,3 +1,5 @@
!!samps diffuse
struct a2v struct a2v
{ {
float4 pos: POSITION; float4 pos: POSITION;

View file

@ -1,3 +1,5 @@
!!samps diffuse fullbright lightmap
struct a2v struct a2v
{ {
float4 pos: POSITION; float4 pos: POSITION;

View file

@ -1,3 +1,4 @@
!!samps diffuse
!!cvarf r_wateralpha !!cvarf r_wateralpha
struct a2v struct a2v

View file

@ -1,3 +1,5 @@
!!samps lightmap
struct a2v struct a2v
{ {
float4 pos: POSITION; float4 pos: POSITION;

View file

@ -1,3 +1,4 @@
!!samps 1
struct a2v struct a2v
{ {
float4 pos: POSITION; float4 pos: POSITION;

View file

@ -1,3 +1,4 @@
!!samps 1
!!cvard3 r_menutint=0.2 0.2 0.2 !!cvard3 r_menutint=0.2 0.2 0.2
!!cvardf r_menutint_inverse=0.0 !!cvardf r_menutint_inverse=0.0

View file

@ -1,10 +1,11 @@
!!samps diffuse normalmap specular upper lower shadowmap projectionmap
!!permu BUMP !!permu BUMP
!!permu FRAMEBLEND !!permu FRAMEBLEND
!!permu SKELETAL !!permu SKELETAL
!!permu UPPERLOWER !!permu UPPERLOWER
!!permu FOG !!permu FOG
!!cvarf r_glsl_offsetmapping_scale !!cvarf r_glsl_offsetmapping_scale
!!cvardf r_glsl_pcf !!cvardf r_glsl_pcf=5
//this is the main shader responsible for realtime dlights. //this is the main shader responsible for realtime dlights.
@ -77,21 +78,21 @@ struct v2f
#ifdef FRAGMENT_SHADER #ifdef FRAGMENT_SHADER
Texture2D t_diffuse : register(t0); Texture2D t_shadowmap : register(t0);
Texture2D t_normalmap : register(t1); TextureCube t_projectionmap : register(t1);
Texture2D t_specular : register(t2); Texture2D t_diffuse : register(t2);
Texture2D t_upper : register(t3); Texture2D t_normalmap : register(t3);
Texture2D t_lower : register(t4); Texture2D t_specular : register(t4);
Texture2D t_shadowmap : register(t5); Texture2D t_upper : register(t5);
TextureCube t_projectionmap : register(t6); Texture2D t_lower : register(t6);
SamplerState s_diffuse : register(s0); SamplerComparisonState s_shadowmap : register(s0);
SamplerState s_normalmap : register(s1); SamplerState s_projectionmap : register(s1);
SamplerState s_specular : register(s2); SamplerState s_diffuse : register(s2);
SamplerState s_upper : register(s3); SamplerState s_normalmap : register(s3);
SamplerState s_lower : register(s4); SamplerState s_specular : register(s4);
SamplerComparisonState s_shadowmap : register(s5); SamplerState s_upper : register(s5);
SamplerState s_projectionmap : register(s6); SamplerState s_lower : register(s6);
#ifdef PCF #ifdef PCF

View file

@ -994,6 +994,7 @@ qboolean SW_SCR_UpdateScreen(void)
SCR_DrawTwoDimensional(0, 0); SCR_DrawTwoDimensional(0, 0);
V_UpdatePalette (false); V_UpdatePalette (false);
return true;
} }
void SW_VBO_Begin(vbobctx_t *ctx, size_t maxsize) void SW_VBO_Begin(vbobctx_t *ctx, size_t maxsize)

View file

@ -289,6 +289,7 @@ extern int be_maxpasses;
struct blobheader struct blobheader
{ {
unsigned char blobmagic[4];
unsigned int blobversion; unsigned int blobversion;
unsigned int defaulttextures; //s_diffuse etc flags unsigned int defaulttextures; //s_diffuse etc flags
unsigned int numtextures; //s_t0 count unsigned int numtextures; //s_t0 count
@ -404,97 +405,9 @@ static VkSampler VK_GetSampler(unsigned int flags)
} }
#endif #endif
qboolean VK_LoadBlob(program_t *prog, void *blobdata, const char *name) //creates the layout stuff for the prog.
static VK_FinishProg(program_t *prog, const char *name)
{ {
//fixme: should validate that the offset+lengths are within the blobdata.
struct blobheader *blob = blobdata;
VkShaderModuleCreateInfo info = {VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO};
VkShaderModule vert, frag;
unsigned char *cvardata;
if (blob->blobversion != 1)
{
Con_Printf("Blob %s is outdated\n", name);
return false;
}
info.flags = 0;
info.codeSize = blob->vertlength;
info.pCode = (uint32_t*)((char*)blob+blob->vertoffset);
VkAssert(vkCreateShaderModule(vk.device, &info, vkallocationcb, &vert));
info.flags = 0;
info.codeSize = blob->fraglength;
info.pCode = (uint32_t*)((char*)blob+blob->fragoffset);
VkAssert(vkCreateShaderModule(vk.device, &info, vkallocationcb, &frag));
prog->vert = vert;
prog->frag = frag;
prog->nofixedcompat = true;
prog->numsamplers = blob->numtextures;
prog->defaulttextures = blob->defaulttextures;
prog->supportedpermutations = blob->permutations;
if (blob->cvarslength)
{
prog->cvardata = BZ_Malloc(blob->cvarslength);
prog->cvardatasize = blob->cvarslength;
memcpy(prog->cvardata, (char*)blob+blob->cvarsoffset, blob->cvarslength);
}
else
{
prog->cvardata = NULL;
prog->cvardatasize = 0;
}
//go through the cvars and a) validate them. b) create them with the right defaults.
//FIXME: validate
for (cvardata = prog->cvardata; cvardata < prog->cvardata + prog->cvardatasize; )
{
unsigned char type = cvardata[2], size = cvardata[3]-'0';
char *cvarname;
cvar_t *var;
cvardata += 4;
cvarname = cvardata;
cvardata += strlen(cvarname)+1;
if (type >= 'A' && type <= 'Z')
{ //args will be handled by the blob loader.
VK_ShaderReadArgument(name, cvarname, type, size, cvardata);
}
else
{
var = Cvar_FindVar(cvarname);
if (var)
var->flags |= CVAR_SHADERSYSTEM; //just in case
else
{
union
{
int i;
float f;
} u;
char value[128];
uint32_t i;
for (i = 0; i < size; i++)
{
u.i = (cvardata[i*4+0]<<24)|(cvardata[i*4+0]<<16)|(cvardata[i*4+0]<<8)|(cvardata[i*4+0]<<0);
if (i)
Q_strncatz(value, " ", sizeof(value));
if (type == 'i' || type == 'b')
Q_strncatz(value, va("%i", u.i), sizeof(value));
else
Q_strncatz(value, va("%f", u.f), sizeof(value));
}
Cvar_Get(cvarname, value, CVAR_SHADERSYSTEM, "GLSL Settings");
}
}
cvardata += 4*size;
}
{ {
VkDescriptorSetLayout desclayout; VkDescriptorSetLayout desclayout;
VkDescriptorSetLayoutCreateInfo descSetLayoutCreateInfo = {VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO}; VkDescriptorSetLayoutCreateInfo descSetLayoutCreateInfo = {VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO};
@ -561,6 +474,663 @@ qboolean VK_LoadBlob(program_t *prog, void *blobdata, const char *name)
VkAssert(vkCreatePipelineLayout(vk.device, &pipeLayoutCreateInfo, vkallocationcb, &layout)); VkAssert(vkCreatePipelineLayout(vk.device, &pipeLayoutCreateInfo, vkallocationcb, &layout));
prog->layout = layout; prog->layout = layout;
} }
}
static const char *vulkan_glsl_hdrs[] =
{
"sys/defs.h",
"#define DEFS_DEFINED\n"
"#undef texture2D\n" //nvidia is fucking us over
"#undef textureCube\n" //nvidia is fucking us over
"#define texture2D texture\n"
"#define textureCube texture\n"
"#define e_lmscale e_lmscales[0]\n"
,
"sys/skeletal.h",
"#ifdef SKELETAL\n"
"vec4 skeletaltransform()"
"{"
"mat3x4 wmat;\n"
"wmat = m_bones[int(v_bone.x)] * v_weight.x;\n"
"wmat += m_bones[int(v_bone.y)] * v_weight.y;\n"
"wmat += m_bones[int(v_bone.z)] * v_weight.z;\n"
"wmat += m_bones[int(v_bone.w)] * v_weight.w;\n"
"return m_modelviewprojection * vec4(vec4(v_position.xyz, 1.0) * wmat, 1.0);"
"}\n"
"vec4 skeletaltransform_nst(out vec3 n, out vec3 t, out vec3 b)"
"{"
"mat3x4 wmat;\n"
"wmat = m_bones[int(v_bone.x)] * v_weight.x;"
"wmat += m_bones[int(v_bone.y)] * v_weight.y;"
"wmat += m_bones[int(v_bone.z)] * v_weight.z;"
"wmat += m_bones[int(v_bone.w)] * v_weight.w;"
"n = vec4(v_normal.xyz, 0.0) * wmat;"
"t = vec4(v_svector.xyz, 0.0) * wmat;"
"b = vec4(v_tvector.xyz, 0.0) * wmat;"
"return m_modelviewprojection * vec4(vec4(v_position.xyz, 1.0) * wmat, 1.0);"
"}\n"
"vec4 skeletaltransform_wnst(out vec3 w, out vec3 n, out vec3 t, out vec3 b)"
"{"
"mat3x4 wmat;\n"
"wmat = m_bones[int(v_bone.x)] * v_weight.x;"
"wmat += m_bones[int(v_bone.y)] * v_weight.y;"
"wmat += m_bones[int(v_bone.z)] * v_weight.z;"
"wmat += m_bones[int(v_bone.w)] * v_weight.w;"
"n = vec4(v_normal.xyz, 0.0) * wmat;"
"t = vec4(v_svector.xyz, 0.0) * wmat;"
"b = vec4(v_tvector.xyz, 0.0) * wmat;"
"w = vec4(v_position.xyz, 1.0) * wmat;"
"return m_modelviewprojection * vec4(w, 1.0);"
"}\n"
"vec4 skeletaltransform_n(out vec3 n)"
"{"
"mat3x4 wmat;\n"
"wmat = m_bones[int(v_bone.x)] * v_weight.x;"
"wmat += m_bones[int(v_bone.y)] * v_weight.y;"
"wmat += m_bones[int(v_bone.z)] * v_weight.z;"
"wmat += m_bones[int(v_bone.w)] * v_weight.w;"
"n = vec4(v_normal.xyz, 0.0) * wmat;"
"return m_modelviewprojection * vec4(vec4(v_position.xyz, 1.0) * wmat, 1.0);"
"}\n"
"#else\n"
"#define skeletaltransform ftetransform\n"
"vec4 skeletaltransform_wnst(out vec3 w, out vec3 n, out vec3 t, out vec3 b)"
"{"
"n = v_normal;"
"t = v_svector;"
"b = v_tvector;"
"w = v_position.xyz;"
"return ftetransform();"
"}\n"
"vec4 skeletaltransform_nst(out vec3 n, out vec3 t, out vec3 b)"
"{"
"n = v_normal;"
"t = v_svector;"
"b = v_tvector;"
"return ftetransform();"
"}\n"
"vec4 skeletaltransform_n(out vec3 n)"
"{"
"n = v_normal;"
"return ftetransform();"
"}\n"
"#endif\n"
,
"sys/fog.h",
"#ifdef FRAGMENT_SHADER\n"
"#ifdef FOG\n"
"vec3 fog3(in vec3 regularcolour)"
"{"
"float z = w_fogdensity * gl_FragCoord.z / gl_FragCoord.w;\n"
"z = max(0.0,z-w_fogdepthbias);\n"
"#if #include \"cvar/r_fog_exp2\"\n"
"z *= z;\n"
"#endif\n"
"float fac = exp2(-(z * 1.442695));\n"
"fac = (1.0-w_fogalpha) + (clamp(fac, 0.0, 1.0)*w_fogalpha);\n"
"return mix(w_fogcolour, regularcolour, fac);\n"
"}\n"
"vec3 fog3additive(in vec3 regularcolour)"
"{"
"float z = w_fogdensity * gl_FragCoord.z / gl_FragCoord.w;\n"
"z = max(0.0,z-w_fogdepthbias);\n"
"#if #include \"cvar/r_fog_exp2\"\n"
"z *= z;\n"
"#endif\n"
"float fac = exp2(-(z * 1.442695));\n"
"fac = (1.0-w_fogalpha) + (clamp(fac, 0.0, 1.0)*w_fogalpha);\n"
"return regularcolour * fac;\n"
"}\n"
"vec4 fog4(in vec4 regularcolour)"
"{"
"return vec4(fog3(regularcolour.rgb), 1.0) * regularcolour.a;\n"
"}\n"
"vec4 fog4additive(in vec4 regularcolour)"
"{"
"float z = w_fogdensity * gl_FragCoord.z / gl_FragCoord.w;\n"
"z = max(0.0,z-w_fogdepthbias);\n"
"#if #include \"cvar/r_fog_exp2\"\n"
"z *= z;\n"
"#endif\n"
"float fac = exp2(-(z * 1.442695));\n"
"fac = (1.0-w_fogalpha) + (clamp(fac, 0.0, 1.0)*w_fogalpha);\n"
"return regularcolour * vec4(fac, fac, fac, 1.0);\n"
"}\n"
"vec4 fog4blend(in vec4 regularcolour)"
"{"
"float z = w_fogdensity * gl_FragCoord.z / gl_FragCoord.w;\n"
"z = max(0.0,z-w_fogdepthbias);\n"
"#if #include \"cvar/r_fog_exp2\"\n"
"z *= z;\n"
"#endif\n"
"float fac = exp2(-(z * 1.442695));\n"
"fac = (1.0-w_fogalpha) + (clamp(fac, 0.0, 1.0)*w_fogalpha);\n"
"return regularcolour * vec4(1.0, 1.0, 1.0, fac);\n"
"}\n"
"#else\n"
/*don't use macros for this - mesa bugs out*/
"vec3 fog3(in vec3 regularcolour) { return regularcolour; }\n"
"vec3 fog3additive(in vec3 regularcolour) { return regularcolour; }\n"
"vec4 fog4(in vec4 regularcolour) { return regularcolour; }\n"
"vec4 fog4additive(in vec4 regularcolour) { return regularcolour; }\n"
"vec4 fog4blend(in vec4 regularcolour) { return regularcolour; }\n"
"#endif\n"
"#endif\n"
,
"sys/offsetmapping.h",
"uniform float cvar_r_glsl_offsetmapping_scale;\n"
"vec2 offsetmap(sampler2D normtex, vec2 base, vec3 eyevector)\n"
"{\n"
"#if !defined(OFFSETMAPPING_SCALE)\n"
"#define OFFSETMAPPING_SCALE 1.0\n"
"#endif\n"
"#if defined(RELIEFMAPPING) && !defined(GL_ES)\n"
"float i, f;\n"
"vec3 OffsetVector = vec3(normalize(eyevector.xyz).xy * cvar_r_glsl_offsetmapping_scale * OFFSETMAPPING_SCALE * vec2(-1.0, 1.0), -1.0);\n"
"vec3 RT = vec3(vec2(base.xy"/* - OffsetVector.xy*OffsetMapping_Bias*/"), 1.0);\n"
"OffsetVector /= 10.0;\n"
"for(i = 1.0; i < 10.0; ++i)\n"
"RT += OffsetVector * step(texture2D(normtex, RT.xy).a, RT.z);\n"
"for(i = 0.0, f = 1.0; i < 5.0; ++i, f *= 0.5)\n"
"RT += OffsetVector * (step(texture2D(normtex, RT.xy).a, RT.z) * f - 0.5 * f);\n"
"return RT.xy;\n"
"#elif defined(OFFSETMAPPING)\n"
"vec2 OffsetVector = normalize(eyevector).xy * cvar_r_glsl_offsetmapping_scale * OFFSETMAPPING_SCALE * vec2(-1.0, 1.0);\n"
"vec2 tc = base;\n"
"tc += OffsetVector;\n"
"OffsetVector *= 0.333;\n"
"tc -= OffsetVector * texture2D(normtex, tc).w;\n"
"tc -= OffsetVector * texture2D(normtex, tc).w;\n"
"tc -= OffsetVector * texture2D(normtex, tc).w;\n"
"return tc;\n"
"#else\n"
"return base;\n"
"#endif\n"
"}\n"
,
"sys/pcf.h",
"#ifndef r_glsl_pcf\n"
"#define r_glsl_pcf 9\n"
"#endif\n"
"#if r_glsl_pcf < 1\n"
"#undef r_glsl_pcf\n"
"#define r_glsl_pcf 9\n"
"#endif\n"
"vec3 ShadowmapCoord(void)\n"
"{\n"
"#ifdef SPOT\n"
//bias it. don't bother figuring out which side or anything, its not needed
//l_projmatrix contains the light's projection matrix so no other magic needed
"return ((vtexprojcoord.xyz-vec3(0.0,0.0,0.015))/vtexprojcoord.w + vec3(1.0, 1.0, 1.0)) * vec3(0.5, 0.5, 0.5);\n"
//"#elif defined(CUBESHADOW)\n"
// vec3 shadowcoord = vshadowcoord.xyz / vshadowcoord.w;
// #define dosamp(x,y) shadowCube(s_t4, shadowcoord + vec2(x,y)*texscale.xy).r
"#else\n"
//figure out which axis to use
//texture is arranged thusly:
//forward left up
//back right down
"vec3 dir = abs(vtexprojcoord.xyz);\n"
//assume z is the major axis (ie: forward from the light)
"vec3 t = vtexprojcoord.xyz;\n"
"float ma = dir.z;\n"
"vec3 axis = vec3(0.5/3.0, 0.5/2.0, 0.5);\n"
"if (dir.x > ma)\n"
"{\n"
"ma = dir.x;\n"
"t = vtexprojcoord.zyx;\n"
"axis.x = 0.5;\n"
"}\n"
"if (dir.y > ma)\n"
"{\n"
"ma = dir.y;\n"
"t = vtexprojcoord.xzy;\n"
"axis.x = 2.5/3.0;\n"
"}\n"
//if the axis is negative, flip it.
"if (t.z > 0.0)\n"
"{\n"
"axis.y = 1.5/2.0;\n"
"t.z = -t.z;\n"
"}\n"
//we also need to pass the result through the light's projection matrix too
//the 'matrix' we need only contains 5 actual values. and one of them is a -1. So we might as well just use a vec4.
//note: the projection matrix also includes scalers to pinch the image inwards to avoid sampling over borders, as well as to cope with non-square source image
//the resulting z is prescaled to result in a value between -0.5 and 0.5.
//also make sure we're in the right quadrant type thing
"return axis + ((l_shadowmapproj.xyz*t.xyz + vec3(0.0, 0.0, l_shadowmapproj.w)) / -t.z);\n"
"#endif\n"
"}\n"
"float ShadowmapFilter(sampler2DShadow smap)\n"
"{\n"
"vec3 shadowcoord = ShadowmapCoord();\n"
"#if 0\n"//def GL_ARB_texture_gather
"vec2 ipart, fpart;\n"
"#define dosamp(x,y) textureGatherOffset(smap, ipart.xy, vec2(x,y)))\n"
"vec4 tl = step(shadowcoord.z, dosamp(-1.0, -1.0));\n"
"vec4 bl = step(shadowcoord.z, dosamp(-1.0, 1.0));\n"
"vec4 tr = step(shadowcoord.z, dosamp(1.0, -1.0));\n"
"vec4 br = step(shadowcoord.z, dosamp(1.0, 1.0));\n"
//we now have 4*4 results, woo
//we can just average them for 1/16th precision, but that's still limited graduations
//the middle four pixels are 'full strength', but we interpolate the sides to effectively give 3*3
"vec4 col = vec4(tl.ba, tr.ba) + vec4(bl.rg, br.rg) + " //middle two rows are full strength
"mix(vec4(tl.rg, tr.rg), vec4(bl.ba, br.ba), fpart.y);\n" //top+bottom rows
"return dot(mix(col.rgb, col.agb, fpart.x), vec3(1.0/9.0));\n" //blend r+a, gb are mixed because its pretty much free and gives a nicer dot instruction instead of lots of adds.
"#else\n"
"#define dosamp(x,y) shadow2D(smap, shadowcoord.xyz + (vec3(x,y,0.0)*l_shadowmapscale.xyx)).r\n"
"float s = 0.0;\n"
"#if r_glsl_pcf >= 1 && r_glsl_pcf < 5\n"
"s += dosamp(0.0, 0.0);\n"
"return s;\n"
"#elif r_glsl_pcf >= 5 && r_glsl_pcf < 9\n"
"s += dosamp(-1.0, 0.0);\n"
"s += dosamp(0.0, -1.0);\n"
"s += dosamp(0.0, 0.0);\n"
"s += dosamp(0.0, 1.0);\n"
"s += dosamp(1.0, 0.0);\n"
"return s/5.0;\n"
"#else\n"
"s += dosamp(-1.0, -1.0);\n"
"s += dosamp(-1.0, 0.0);\n"
"s += dosamp(-1.0, 1.0);\n"
"s += dosamp(0.0, -1.0);\n"
"s += dosamp(0.0, 0.0);\n"
"s += dosamp(0.0, 1.0);\n"
"s += dosamp(1.0, -1.0);\n"
"s += dosamp(1.0, 0.0);\n"
"s += dosamp(1.0, 1.0);\n"
"return s/9.0;\n"
"#endif\n"
"#endif\n"
"}\n"
,
NULL
};
//glsl doesn't officially support #include, this might be vulkan, but don't push things.
qboolean Vulkan_GenerateIncludes(int maxstrings, int *strings, const char *prstrings[], int length[], const char *shadersource)
{
int i;
char *incline, *inc;
char incname[256];
while((incline=strstr(shadersource, "#include")))
{
if (*strings == maxstrings)
return false;
/*emit up to the include*/
if (incline - shadersource)
{
prstrings[*strings] = shadersource;
length[*strings] = incline - shadersource;
*strings += 1;
}
incline += 8;
incline = COM_ParseOut (incline, incname, sizeof(incname));
if (!strncmp(incname, "cvar/", 5))
{
cvar_t *var = Cvar_Get(incname+5, "0", 0, "shader cvars");
if (var)
{
var->flags |= CVAR_SHADERSYSTEM;
if (!Vulkan_GenerateIncludes(maxstrings, strings, prstrings, length, var->string))
return false;
}
else
{
/*dump something if the cvar doesn't exist*/
if (*strings == maxstrings)
return false;
prstrings[*strings] = "0";
length[*strings] = strlen("0");
*strings += 1;
}
}
else
{
for (i = 0; vulkan_glsl_hdrs[i]; i += 2)
{
if (!strcmp(incname, vulkan_glsl_hdrs[i]))
{
if (!Vulkan_GenerateIncludes(maxstrings, strings, prstrings, length, vulkan_glsl_hdrs[i+1]))
return false;
break;
}
}
if (!vulkan_glsl_hdrs[i])
{
if (FS_LoadFile(incname, (void**)&inc) != (qofs_t)-1)
{
if (!Vulkan_GenerateIncludes(maxstrings, strings, prstrings, length, inc))
{
FS_FreeFile(inc);
return false;
}
FS_FreeFile(inc);
}
}
}
/*move the pointer past the include*/
shadersource = incline;
}
if (*shadersource)
{
if (*strings == maxstrings)
return false;
/*dump the remaining shader string*/
prstrings[*strings] = shadersource;
length[*strings] = strlen(prstrings[*strings]);
*strings += 1;
}
return true;
}
//assumes VK_NV_glsl_shader for raw glsl
VkShaderModule VK_CreateGLSLModule(program_t *prog, const char *name, int ver, const char **precompilerconstants, const char *body, int isfrag)
{
VkShaderModuleCreateInfo info = {VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO};
VkShaderModule mod;
const char *strings[256];
int lengths[256];
unsigned int numstrings = 0;
char *blob;
size_t blobsize;
unsigned int i;
strings[numstrings++] = "#version 450 core\n";
strings[numstrings++] = "#define ENGINE_"DISTRIBUTION"\n";
strings[numstrings++] =
"layout(std140, binding=0) uniform entityblock"
"{\n"
"mat4 m_modelviewproj;"
"mat4 m_model;"
"mat4 m_modelinv;"
"vec3 e_eyepos;"
"float e_time;"
"vec3 e_light_ambient; float epad1;"
"vec3 e_light_dir; float epad2;"
"vec3 e_light_mul; float epad3;"
"vec4 e_lmscales[4];"
"vec3 e_uppercolour; float epad4;"
"vec3 e_lowercolour; float epad5;"
"vec4 e_colourident;"
"vec4 w_fogcolours;"
"float w_fogdensity; float w_fogdepthbias; vec2 epad6;"
"};\n"
"layout(std140, binding=1) uniform lightblock"
"{\n"
"mat4 l_cubematrix;"
"vec3 l_lightposition; float lpad1;"
"vec3 l_lightcolour; float lpad2;"
"vec3 l_lightcolourscale; float l_lightradius;"
"vec4 l_shadowmapproj;"
"vec2 l_shadowmapscale; vec2 lpad3;"
"};\n"
;
if (isfrag)
{
int bindloc = 0;
const char *bindlocations[] =
{
"layout(set=0, binding=2) ",
"layout(set=0, binding=3) ",
"layout(set=0, binding=4) ",
"layout(set=0, binding=5) ",
"layout(set=0, binding=6) ",
"layout(set=0, binding=7) ",
"layout(set=0, binding=8) ",
"layout(set=0, binding=9) ",
"layout(set=0, binding=10) ",
"layout(set=0, binding=11) ",
"layout(set=0, binding=12) ",
"layout(set=0, binding=13) ",
"layout(set=0, binding=14) ",
"layout(set=0, binding=15) ",
"layout(set=0, binding=16) ",
"layout(set=0, binding=17) ",
"layout(set=0, binding=18) ",
"layout(set=0, binding=19) ",
"layout(set=0, binding=20) ",
"layout(set=0, binding=21) ",
"layout(set=0, binding=22) ",
"layout(set=0, binding=23) ",
"layout(set=0, binding=24) ",
"layout(set=0, binding=25) ",
};
const char *numberedsamplernames[] =
{
"uniform sampler2D s_t0;\n",
"uniform sampler2D s_t1;\n",
"uniform sampler2D s_t2;\n",
"uniform sampler2D s_t3;\n",
"uniform sampler2D s_t4;\n",
"uniform sampler2D s_t5;\n",
"uniform sampler2D s_t6;\n",
"uniform sampler2D s_t7;\n",
};
const char *defaultsamplernames[] =
{
"uniform sampler2D s_shadowmap;\n",
"uniform samplerCube s_projectionmap;\n",
"uniform sampler2D s_diffuse;\n",
"uniform sampler2D s_normalmap;\n",
"uniform sampler2D s_specular;\n",
"uniform sampler2D s_upper;\n",
"uniform sampler2D s_lower;\n",
"uniform sampler2D s_fullbright;\n",
"uniform sampler2D s_paletted;\n",
"uniform samplerCube s_reflectcube;\n",
"uniform sampler2D s_reflectmask;\n",
"uniform sampler2D s_lightmap;\n#define s_lightmap0 s_lightmap\n",
"uniform sampler2D s_deluxmap;\n#define s_deluxmap0 s_deluxmap\n",
"uniform sampler2D s_lightmap1;\n",
"uniform sampler2D s_lightmap2;\n",
"uniform sampler2D s_lightmap3;\n",
"uniform sampler2D s_deluxmap1;\n",
"uniform sampler2D s_deluxmap2;\n",
"uniform sampler2D s_deluxmap3;\n",
};
strings[numstrings++] = "#define FRAGMENT_SHADER\n"
"#define varying in\n"
"layout(location=0) out vec4 outcolour;\n"
"#define gl_FragColor outcolour\n"
;
for (i = 0; i < countof(defaultsamplernames); i++)
{
if (prog->defaulttextures & (1u<<i))
{
strings[numstrings++] = bindlocations[bindloc++];
strings[numstrings++] = defaultsamplernames[i];
}
}
for (i = 0; i < prog->numsamplers && i < countof(numberedsamplernames); i++)
{
strings[numstrings++] = bindlocations[bindloc++];
strings[numstrings++] = numberedsamplernames[i];
}
}
else
{
strings[numstrings++] = "#define VERTEX_SHADER\n"
"#define attribute in\n"
"#define varying out\n"
"out gl_PerVertex"
"{"
"vec4 gl_Position;"
"};"
"layout(location=0) attribute vec3 v_position;"
"layout(location=1) attribute vec2 v_texcoord;"
"layout(location=2) attribute vec4 v_colour;"
"layout(location=3) attribute vec2 v_lmcoord;"
"layout(location=4) attribute vec3 v_normal;"
"layout(location=5) attribute vec3 v_svector;"
"layout(location=6) attribute vec3 v_tvector;"
//"layout(location=7) attribute vec4 v_boneweights;"
//"layout(location=8) attribute ivec4 v_bonenums;"
"\n"
"vec4 ftetransform()"
"{"
"vec4 proj = (m_modelviewproj*vec4(v_position,1.0));"
"proj.y *= -1;"
"proj.z = (proj.z + proj.w) / 2.0;"
"return proj;"
"}\n"
;
}
while (*precompilerconstants)
strings[numstrings++] = *precompilerconstants++;
for (i = 0, blobsize = 0; i < numstrings; i++)
lengths[i] = strlen(strings[i]);
Vulkan_GenerateIncludes(countof(strings), &numstrings, strings, lengths, body);
//now glue it all together into a single blob
for (i = 0, blobsize = 0; i < numstrings; i++)
blobsize += lengths[i];
blobsize++;
blob = malloc(blobsize);
for (i = 0, blobsize = 0; i < numstrings; i++)
{
memcpy(blob+blobsize, strings[i], lengths[i]);
blobsize += lengths[i];
}
blob[blobsize] = 0;
//and submit it.
info.flags = 0;
info.codeSize = blobsize;
info.pCode = (void*)blob;
VkAssert(vkCreateShaderModule(vk.device, &info, vkallocationcb, &mod));
return mod;
}
qboolean VK_LoadGLSL(program_t *prog, const char *name, unsigned int permu, int ver, const char **precompilerconstants, const char *vert, const char *tcs, const char *tes, const char *geom, const char *frag, qboolean noerrors, vfsfile_t *blobfile)
{
if (permu) //FIXME...
return false;
prog->pipelines = NULL;
prog->vert = VK_CreateGLSLModule(prog, name, ver, precompilerconstants, vert, false);
prog->frag = VK_CreateGLSLModule(prog, name, ver, precompilerconstants, frag, true);
VK_FinishProg(prog, name);
return true;
}
qboolean VK_LoadBlob(program_t *prog, void *blobdata, const char *name)
{
//fixme: should validate that the offset+lengths are within the blobdata.
struct blobheader *blob = blobdata;
VkShaderModuleCreateInfo info = {VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO};
VkShaderModule vert, frag;
unsigned char *cvardata;
if (blob->blobmagic[0] != 0xff || blob->blobmagic[1] != 'S' || blob->blobmagic[2] != 'P' || blob->blobmagic[3] != 'V')
return false; //assume its glsl. this is going to be 'fun'.
if (blob->blobversion != 1)
{
Con_Printf("Blob %s is outdated\n", name);
return false;
}
info.flags = 0;
info.codeSize = blob->vertlength;
info.pCode = (uint32_t*)((char*)blob+blob->vertoffset);
VkAssert(vkCreateShaderModule(vk.device, &info, vkallocationcb, &vert));
info.flags = 0;
info.codeSize = blob->fraglength;
info.pCode = (uint32_t*)((char*)blob+blob->fragoffset);
VkAssert(vkCreateShaderModule(vk.device, &info, vkallocationcb, &frag));
prog->vert = vert;
prog->frag = frag;
prog->nofixedcompat = true;
prog->numsamplers = blob->numtextures;
prog->defaulttextures = blob->defaulttextures;
prog->supportedpermutations = blob->permutations;
if (blob->cvarslength)
{
prog->cvardata = BZ_Malloc(blob->cvarslength);
prog->cvardatasize = blob->cvarslength;
memcpy(prog->cvardata, (char*)blob+blob->cvarsoffset, blob->cvarslength);
}
else
{
prog->cvardata = NULL;
prog->cvardatasize = 0;
}
//go through the cvars and a) validate them. b) create them with the right defaults.
//FIXME: validate
for (cvardata = prog->cvardata; cvardata < prog->cvardata + prog->cvardatasize; )
{
unsigned char type = cvardata[2], size = cvardata[3]-'0';
char *cvarname;
cvar_t *var;
cvardata += 4;
cvarname = cvardata;
cvardata += strlen(cvarname)+1;
if (type >= 'A' && type <= 'Z')
{ //args will be handled by the blob loader.
VK_ShaderReadArgument(name, cvarname, type, size, cvardata);
}
else
{
var = Cvar_FindVar(cvarname);
if (var)
var->flags |= CVAR_SHADERSYSTEM; //just in case
else
{
union
{
int i;
float f;
} u;
char value[128];
uint32_t i;
*value = 0;
for (i = 0; i < size; i++)
{
u.i = (cvardata[i*4+0]<<24)|(cvardata[i*4+1]<<16)|(cvardata[i*4+2]<<8)|(cvardata[i*4+3]<<0);
if (i)
Q_strncatz(value, " ", sizeof(value));
if (type == 'i' || type == 'b')
Q_strncatz(value, va("%i", u.i), sizeof(value));
else
Q_strncatz(value, va("%f", u.f), sizeof(value));
}
Cvar_Get(cvarname, value, CVAR_SHADERSYSTEM, "GLSL Settings");
}
}
cvardata += 4*size;
}
VK_FinishProg(prog, name);
prog->pipelines = NULL; //generated as needed, depending on blend states etc. prog->pipelines = NULL; //generated as needed, depending on blend states etc.
return true; return true;
@ -574,7 +1144,8 @@ void VKBE_DeleteProg(program_t *prog)
pipe = prog->pipelines; pipe = prog->pipelines;
prog->pipelines = pipe->next; prog->pipelines = pipe->next;
vkDestroyPipeline(vk.device, pipe->pipeline, vkallocationcb); if (pipe->pipeline)
vkDestroyPipeline(vk.device, pipe->pipeline, vkallocationcb);
Z_Free(pipe); Z_Free(pipe);
} }
if (prog->layout) if (prog->layout)
@ -2386,7 +2957,14 @@ static void BE_CreatePipeline(program_t *p, unsigned int shaderflags, unsigned i
err = vkCreateGraphicsPipelines(vk.device, vk.pipelinecache, 1, &pipeCreateInfo, vkallocationcb, &pipe->pipeline); err = vkCreateGraphicsPipelines(vk.device, vk.pipelinecache, 1, &pipeCreateInfo, vkallocationcb, &pipe->pipeline);
if (err) if (err)
Sys_Error("Error %i creating pipeline for %s. Check spir-v modules / drivers.\n", err, shaderstate.curshader->name); {
shaderstate.activepipeline = VK_NULL_HANDLE;
if (err != VK_ERROR_INVALID_SHADER_NV)
Sys_Error("Error %i creating pipeline for %s. Check spir-v modules / drivers.\n", err, shaderstate.curshader->name);
else
Con_Printf("Error creating pipeline for %s. Check glsl / spir-v modules / drivers.\n", shaderstate.curshader->name);
return;
}
vkCmdBindPipeline(vk.frame->cbuf, VK_PIPELINE_BIND_POINT_GRAPHICS, shaderstate.activepipeline=pipe->pipeline); vkCmdBindPipeline(vk.frame->cbuf, VK_PIPELINE_BIND_POINT_GRAPHICS, shaderstate.activepipeline=pipe->pipeline);
} }
@ -2416,7 +2994,8 @@ static void BE_BindPipeline(program_t *p, unsigned int shaderflags, unsigned int
if (pipe->pipeline != shaderstate.activepipeline) if (pipe->pipeline != shaderstate.activepipeline)
{ {
shaderstate.activepipeline = pipe->pipeline; shaderstate.activepipeline = pipe->pipeline;
vkCmdBindPipeline(vk.frame->cbuf, VK_PIPELINE_BIND_POINT_GRAPHICS, shaderstate.activepipeline); if (shaderstate.activepipeline)
vkCmdBindPipeline(vk.frame->cbuf, VK_PIPELINE_BIND_POINT_GRAPHICS, shaderstate.activepipeline);
} }
return; return;
} }
@ -2460,9 +3039,11 @@ static void BE_SetupUBODescriptor(VkDescriptorSet set, VkWriteDescriptorSet *fir
desc->pTexelBufferView = NULL; desc->pTexelBufferView = NULL;
} }
static void BE_RenderMeshProgram(program_t *p, shaderpass_t *pass, unsigned int shaderbits, unsigned int idxfirst, unsigned int idxcount) static qboolean BE_SetupMeshProgram(program_t *p, shaderpass_t *pass, unsigned int shaderbits, unsigned int idxcount)
{ {
int perm = 0; int perm = 0;
if (!p)
return false;
if (TEXLOADED(shaderstate.curtexnums->bump)) if (TEXLOADED(shaderstate.curtexnums->bump))
perm |= PERMUTATION_BUMPMAP; perm |= PERMUTATION_BUMPMAP;
@ -2477,6 +3058,8 @@ static void BE_RenderMeshProgram(program_t *p, shaderpass_t *pass, unsigned int
perm &= p->supportedpermutations; perm &= p->supportedpermutations;
BE_BindPipeline(p, shaderbits, VKBE_ApplyShaderBits(pass->shaderbits), perm); BE_BindPipeline(p, shaderbits, VKBE_ApplyShaderBits(pass->shaderbits), perm);
if (!shaderstate.activepipeline)
return false; //err, something bad happened.
//most gpus will have a fairly low descriptor set limit of 4 (this is the minimum required) //most gpus will have a fairly low descriptor set limit of 4 (this is the minimum required)
//that isn't enough for all our textures, so we need to make stuff up as required. //that isn't enough for all our textures, so we need to make stuff up as required.
@ -2567,6 +3150,8 @@ static void BE_RenderMeshProgram(program_t *p, shaderpass_t *pass, unsigned int
RQuantAdd(RQUANT_PRIMITIVEINDICIES, idxcount); RQuantAdd(RQUANT_PRIMITIVEINDICIES, idxcount);
RQuantAdd(RQUANT_DRAWS, 1); RQuantAdd(RQUANT_DRAWS, 1);
return true;
} }
static void BE_DrawMeshChain_Internal(void) static void BE_DrawMeshChain_Internal(void)
@ -2933,8 +3518,8 @@ static void BE_DrawMeshChain_Internal(void)
} }
vkCmdBindVertexBuffers(vk.frame->cbuf, 0, VK_BUFF_MAX, vertexbuffers, vertexoffsets); vkCmdBindVertexBuffers(vk.frame->cbuf, 0, VK_BUFF_MAX, vertexbuffers, vertexoffsets);
BE_RenderMeshProgram(altshader->prog, altshader->passes, altshader->flags, idxfirst, idxcount); if (BE_SetupMeshProgram(altshader->prog, altshader->passes, altshader->flags, idxcount))
vkCmdDrawIndexed(vk.frame->cbuf, idxcount, 1, idxfirst, 0, 0); vkCmdDrawIndexed(vk.frame->cbuf, idxcount, 1, idxfirst, 0, 0);
} }
else if (1) else if (1)
{ {
@ -2998,16 +3583,18 @@ static void BE_DrawMeshChain_Internal(void)
vertexoffsets[VK_BUFF_COL] = 0; vertexoffsets[VK_BUFF_COL] = 0;
vkCmdBindVertexBuffers(vk.frame->cbuf, 0, VK_BUFF_MAX, vertexbuffers, vertexoffsets); vkCmdBindVertexBuffers(vk.frame->cbuf, 0, VK_BUFF_MAX, vertexbuffers, vertexoffsets);
BE_RenderMeshProgram(shaderstate.programfixedemu[1], p, altshader->flags, idxfirst, idxcount); if (BE_SetupMeshProgram(shaderstate.programfixedemu[1], p, altshader->flags, idxcount))
vkCmdPushConstants(vk.frame->cbuf, shaderstate.programfixedemu[1]->layout, VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(passcolour), passcolour); {
vkCmdDrawIndexed(vk.frame->cbuf, idxcount, 1, idxfirst, 0, 0); vkCmdPushConstants(vk.frame->cbuf, shaderstate.programfixedemu[1]->layout, VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(passcolour), passcolour);
vkCmdDrawIndexed(vk.frame->cbuf, idxcount, 1, idxfirst, 0, 0);
}
} }
else else
{ {
BE_GenerateColourMods(vertcount, p, &vertexbuffers[VK_BUFF_COL], &vertexoffsets[VK_BUFF_COL]); BE_GenerateColourMods(vertcount, p, &vertexbuffers[VK_BUFF_COL], &vertexoffsets[VK_BUFF_COL]);
vkCmdBindVertexBuffers(vk.frame->cbuf, 0, VK_BUFF_MAX, vertexbuffers, vertexoffsets); vkCmdBindVertexBuffers(vk.frame->cbuf, 0, VK_BUFF_MAX, vertexbuffers, vertexoffsets);
BE_RenderMeshProgram(shaderstate.programfixedemu[0], p, altshader->flags, idxfirst, idxcount); if (BE_SetupMeshProgram(shaderstate.programfixedemu[0], p, altshader->flags, idxcount))
vkCmdDrawIndexed(vk.frame->cbuf, idxcount, 1, idxfirst, 0, 0); vkCmdDrawIndexed(vk.frame->cbuf, idxcount, 1, idxfirst, 0, 0);
} }
} }
} }
@ -3060,7 +3647,10 @@ qboolean VKBE_SelectDLight(dlight_t *dl, vec3_t colour, vec3_t axis[3], unsigned
{ {
lmode &= ~(LSHADER_SMAP|LSHADER_CUBE); lmode &= ~(LSHADER_SMAP|LSHADER_CUBE);
if (!VKBE_GenerateRTLightShader(lmode)) if (!VKBE_GenerateRTLightShader(lmode))
{
VKBE_SetupLightCBuffer(NULL, colour);
return false; return false;
}
} }
shaderstate.curdlight = dl; shaderstate.curdlight = dl;
shaderstate.curlmode = lmode; shaderstate.curlmode = lmode;
@ -3835,10 +4425,13 @@ void VKBE_RT_Gen(struct vk_rendertarg *targ, uint32_t width, uint32_t height)
return; //no work to do. return; //no work to do.
if (targ->framebuffer) if (targ->framebuffer)
{ //schedule the old one to be destroyed at the end of the current frame. DIE OLD ONE, DIE! { //schedule the old one to be destroyed at the end of the current frame. DIE OLD ONE, DIE!
purge = VK_AtFrameEnd(VKBE_RT_Purge, sizeof(purge)); purge = VK_AtFrameEnd(VKBE_RT_Purge, sizeof(*purge));
purge->framebuffer = targ->framebuffer; purge->framebuffer = targ->framebuffer;
purge->colour = targ->colour; purge->colour = targ->colour;
purge->depth = targ->depth; purge->depth = targ->depth;
memset(&targ->colour, 0, sizeof(targ->colour));
memset(&targ->depth, 0, sizeof(targ->depth));
targ->framebuffer = VK_NULL_HANDLE;
} }
targ->q_colour.vkimage = &targ->colour; targ->q_colour.vkimage = &targ->colour;
@ -4861,8 +5454,8 @@ void VKBE_RenderShadowBuffer(struct vk_shadowbuffer *buf)
vkCmdBindVertexBuffers(vk.frame->cbuf, 0, 1, &buf->vbuffer, &buf->voffset); vkCmdBindVertexBuffers(vk.frame->cbuf, 0, 1, &buf->vbuffer, &buf->voffset);
vkCmdBindIndexBuffer(vk.frame->cbuf, buf->ibuffer, buf->ioffset, VK_INDEX_TYPE); vkCmdBindIndexBuffer(vk.frame->cbuf, buf->ibuffer, buf->ioffset, VK_INDEX_TYPE);
BE_RenderMeshProgram(depthonlyshader->prog, depthonlyshader->passes, 0, 0, buf->numindicies); if (BE_SetupMeshProgram(depthonlyshader->prog, depthonlyshader->passes, 0, buf->numindicies))
vkCmdDrawIndexed(vk.frame->cbuf, buf->numindicies, 1, 0, 0, 0); vkCmdDrawIndexed(vk.frame->cbuf, buf->numindicies, 1, 0, 0, 0);
} }

View file

@ -8,6 +8,7 @@
extern qboolean vid_isfullscreen; extern qboolean vid_isfullscreen;
extern cvar_t vk_submissionthread; extern cvar_t vk_submissionthread;
extern cvar_t vk_debug; extern cvar_t vk_debug;
extern cvar_t vk_loadglsl;
extern cvar_t vid_srgb, vid_vsync, vid_triplebuffer, r_stereo_method; extern cvar_t vid_srgb, vid_vsync, vid_triplebuffer, r_stereo_method;
void R2D_Console_Resize(void); void R2D_Console_Resize(void);
@ -138,10 +139,13 @@ static void VK_DestroySwapChain(void)
{ {
uint32_t i; uint32_t i;
Sys_LockConditional(vk.submitcondition); if (vk.submitcondition)
vk.neednewswapchain = true; {
Sys_ConditionSignal(vk.submitcondition); Sys_LockConditional(vk.submitcondition);
Sys_UnlockConditional(vk.submitcondition); vk.neednewswapchain = true;
Sys_ConditionSignal(vk.submitcondition);
Sys_UnlockConditional(vk.submitcondition);
}
if (vk.submitthread) if (vk.submitthread)
{ {
Sys_WaitOnThread(vk.submitthread); Sys_WaitOnThread(vk.submitthread);
@ -160,7 +164,8 @@ static void VK_DestroySwapChain(void)
VK_Submit_DoWork(); VK_Submit_DoWork();
Sys_UnlockConditional(vk.submitcondition); Sys_UnlockConditional(vk.submitcondition);
} }
vkDeviceWaitIdle(vk.device); if (vk.device)
vkDeviceWaitIdle(vk.device);
VK_FencedCheck(); VK_FencedCheck();
while(vk.frameendjobs) while(vk.frameendjobs)
{ //we've fully synced the gpu now, we can clean up any resources that were pending but not assigned yet. { //we've fully synced the gpu now, we can clean up any resources that were pending but not assigned yet.
@ -377,7 +382,7 @@ static qboolean VK_CreateSwapChain(void)
VkAssert(vkCreateFence(vk.device,&fci,vkallocationcb,&vk.acquirefences[i])); VkAssert(vkCreateFence(vk.device,&fci,vkallocationcb,&vk.acquirefences[i]));
} }
/*-1 to hide any weird thread issues*/ /*-1 to hide any weird thread issues*/
while (vk.aquirelast < ACQUIRELIMIT-1 && vk.aquirelast < vk.backbuf_count && vk.aquirelast < 2 && vk.aquirelast <= vk.backbuf_count-surfcaps.minImageCount) while (vk.aquirelast < ACQUIRELIMIT-1 && vk.aquirelast < vk.backbuf_count && vk.aquirelast <= vk.backbuf_count-surfcaps.minImageCount)
{ {
VkAssert(vkAcquireNextImageKHR(vk.device, vk.swapchain, UINT64_MAX, VK_NULL_HANDLE, vk.acquirefences[vk.aquirelast%ACQUIRELIMIT], &vk.acquirebufferidx[vk.aquirelast%ACQUIRELIMIT])); VkAssert(vkAcquireNextImageKHR(vk.device, vk.swapchain, UINT64_MAX, VK_NULL_HANDLE, vk.acquirefences[vk.aquirelast%ACQUIRELIMIT], &vk.acquirebufferidx[vk.aquirelast%ACQUIRELIMIT]));
vk.aquirelast++; vk.aquirelast++;
@ -805,7 +810,6 @@ void VK_FencedSync(void *work)
//the command buffer in question may even have not yet been submitted yet. //the command buffer in question may even have not yet been submitted yet.
void *VK_AtFrameEnd(void (*passed)(void *work), size_t worksize) void *VK_AtFrameEnd(void (*passed)(void *work), size_t worksize)
{ {
//FIXME: OMG! BIG LEAK!
struct vk_fencework *w = Z_Malloc(worksize?worksize:sizeof(*w)); struct vk_fencework *w = Z_Malloc(worksize?worksize:sizeof(*w));
w->Passed = passed; w->Passed = passed;
@ -1090,39 +1094,12 @@ void VK_R_DeInit (void)
void VK_SetupViewPortProjection(void) void VK_SetupViewPortProjection(void)
{ {
extern cvar_t gl_mindist; extern cvar_t gl_mindist;
int x, x2, y2, y, w, h;
float fov_x, fov_y; float fov_x, fov_y;
AngleVectors (r_refdef.viewangles, vpn, vright, vup); AngleVectors (r_refdef.viewangles, vpn, vright, vup);
VectorCopy (r_refdef.vieworg, r_origin); VectorCopy (r_refdef.vieworg, r_origin);
//
// set up viewpoint
//
x = r_refdef.vrect.x * vid.pixelwidth/(int)vid.width;
x2 = (r_refdef.vrect.x + r_refdef.vrect.width) * vid.pixelwidth/(int)vid.width;
y = (r_refdef.vrect.y) * vid.pixelheight/(int)vid.height;
y2 = ((int)(r_refdef.vrect.y + r_refdef.vrect.height)) * vid.pixelheight/(int)vid.height;
// fudge around because of frac screen scale
if (x > 0)
x--;
if (x2 < vid.pixelwidth)
x2++;
if (y < 0)
y--;
if (y2 < vid.pixelheight)
y2++;
w = x2 - x;
h = y2 - y;
r_refdef.pxrect.x = x;
r_refdef.pxrect.y = y;
r_refdef.pxrect.width = w;
r_refdef.pxrect.height = h;
fov_x = r_refdef.fov_x;//+sin(cl.time)*5; fov_x = r_refdef.fov_x;//+sin(cl.time)*5;
fov_y = r_refdef.fov_y;//-sin(cl.time+1)*5; fov_y = r_refdef.fov_y;//-sin(cl.time+1)*5;
@ -1315,6 +1292,15 @@ void VK_Init_PostProc(void)
); );
vk.scenepp_waterwarp->defaulttextures->upperoverlay = scenepp_texture_warp; vk.scenepp_waterwarp->defaulttextures->upperoverlay = scenepp_texture_warp;
vk.scenepp_waterwarp->defaulttextures->loweroverlay = scenepp_texture_edge; vk.scenepp_waterwarp->defaulttextures->loweroverlay = scenepp_texture_edge;
vk.scenepp_antialias = R_RegisterShader("fte_ppantialias", 0,
"{\n"
"program fxaa\n"
"{\n"
"map $sourcecolour\n"
"}\n"
"}\n"
);
} }
@ -1322,6 +1308,10 @@ void VK_R_RenderView (void)
{ {
extern unsigned int r_viewcontents; extern unsigned int r_viewcontents;
struct vk_rendertarg *rt; struct vk_rendertarg *rt;
extern cvar_t r_fxaa;
extern cvar_t r_renderscale, r_postprocshader;
float renderscale = r_renderscale.value;
shader_t *custompostproc;
if (r_norefresh.value || !vid.fbpwidth || !vid.fbpwidth) if (r_norefresh.value || !vid.fbpwidth || !vid.fbpwidth)
{ {
@ -1357,12 +1347,59 @@ void VK_R_RenderView (void)
r_refdef.globalfog.density /= 64; //FIXME r_refdef.globalfog.density /= 64; //FIXME
} }
VK_SetupViewPortProjection(); custompostproc = NULL;
if (!(r_refdef.flags & RDF_NOWORLDMODEL) && (*r_postprocshader.string))
//FIXME: RDF_BLOOM|RDF_FISHEYE|RDF_CUSTOMPOSTPROC|RDF_ANTIALIAS|RDF_RENDERSCALE
if (r_refdef.flags & RDF_ALLPOSTPROC)
{ {
custompostproc = R_RegisterCustom(r_postprocshader.string, SUF_NONE, NULL, NULL);
if (custompostproc)
r_refdef.flags |= RDF_CUSTOMPOSTPROC;
}
if (!(r_refdef.flags & RDF_NOWORLDMODEL) && r_fxaa.ival) //overlays will have problems.
r_refdef.flags |= RDF_ANTIALIAS;
//
// figure out the viewport
//
{
int x = r_refdef.vrect.x * vid.pixelwidth/(int)vid.width;
int x2 = (r_refdef.vrect.x + r_refdef.vrect.width) * vid.pixelwidth/(int)vid.width;
int y = (r_refdef.vrect.y) * vid.pixelheight/(int)vid.height;
int y2 = ((int)(r_refdef.vrect.y + r_refdef.vrect.height)) * vid.pixelheight/(int)vid.height;
// fudge around because of frac screen scale
if (x > 0)
x--;
if (x2 < vid.pixelwidth)
x2++;
if (y < 0)
y--;
if (y2 < vid.pixelheight)
y2++;
r_refdef.pxrect.x = x;
r_refdef.pxrect.y = y;
r_refdef.pxrect.width = x2 - x;
r_refdef.pxrect.height = y2 - y;
}
if (renderscale != 1.0)
{
r_refdef.flags |= RDF_RENDERSCALE;
r_refdef.pxrect.width *= renderscale;
r_refdef.pxrect.height *= renderscale;
}
if (r_refdef.pxrect.width <= 0 || r_refdef.pxrect.height <= 0)
return; //you're not allowed to do that, dude.
//FIXME: RDF_BLOOM|RDF_FISHEYE
//FIXME: VF_RT_*
if (r_refdef.flags & (RDF_ALLPOSTPROC|RDF_RENDERSCALE))
{
r_refdef.pxrect.x = 0;
r_refdef.pxrect.y = 0;
rt = &postproc[postproc_buf++%countof(postproc)]; rt = &postproc[postproc_buf++%countof(postproc)];
if (rt->width != r_refdef.pxrect.width || rt->height != r_refdef.pxrect.height) if (rt->width != r_refdef.pxrect.width || rt->height != r_refdef.pxrect.height)
VKBE_RT_Gen(rt, r_refdef.pxrect.width, r_refdef.pxrect.height); VKBE_RT_Gen(rt, r_refdef.pxrect.width, r_refdef.pxrect.height);
@ -1371,39 +1408,8 @@ void VK_R_RenderView (void)
else else
rt = NULL; rt = NULL;
/* VK_SetupViewPortProjection();
{
VkClearDepthStencilValue val;
VkImageSubresourceRange range;
val.depth = 1;
val.stencil = 0;
range.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
range.baseArrayLayer = 0;
range.baseMipLevel = 0;
range.layerCount = 1;
range.levelCount = 1;
vkCmdClearDepthStencilImage(vk.frame->cbuf, vk.depthbuf.image, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, &val, 1, &range);
}
*/
/*
vkCmdEndRenderPass(vk.frame->cbuf);
{
VkRenderPassBeginInfo rpiinfo = {VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO};
VkClearValue clearvalues[1];
clearvalues[0].depthStencil.depth = 1.0;
clearvalues[0].depthStencil.stencil = 0;
rpiinfo.renderPass = vk.renderpass[1];
rpiinfo.renderArea.offset.x = r_refdef.pxrect.x;
rpiinfo.renderArea.offset.y = r_refdef.pxrect.y;
rpiinfo.renderArea.extent.width = r_refdef.pxrect.width;
rpiinfo.renderArea.extent.height = r_refdef.pxrect.height;
rpiinfo.framebuffer = vk.frame->backbuf->framebuffer;
rpiinfo.clearValueCount = 1;
rpiinfo.pClearValues = clearvalues;
vkCmdBeginRenderPass(vk.frame->cbuf, &rpiinfo, VK_SUBPASS_CONTENTS_INLINE);
}
*/
{ {
VkViewport vp[1]; VkViewport vp[1];
VkRect2D scissor[1]; VkRect2D scissor[1];
@ -1465,7 +1471,6 @@ void VK_R_RenderView (void)
r_refdef.flags &= ~RDF_WATERWARP; r_refdef.flags &= ~RDF_WATERWARP;
VKBE_RT_End(); //WARNING: redundant begin+end renderpasses. VKBE_RT_End(); //WARNING: redundant begin+end renderpasses.
vk.sourcecolour = &rt->q_colour; vk.sourcecolour = &rt->q_colour;
vk.sourcecolour = &rt->q_colour;
if (r_refdef.flags & RDF_ALLPOSTPROC) if (r_refdef.flags & RDF_ALLPOSTPROC)
{ {
rt = &postproc[postproc_buf++]; rt = &postproc[postproc_buf++];
@ -1475,6 +1480,51 @@ void VK_R_RenderView (void)
R2D_Image(r_refdef.vrect.x, r_refdef.vrect.y, r_refdef.vrect.width, r_refdef.vrect.height, 0, 0, 1, 1, vk.scenepp_waterwarp); R2D_Image(r_refdef.vrect.x, r_refdef.vrect.y, r_refdef.vrect.width, r_refdef.vrect.height, 0, 0, 1, 1, vk.scenepp_waterwarp);
R2D_Flush(); R2D_Flush();
} }
if (r_refdef.flags & RDF_CUSTOMPOSTPROC)
{
r_refdef.flags &= ~RDF_CUSTOMPOSTPROC;
VKBE_RT_End(); //WARNING: redundant begin+end renderpasses.
vk.sourcecolour = &rt->q_colour;
if (r_refdef.flags & RDF_ALLPOSTPROC)
{
rt = &postproc[postproc_buf++];
VKBE_RT_Begin(rt, 320, 240);
}
R2D_Image(r_refdef.vrect.x, r_refdef.vrect.y, r_refdef.vrect.width, r_refdef.vrect.height, 0, 1, 1, 0, custompostproc);
R2D_Flush();
}
if (r_refdef.flags & RDF_ANTIALIAS)
{
r_refdef.flags &= ~RDF_ANTIALIAS;
VKBE_RT_End(); //WARNING: redundant begin+end renderpasses.
vk.sourcecolour = &rt->q_colour;
if (r_refdef.flags & RDF_ALLPOSTPROC)
{
rt = &postproc[postproc_buf++];
VKBE_RT_Begin(rt, 320, 240);
}
R2D_Image(r_refdef.vrect.x, r_refdef.vrect.y, r_refdef.vrect.width, r_refdef.vrect.height, 0, 1, 1, 0, vk.scenepp_antialias);
R2D_Flush();
}
//FIXME: bloom
}
else if (r_refdef.flags & RDF_RENDERSCALE)
{
if (!vk.scenepp_rescale)
vk.scenepp_rescale = R_RegisterShader("fte_rescaler", 0,
"{\n"
"program default2d\n"
"{\n"
"map $sourcecolour\n"
"}\n"
"}\n"
);
VKBE_RT_End(); //WARNING: redundant begin+end renderpasses.
vk.sourcecolour = &rt->q_colour;
R2D_Image(r_refdef.vrect.x, r_refdef.vrect.y, r_refdef.vrect.width, r_refdef.vrect.height, 0, 0, 1, 1, vk.scenepp_rescale);
R2D_Flush();
} }
vk.sourcecolour = r_nulltex; vk.sourcecolour = r_nulltex;
@ -1741,12 +1791,11 @@ qboolean VK_SCR_GrabBackBuffer(void)
#ifdef THREADACQUIRE #ifdef THREADACQUIRE
while (vk.aquirenext == vk.aquirelast) while (vk.aquirenext == vk.aquirelast)
{ //we're still waiting for the render thread to increment acquirelast. { //we're still waiting for the render thread to increment acquirelast.
if (vk.vsync) Sys_Sleep(0); //o.O
Sys_Sleep(0); //o.O
} }
//wait for the queued acquire to actually finish //wait for the queued acquire to actually finish
if (vk.vsync) if (1)//vk.vsync)
{ {
//friendly wait //friendly wait
VkAssert(vkWaitForFences(vk.device, 1, &vk.acquirefences[vk.aquirenext%ACQUIRELIMIT], VK_FALSE, UINT64_MAX)); VkAssert(vkWaitForFences(vk.device, 1, &vk.acquirefences[vk.aquirenext%ACQUIRELIMIT], VK_FALSE, UINT64_MAX));
@ -1880,7 +1929,7 @@ qboolean VK_SCR_GrabBackBuffer(void)
if (r_clear.ival) if (r_clear.ival)
rpbi.renderPass = vk.renderpass[2]; rpbi.renderPass = vk.renderpass[2];
else else
rpbi.renderPass = vk.renderpass[1]; rpbi.renderPass = vk.renderpass[1]; //may still clear
rpbi.framebuffer = vk.frame->backbuf->framebuffer; rpbi.framebuffer = vk.frame->backbuf->framebuffer;
rpbi.renderArea.offset.x = 0; rpbi.renderArea.offset.x = 0;
rpbi.renderArea.offset.y = 0; rpbi.renderArea.offset.y = 0;
@ -1951,7 +2000,6 @@ void VK_DebugFramerate(void)
qboolean VK_SCR_UpdateScreen (void) qboolean VK_SCR_UpdateScreen (void)
{ {
RSpeedLocals();
VkCommandBuffer bufs[1]; VkCommandBuffer bufs[1];
VK_FencedCheck(); VK_FencedCheck();
@ -1991,7 +2039,7 @@ qboolean VK_SCR_UpdateScreen (void)
VK_CreateSwapChain(); VK_CreateSwapChain();
vk.neednewswapchain = false; vk.neednewswapchain = false;
if (vk_submissionthread.ival) if (vk_submissionthread.ival || !*vk_submissionthread.string)
{ {
vk.submitthread = Sys_CreateThread("vksubmission", VK_Submit_Thread, NULL, THREADP_HIGHEST, 0); vk.submitthread = Sys_CreateThread("vksubmission", VK_Submit_Thread, NULL, THREADP_HIGHEST, 0);
} }
@ -2031,11 +2079,7 @@ qboolean VK_SCR_UpdateScreen (void)
// vkCmdWriteTimestamp(vk.frame->cbuf, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, querypool, vk.bufferidx*2+1); // vkCmdWriteTimestamp(vk.frame->cbuf, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, querypool, vk.bufferidx*2+1);
vkEndCommandBuffer(vk.frame->cbuf); vkEndCommandBuffer(vk.frame->cbuf);
{ VKBE_FlushDynamicBuffers();
RSpeedRemark();
VKBE_FlushDynamicBuffers();
RSpeedEnd(RSPEED_SUBMIT);
}
bufs[0] = vk.frame->cbuf; bufs[0] = vk.frame->cbuf;
@ -2387,16 +2431,13 @@ qboolean VK_Init(rendererstate_t *info, const char *sysextname, qboolean (*creat
VkResult err; VkResult err;
VkApplicationInfo app; VkApplicationInfo app;
VkInstanceCreateInfo inst_info; VkInstanceCreateInfo inst_info;
const char *extensions[] = { sysextname, const char *extensions[8];
VK_KHR_SURFACE_EXTENSION_NAME, qboolean nvglsl = false;
VK_EXT_DEBUG_REPORT_EXTENSION_NAME uint32_t extensions_count = 0;
}; extensions[extensions_count++] = sysextname;
uint32_t extensions_count; extensions[extensions_count++] = VK_KHR_SURFACE_EXTENSION_NAME;
if (vk_debug.ival) if (vk_debug.ival)
extensions_count = 3; extensions[extensions_count++] = VK_EXT_DEBUG_REPORT_EXTENSION_NAME;
else
extensions_count = 2;
vk.neednewswapchain = true; vk.neednewswapchain = true;
vk.triplebuffer = info->triplebuffer; vk.triplebuffer = info->triplebuffer;
@ -2629,12 +2670,31 @@ qboolean VK_Init(rendererstate_t *info, const char *sysextname, qboolean (*creat
} }
} }
{ {
const char *devextensions[] = { VK_KHR_SWAPCHAIN_EXTENSION_NAME}; uint32_t extcount = 0;
VkExtensionProperties *ext;
vkEnumerateDeviceExtensionProperties(vk.gpu, NULL, &extcount, NULL);
ext = malloc(sizeof(*ext)*extcount);
vkEnumerateDeviceExtensionProperties(vk.gpu, NULL, &extcount, ext);
while (extcount --> 0)
{
if (!strcmp(ext[extcount].extensionName, VK_NV_GLSL_SHADER_EXTENSION_NAME))
nvglsl = !!vk_loadglsl.ival;
}
free(ext);
}
{
const char *devextensions[8];
size_t numdevextensions = 0;
float queue_priorities[1] = {1.0}; float queue_priorities[1] = {1.0};
VkDeviceQueueCreateInfo queueinf[2] = {{VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO},{VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO}}; VkDeviceQueueCreateInfo queueinf[2] = {{VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO},{VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO}};
VkDeviceCreateInfo devinf = {VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO}; VkDeviceCreateInfo devinf = {VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO};
devextensions[numdevextensions++] = VK_KHR_SWAPCHAIN_EXTENSION_NAME;
if (nvglsl)
devextensions[numdevextensions++] = VK_NV_GLSL_SHADER_EXTENSION_NAME;
queueinf[0].pNext = NULL; queueinf[0].pNext = NULL;
queueinf[0].queueFamilyIndex = vk.queueidx[0]; queueinf[0].queueFamilyIndex = vk.queueidx[0];
queueinf[0].queueCount = countof(queue_priorities); queueinf[0].queueCount = countof(queue_priorities);
@ -2648,7 +2708,7 @@ qboolean VK_Init(rendererstate_t *info, const char *sysextname, qboolean (*creat
devinf.pQueueCreateInfos = queueinf; devinf.pQueueCreateInfos = queueinf;
devinf.enabledLayerCount = vklayercount; devinf.enabledLayerCount = vklayercount;
devinf.ppEnabledLayerNames = vklayerlist; devinf.ppEnabledLayerNames = vklayerlist;
devinf.enabledExtensionCount = countof(devextensions); devinf.enabledExtensionCount = numdevextensions;
devinf.ppEnabledExtensionNames = devextensions; devinf.ppEnabledExtensionNames = devextensions;
devinf.pEnabledFeatures = NULL; devinf.pEnabledFeatures = NULL;
@ -2690,12 +2750,18 @@ qboolean VK_Init(rendererstate_t *info, const char *sysextname, qboolean (*creat
} }
sh_config.progpath = NULL;//"vulkan"; sh_config.progpath = NULL;
sh_config.blobpath = "spirv"; sh_config.blobpath = "spirv";
sh_config.shadernamefmt = NULL;//".spv"; sh_config.shadernamefmt = NULL;//".spv";
if (nvglsl)
{
sh_config.progpath = "glsl/%s.glsl";
sh_config.shadernamefmt = "%s_glsl";
}
sh_config.progs_supported = true; sh_config.progs_supported = true;
sh_config.progs_required = false;//true; sh_config.progs_required = true;
sh_config.minver = -1; sh_config.minver = -1;
sh_config.maxver = -1; sh_config.maxver = -1;
@ -2714,7 +2780,10 @@ qboolean VK_Init(rendererstate_t *info, const char *sysextname, qboolean (*creat
sh_config.pDeleteProg = NULL; sh_config.pDeleteProg = NULL;
sh_config.pLoadBlob = NULL; sh_config.pLoadBlob = NULL;
sh_config.pCreateProgram = NULL; if (nvglsl)
sh_config.pCreateProgram = VK_LoadGLSL;
else
sh_config.pCreateProgram = NULL;
sh_config.pValidateProgram = NULL; sh_config.pValidateProgram = NULL;
sh_config.pProgAutoFields = NULL; sh_config.pProgAutoFields = NULL;
@ -2760,7 +2829,7 @@ qboolean VK_Init(rendererstate_t *info, const char *sysextname, qboolean (*creat
{ {
vk.neednewswapchain = false; vk.neednewswapchain = false;
if (vk_submissionthread.ival) if (vk_submissionthread.ival || !*vk_submissionthread.string)
{ {
vk.submitthread = Sys_CreateThread("vksubmission", VK_Submit_Thread, NULL, THREADP_HIGHEST, 0); vk.submitthread = Sys_CreateThread("vksubmission", VK_Submit_Thread, NULL, THREADP_HIGHEST, 0);
} }

View file

@ -40,6 +40,7 @@
//funcs specific to an instance //funcs specific to an instance
#define VKInst2Funcs \ #define VKInst2Funcs \
VKFunc(EnumeratePhysicalDevices) \ VKFunc(EnumeratePhysicalDevices) \
VKFunc(EnumerateDeviceExtensionProperties) \
VKFunc(GetPhysicalDeviceProperties) \ VKFunc(GetPhysicalDeviceProperties) \
VKFunc(GetPhysicalDeviceQueueFamilyProperties) \ VKFunc(GetPhysicalDeviceQueueFamilyProperties) \
VKFunc(GetPhysicalDeviceSurfaceSupportKHR) \ VKFunc(GetPhysicalDeviceSurfaceSupportKHR) \
@ -314,6 +315,8 @@ extern struct vulkaninfo_s
texid_t sourcedepth; texid_t sourcedepth;
shader_t *scenepp_waterwarp; shader_t *scenepp_waterwarp;
shader_t *scenepp_antialias;
shader_t *scenepp_rescale;
} vk; } vk;
struct pipeline_s struct pipeline_s
@ -333,6 +336,9 @@ qboolean VK_LoadTextureMips (texid_t tex, struct pendingtextureinfo *mips);
qboolean VK_Init(rendererstate_t *info, const char *sysextname, qboolean (*createSurface)(void)); qboolean VK_Init(rendererstate_t *info, const char *sysextname, qboolean (*createSurface)(void));
void VK_Shutdown(void); void VK_Shutdown(void);
struct programshared_s;
qboolean VK_LoadGLSL(struct programshared_s *prog, const char *name, unsigned int permu, int ver, const char **precompilerconstants, const char *vert, const char *tcs, const char *tes, const char *geom, const char *frag, qboolean noerrors, vfsfile_t *blobfile);
void VKBE_Init(void); void VKBE_Init(void);
void VKBE_InitFramePools(struct vkframe *frame); void VKBE_InitFramePools(struct vkframe *frame);
void VKBE_RestartFrame(void); void VKBE_RestartFrame(void);

View file

@ -82,12 +82,13 @@ nonstatic void(mitem_desktop desktop) M_Main =
#endif #endif
{menuitemtext_cladd16(m, _("Join Server"), "m_pop;m_servers", y); y += 16;} {menuitemtext_cladd16(m, _("Join Server"), "m_pop;m_servers", y); y += 16;}
if (assumetruecheckcommand("map")) {menuitemtext_cladd16(m, _("New Game"), "m_pop;m_newgame", y); y += 16;} if (assumetruecheckcommand("map")) {menuitemtext_cladd16(m, _("New Game"), "m_pop;m_newgame", y); y += 16;}
if (assumetruecheckcommand("menu_demo")) {menuitemtext_cladd16(m, _("Demos"), "m_pop;menu_demo", y); y += 16;} if (assumefalsecheckcommand("menu_demo")) {menuitemtext_cladd16(m, _("Demos"), "m_pop;menu_demo", y); y += 16;}
if (assumetruecheckcommand("save") && (isserver()||dp_workarounds)) {menuitemtext_cladd16(m, _("Save"), "m_pop;m_save", y); y += 16;} if (assumetruecheckcommand("save") && (isserver()||dp_workarounds)) {menuitemtext_cladd16(m, _("Save"), "m_pop;m_save", y); y += 16;}
if (assumetruecheckcommand("load")) {menuitemtext_cladd16(m, _("Load"), "m_pop;m_load", y); y += 16;} if (assumetruecheckcommand("load")) {menuitemtext_cladd16(m, _("Load"), "m_pop;m_load", y); y += 16;}
if (assumefalsecheckcommand("cef")) {menuitemtext_cladd16(m, _("Browser"), "m_pop;cef google.com", y); y += 16;} if (assumefalsecheckcommand("cef")) {menuitemtext_cladd16(m, _("Browser"), "m_pop;cef google.com", y); y += 16;}
if (assumefalsecheckcommand("xmpp")) {menuitemtext_cladd16(m, _("Social"), "m_pop;xmpp", y); y += 16;} if (assumefalsecheckcommand("xmpp")) {menuitemtext_cladd16(m, _("Social"), "m_pop;xmpp", y); y += 16;}
if (assumefalsecheckcommand("irc")) {menuitemtext_cladd16(m, _("IRC"), "m_pop;irc /info", y); y += 16;} if (assumefalsecheckcommand("irc")) {menuitemtext_cladd16(m, _("IRC"), "m_pop;irc /info", y); y += 16;}
if (assumefalsecheckcommand("menu_download")) {menuitemtext_cladd16(m, _("Updates+Packages"), "m_pop;menu_download", y); y += 16;}
if (assumefalsecheckcommand("qi")) {menuitemtext_cladd16(m, _("Quake Injector"), "m_pop;qi", y); y += 16;} if (assumefalsecheckcommand("qi")) {menuitemtext_cladd16(m, _("Quake Injector"), "m_pop;qi", y); y += 16;}
{menuitemtext_cladd16(m, _("Options"), "m_pop;m_options", y); y += 16;} {menuitemtext_cladd16(m, _("Options"), "m_pop;m_options", y); y += 16;}
{menuitemtext_cladd16(m, _("Quit"), "m_pop;m_quit", y); y += 16;} {menuitemtext_cladd16(m, _("Quit"), "m_pop;m_quit", y); y += 16;}