vulkan: rewrote render target stuff so bloom, r_projection, fxaa, should now be working.

gl: fix r_projection when using vid_restart.
hdr: fixed iris stuff to work in more renderers.
ircclient: don't disconnect instantly. that's just stupid.

git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@5010 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
Spoike 2016-07-28 13:18:22 +00:00
parent b14854ae04
commit 151bd6d0b1
25 changed files with 11954 additions and 8109 deletions

View file

@ -1944,6 +1944,6 @@ INSTALL ?= install
INSTALL_PROGRAM ?= $(INSTALL)
INSTALL_DATA ?= ${INSTALL} -m 644
install: sv-rel gl-rel mingl-rel qcc-rel
$(INSTALL_PROGRAM) $(RELEASE_DIR)fteqw $(DESTDIR)$(bindir)/fteqw
$(INSTALL_PROGRAM) $(RELEASE_DIR)fteqwsv $(DESTDIR)$(bindir)/fteqwsv
$(INSTALL_PROGRAM) $(RELEASE_DIR)fteqcc $(DESTDIR)$(bindir)/fteqcc
$(INSTALL_PROGRAM) $(RELEASE_DIR)/fteqw $(DESTDIR)$(bindir)/fteqw
$(INSTALL_PROGRAM) $(RELEASE_DIR)/fteqwsv $(DESTDIR)$(bindir)/fteqwsv
$(INSTALL_PROGRAM) $(RELEASE_DIR)/fteqcc $(DESTDIR)$(bindir)/fteqcc

View file

@ -726,7 +726,7 @@ static void Stats_LoadFragFile(char *name)
}
static int qm_strcmp(char *s1, char *s2)//not like strcmp at all...
static int qm_strcmp(const char *s1, const char *s2)//not like strcmp at all...
{
while(*s1)
{
@ -757,7 +757,7 @@ static int qm_stricmp(char *s1, char *s2)//not like strcmp at all...
}
*/
static int Stats_ExtractName(char **line)
static int Stats_ExtractName(const char **line)
{
int i;
int bm;
@ -801,7 +801,7 @@ qboolean Stats_ParsePrintLine(const char *line)
statmessage_t *ms;
int p1;
int p2;
char *m2;
const char *m2;
p1 = Stats_ExtractName(&line);
if (p1<0) //reject it.

View file

@ -128,28 +128,28 @@ cvar_t r_floorcolour = CVARAF ("r_floorcolour", "64 64 128",
// CVAR_RENDERERCALLBACK|CVAR_SHADERSYSTEM);
cvar_t r_fullbright = CVARFD ("r_fullbright", "0",
CVAR_CHEAT|CVAR_SHADERSYSTEM, "Ignore world lightmaps, drawing everything fully lit.");
cvar_t r_fullbrightSkins = SCVARF ("r_fullbrightSkins", "0.8", /*don't default to 1, as it looks a little ugly (too bright), but don't default to 0 either because then you're handicapped in the dark*/
cvar_t r_fullbrightSkins = CVARF ("r_fullbrightSkins", "0.8", /*don't default to 1, as it looks a little ugly (too bright), but don't default to 0 either because then you're handicapped in the dark*/
CVAR_SEMICHEAT|CVAR_SHADERSYSTEM);
cvar_t r_lightmap_saturation = SCVAR ("r_lightmap_saturation", "1");
cvar_t r_lightstylesmooth = CVARF ("r_lightstylesmooth", "0", CVAR_ARCHIVE);
cvar_t r_lightstylesmooth_limit = SCVAR ("r_lightstylesmooth_limit", "2");
cvar_t r_lightstylespeed = SCVAR ("r_lightstylespeed", "10");
cvar_t r_lightstylescale = SCVAR ("r_lightstylescale", "1");
cvar_t r_hdr_irisadaptation = CVARF ("r_hdr_irisadaptation", "0", CVAR_ARCHIVE);
cvar_t r_hdr_irisadaptation_multiplier = CVAR ("r_hdr_irisadaptation_multiplier", "2");
cvar_t r_hdr_irisadaptation_minvalue = CVAR ("r_hdr_irisadaptation_minvalue", "0.5");
cvar_t r_hdr_irisadaptation_maxvalue = CVAR ("r_hdr_irisadaptation_maxvalue", "4");
cvar_t r_hdr_irisadaptation_fade_down = CVAR ("r_hdr_irisadaptation_fade_down", "0.5");
cvar_t r_hdr_irisadaptation_fade_up = CVAR ("r_hdr_irisadaptation_fade_up", "0.1");
cvar_t r_loadlits = CVARF ("r_loadlit", "1", CVAR_ARCHIVE);
cvar_t r_menutint = SCVARF ("r_menutint", "0.68 0.4 0.13",
cvar_t r_lightmap_saturation = SCVAR ("r_lightmap_saturation", "1");
cvar_t r_lightstylesmooth = CVARF ("r_lightstylesmooth", "0", CVAR_ARCHIVE);
cvar_t r_lightstylesmooth_limit = SCVAR ("r_lightstylesmooth_limit", "2");
cvar_t r_lightstylespeed = SCVAR ("r_lightstylespeed", "10");
cvar_t r_lightstylescale = SCVAR ("r_lightstylescale", "1");
cvar_t r_hdr_irisadaptation = CVARF ("r_hdr_irisadaptation", "0", CVAR_ARCHIVE);
cvar_t r_hdr_irisadaptation_multiplier = CVAR ("r_hdr_irisadaptation_multiplier", "2");
cvar_t r_hdr_irisadaptation_minvalue = CVAR ("r_hdr_irisadaptation_minvalue", "0.5");
cvar_t r_hdr_irisadaptation_maxvalue = CVAR ("r_hdr_irisadaptation_maxvalue", "4");
cvar_t r_hdr_irisadaptation_fade_down = CVAR ("r_hdr_irisadaptation_fade_down", "0.5");
cvar_t r_hdr_irisadaptation_fade_up = CVAR ("r_hdr_irisadaptation_fade_up", "0.1");
cvar_t r_loadlits = CVARF ("r_loadlit", "1", CVAR_ARCHIVE);
cvar_t r_menutint = CVARF ("r_menutint", "0.68 0.4 0.13",
CVAR_RENDERERCALLBACK);
cvar_t r_netgraph = SCVAR ("r_netgraph", "0");
cvar_t r_netgraph = CVAR ("r_netgraph", "0");
extern cvar_t r_lerpmuzzlehack;
cvar_t r_nolerp = CVARF ("r_nolerp", "0", CVAR_ARCHIVE);
cvar_t r_noframegrouplerp = CVARF ("r_noframegrouplerp", "0", CVAR_ARCHIVE);
cvar_t r_nolightdir = CVARF ("r_nolightdir", "0", CVAR_ARCHIVE);
cvar_t r_novis = CVARF ("r_novis", "0", CVAR_ARCHIVE);
cvar_t r_nolerp = CVARF ("r_nolerp", "0", CVAR_ARCHIVE);
cvar_t r_noframegrouplerp = CVARF ("r_noframegrouplerp", "0", CVAR_ARCHIVE);
cvar_t r_nolightdir = CVARF ("r_nolightdir", "0", CVAR_ARCHIVE);
cvar_t r_novis = CVARF ("r_novis", "0", CVAR_ARCHIVE);
cvar_t r_part_rain = CVARFD ("r_part_rain", "0",
CVAR_ARCHIVE,
"Enable particle effects to emit off of surfaces. Mainly used for weather or lava/slime effects.");
@ -523,8 +523,6 @@ void GLRenderer_Init(void)
Cvar_Register (&gl_lightmap_nearest, GLRENDEREROPTIONS);
Cvar_Register (&gl_lightmap_average, GLRENDEREROPTIONS);
R_BloomRegister();
}
#endif
@ -634,6 +632,10 @@ void Renderer_Init(void)
GLRenderer_Init();
#endif
#if defined(GLQUAKE) || defined(VKQUAKE)
R_BloomRegister();
#endif
#ifdef SWQUAKE
{
extern cvar_t sw_interlace;

View file

@ -5069,7 +5069,7 @@ static int COM_WorkerThread(void *arg)
static void Sys_ErrorThread(void *ctx, void *data, size_t a, size_t b)
{
//posted to main thread from a worker.
Sys_Error(data);
Sys_Error("%s", data);
}
void COM_WorkerAbort(char *message)
{

View file

@ -3578,6 +3578,7 @@ void D3D11BE_DrawWorld (batch_t **worldbatches, qbyte *vis)
else
#endif
shaderstate.identitylighting = 1;
shaderstate.identitylighting *= r_refdef.hdr_value;
// shaderstate.identitylightmap = shaderstate.identitylighting / (1<<gl_overbright.ival);
BE_SelectMode(BEM_STANDARD);

View file

@ -41,7 +41,7 @@ http://prideout.net/archive/bloom/ contains some sample code
#include "quakedef.h"
#ifdef GLQUAKE
#if defined(GLQUAKE) || defined(VKQUAKE)
#include "shader.h"
#include "glquake.h"
#include "gl_draw.h"
@ -173,16 +173,130 @@ qboolean R_CanBloom(void)
{
if (!r_bloom.value)
return false;
if (!gl_config.ext_framebuffer_objects)
return false;
if (!gl_config.arb_shader_objects)
return false;
if (!sh_config.texture_non_power_of_two_pic)
switch(qrenderer)
{
#ifdef GLQUAKE
case QR_OPENGL:
if (!gl_config.ext_framebuffer_objects)
return false;
if (!gl_config.arb_shader_objects)
return false;
if (!sh_config.texture_non_power_of_two_pic)
return false;
break;
#endif
#ifdef VKQUAKE
case QR_VULKAN:
break;
#endif
default:
return false;
}
return true;
}
#ifdef VKQUAKE
#include "../vk/vkrenderer.h"
struct vk_rendertarg vk_rt_bloom[2][MAXLEVELS], vk_rt_filter;
void VK_R_BloomBlend (texid_t source, int x, int y, int w, int h)
{
int i;
struct vk_rendertarg *oldfbo = vk.rendertarg;
texid_t intex;
int pixels = 1;
int targetpixels = r_bloom_size.value * vid.pixelwidth / 320;
targetpixels *= r_bloom_initialscale.value;
/*whu?*/
if (!w || !h)
return;
/*update textures if we need to resize them*/
R_SetupBloomTextures(w, h);
if (R2D_Flush)
R2D_Flush();
#if 1
/*filter the screen into a downscaled image*/
VKBE_RT_Gen(&vk_rt_filter, texwidth[0], texheight[0], false);
VKBE_RT_Begin(&vk_rt_filter);
vk.sourcecolour = source;
R2D_ScalePic(0, 0, vid.width, vid.height, bloomfilter);
R2D_Flush();
intex = &vk_rt_filter.q_colour;
#else
intex = source;
#endif
for (pixels = 1, i = 0; pixels < targetpixels && i < MAXLEVELS; i++, pixels <<= 1)
{
//downsize the blur, for added accuracy
/*if (i > 0 && r_bloom_downsize.ival)
{
//simple downscale that multiple times
VKBE_RT_Gen(&vk_rt_bloom[0][i], texwidth[i], texheight[i], false);
VKBE_RT_Begin(&vk_rt_bloom[0][i]);
vk.sourcecolour = source;
R2D_ScalePic(0, vid.height, vid.width, -(int)vid.height, bloomrescale);
if (R2D_Flush)
R2D_Flush();
intex = &vk_rt_bloom[0][i];
r_worldentity.glowmod[0] = 1.0 / intex->width;
}
else*/
r_worldentity.glowmod[0] = 2.0 / intex->width;
r_worldentity.glowmod[1] = 0;
VKBE_RT_Gen(&vk_rt_bloom[1][i], texwidth[i], texheight[i], false);
VKBE_RT_Begin(&vk_rt_bloom[1][i]);
vk.sourcecolour = intex;
BE_SelectEntity(&r_worldentity);
R2D_ScalePic(0, 0, vid.width, vid.height, bloomblur);
R2D_Flush();
r_worldentity.glowmod[0] = 0;
r_worldentity.glowmod[1] = 1.0 / texheight[i];
VKBE_RT_Gen(&vk_rt_bloom[0][i], texwidth[i], texheight[i], false);
VKBE_RT_Begin(&vk_rt_bloom[0][i]);
vk.sourcecolour = &vk_rt_bloom[1][i].q_colour;
BE_SelectEntity(&r_worldentity);
R2D_ScalePic(0, 0, vid.width, vid.height, bloomblur);
R2D_Flush();
intex = &vk_rt_bloom[0][i].q_colour;
}
r_worldentity.glowmod[0] = 0;
r_worldentity.glowmod[1] = 0;
VKBE_RT_Begin(oldfbo);
//go back to the screen fbo
/*combine them onto the screen*/
bloomfinal->defaulttextures->base = intex;
bloomfinal->defaulttextures->loweroverlay = (i >= 2)?&vk_rt_bloom[0][i-2].q_colour:0;
bloomfinal->defaulttextures->upperoverlay = (i >= 3)?&vk_rt_bloom[0][i-3].q_colour:0;
vk.sourcecolour = source;
R2D_ScalePic(x, y, w, h, bloomfinal);
R2D_Flush();
}
void VK_R_BloomShutdown(void)
{
int i;
for (i = 0; i < MAXLEVELS; i++)
{
VKBE_RT_Gen(&vk_rt_bloom[0][i], 0, 0, false);
VKBE_RT_Gen(&vk_rt_bloom[1][i], 0, 0, false);
}
VKBE_RT_Gen(&vk_rt_filter, 0, 0, false);
R_InitBloomTextures();
}
#endif
#ifdef GLQUAKE
void R_BloomBlend (texid_t source, int x, int y, int w, int h)
{
int i;
@ -298,5 +412,6 @@ void R_BloomShutdown(void)
R_InitBloomTextures();
}
#endif
#endif

View file

@ -99,6 +99,7 @@ int scenepp_postproc_cube_size;
fbostate_t fbo_gameview;
fbostate_t fbo_postproc;
fbostate_t fbo_postproc_cube;
// KrimZon - init post processing - called in GL_CheckExtensions, when they're called
// I put it here so that only this file need be changed when messing with the post
@ -131,6 +132,7 @@ void GL_ShutdownPostProcessing(void)
{
GLBE_FBO_Destroy(&fbo_gameview);
GLBE_FBO_Destroy(&fbo_postproc);
GLBE_FBO_Destroy(&fbo_postproc_cube);
R_BloomShutdown();
}
@ -1418,7 +1420,6 @@ qboolean R_RenderScene_Cubemap(void)
extern cvar_t r_projection;
int oldfbo = -1;
qboolean usefbo = true; //this appears to be a 20% speedup in my tests.
static fbostate_t fbostate; //FIXME
qboolean fboreset = false;
int osm = r_refdef.stereomethod;
@ -1629,7 +1630,7 @@ qboolean R_RenderScene_Cubemap(void)
if (usefbo)
{
int r = GLBE_FBO_Update(&fbostate, FBO_RB_DEPTH|(fboreset?FBO_RESET:0), &scenepp_postproc_cube, 1, r_nulltex, cmapsize, cmapsize, i);
int r = GLBE_FBO_Update(&fbo_postproc_cube, FBO_RB_DEPTH|(fboreset?FBO_RESET:0), &scenepp_postproc_cube, 1, r_nulltex, cmapsize, cmapsize, i);
fboreset = false;
if (oldfbo < 0)
oldfbo = r;

File diff suppressed because it is too large Load diff

33
engine/shaders/Makefile Normal file
View file

@ -0,0 +1,33 @@
CC=i686-pc-mingw32-gcc
all:
NAMES= fixedemu altwater bloom_blur bloom_filter bloom_final colourtint crepuscular_opaque crepuscular_rays crepuscular_sky depthonly default2d defaultadditivesprite defaultskin defaultsky defaultfill defaultsprite defaultwall defaultwarp defaultgammacb drawflat_wall lpp_depthnorm lpp_light lpp_wall postproc_fisheye postproc_panorama postproc_laea postproc_stereographic postproc_equirectangular fxaa underwaterwarp menutint terrain rtlight
ALLNAMES+=$(foreach v,$(NAMES),glsl/$v.glsl)
ALLNAMES+=$(foreach v,$(NAMES),hlsl9/$v.hlsl)
ALLNAMES+=$(foreach v,$(NAMES),hlsl11/$v.hlsl)
ALLNAMES:=$(realpath $(ALLNAMES))
VKNAMES=$(realpath $(foreach v,$(NAMES),vulkan/$v.glsl))
VKNAMES+=postproc_fisheye
VKNAMES:=$(foreach v,$(VKNAMES),vulkanblobs/$(notdir $(basename $v)).fvb)
ALLNAMES+=$(VKNAMES)
generatebuiltinsl: generatebuiltinsl.c
$(CC) $< -o $@
makevulkanblob: makevulkanblob.c
$(CC) $< -o $@
vulkanblobs/%.fvb: vulkan/%.glsl makevulkanblob vulkan/sys/defs.h vulkan/sys/fog.h vulkan/sys/offsetmapping.h vulkan/sys/skeletal.h
./makevulkanblob $< $@
vulkanblobs/%.fvb: glsl/%.glsl makevulkanblob vulkan/sys/defs.h vulkan/sys/fog.h vulkan/sys/offsetmapping.h vulkan/sys/skeletal.h
./makevulkanblob $< $@
all: generatebuiltinsl $(ALLNAMES)
which glslangValidator
./generatebuiltinsl

View file

@ -76,12 +76,19 @@ void dumpprogstring(FILE *out, FILE *src)
}
fflush(out);
}
void dumpprogblob(FILE *out, unsigned char *buf, unsigned int size)
void dumpprogblob(FILE *out, FILE *src)
{
unsigned char *buf;
unsigned int size;
fseek(src, 0, SEEK_END);
size = ftell(src);
fseek(src, 0, SEEK_SET);
buf = malloc(size);
fread(buf, size, 1, src);
size_t totallen, i, linelen;
totallen = 0;
linelen = 32;
fflush(out);
fprintf(out, "\"");
for (i=0;i<size;i++)
{
@ -90,408 +97,22 @@ void dumpprogblob(FILE *out, unsigned char *buf, unsigned int size)
fprintf(out, "\"\n\"");
}
fprintf(out, "\"");
fflush(out);
}
struct blobheader
{
unsigned char blobmagic[4]; //\xffSPV
unsigned int blobversion;
unsigned int defaulttextures; //s_diffuse etc flags
unsigned int numtextures; //s_t0 count
unsigned int permutations; //
unsigned int cvarsoffset; //double-null terminated string. I,XYZW prefixes
unsigned int cvarslength;
unsigned int vertoffset;
unsigned int vertlength;
unsigned int fragoffset;
unsigned int fraglength;
};
void generateprogsblob(struct blobheader *prototype, FILE *out, FILE *vert, FILE *frag)
{
struct blobheader *blob;
int fraglen, vertlen, blobsize, cvarlen;
cvarlen = prototype->cvarslength;
cvarlen = (cvarlen + 3) & ~3; //round up for padding.
fseek(vert, 0, SEEK_END);
fseek(frag, 0, SEEK_END);
vertlen = ftell(vert);
fraglen = ftell(frag);
fseek(vert, 0, SEEK_SET);
fseek(frag, 0, SEEK_SET);
blobsize = sizeof(*blob) + cvarlen + fraglen + vertlen;
blob = malloc(blobsize);
*blob = *prototype;
blob->cvarsoffset = sizeof(*blob);
blob->cvarslength = prototype->cvarslength; //unpadded length
blob->vertoffset = blob->cvarsoffset+cvarlen;
blob->vertlength = vertlen;
blob->fragoffset = blob->vertoffset+vertlen;
blob->fraglength = fraglen;
memcpy((char*)blob+blob->cvarsoffset, (char*)prototype+prototype->cvarsoffset, prototype->cvarslength);
fread((char*)blob+blob->vertoffset, blob->vertlength, 1, vert);
fread((char*)blob+blob->fragoffset, blob->fraglength, 1, frag);
dumpprogblob(out, (unsigned char*)blob, blobsize);
free(blob);
}
int generatevulkanblobs(struct blobheader *blob, size_t maxblobsize, char *fname)
{
char command[1024];
char glslname[256];
char tempname[256];
int inheader = 1;
int i;
unsigned short constid = 256; //first few are reserved.
const char *permutationnames[] =
{
"BUMP",
"FULLBRIGHT",
"UPPERLOWER",
"REFLECTCUBEMASK",
"SKELETAL",
"FOG",
"FRAMEBLEND",
"LIGHTSTYLED",
NULL
};
snprintf(glslname, sizeof(glslname), "vulkan/%s.glsl", fname);
snprintf(tempname, sizeof(tempname), "vulkan/%s.tmp", fname);
// snprintf(vertname, sizeof(vertname), "vulkan/%s.vert", fname);
// snprintf(fragname, sizeof(fragname), "vulkan/%s.frag", fname);
memcpy(blob->blobmagic, "\xffSPV", 4);
blob->blobversion = 1;
blob->defaulttextures = 0;
blob->numtextures = 0;
blob->permutations = 0;
blob->cvarsoffset = sizeof(*blob);
blob->cvarslength = 0;
FILE *glsl = fopen(glslname, "rt");
if (!glsl)
return 0;
FILE *temp = fopen(tempname, "wt");
while(fgets(command, sizeof(command), glsl))
{
if (inheader && !strncmp(command, "!!", 2))
{
if (!strncmp(command, "!!cvar", 6) || !strncmp(command, "!!arg", 5))
{
unsigned int type;
unsigned int size;
union
{
float f;
unsigned int u;
} u[4];
char *arg;
unsigned char *cb = (unsigned char*)blob + blob->cvarsoffset + blob->cvarslength;
if (command[2] == 'a')
{
type = command[5] == 'i' || command[5] == 'f' || command[5] == 'b';
size = type?1:(command[5]-'0');
arg = strtok(command+7, " ,=\n");
type = command[6-type] - 'a' + 'A';
}
else
{
type = command[6] == 'i' || command[6] == 'f' || command[6] == 'b';
size = type?1:(command[6]-'0');
arg = strtok(command+8, " ,=\n");
type = command[7-type];
}
cb[0] = (constid>>8)&0xff;
cb[1] = (constid>>0)&0xff;
cb[2] = type;
cb[3] = size + '0';
cb += 4;
while(*arg)
*cb++ = *arg++;
*cb++ = 0;
for (i = 0; i < size; i++)
{
if (arg)
{
arg = strtok(NULL, " ,=\n");
if (type == 'f' || type == 'F')
u[i].f = atof(arg);
else
u[i].u = atoi(arg);
}
else
u[i].u = 0;
*cb++ = (u[i].u>>24)&0xff;
*cb++ = (u[i].u>>16)&0xff;
*cb++ = (u[i].u>>8)&0xff;
*cb++ = (u[i].u>>0)&0xff;
}
blob->cvarslength = cb - ((unsigned char*)blob + blob->cvarsoffset);
constid += size;
}
else if (!strncmp(command, "!!permu", 7))
{
char *arg = strtok(command+7, " ,\n");
for (i = 0; permutationnames[i]; i++)
{
if (!strcmp(arg, permutationnames[i]))
{
blob->permutations |= 1u<<i;
break;
}
}
if (!permutationnames[i])
printf("Unknown permutation: \"%s\"\n", arg);
}
else if (!strncmp(command, "!!samps", 7))
{
char *arg = strtok(command+7, " ,\n");
do
{
//light
if (!strcasecmp(arg, "shadowmap"))
blob->defaulttextures |= 1u<<0;
else if (!strcasecmp(arg, "projectionmap"))
blob->defaulttextures |= 1u<<1;
//material
else if (!strcasecmp(arg, "diffuse"))
blob->defaulttextures |= 1u<<2;
else if (!strcasecmp(arg, "normalmap"))
blob->defaulttextures |= 1u<<3;
else if (!strcasecmp(arg, "specular"))
blob->defaulttextures |= 1u<<4;
else if (!strcasecmp(arg, "upper"))
blob->defaulttextures |= 1u<<5;
else if (!strcasecmp(arg, "lower"))
blob->defaulttextures |= 1u<<6;
else if (!strcasecmp(arg, "fullbright"))
blob->defaulttextures |= 1u<<7;
else if (!strcasecmp(arg, "paletted"))
blob->defaulttextures |= 1u<<8;
else if (!strcasecmp(arg, "reflectcube"))
blob->defaulttextures |= 1u<<9;
else if (!strcasecmp(arg, "reflectmask"))
blob->defaulttextures |= 1u<<10;
//batch
else if (!strcasecmp(arg, "lightmap"))
blob->defaulttextures |= 1u<<11;
else if (!strcasecmp(arg, "deluxmap"))
blob->defaulttextures |= 1u<<12;
else if (!strcasecmp(arg, "lightmaps"))
blob->defaulttextures |= 1u<<11 | 1u<<13 | 1u<<14 | 1u<<15;
else if (!strcasecmp(arg, "deluxmaps"))
blob->defaulttextures |= 1u<<12 | 1u<<16 | 1u<<17 | 1u<<18;
//shader pass
else if (atoi(arg))
blob->numtextures = atoi(arg);
else
printf("Unknown texture: \"%s\"\n", arg);
} while((arg = strtok(NULL, " ,\n")));
}
continue;
}
else if (inheader && !strncmp(command, "//", 2))
continue;
else if (inheader)
{
const char *specialnames[] =
{
//light
"uniform sampler2DShadow s_shadowmap;\n",
"uniform samplerCube s_projectionmap;\n",
//material
"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",
//batch
"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"
};
int binding = 2;
inheader = 0;
fprintf(temp, "#define OFFSETMAPPING (cvar_r_glsl_offsetmapping>0)\n");
fprintf(temp, "#define SPECULAR (cvar_gl_specular>0)\n");
fprintf(temp, "#ifdef FRAGMENT_SHADER\n");
for (i = 0; i < sizeof(specialnames)/sizeof(specialnames[0]); i++)
{
if (blob->defaulttextures & (1u<<i))
fprintf(temp, "layout(set=0, binding=%u) %s", binding++, specialnames[i]);
}
for (i = 0; i < blob->numtextures; i++)
{
fprintf(temp, "layout(set=0, binding=%u) uniform sampler2D s_t%u;\n", binding++, i);
}
fprintf(temp, "#endif\n");
//cvar specialisation constants
{
unsigned char *cb = (unsigned char*)blob + blob->cvarsoffset;
while (cb < (unsigned char*)blob + blob->cvarsoffset + blob->cvarslength)
{
union
{
float f;
unsigned int u;
} u[4];
unsigned short id;
unsigned char type;
unsigned char size;
char *name;
id = *cb++<<8;
id |= *cb++;
type = *cb++;
size = (*cb++)-'0';
name = cb;
cb += strlen(name)+1;
for (i = 0; i < size; i++)
{
u[i].u = (cb[0]<<24)|(cb[1]<<16)|(cb[2]<<8)|(cb[3]<<0);
cb+=4;
}
#if 0 //all is well
if (size == 1 && type == 'b')
fprintf(temp, "layout(constant_id=%u) const bool cvar_%s = %s;\n", id, name, (int)u[0].u?"true":"false");
else if (size == 1 && type == 'i')
fprintf(temp, "layout(constant_id=%u) const int cvar_%s = %i;\n", id, name, (int)u[0].u);
else if (size == 1 && type == 'f')
fprintf(temp, "layout(constant_id=%u) const float cvar_%s = %f;\n", id, name, u[0].f);
else if (size == 3 && type == 'f')
{
fprintf(temp, "layout(constant_id=%u) const float cvar_%s_x = %f;\n", id+0, name, u[0].f);
fprintf(temp, "layout(constant_id=%u) const float cvar_%s_y = %f;\n", id+1, name, u[1].f);
fprintf(temp, "layout(constant_id=%u) const float cvar_%s_z = %f;\n", id+2, name, u[2].f);
fprintf(temp, "vec3 cvar_%s = vec3(cvar_%s_x, cvar_%s_y, cvar_%s_z);\n", name, name, name, name);
}
else if (size == 1 && type == 'B')
fprintf(temp, "layout(constant_id=%u) const bool arg_%s = %s;\n", id, name, (int)u[0].u?"true":"false");
else if (size == 1 && type == 'I')
fprintf(temp, "layout(constant_id=%u) const int arg_%s = %i;\n", id, name, (int)u[0].u);
else if (size == 1 && type == 'F')
fprintf(temp, "layout(constant_id=%u) const float arg_%s = %i;\n", id, name, u[0].f);
else if (size == 3 && type == 'F')
{
fprintf(temp, "layout(constant_id=%u) const float arg_%s_x = %f;\n", id+0, name, u[0].f);
fprintf(temp, "layout(constant_id=%u) const float arg_%s_y = %f;\n", id+1, name, u[1].f);
fprintf(temp, "layout(constant_id=%u) const float arg_%s_z = %f;\n", id+2, name, u[2].f);
fprintf(temp, "vec3 arg_%s = vec3(arg_%s_x, arg_%s_y, arg_%s_z);\n", name, name, name, name);
}
#else
//these initialised values are fucked up because glslangvalidator's spirv generator is fucked up and folds specialisation constants.
//we get around this by ensuring that all such constants are given unique values to prevent them being folded, with the engine overriding everything explicitly.
if (size == 1 && type == 'b')
{
fprintf(temp, "layout(constant_id=%u) const int _cvar_%s = %i;\n", id, name, id);//(int)u[0].u?"true":"false");
fprintf(temp, "#define cvar_%s (_cvar_%s!=0)\n", name, name);
}
else if (size == 1 && type == 'i')
fprintf(temp, "layout(constant_id=%u) const int cvar_%s = %i;\n", id, name, id);//(int)u[0].u);
else if (size == 1 && type == 'f')
fprintf(temp, "layout(constant_id=%u) const float cvar_%s = %i;\n", id, name, id);//u[0].f);
else if (size == 3 && type == 'f')
{
fprintf(temp, "layout(constant_id=%u) const float cvar_%s_x = %i;\n", id+0, name, id+0);//u[0].f);
fprintf(temp, "layout(constant_id=%u) const float cvar_%s_y = %i;\n", id+1, name, id+1);//u[1].f);
fprintf(temp, "layout(constant_id=%u) const float cvar_%s_z = %i;\n", id+2, name, id+2);//u[2].f);
fprintf(temp, "vec3 cvar_%s = vec3(cvar_%s_x, cvar_%s_y, cvar_%s_z);\n", name, name, name, name);
}
else if (size == 1 && type == 'B')
{
fprintf(temp, "layout(constant_id=%u) const int _arg_%s = %i;\n", id, name, id);//(int)u[0].u?"true":"false");
fprintf(temp, "#define arg_%s (_arg_%s!=0)\n", name, name);
}
else if (size == 1 && type == 'I')
fprintf(temp, "layout(constant_id=%u) const int arg_%s = %i;\n", id, name, id);//(int)u[0].u);
else if (size == 1 && type == 'F')
fprintf(temp, "layout(constant_id=%u) const float arg_%s = %i;\n", id, name, id);//u[0].f);
else if (size == 3 && type == 'F')
{
fprintf(temp, "layout(constant_id=%u) const float arg_%s_x = %i;\n", id+0, name, id+0);//u[0].f);
fprintf(temp, "layout(constant_id=%u) const float arg_%s_y = %i;\n", id+1, name, id+1);//u[1].f);
fprintf(temp, "layout(constant_id=%u) const float arg_%s_z = %i;\n", id+2, name, id+2);//u[2].f);
fprintf(temp, "vec3 arg_%s = vec3(arg_%s_x, arg_%s_y, arg_%s_z);\n", name, name, name, name);
}
#endif
}
}
//permutation stuff
for (i = 0; i < sizeof(specialnames)/sizeof(specialnames[0]); i++)
{
if (blob->permutations & (1<<i))
{
#if 0 //all is well
fprintf(temp, "layout(constant_id=%u) const bool %s = %s;\n", 16+i, permutationnames[i], "false");
#else
fprintf(temp, "layout(constant_id=%u) const int _%s = %i;\n", 16+i, permutationnames[i], 16+i);
fprintf(temp, "#define %s (_%s!=0)\n", permutationnames[i], permutationnames[i]);
#endif
}
}
}
fputs(command, temp);
}
fclose(temp);
fclose(glsl);
snprintf(command, sizeof(command),
/*preprocess the vertex shader*/
"echo #version 450 core > vulkan/%s.vert && "
"cpp vulkan/%s.tmp -DVULKAN -DVERTEX_SHADER -P >> vulkan/%s.vert && "
/*preprocess the fragment shader*/
"echo #version 450 core > vulkan/%s.frag && "
"cpp vulkan/%s.tmp -DVULKAN -DFRAGMENT_SHADER -P >> vulkan/%s.frag && "
/*convert to spir-v (annoyingly we have no control over the output file names*/
"glslangValidator -V -l -d vulkan/%s.vert vulkan/%s.frag"
/*strip stuff out, so drivers don't glitch out from stuff that we don't use*/
" && spirv-remap -i vert.spv frag.spv -o vulkan/remap"
,fname, fname, fname, fname, fname, fname, fname, fname);
system(command);
return 1;
}
struct shadertype_s
{
char *abrv;
char *filepattern;
char *preprocessor;
char *rendererapi;
int apiversion;
int apiversion; //-1 is a binary blob.
} shadertype[] =
{
{"glsl/%s.glsl", "GLQUAKE", "QR_OPENGL", 110}, //gl2+
//{"gles/%s.glsl", "GLQUAKE", "QR_OPENGL", 100}, //gles
{"hlsl9/%s.hlsl", "D3D9QUAKE", "QR_DIRECT3D9", 9}, //d3d9
{"hlsl11/%s.hlsl", "D3D11QUAKE", "QR_DIRECT3D11", 11}, //d3d11
{"vulkan/remap/%s.spv", "VKQUAKE", "QR_VULKAN", -1}, //vulkan
{"GL", "glsl/%s.glsl", "GLQUAKE", "QR_OPENGL", 110}, //gl2+
//{"ES","gles/%s.glsl", "GLQUAKE", "QR_OPENGL", 100}, //gles
{"VK", "vulkanblobs/%s.fvb", "VKQUAKE", "QR_VULKAN", -1}, //vulkan
{"D9", "hlsl9/%s.hlsl", "D3D9QUAKE", "QR_DIRECT3D9", 9}, //d3d9
{"D11","hlsl11/%s.hlsl", "D3D11QUAKE", "QR_DIRECT3D11", 11}, //d3d11
};
//tbh we should precompile the d3d shaders.
@ -512,49 +133,33 @@ int main(void)
for (i = 0; *shaders[i]; i++)
{
printf("%25s: ", shaders[i]);
for (a = 0; a < sizeof(shadertype)/sizeof(shadertype[0]); a++)
{
sprintf(line, shadertype[a].filepattern, shaders[i]);
if (shadertype[a].apiversion == -1)
{
FILE *v, *f;
char proto[8192];
if (!generatevulkanblobs((struct blobheader*)proto, sizeof(proto), shaders[i]))
continue;
sprintf(line, shadertype[a].filepattern, "vert");
v = fopen(line, "rb");
sprintf(line, shadertype[a].filepattern, "frag");
f = fopen(line, "rb");
if (f && v)
{
fprintf(c, "#ifdef %s\n", shadertype[a].preprocessor);
fprintf(c, "{%s, %i, \"%s\",\n", shadertype[a].rendererapi, shadertype[a].apiversion, shaders[i]);
generateprogsblob((struct blobheader*)proto, c, v, f);
fputs("},\n", c);
fprintf(c, "#endif\n");
}
fclose(f);
fclose(v);
}
s = fopen(line, "rb");
else
{
sprintf(line, shadertype[a].filepattern, shaders[i]);
s = fopen(line, "rt");
if (!s)
{
printf("unable to open %s\n", line);
continue;
}
fprintf(c, "#ifdef %s\n", shadertype[a].preprocessor);
fprintf(c, "{%s, %i, \"%s\",\n", shadertype[a].rendererapi, shadertype[a].apiversion, shaders[i]);
dumpprogstring(c, s);
fputs("},\n", c);
fprintf(c, "#endif\n");
fclose(s);
if (!s)
{
printf("%4s", "");
continue;
}
fprintf(c, "#ifdef %s\n", shadertype[a].preprocessor);
fprintf(c, "{%s, %i, \"%s\",\n", shadertype[a].rendererapi, shadertype[a].apiversion, shaders[i]);
if (shadertype[a].apiversion == -1)
dumpprogblob(c,s);
else
dumpprogstring(c, s);
fputs("},\n", c);
fprintf(c, "#endif\n");
fclose(s);
fflush(c);
printf("%4s", shadertype[a].abrv);
}
printf("\n");
}
fclose(c);

View file

@ -1,3 +1,5 @@
!!samps 1
#include "sys/defs.h"
//
//This shader implements super-sampled anti-aliasing.
//
@ -5,7 +7,6 @@
varying vec2 texcoord;
#ifdef VERTEX_SHADER
attribute vec2 v_texcoord;
void main()
{
texcoord = v_texcoord.xy;
@ -14,7 +15,6 @@ void main()
}
#endif
#ifdef FRAGMENT_SHADER
uniform sampler2D s_t0;
uniform vec2 e_sourcesize;
void main( void )

View file

@ -0,0 +1,462 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void dumpprogblob(FILE *out, unsigned char *buf, unsigned int size)
{
if (out)
{
fwrite(buf, 1, size, out);
return;
}
else
out = stdout;
size_t totallen, i, linelen;
totallen = 0;
linelen = 32;
fflush(out);
fprintf(out, "\"");
for (i=0;i<size;i++)
{
fprintf(out, "\\x%02X",buf[i]);
if (i % linelen == linelen - 1)
fprintf(out, "\"\n\"");
}
fprintf(out, "\"");
fflush(out);
}
struct blobheader
{
unsigned char blobmagic[4]; //\xffSPV
unsigned int blobversion;
unsigned int defaulttextures; //s_diffuse etc flags
unsigned int numtextures; //s_t0 count
unsigned int permutations; //
unsigned int cvarsoffset; //double-null terminated string. I,XYZW prefixes
unsigned int cvarslength;
unsigned int vertoffset;
unsigned int vertlength;
unsigned int fragoffset;
unsigned int fraglength;
};
void generateprogsblob(struct blobheader *prototype, FILE *out, FILE *vert, FILE *frag)
{
struct blobheader *blob;
int fraglen, vertlen, blobsize, cvarlen;
cvarlen = prototype->cvarslength;
cvarlen = (cvarlen + 3) & ~3; //round up for padding.
fseek(vert, 0, SEEK_END);
fseek(frag, 0, SEEK_END);
vertlen = ftell(vert);
fraglen = ftell(frag);
fseek(vert, 0, SEEK_SET);
fseek(frag, 0, SEEK_SET);
blobsize = sizeof(*blob) + cvarlen + fraglen + vertlen;
blob = malloc(blobsize);
*blob = *prototype;
blob->cvarsoffset = sizeof(*blob);
blob->cvarslength = prototype->cvarslength; //unpadded length
blob->vertoffset = blob->cvarsoffset+cvarlen;
blob->vertlength = vertlen;
blob->fragoffset = blob->vertoffset+vertlen;
blob->fraglength = fraglen;
memcpy((char*)blob+blob->cvarsoffset, (char*)prototype+prototype->cvarsoffset, prototype->cvarslength);
fread((char*)blob+blob->vertoffset, blob->vertlength, 1, vert);
fread((char*)blob+blob->fragoffset, blob->fraglength, 1, frag);
dumpprogblob(out, (unsigned char*)blob, blobsize);
free(blob);
}
int generatevulkanblobs(struct blobheader *blob, size_t maxblobsize, const char *glslname)
{
char command[1024];
char tempname[256];
char tempvert[256];
char tempfrag[256];
int inheader = 1;
int i;
unsigned short constid = 256; //first few are reserved.
const char *permutationnames[] =
{
"BUMP",
"FULLBRIGHT",
"UPPERLOWER",
"REFLECTCUBEMASK",
"SKELETAL",
"FOG",
"FRAMEBLEND",
"LIGHTSTYLED",
NULL
};
snprintf(tempname, sizeof(tempname), "vulkan/temp.tmp");
snprintf(tempvert, sizeof(tempvert), "vulkan/temp.vert");
snprintf(tempfrag, sizeof(tempfrag), "vulkan/temp.frag");
memcpy(blob->blobmagic, "\xffSPV", 4);
blob->blobversion = 1;
blob->defaulttextures = 0;
blob->numtextures = 0;
blob->permutations = 0;
blob->cvarsoffset = sizeof(*blob);
blob->cvarslength = 0;
FILE *glsl = fopen(glslname, "rt");
if (!glsl)
return 0;
FILE *temp = fopen(tempname, "wt");
while(fgets(command, sizeof(command), glsl))
{
if (inheader && !strncmp(command, "!!", 2))
{
if (!strncmp(command, "!!cvar", 6) || !strncmp(command, "!!arg", 5))
{
unsigned int type;
unsigned int size;
union
{
float f;
unsigned int u;
} u[4];
char *arg;
unsigned char *cb = (unsigned char*)blob + blob->cvarsoffset + blob->cvarslength;
if (command[2] == 'a')
{
type = command[5] == 'i' || command[5] == 'f' || command[5] == 'b';
size = type?1:(command[5]-'0');
arg = strtok(command+7, " ,=\n");
type = command[6-type] - 'a' + 'A';
}
else
{
type = command[6] == 'i' || command[6] == 'f' || command[6] == 'b';
size = type?1:(command[6]-'0');
arg = strtok(command+8, " ,=\n");
type = command[7-type];
}
cb[0] = (constid>>8)&0xff;
cb[1] = (constid>>0)&0xff;
cb[2] = type;
cb[3] = size + '0';
cb += 4;
while(*arg)
*cb++ = *arg++;
*cb++ = 0;
for (i = 0; i < size; i++)
{
if (arg)
{
arg = strtok(NULL, " ,=\n");
if (type == 'f' || type == 'F')
u[i].f = atof(arg);
else
u[i].u = atoi(arg);
}
else
u[i].u = 0;
*cb++ = (u[i].u>>24)&0xff;
*cb++ = (u[i].u>>16)&0xff;
*cb++ = (u[i].u>>8)&0xff;
*cb++ = (u[i].u>>0)&0xff;
}
blob->cvarslength = cb - ((unsigned char*)blob + blob->cvarsoffset);
constid += size;
}
else if (!strncmp(command, "!!permu", 7))
{
char *arg = strtok(command+7, " ,\n");
for (i = 0; permutationnames[i]; i++)
{
if (!strcmp(arg, permutationnames[i]))
{
blob->permutations |= 1u<<i;
break;
}
}
if (!permutationnames[i])
{
printf("Unknown permutation: \"%s\"\n", arg);
for (i = 0; permutationnames[i]; i++)
printf("%s ", permutationnames[i]);
printf("\n");
}
}
else if (!strncmp(command, "!!samps", 7))
{
char *arg = strtok(command+7, " ,\n");
do
{
//light
if (!strcasecmp(arg, "shadowmap"))
blob->defaulttextures |= 1u<<0;
else if (!strcasecmp(arg, "projectionmap"))
blob->defaulttextures |= 1u<<1;
//material
else if (!strcasecmp(arg, "diffuse"))
blob->defaulttextures |= 1u<<2;
else if (!strcasecmp(arg, "normalmap"))
blob->defaulttextures |= 1u<<3;
else if (!strcasecmp(arg, "specular"))
blob->defaulttextures |= 1u<<4;
else if (!strcasecmp(arg, "upper"))
blob->defaulttextures |= 1u<<5;
else if (!strcasecmp(arg, "lower"))
blob->defaulttextures |= 1u<<6;
else if (!strcasecmp(arg, "fullbright"))
blob->defaulttextures |= 1u<<7;
else if (!strcasecmp(arg, "paletted"))
blob->defaulttextures |= 1u<<8;
else if (!strcasecmp(arg, "reflectcube"))
blob->defaulttextures |= 1u<<9;
else if (!strcasecmp(arg, "reflectmask"))
blob->defaulttextures |= 1u<<10;
//batch
else if (!strcasecmp(arg, "lightmap"))
blob->defaulttextures |= 1u<<11;
else if (!strcasecmp(arg, "deluxmap"))
blob->defaulttextures |= 1u<<12;
else if (!strcasecmp(arg, "lightmaps"))
blob->defaulttextures |= 1u<<11 | 1u<<13 | 1u<<14 | 1u<<15;
else if (!strcasecmp(arg, "deluxmaps"))
blob->defaulttextures |= 1u<<12 | 1u<<16 | 1u<<17 | 1u<<18;
//shader pass
else if (atoi(arg))
blob->numtextures = atoi(arg);
else
printf("Unknown texture: \"%s\"\n", arg);
} while((arg = strtok(NULL, " ,\n")));
}
continue;
}
else if (inheader && !strncmp(command, "//", 2))
continue;
else if (inheader)
{
const char *specialnames[] =
{
//light
"uniform sampler2DShadow s_shadowmap;\n",
"uniform samplerCube s_projectionmap;\n",
//material
"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",
//batch
"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"
};
int binding = 2;
inheader = 0;
fprintf(temp, "#define OFFSETMAPPING (cvar_r_glsl_offsetmapping>0)\n");
fprintf(temp, "#define SPECULAR (cvar_gl_specular>0)\n");
fprintf(temp, "#ifdef FRAGMENT_SHADER\n");
for (i = 0; i < sizeof(specialnames)/sizeof(specialnames[0]); i++)
{
if (blob->defaulttextures & (1u<<i))
fprintf(temp, "layout(set=0, binding=%u) %s", binding++, specialnames[i]);
}
for (i = 0; i < blob->numtextures; i++)
{
fprintf(temp, "layout(set=0, binding=%u) uniform sampler2D s_t%u;\n", binding++, i);
}
fprintf(temp, "#endif\n");
//cvar specialisation constants
{
unsigned char *cb = (unsigned char*)blob + blob->cvarsoffset;
while (cb < (unsigned char*)blob + blob->cvarsoffset + blob->cvarslength)
{
union
{
float f;
unsigned int u;
} u[4];
unsigned short id;
unsigned char type;
unsigned char size;
char *name;
id = *cb++<<8;
id |= *cb++;
type = *cb++;
size = (*cb++)-'0';
name = cb;
cb += strlen(name)+1;
for (i = 0; i < size; i++)
{
u[i].u = (cb[0]<<24)|(cb[1]<<16)|(cb[2]<<8)|(cb[3]<<0);
cb+=4;
}
#if 0 //all is well
if (size == 1 && type == 'b')
fprintf(temp, "layout(constant_id=%u) const bool cvar_%s = %s;\n", id, name, (int)u[0].u?"true":"false");
else if (size == 1 && type == 'i')
fprintf(temp, "layout(constant_id=%u) const int cvar_%s = %i;\n", id, name, (int)u[0].u);
else if (size == 1 && type == 'f')
fprintf(temp, "layout(constant_id=%u) const float cvar_%s = %f;\n", id, name, u[0].f);
else if (size == 3 && type == 'f')
{
fprintf(temp, "layout(constant_id=%u) const float cvar_%s_x = %f;\n", id+0, name, u[0].f);
fprintf(temp, "layout(constant_id=%u) const float cvar_%s_y = %f;\n", id+1, name, u[1].f);
fprintf(temp, "layout(constant_id=%u) const float cvar_%s_z = %f;\n", id+2, name, u[2].f);
fprintf(temp, "vec3 cvar_%s = vec3(cvar_%s_x, cvar_%s_y, cvar_%s_z);\n", name, name, name, name);
}
else if (size == 1 && type == 'B')
fprintf(temp, "layout(constant_id=%u) const bool arg_%s = %s;\n", id, name, (int)u[0].u?"true":"false");
else if (size == 1 && type == 'I')
fprintf(temp, "layout(constant_id=%u) const int arg_%s = %i;\n", id, name, (int)u[0].u);
else if (size == 1 && type == 'F')
fprintf(temp, "layout(constant_id=%u) const float arg_%s = %i;\n", id, name, u[0].f);
else if (size == 3 && type == 'F')
{
fprintf(temp, "layout(constant_id=%u) const float arg_%s_x = %f;\n", id+0, name, u[0].f);
fprintf(temp, "layout(constant_id=%u) const float arg_%s_y = %f;\n", id+1, name, u[1].f);
fprintf(temp, "layout(constant_id=%u) const float arg_%s_z = %f;\n", id+2, name, u[2].f);
fprintf(temp, "vec3 arg_%s = vec3(arg_%s_x, arg_%s_y, arg_%s_z);\n", name, name, name, name);
}
#else
//these initialised values are fucked up because glslangvalidator's spirv generator is fucked up and folds specialisation constants.
//we get around this by ensuring that all such constants are given unique values to prevent them being folded, with the engine overriding everything explicitly.
if (size == 1 && type == 'b')
{
fprintf(temp, "layout(constant_id=%u) const int _cvar_%s = %i;\n", id, name, id);//(int)u[0].u?"true":"false");
fprintf(temp, "#define cvar_%s (_cvar_%s!=0)\n", name, name);
}
else if (size == 1 && type == 'i')
fprintf(temp, "layout(constant_id=%u) const int cvar_%s = %i;\n", id, name, id);//(int)u[0].u);
else if (size == 1 && type == 'f')
fprintf(temp, "layout(constant_id=%u) const float cvar_%s = %i;\n", id, name, id);//u[0].f);
else if (size == 3 && type == 'f')
{
fprintf(temp, "layout(constant_id=%u) const float cvar_%s_x = %i;\n", id+0, name, id+0);//u[0].f);
fprintf(temp, "layout(constant_id=%u) const float cvar_%s_y = %i;\n", id+1, name, id+1);//u[1].f);
fprintf(temp, "layout(constant_id=%u) const float cvar_%s_z = %i;\n", id+2, name, id+2);//u[2].f);
fprintf(temp, "vec3 cvar_%s = vec3(cvar_%s_x, cvar_%s_y, cvar_%s_z);\n", name, name, name, name);
}
else if (size == 1 && type == 'B')
{
fprintf(temp, "layout(constant_id=%u) const int _arg_%s = %i;\n", id, name, id);//(int)u[0].u?"true":"false");
fprintf(temp, "#define arg_%s (_arg_%s!=0)\n", name, name);
}
else if (size == 1 && type == 'I')
fprintf(temp, "layout(constant_id=%u) const int arg_%s = %i;\n", id, name, id);//(int)u[0].u);
else if (size == 1 && type == 'F')
fprintf(temp, "layout(constant_id=%u) const float arg_%s = %i;\n", id, name, id);//u[0].f);
else if (size == 3 && type == 'F')
{
fprintf(temp, "layout(constant_id=%u) const float arg_%s_x = %i;\n", id+0, name, id+0);//u[0].f);
fprintf(temp, "layout(constant_id=%u) const float arg_%s_y = %i;\n", id+1, name, id+1);//u[1].f);
fprintf(temp, "layout(constant_id=%u) const float arg_%s_z = %i;\n", id+2, name, id+2);//u[2].f);
fprintf(temp, "vec3 arg_%s = vec3(arg_%s_x, arg_%s_y, arg_%s_z);\n", name, name, name, name);
}
#endif
}
}
//permutation stuff
for (i = 0; i < sizeof(specialnames)/sizeof(specialnames[0]); i++)
{
if (blob->permutations & (1<<i))
{
#if 0 //all is well
fprintf(temp, "layout(constant_id=%u) const bool %s = %s;\n", 16+i, permutationnames[i], "false");
#else
fprintf(temp, "layout(constant_id=%u) const int _%s = %i;\n", 16+i, permutationnames[i], 16+i);
fprintf(temp, "#define %s (_%s!=0)\n", permutationnames[i], permutationnames[i]);
#endif
}
}
}
fputs(command, temp);
}
fclose(temp);
fclose(glsl);
snprintf(command, sizeof(command),
/*preprocess the vertex shader*/
"echo #version 450 core > %s && "
"cpp %s -DVULKAN -DVERTEX_SHADER -P >> %s && "
/*preprocess the fragment shader*/
"echo #version 450 core > %s && "
"cpp %s -DVULKAN -DFRAGMENT_SHADER -P >> %s && "
/*convert to spir-v (annoyingly we have no control over the output file names*/
"glslangValidator -V -l -d %s %s"
/*strip stuff out, so drivers don't glitch out from stuff that we don't use*/
" && spirv-remap -i vert.spv frag.spv -o vulkan/remap"
,tempvert, tempname, tempvert, tempfrag, tempname, tempfrag, tempvert, tempfrag);
system(command);
unlink(tempname);
unlink(tempvert);
unlink(tempfrag);
return 1;
}
int main(int argc, const char **argv)
{
const char *inname = argv[1];
const char *blobname = argv[2];
FILE *v, *f, *o;
char proto[8192];
char line[256];
int r = 1;
if (!generatevulkanblobs((struct blobheader*)proto, sizeof(proto), inname))
return 1;
//should have generated two files
v = fopen("vert.spv", "rb");
f = fopen("frag.spv", "rb");
if (f && v)
{
if (argc < 3)
{
generateprogsblob((struct blobheader*)proto, NULL, v, f);
r = 0;
}
else
{
o = fopen(blobname, "wb");
if (o)
{
generateprogsblob((struct blobheader*)proto, o, v, f);
fclose(o);
r = 0;
}
}
}
fclose(f);
fclose(v);
unlink("vert.spv");
unlink("frag.spv");
return r;
}

View file

@ -92,7 +92,7 @@ void main ()
vec3 lightmaps;
if (arg_vertexlit)
lightmaps = vc.rgb * e_lmscale[0].rgb;
lightmaps = vc.rgb * e_lmscale.rgb;
else
{
//modulate that by the lightmap(s) including deluxemap(s)
@ -118,10 +118,10 @@ void main ()
//don't bother if its lightstyled, such cases will have unpredictable correlations anyway.
//FIXME: this rounding is likely not correct with respect to software rendering. oh well.
vec2 nearestlm0 = floor(lm0 * 256.0*8.0)/(256.0*8.0);
lightmaps = (texture2D(s_lightmap, nearestlm0) * e_lmscale[0]).rgb;
lightmaps = (texture2D(s_lightmap, nearestlm0) * e_lmscale).rgb;
}
else
lightmaps = (texture2D(s_lightmap, lm0) * e_lmscale[0]).rgb;
lightmaps = (texture2D(s_lightmap, lm0) * e_lmscale).rgb;
//modulate by the bumpmap dot light
if (DELUXE)
{

View file

@ -0,0 +1,66 @@
!!samps 1
#include "sys/defs.h"
//
//This shader implements super-sampled anti-aliasing.
//
varying vec2 texcoord;
varying vec2 e_sourcesize;
#ifdef VERTEX_SHADER
void main()
{
texcoord = v_texcoord.xy;
texcoord.y = 1.0 - texcoord.y;
e_sourcesize = v_colour.rg;
gl_Position = ftetransform();
}
#endif
#ifdef FRAGMENT_SHADER
//uniform vec2 e_sourcesize;
void main( void )
{
float FXAA_SPAN_MAX = 8.0;
float FXAA_REDUCE_MUL = 1.0/8.0;
float FXAA_REDUCE_MIN = 1.0/128.0;
vec3 rgbNW=texture2D(s_t0,texcoord+(vec2(-1.0,-1.0)/e_sourcesize)).xyz;
vec3 rgbNE=texture2D(s_t0,texcoord+(vec2(1.0,-1.0)/e_sourcesize)).xyz;
vec3 rgbSW=texture2D(s_t0,texcoord+(vec2(-1.0,1.0)/e_sourcesize)).xyz;
vec3 rgbSE=texture2D(s_t0,texcoord+(vec2(1.0,1.0)/e_sourcesize)).xyz;
vec3 rgbM=texture2D(s_t0,texcoord).xyz;
vec3 luma=vec3(0.299, 0.587, 0.114);
float lumaNW = dot(rgbNW, luma);
float lumaNE = dot(rgbNE, luma);
float lumaSW = dot(rgbSW, luma);
float lumaSE = dot(rgbSE, luma);
float lumaM = dot(rgbM, luma);
float lumaMin = min(lumaM, min(min(lumaNW, lumaNE), min(lumaSW, lumaSE)));
float lumaMax = max(lumaM, max(max(lumaNW, lumaNE), max(lumaSW, lumaSE)));
vec2 dir;
dir.x = -((lumaNW + lumaNE) - (lumaSW + lumaSE));
dir.y = ((lumaNW + lumaSW) - (lumaNE + lumaSE));
float dirReduce = max((lumaNW + lumaNE + lumaSW + lumaSE) * (0.25 * FXAA_REDUCE_MUL), FXAA_REDUCE_MIN);
float rcpDirMin = 1.0/(min(abs(dir.x), abs(dir.y)) + dirReduce);
dir = min(vec2( FXAA_SPAN_MAX, FXAA_SPAN_MAX),
max(vec2(-FXAA_SPAN_MAX, -FXAA_SPAN_MAX),
dir * rcpDirMin)) / e_sourcesize;
vec3 rgbA = (1.0/2.0) * (texture2D(s_t0, texcoord.xy + dir * (1.0/3.0 - 0.5)).xyz + texture2D(s_t0, texcoord.xy + dir * (2.0/3.0 - 0.5)).xyz);
vec3 rgbB = rgbA * (1.0/2.0) + (1.0/4.0) * (texture2D(s_t0, texcoord.xy + dir * (0.0/3.0 - 0.5)).xyz + texture2D(s_t0, texcoord.xy + dir * (3.0/3.0 - 0.5)).xyz);
float lumaB = dot(rgbB, luma);
if((lumaB < lumaMin) || (lumaB > lumaMax))
gl_FragColor.xyz=rgbA;
else
gl_FragColor.xyz=rgbB;
gl_FragColor.a = 1.0;
}
#endif

View file

@ -0,0 +1,32 @@
!!cvarf ffov
!!samps reflectcube
#include "sys/defs.h"
//fisheye view rendering, for silly fovs that are still playable.
#ifdef VERTEX_SHADER
varying vec2 texcoord;
void main()
{
texcoord = v_texcoord.xy;
gl_Position = ftetransform();
}
#endif
#ifdef FRAGMENT_SHADER
varying vec2 texcoord;
//uniform float cvar_ffov;
void main()
{
vec3 tc;
vec2 d;
vec2 ang;
d = texcoord;
ang.x = sqrt(d.x*d.x+d.y*d.y)*radians(cvar_ffov);
ang.y = -atan(d.y, d.x);
tc.x = sin(ang.x) * cos(ang.y);
tc.y = sin(ang.x) * sin(ang.y);
tc.z = cos(ang.x);
gl_FragColor = textureCube(s_reflectcube, tc);
}
#endif

View file

@ -0,0 +1,27 @@
!!cvarf ffov
!!samps reflectcube
#include "sys/defs.h"
//panoramic view rendering, for promo map shots or whatever.
#ifdef VERTEX_SHADER
varying vec2 texcoord;
void main()
{
texcoord = v_texcoord.xy;
gl_Position = ftetransform();
}
#endif
#ifdef FRAGMENT_SHADER
varying vec2 texcoord;
void main()
{
vec3 tc;
float ang;
ang = texcoord.x*radians(cvar_ffov);
tc.x = sin(ang);
tc.y = -texcoord.y;
tc.z = cos(ang);
gl_FragColor = textureCube(s_reflectcube, tc);
}
#endif

View file

@ -0,0 +1,37 @@
!!cvarf ffov
!!samps reflectcube
#include "sys/defs.h"
//stereographic view rendering, for high fovs that are still playable.
#ifdef VERTEX_SHADER
varying vec2 texcoord;
//uniform float cvar_ffov;
void main()
{
texcoord = v_texcoord.xy;
//make sure the ffov cvar actually does something meaningful
texcoord *= cvar_ffov / 90.0;
gl_Position = ftetransform();
}
#endif
#ifdef FRAGMENT_SHADER
varying vec2 texcoord;
void main()
{
vec3 tc;
vec2 d;
vec2 ang;
d = texcoord;
//compute the 2d->3d projection
float div = 1.0 + d.x*d.x + d.y*d.y;
tc.x = 2.0*d.x/div;
tc.y = -2.0*d.y/div;
tc.z = -(-1.0 + d.x*d.x + d.y*d.y)/div;
gl_FragColor = textureCube(s_reflectcube, tc);
}
#endif

View file

@ -21,13 +21,15 @@ layout(std140, binding=0) uniform entityblock
vec3 e_light_ambient; float epad1;
vec3 e_light_dir; float epad2;
vec3 e_light_mul; float epad3;
vec4 e_lmscale[4];
vec4 e_lmscales[4];
vec3 e_uppercolour; float epad4;
vec3 e_lowercolour; float epad5;
vec3 e_glowmod; float epad6;
vec4 e_colourident;
vec4 w_fogcolours;
float w_fogdensity; float w_fogdepthbias; vec2 epad6;
float w_fogdensity; float w_fogdepthbias; vec2 epad7;
};
#define e_lmscale (e_lmscales[0])
layout(std140, binding=1) uniform lightblock
{

View file

@ -174,9 +174,10 @@ typedef struct
vec4_t e_lmscale[4];
vec3_t e_uppercolour; float pad4;
vec3_t e_lowercolour; float pad5;
vec3_t e_glowmod; float pad6;
vec4_t e_colourident;
vec4_t w_fogcolours;
float w_fogdensity; float w_fogdepthbias; vec2_t pad6;
float w_fogdensity; float w_fogdepthbias; vec2_t pad7;
} cbuf_entity_t;
enum
@ -1029,6 +1030,10 @@ qboolean VK_LoadGLSL(program_t *prog, const char *name, unsigned int permu, int
if (permu) //FIXME...
return false;
prog->nofixedcompat = false;
// prog->supportedpermutations = 0;
prog->cvardata = NULL;
prog->cvardatasize = 0;
prog->pipelines = NULL;
prog->vert = VK_CreateGLSLModule(prog, name, ver, precompilerconstants, vert, false);
prog->frag = VK_CreateGLSLModule(prog, name, ver, precompilerconstants, frag, true);
@ -1310,7 +1315,7 @@ void VKBE_Init(void)
}
}
else
vk_usedynamicstaging = ~0u;
vk_usedynamicstaging = 0u;
}
static struct descpool *VKBE_CreateDescriptorPool(void)
@ -4245,36 +4250,20 @@ static void BE_RotateForEntity (const entity_t *e, const model_t *mod)
VectorScale((m+8), mod->clampscale, (m+8));
}
memcpy(cbe->m_model, m, sizeof(cbe->m_model));
Matrix4_Invert(modelmatrix, cbe->m_modelinv);
{
float modelview[16];
Matrix4_Multiply(r_refdef.m_view, m, modelview);
Matrix4_Multiply(r_refdef.m_projection, modelview, cbe->m_modelviewproj);
}
memcpy(cbe->m_model, m, sizeof(cbe->m_model));
Matrix4_Invert(modelmatrix, cbe->m_modelinv);
Matrix4x4_CM_Transform3(cbe->m_modelinv, r_origin, cbe->e_eyepos);
cbe->e_time = shaderstate.curtime = r_refdef.time - shaderstate.curentity->shaderTime;
VectorCopy(e->light_avg, cbe->e_light_ambient);
VectorCopy(e->light_dir, cbe->e_light_dir);
VectorCopy(e->light_range, cbe->e_light_mul);
R_FetchPlayerColour(e->topcolour, cbe->e_uppercolour);
R_FetchPlayerColour(e->bottomcolour, cbe->e_lowercolour);
if (shaderstate.flags & BEF_FORCECOLOURMOD)
Vector4Copy(e->shaderRGBAf, cbe->e_colourident);
else
Vector4Set(cbe->e_colourident, 1, 1, 1, e->shaderRGBAf[3]);
VectorCopy(r_refdef.globalfog.colour, cbe->w_fogcolours);
cbe->w_fogcolours[3] = r_refdef.globalfog.alpha;
cbe->w_fogdensity = r_refdef.globalfog.density;
cbe->w_fogdepthbias = r_refdef.globalfog.depthbias;
//various stuff in modelspace
Matrix4x4_CM_Transform3(cbe->m_modelinv, r_origin, cbe->e_eyepos);
VectorCopy(e->light_avg, cbe->e_light_ambient); cbe->pad1 = 0;
VectorCopy(e->light_dir, cbe->e_light_dir); cbe->pad2 = 0;
VectorCopy(e->light_range, cbe->e_light_mul); cbe->pad3 = 0;
for (i = 0; i < MAXRLIGHTMAPS ; i++)
{
@ -4312,6 +4301,21 @@ static void BE_RotateForEntity (const entity_t *e, const model_t *mod)
Vector4Set(cbe->e_lmscale[i], sc, sc, sc, 1);
}
R_FetchPlayerColour(e->topcolour, cbe->e_uppercolour); cbe->pad4 = 0;
R_FetchPlayerColour(e->bottomcolour, cbe->e_lowercolour); cbe->pad5 = 0;
VectorCopy(e->glowmod, cbe->e_glowmod); cbe->pad6 = 0;
if (shaderstate.flags & BEF_FORCECOLOURMOD)
Vector4Copy(e->shaderRGBAf, cbe->e_colourident);
else
Vector4Set(cbe->e_colourident, 1, 1, 1, e->shaderRGBAf[3]);
VectorCopy(r_refdef.globalfog.colour, cbe->w_fogcolours);
cbe->w_fogcolours[3] = r_refdef.globalfog.alpha;
cbe->w_fogdensity = r_refdef.globalfog.density;
cbe->w_fogdepthbias = r_refdef.globalfog.depthbias;
Vector2Set(cbe->pad7, 0, 0);
ndr = (e->flags & RF_DEPTHHACK)?0.333:1;
if (ndr != shaderstate.depthrange)
{
@ -4400,6 +4404,7 @@ void VKBE_RT_Destroy(struct vk_rendertarg *targ)
memset(targ, 0, sizeof(*targ));
}
struct vkbe_rtpurge
{
struct vk_fencework fw;
@ -4414,15 +4419,24 @@ static void VKBE_RT_Purge(void *ptr)
VK_DestroyVkTexture(&ctx->depth);
VK_DestroyVkTexture(&ctx->colour);
}
void VKBE_RT_Gen(struct vk_rendertarg *targ, uint32_t width, uint32_t height)
void VKBE_RT_Gen(struct vk_rendertarg *targ, uint32_t width, uint32_t height, qboolean clear)
{
//sooooo much work...
VkImageCreateInfo colour_imginfo = {VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO};
VkImageCreateInfo depth_imginfo;
struct vkbe_rtpurge *purge;
static VkClearValue clearvalues[2];
if (clear)
targ->restartinfo.renderPass = vk.renderpass[2];
else
targ->restartinfo.renderPass = vk.renderpass[1]; //don't care
targ->restartinfo.clearValueCount = 2;
targ->depthcleared = true; //will be once its activated.
if (targ->width == width && targ->height == height)
return; //no work to do.
if (targ->framebuffer)
{ //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));
@ -4436,15 +4450,22 @@ void VKBE_RT_Gen(struct vk_rendertarg *targ, uint32_t width, uint32_t height)
targ->q_colour.vkimage = &targ->colour;
targ->q_depth.vkimage = &targ->depth;
targ->q_colour.status = TEX_LOADED;
targ->q_colour.width = width;
targ->q_colour.height = height;
targ->width = width;
targ->height = height;
if (width == 0 && height == 0)
return; //destroyed
colour_imginfo.format = VK_FORMAT_R8G8B8A8_UNORM;
colour_imginfo.flags = 0;
colour_imginfo.imageType = VK_IMAGE_TYPE_2D;
colour_imginfo.extent.width = width;
colour_imginfo.extent.height = height;
colour_imginfo.extent.depth = 1;
colour_imginfo.mipLevels = 1;
colour_imginfo.arrayLayers = 1;
colour_imginfo.samples = VK_SAMPLE_COUNT_1_BIT;
@ -4547,69 +4568,265 @@ void VKBE_RT_Gen(struct vk_rendertarg *targ, uint32_t width, uint32_t height)
fbinfo.layers = 1;
VkAssert(vkCreateFramebuffer(vk.device, &fbinfo, vkallocationcb, &targ->framebuffer));
}
targ->restartinfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
targ->restartinfo.pNext = NULL;
targ->restartinfo.framebuffer = targ->framebuffer;
targ->restartinfo.renderArea.offset.x = 0;
targ->restartinfo.renderArea.offset.y = 0;
targ->restartinfo.renderArea.extent.width = width;
targ->restartinfo.renderArea.extent.height = height;
targ->restartinfo.pClearValues = clearvalues;
clearvalues[1].depthStencil.depth = 1;
}
void VKBE_RT_Begin(struct vk_rendertarg *targ, uint32_t width, uint32_t height)
struct vkbe_rtpurge_cube
{
vkCmdEndRenderPass(vk.frame->cbuf);
struct vk_fencework fw;
vk_image_t colour;
vk_image_t depth;
struct
{
VkFramebuffer framebuffer;
VkImageView iv[2];
} face[6];
};
static void VKBE_RT_Purge_Cube(void *ptr)
{
uint32_t f;
struct vkbe_rtpurge_cube *ctx = ptr;
for (f = 0; f < 6; f++)
{
vkDestroyFramebuffer(vk.device, ctx->face[f].framebuffer, vkallocationcb);
vkDestroyImageView(vk.device, ctx->face[f].iv[0], vkallocationcb);
vkDestroyImageView(vk.device, ctx->face[f].iv[1], vkallocationcb);
}
VK_DestroyVkTexture(&ctx->depth);
VK_DestroyVkTexture(&ctx->colour);
}
//generate a cubemap-compatible 2d array, set up 6 render targets that render to their own views
void VKBE_RT_Gen_Cube(struct vk_rendertarg_cube *targ, uint32_t size, qboolean clear)
{
VkImageCreateInfo colour_imginfo = {VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO};
VkImageCreateInfo depth_imginfo;
struct vkbe_rtpurge_cube *purge;
uint32_t f;
static VkClearValue clearvalues[2];
if (width != targ->width || height != targ->height)
VKBE_RT_Gen(targ, width, height);
for (f = 0; f < 6; f++)
{
if (clear)
targ->face[f].restartinfo.renderPass = vk.renderpass[2];
else
targ->face[f].restartinfo.renderPass = vk.renderpass[1]; //don't care
targ->face[f].restartinfo.clearValueCount = 2;
}
if (targ->size == size)
return; //no work to do.
if (targ->size)
{ //schedule the old one to be destroyed at the end of the current frame. DIE OLD ONE, DIE!
purge = VK_AtFrameEnd(VKBE_RT_Purge_Cube, sizeof(*purge));
for (f = 0; f < 6; f++)
{
purge->face[f].framebuffer = targ->face[f].framebuffer;
targ->face[f].framebuffer = VK_NULL_HANDLE;
purge->face[f].iv[0] = targ->face[f].colour.view;
purge->face[f].iv[1] = targ->face[f].depth.view;
targ->face[f].colour.view = VK_NULL_HANDLE;
targ->face[f].depth.view = VK_NULL_HANDLE;
}
purge->colour = targ->colour;
purge->depth = targ->depth;
memset(&targ->colour, 0, sizeof(targ->colour));
memset(&targ->depth, 0, sizeof(targ->depth));
}
targ->size = size;
if (!size)
return;
targ->q_colour.vkimage = &targ->colour;
targ->q_depth.vkimage = &targ->depth;
colour_imginfo.format = VK_FORMAT_R8G8B8A8_UNORM;
colour_imginfo.flags = VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT;
colour_imginfo.imageType = VK_IMAGE_TYPE_2D;
colour_imginfo.extent.width = size;
colour_imginfo.extent.height = size;
colour_imginfo.mipLevels = 1;
colour_imginfo.arrayLayers = 6;
colour_imginfo.samples = VK_SAMPLE_COUNT_1_BIT;
colour_imginfo.tiling = VK_IMAGE_TILING_OPTIMAL;
colour_imginfo.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT|VK_IMAGE_USAGE_SAMPLED_BIT;
colour_imginfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
colour_imginfo.queueFamilyIndexCount = 0;
colour_imginfo.pQueueFamilyIndices = NULL;
colour_imginfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
VkAssert(vkCreateImage(vk.device, &colour_imginfo, vkallocationcb, &targ->colour.image));
depth_imginfo = colour_imginfo;
depth_imginfo.format = vk.depthformat;
depth_imginfo.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT|VK_IMAGE_USAGE_SAMPLED_BIT;
VkAssert(vkCreateImage(vk.device, &depth_imginfo, vkallocationcb, &targ->depth.image));
{
VkMemoryRequirements mem_reqs;
VkMemoryAllocateInfo memAllocInfo = {VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO};
vkGetImageMemoryRequirements(vk.device, targ->colour.image, &mem_reqs);
memAllocInfo.allocationSize = mem_reqs.size;
memAllocInfo.memoryTypeIndex = vk_find_memory_require(mem_reqs.memoryTypeBits, 0);
VkAssert(vkAllocateMemory(vk.device, &memAllocInfo, vkallocationcb, &targ->colour.memory));
VkAssert(vkBindImageMemory(vk.device, targ->colour.image, targ->colour.memory, 0));
}
{
VkMemoryRequirements mem_reqs;
VkMemoryAllocateInfo memAllocInfo = {VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO};
vkGetImageMemoryRequirements(vk.device, targ->depth.image, &mem_reqs);
memAllocInfo.allocationSize = mem_reqs.size;
memAllocInfo.memoryTypeIndex = vk_find_memory_require(mem_reqs.memoryTypeBits, 0);
VkAssert(vkAllocateMemory(vk.device, &memAllocInfo, vkallocationcb, &targ->depth.memory));
VkAssert(vkBindImageMemory(vk.device, targ->depth.image, targ->depth.memory, 0));
}
// set_image_layout(vk.frame->cbuf, targ->colour.image, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
// set_image_layout(vk.frame->cbuf, targ->depth.image, VK_IMAGE_ASPECT_DEPTH_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
//public sampler
{
VkSamplerCreateInfo lmsampinfo = {VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO};
lmsampinfo.minFilter = lmsampinfo.magFilter = VK_FILTER_LINEAR;
lmsampinfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR;
lmsampinfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
lmsampinfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
lmsampinfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
lmsampinfo.mipLodBias = 0.0;
lmsampinfo.anisotropyEnable = VK_FALSE;
lmsampinfo.maxAnisotropy = 0;
lmsampinfo.compareOp = VK_COMPARE_OP_LESS_OR_EQUAL;
lmsampinfo.minLod = 0;
lmsampinfo.maxLod = 0;
lmsampinfo.borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE;
lmsampinfo.unnormalizedCoordinates = VK_FALSE;
lmsampinfo.compareEnable = VK_FALSE;
VkAssert(vkCreateSampler(vk.device, &lmsampinfo, NULL, &targ->colour.sampler));
lmsampinfo.compareEnable = VK_TRUE;
VkAssert(vkCreateSampler(vk.device, &lmsampinfo, NULL, &targ->depth.sampler));
}
//public cubemap views
{
VkImageViewCreateInfo ivci = {VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO};
ivci.components.r = VK_COMPONENT_SWIZZLE_R;
ivci.components.g = VK_COMPONENT_SWIZZLE_G;
ivci.components.b = VK_COMPONENT_SWIZZLE_B;
ivci.components.a = VK_COMPONENT_SWIZZLE_A;
ivci.subresourceRange.baseMipLevel = 0;
ivci.subresourceRange.levelCount = 1;
ivci.subresourceRange.baseArrayLayer = 0;
ivci.subresourceRange.layerCount = 6;
ivci.viewType = VK_IMAGE_VIEW_TYPE_CUBE;
ivci.flags = 0;
ivci.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
ivci.format = colour_imginfo.format;
ivci.image = targ->colour.image;
VkAssert(vkCreateImageView(vk.device, &ivci, vkallocationcb, &targ->colour.view));
ivci.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
ivci.format = depth_imginfo.format;
ivci.image = targ->depth.image;
VkAssert(vkCreateImageView(vk.device, &ivci, vkallocationcb, &targ->depth.view));
}
for (f = 0; f < 6; f++)
{
targ->face[f].width = targ->face[f].height = size;
//per-face view for the framebuffer
{
VkImageViewCreateInfo ivci = {VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO};
ivci.components.r = VK_COMPONENT_SWIZZLE_R;
ivci.components.g = VK_COMPONENT_SWIZZLE_G;
ivci.components.b = VK_COMPONENT_SWIZZLE_B;
ivci.components.a = VK_COMPONENT_SWIZZLE_A;
ivci.subresourceRange.baseMipLevel = 0;
ivci.subresourceRange.levelCount = 1;
ivci.subresourceRange.baseArrayLayer = f;
ivci.subresourceRange.layerCount = 1;
ivci.viewType = VK_IMAGE_VIEW_TYPE_2D;
ivci.flags = 0;
ivci.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
ivci.format = colour_imginfo.format;
ivci.image = targ->colour.image;
VkAssert(vkCreateImageView(vk.device, &ivci, vkallocationcb, &targ->face[f].colour.view));
ivci.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
ivci.format = depth_imginfo.format;
ivci.image = targ->depth.image;
VkAssert(vkCreateImageView(vk.device, &ivci, vkallocationcb, &targ->face[f].depth.view));
}
targ->colour.layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
targ->depth.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL;
{
VkFramebufferCreateInfo fbinfo = {VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO};
VkImageView attachments[2] = {targ->face[f].colour.view, targ->face[f].depth.view};
fbinfo.flags = 0;
fbinfo.renderPass = vk.renderpass[2];
fbinfo.attachmentCount = countof(attachments);
fbinfo.pAttachments = attachments;
fbinfo.width = size;
fbinfo.height = size;
fbinfo.layers = 1;
VkAssert(vkCreateFramebuffer(vk.device, &fbinfo, vkallocationcb, &targ->face[f].framebuffer));
}
targ->face[f].restartinfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
targ->face[f].restartinfo.pNext = NULL;
targ->face[f].restartinfo.framebuffer = targ->face[f].framebuffer;
targ->face[f].restartinfo.renderArea.offset.x = 0;
targ->face[f].restartinfo.renderArea.offset.y = 0;
targ->face[f].restartinfo.renderArea.extent.width = size;
targ->face[f].restartinfo.renderArea.extent.height = size;
targ->face[f].restartinfo.pClearValues = clearvalues;
}
clearvalues[1].depthStencil.depth = 1;
}
void VKBE_RT_Begin(struct vk_rendertarg *targ)
{
if (vk.rendertarg == targ)
return;
if (vk.rendertarg)
vkCmdEndRenderPass(vk.frame->cbuf);
r_refdef.pxrect.x = 0;
r_refdef.pxrect.y = 0;
r_refdef.pxrect.width = targ->width;
r_refdef.pxrect.height = targ->height;
r_refdef.pxrect.maxheight = targ->height;
vid.fbpwidth = targ->width;
vid.fbpheight = targ->height;
vkCmdBeginRenderPass(vk.frame->cbuf, &targ->restartinfo, VK_SUBPASS_CONTENTS_INLINE);
//future reuse shouldn't clear stuff
if (targ->restartinfo.clearValueCount)
{
VkClearValue clearvalues[2];
VkRenderPassBeginInfo rpass = {VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO};
rpass.renderPass = vk.renderpass[2];
rpass.framebuffer = targ->framebuffer;
rpass.renderArea.offset.x = 0;
rpass.renderArea.offset.y = 0;
rpass.renderArea.extent.width = targ->width;
rpass.renderArea.extent.height = targ->height;
rpass.clearValueCount = 2;
rpass.pClearValues = clearvalues;
Vector4Set(clearvalues[0].color.float32, 0, 0, 0, 0);
clearvalues[1].depthStencil.depth = 1;
clearvalues[1].depthStencil.stencil = 0;
vkCmdBeginRenderPass(vk.frame->cbuf, &rpass, VK_SUBPASS_CONTENTS_INLINE);
rpass.renderPass = vk.renderpass[0];
rpass.pClearValues = NULL;
rpass.clearValueCount = 0;
targ->restartinfo = rpass;
targ->prev = vk.rendertarg;
vk.rendertarg = targ;
targ->depthcleared = true;
targ->restartinfo.renderPass = vk.renderpass[0];
targ->restartinfo.clearValueCount = 0;
}
{
VkRect2D wrekt;
VkViewport viewport;
viewport.x = r_refdef.pxrect.x;
viewport.y = r_refdef.pxrect.y;
viewport.width = r_refdef.pxrect.width;
viewport.height = r_refdef.pxrect.height;
viewport.minDepth = 0;
viewport.maxDepth = shaderstate.depthrange;
vkCmdSetViewport(vk.frame->cbuf, 0, 1, &viewport);
wrekt.offset.x = viewport.x;
wrekt.offset.y = viewport.y;
wrekt.extent.width = viewport.width;
wrekt.extent.height = viewport.height;
vkCmdSetScissor(vk.frame->cbuf, 0, 1, &wrekt);
}
}
void VKBE_RT_End(void)
{
vkCmdEndRenderPass(vk.frame->cbuf);
vk.rendertarg = vk.rendertarg->prev;
vkCmdBeginRenderPass(vk.frame->cbuf, &vk.rendertarg->restartinfo, VK_SUBPASS_CONTENTS_INLINE);
vk.rendertarg = targ;
{
VkRect2D wrekt;
@ -4633,6 +4850,7 @@ static qboolean BE_GenerateRefraction(batch_t *batch, shader_t *bs)
{
float oldil;
int oldbem;
struct vk_rendertarg *targ;
//these flags require rendering some view as an fbo
if (r_refdef.recurse)
return false;
@ -4640,9 +4858,11 @@ static qboolean BE_GenerateRefraction(batch_t *batch, shader_t *bs)
return false;
oldbem = shaderstate.mode;
oldil = shaderstate.identitylighting;
targ = vk.rendertarg;
if (bs->flags & SHADER_HASREFLECT)
{
struct vk_rendertarg *targ = vk.rendertarg;
vrect_t orect = r_refdef.vrect;
pxrect_t oprect = r_refdef.pxrect;
@ -4650,11 +4870,11 @@ static qboolean BE_GenerateRefraction(batch_t *batch, shader_t *bs)
r_refdef.vrect.y = 0;
r_refdef.vrect.width = vid.fbvwidth/2;
r_refdef.vrect.height = vid.fbvheight/2;
VKBE_RT_Begin(&shaderstate.rt_reflection, vid.fbpwidth/2, vid.fbpheight/2);
VKBE_RT_Gen(&shaderstate.rt_reflection, vid.fbpwidth/2, vid.fbpheight/2, false);
VKBE_RT_Begin(&shaderstate.rt_reflection);
R_DrawPortal(batch, cl.worldmodel->batches, NULL, 1);
r_refdef.vrect = orect;
r_refdef.pxrect = oprect;
VKBE_RT_End();
}
if (bs->flags & (SHADER_HASREFRACT|SHADER_HASREFRACTDEPTH))
{
@ -4668,16 +4888,18 @@ static qboolean BE_GenerateRefraction(batch_t *batch, shader_t *bs)
r_refdef.vrect.y = 0;
r_refdef.vrect.width = vid.fbvwidth/2;
r_refdef.vrect.height = vid.fbvheight/2;
VKBE_RT_Begin(&shaderstate.rt_refraction, vid.fbpwidth/2, vid.fbpheight/2);
VKBE_RT_Gen(&shaderstate.rt_refraction, vid.fbpwidth/2, vid.fbpheight/2, false);
VKBE_RT_Begin(&shaderstate.rt_refraction);
R_DrawPortal(batch, cl.worldmodel->batches, NULL, ((bs->flags & SHADER_HASREFRACTDEPTH)?3:2)); //fixme
r_refdef.vrect = ovrect;
r_refdef.pxrect = oprect;
VKBE_RT_End();
shaderstate.tex_refraction = &shaderstate.rt_refraction.q_colour;
VKBE_RT_Begin(targ);
}
else
{
VKBE_RT_Begin(targ);
R_DrawPortal(batch, cl.worldmodel->batches, NULL, 3);
T_Gen_CurrentRender();
shaderstate.tex_refraction = shaderstate.tex_currentrender;
@ -4737,6 +4959,7 @@ static qboolean BE_GenerateRefraction(batch_t *batch, shader_t *bs)
BE_RT_End();
}
*/
VKBE_RT_Begin(targ);
VKBE_SelectMode(oldbem);
shaderstate.identitylighting = oldil;
@ -5698,7 +5921,7 @@ void VKBE_DoneShadows(void)
vkCmdBeginRenderPass(vk.frame->cbuf, &vk.rendertarg->restartinfo, VK_SUBPASS_CONTENTS_INLINE);
viewport.x = r_refdef.pxrect.x;
viewport.y = r_refdef.pxrect.maxheight - (r_refdef.pxrect.y+r_refdef.pxrect.height); //silly GL...
viewport.y = r_refdef.pxrect.y;//r_refdef.pxrect.maxheight - (r_refdef.pxrect.y+r_refdef.pxrect.height); //silly GL...
viewport.width = r_refdef.pxrect.width;
viewport.height = r_refdef.pxrect.height;
viewport.minDepth = 0;
@ -5798,6 +6021,7 @@ void VKBE_DrawWorld (batch_t **worldbatches, qbyte *vis)
else
#endif
shaderstate.identitylighting = 1;
shaderstate.identitylighting *= r_refdef.hdr_value;
shaderstate.identitylightmap = shaderstate.identitylighting / (1<<gl_overbright.ival);
VKBE_SelectMode(BEM_STANDARD);

View file

@ -54,8 +54,9 @@ static void VK_DestroyRenderPass(void);
static void VK_CreateRenderPass(void);
struct vulkaninfo_s vk;
static struct vk_rendertarg postproc[2];
static struct vk_rendertarg postproc[4];
static unsigned int postproc_buf;
static struct vk_rendertarg_cube vk_rt_cubemap;
qboolean VK_SCR_GrabBackBuffer(void);
@ -1091,7 +1092,7 @@ void VK_R_DeInit (void)
Image_Shutdown();
}
void VK_SetupViewPortProjection(void)
void VK_SetupViewPortProjection(qboolean flipy)
{
extern cvar_t gl_mindist;
@ -1112,7 +1113,19 @@ void VK_SetupViewPortProjection(void)
// screenaspect = (float)r_refdef.vrect.width/r_refdef.vrect.height;
/*view matrix*/
Matrix4x4_CM_ModelViewMatrixFromAxis(r_refdef.m_view, vpn, vright, vup, r_refdef.vieworg);
if (flipy) //mimic gl and give bottom-up
{
vec3_t down;
VectorNegate(vup, down);
VectorCopy(down, vup);
Matrix4x4_CM_ModelViewMatrixFromAxis(r_refdef.m_view, vpn, vright, down, r_refdef.vieworg);
r_refdef.flipcull = SHADER_CULL_FRONT | SHADER_CULL_BACK;
}
else
{
Matrix4x4_CM_ModelViewMatrixFromAxis(r_refdef.m_view, vpn, vright, vup, r_refdef.vieworg);
r_refdef.flipcull = 0;
}
Matrix4x4_CM_Projection_Inf(r_refdef.m_projection, fov_x, fov_y, bound(0.1, gl_mindist.value, 4));
}
@ -1304,10 +1317,292 @@ void VK_Init_PostProc(void)
}
static qboolean VK_R_RenderScene_Cubemap(struct vk_rendertarg *fb)
{
int cmapsize = 512;
int i;
static vec3_t ang[6] =
{ {0, -90, 0}, {0, 90, 0},
{90, 0, 0}, {-90, 0, 0},
{0, 0, 0}, {0, -180, 0} };
vec3_t saveang;
vec3_t saveorg;
vrect_t vrect;
pxrect_t prect;
extern cvar_t ffov;
shader_t *shader;
int facemask;
extern cvar_t r_projection;
int oldfbo = -1;
qboolean fboreset = false;
int osm = r_refdef.stereomethod;
struct vk_rendertarg_cube *rtc = &vk_rt_cubemap;
if (!*ffov.string || !strcmp(ffov.string, "0"))
{
if (ffov.vec4[0] != scr_fov.value)
{
ffov.value = ffov.vec4[0] = scr_fov.value;
Shader_NeedReload(false); //gah!
}
}
facemask = 0;
switch(r_projection.ival)
{
default: //invalid.
return false;
case PROJ_STEREOGRAPHIC:
shader = R_RegisterShader("postproc_stereographic", SUF_NONE,
"{\n"
"program postproc_stereographic\n"
"{\n"
"map $sourcecube\n"
"}\n"
"}\n"
);
facemask |= 1<<4; /*front view*/
if (ffov.value > 70)
{
facemask |= (1<<0) | (1<<1); /*side/top*/
if (ffov.value > 85)
facemask |= (1<<2) | (1<<3); /*bottom views*/
if (ffov.value > 300)
facemask |= 1<<5; /*back view*/
}
break;
case PROJ_FISHEYE:
shader = R_RegisterShader("postproc_fisheye", SUF_NONE,
"{\n"
"program postproc_fisheye\n"
"{\n"
"map $sourcecube\n"
"}\n"
"}\n"
);
//fisheye view sees up to a full sphere
facemask |= 1<<4; /*front view*/
if (ffov.value > 77)
facemask |= (1<<0) | (1<<1) | (1<<2) | (1<<3); /*side/top/bottom views*/
if (ffov.value > 270)
facemask |= 1<<5; /*back view*/
break;
case PROJ_PANORAMA:
shader = R_RegisterShader("postproc_panorama", SUF_NONE,
"{\n"
"program postproc_panorama\n"
"{\n"
"map $sourcecube\n"
"}\n"
"}\n"
);
//panoramic view needs at most the four sides
facemask |= 1<<4; /*front view*/
if (ffov.value > 90)
{
facemask |= (1<<0) | (1<<1); /*side views*/
if (ffov.value > 270)
facemask |= 1<<5; /*back view*/
}
facemask = 0x3f;
break;
case PROJ_LAEA:
shader = R_RegisterShader("postproc_laea", SUF_NONE,
"{\n"
"program postproc_laea\n"
"{\n"
"map $sourcecube\n"
"}\n"
"}\n"
);
facemask |= 1<<4; /*front view*/
if (ffov.value > 90)
{
facemask |= (1<<0) | (1<<1) | (1<<2) | (1<<3); /*side/top/bottom views*/
if (ffov.value > 270)
facemask |= 1<<5; /*back view*/
}
break;
case PROJ_EQUIRECTANGULAR:
shader = R_RegisterShader("postproc_equirectangular", SUF_NONE,
"{\n"
"program postproc_equirectangular\n"
"{\n"
"map $sourcecube\n"
"}\n"
"}\n"
);
facemask = 0x3f;
#if 0
facemask |= 1<<4; /*front view*/
if (ffov.value > 90)
{
facemask |= (1<<0) | (1<<1) | (1<<2) | (1<<3); /*side/top/bottom views*/
if (ffov.value > 270)
facemask |= 1<<5; /*back view*/
}
#endif
break;
}
if (!shader || !shader->prog)
return false; //erk. shader failed.
//FIXME: we should be able to rotate the view
vrect = r_refdef.vrect;
prect = r_refdef.pxrect;
// prect.x = (vrect.x * vid.pixelwidth)/vid.width;
// prect.width = (vrect.width * vid.pixelwidth)/vid.width;
// prect.y = (vrect.y * vid.pixelheight)/vid.height;
// prect.height = (vrect.height * vid.pixelheight)/vid.height;
if (sh_config.texture_non_power_of_two_pic)
{
cmapsize = prect.width > prect.height?prect.width:prect.height;
if (cmapsize > 4096)//sh_config.texture_maxsize)
cmapsize = 4096;//sh_config.texture_maxsize;
}
r_refdef.flags |= RDF_FISHEYE;
vid.fbpwidth = vid.fbpheight = cmapsize;
//FIXME: gl_max_size
VectorCopy(r_refdef.vieworg, saveorg);
VectorCopy(r_refdef.viewangles, saveang);
saveang[2] = 0;
r_refdef.stereomethod = STEREO_OFF;
VKBE_RT_Gen_Cube(rtc, cmapsize, r_clear.ival?true:false);
vrect = r_refdef.vrect; //save off the old vrect
r_refdef.vrect.width = (cmapsize * vid.fbvwidth) / vid.fbpwidth;
r_refdef.vrect.height = (cmapsize * vid.fbvheight) / vid.fbpheight;
r_refdef.vrect.x = 0;
r_refdef.vrect.y = prect.y;
ang[0][0] = -saveang[0];
ang[0][1] = -90;
ang[0][2] = -saveang[0];
ang[1][0] = -saveang[0];
ang[1][1] = 90;
ang[1][2] = saveang[0];
ang[5][0] = -saveang[0]*2;
//in theory, we could use a geometry shader to duplicate the polygons to each face.
//that would of course require that every bit of glsl had such a geometry shader.
//it would at least reduce cpu load quite a bit.
for (i = 0; i < 6; i++)
{
if (!(facemask & (1<<i)))
continue;
VKBE_RT_Begin(&rtc->face[i]);
r_refdef.fov_x = 90;
r_refdef.fov_y = 90;
r_refdef.viewangles[0] = saveang[0]+ang[i][0];
r_refdef.viewangles[1] = saveang[1]+ang[i][1];
r_refdef.viewangles[2] = saveang[2]+ang[i][2];
VK_SetupViewPortProjection(true);
/*if (!vk.rendertarg->depthcleared)
{
VkClearAttachment clr;
VkClearRect rect;
clr.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
clr.clearValue.depthStencil.depth = 1;
clr.clearValue.depthStencil.stencil = 0;
clr.colorAttachment = 1;
rect.rect.offset.x = r_refdef.pxrect.x;
rect.rect.offset.y = r_refdef.pxrect.y;
rect.rect.extent.width = r_refdef.pxrect.width;
rect.rect.extent.height = r_refdef.pxrect.height;
rect.layerCount = 1;
rect.baseArrayLayer = 0;
vkCmdClearAttachments(vk.frame->cbuf, 1, &clr, 1, &rect);
vk.rendertarg->depthcleared = true;
}*/
VKBE_SelectEntity(&r_worldentity);
R_SetFrustum (r_refdef.m_projection, r_refdef.m_view);
RQ_BeginFrame();
if (!(r_refdef.flags & RDF_NOWORLDMODEL))
{
if (cl.worldmodel)
P_DrawParticles ();
}
Surf_DrawWorld();
RQ_RenderBatchClear();
vk.rendertarg->depthcleared = false;
if (R2D_Flush)
Con_Printf("no flush\n");
}
r_refdef.vrect = vrect;
r_refdef.pxrect = prect;
VectorCopy(saveorg, r_refdef.vieworg);
r_refdef.stereomethod = osm;
VKBE_RT_Begin(fb);
r_refdef.flipcull = 0;
VK_Set2D();
shader->defaulttextures->reflectcube = &rtc->q_colour;
// draw it through the shader
if (r_projection.ival == PROJ_EQUIRECTANGULAR)
{
//note vr screenshots have requirements here
R2D_Image(vrect.x, vrect.y, vrect.width, vrect.height, 0, 1, 1, 0, shader);
}
else if (r_projection.ival == PROJ_PANORAMA)
{
float saspect = .5;
float taspect = vrect.height / vrect.width * ffov.value / 90;//(0.5 * vrect.width) / vrect.height;
R2D_Image(vrect.x, vrect.y, vrect.width, vrect.height, -saspect, taspect, saspect, -taspect, shader);
}
else if (vrect.width > vrect.height)
{
float aspect = (0.5 * vrect.height) / vrect.width;
R2D_Image(vrect.x, vrect.y, vrect.width, vrect.height, -0.5, aspect, 0.5, -aspect, shader);
}
else
{
float aspect = (0.5 * vrect.width) / vrect.height;
R2D_Image(vrect.x, vrect.y, vrect.width, vrect.height, -aspect, 0.5, aspect, -0.5, shader);
}
if (R2D_Flush)
R2D_Flush();
return true;
}
void VK_R_RenderView (void)
{
extern unsigned int r_viewcontents;
struct vk_rendertarg *rt;
struct vk_rendertarg *rt, *rtscreen = vk.rendertarg;
extern cvar_t r_fxaa;
extern cvar_t r_renderscale, r_postprocshader;
float renderscale = r_renderscale.value;
@ -1381,6 +1676,7 @@ void VK_R_RenderView (void)
r_refdef.pxrect.y = y;
r_refdef.pxrect.width = x2 - x;
r_refdef.pxrect.height = y2 - y;
r_refdef.pxrect.maxheight = vid.pixelheight;
}
if (renderscale != 1.0)
@ -1388,79 +1684,90 @@ void VK_R_RenderView (void)
r_refdef.flags |= RDF_RENDERSCALE;
r_refdef.pxrect.width *= renderscale;
r_refdef.pxrect.height *= renderscale;
r_refdef.pxrect.maxheight = r_refdef.pxrect.height;
}
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_*
//FIXME: if we're meant to be using msaa, render the scene to an msaa target and then resolve.
if (R_CanBloom())
r_refdef.flags |= RDF_BLOOM;
postproc_buf = 0;
if (r_refdef.flags & (RDF_ALLPOSTPROC|RDF_RENDERSCALE))
{
r_refdef.pxrect.x = 0;
r_refdef.pxrect.y = 0;
rt = &postproc[postproc_buf++%countof(postproc)];
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_Begin(rt, rt->width, rt->height);
VKBE_RT_Gen(rt, r_refdef.pxrect.width, r_refdef.pxrect.height, false);
}
else
rt = NULL;
VK_SetupViewPortProjection();
rt = rtscreen;
if (!(r_refdef.flags & RDF_NOWORLDMODEL) && VK_R_RenderScene_Cubemap(rt))
{
VkViewport vp[1];
VkRect2D scissor[1];
vp[0].x = r_refdef.pxrect.x;
vp[0].y = r_refdef.pxrect.y;
vp[0].width = r_refdef.pxrect.width;
vp[0].height = r_refdef.pxrect.height;
vp[0].minDepth = 0.0;
vp[0].maxDepth = 1.0;
scissor[0].offset.x = r_refdef.pxrect.x;
scissor[0].offset.y = r_refdef.pxrect.y;
scissor[0].extent.width = r_refdef.pxrect.width;
scissor[0].extent.height = r_refdef.pxrect.height;
vkCmdSetViewport(vk.frame->cbuf, 0, countof(vp), vp);
vkCmdSetScissor(vk.frame->cbuf, 0, countof(scissor), scissor);
}
if (!vk.rendertarg->depthcleared)
else
{
VkClearAttachment clr;
VkClearRect rect;
clr.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
clr.clearValue.depthStencil.depth = 1;
clr.clearValue.depthStencil.stencil = 0;
clr.colorAttachment = 1;
rect.rect.offset.x = r_refdef.pxrect.x;
rect.rect.offset.y = r_refdef.pxrect.y;
rect.rect.extent.width = r_refdef.pxrect.width;
rect.rect.extent.height = r_refdef.pxrect.height;
rect.layerCount = 1;
rect.baseArrayLayer = 0;
vkCmdClearAttachments(vk.frame->cbuf, 1, &clr, 1, &rect);
vk.rendertarg->depthcleared = true;
VKBE_RT_Begin(rt);
VK_SetupViewPortProjection(false);
{
VkViewport vp[1];
VkRect2D scissor[1];
vp[0].x = r_refdef.pxrect.x;
vp[0].y = r_refdef.pxrect.y;
vp[0].width = r_refdef.pxrect.width;
vp[0].height = r_refdef.pxrect.height;
vp[0].minDepth = 0.0;
vp[0].maxDepth = 1.0;
scissor[0].offset.x = r_refdef.pxrect.x;
scissor[0].offset.y = r_refdef.pxrect.y;
scissor[0].extent.width = r_refdef.pxrect.width;
scissor[0].extent.height = r_refdef.pxrect.height;
vkCmdSetViewport(vk.frame->cbuf, 0, countof(vp), vp);
vkCmdSetScissor(vk.frame->cbuf, 0, countof(scissor), scissor);
}
if (!vk.rendertarg->depthcleared)
{
VkClearAttachment clr;
VkClearRect rect;
clr.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
clr.clearValue.depthStencil.depth = 1;
clr.clearValue.depthStencil.stencil = 0;
clr.colorAttachment = 1;
rect.rect.offset.x = r_refdef.pxrect.x;
rect.rect.offset.y = r_refdef.pxrect.y;
rect.rect.extent.width = r_refdef.pxrect.width;
rect.rect.extent.height = r_refdef.pxrect.height;
rect.layerCount = 1;
rect.baseArrayLayer = 0;
vkCmdClearAttachments(vk.frame->cbuf, 1, &clr, 1, &rect);
vk.rendertarg->depthcleared = true;
}
VKBE_SelectEntity(&r_worldentity);
R_SetFrustum (r_refdef.m_projection, r_refdef.m_view);
RQ_BeginFrame();
if (!(r_refdef.flags & RDF_NOWORLDMODEL))
{
if (cl.worldmodel)
P_DrawParticles ();
}
Surf_DrawWorld();
RQ_RenderBatchClear();
vk.rendertarg->depthcleared = false;
VK_Set2D ();
}
VKBE_SelectEntity(&r_worldentity);
R_SetFrustum (r_refdef.m_projection, r_refdef.m_view);
RQ_BeginFrame();
if (!(r_refdef.flags & RDF_NOWORLDMODEL))
{
if (cl.worldmodel)
P_DrawParticles ();
}
Surf_DrawWorld();
RQ_RenderBatchClear();
vk.rendertarg->depthcleared = false;
VK_Set2D ();
if (r_refdef.flags & RDF_ALLPOSTPROC)
{
if (!vk.scenepp_waterwarp)
@ -1469,46 +1776,56 @@ void VK_R_RenderView (void)
if (r_refdef.flags & RDF_WATERWARP)
{
r_refdef.flags &= ~RDF_WATERWARP;
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);
VKBE_RT_Gen(rt, 320, 200, false);
}
else
rt = rtscreen;
VKBE_RT_Begin(rt);
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();
}
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);
VKBE_RT_Gen(rt, 320, 200, false);
}
else
rt = rtscreen;
VKBE_RT_Begin(rt);
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.
R2D_ImageColours(rt->width, rt->height, 1, 1);
vk.sourcecolour = &rt->q_colour;
if (r_refdef.flags & RDF_ALLPOSTPROC)
{
rt = &postproc[postproc_buf++];
VKBE_RT_Begin(rt, 320, 240);
VKBE_RT_Gen(rt, 320, 200, false);
}
else
rt = rtscreen;
VKBE_RT_Begin(rt);
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_ImageColours(1, 1, 1, 1);
R2D_Flush();
}
//FIXME: bloom
if (r_refdef.flags & RDF_BLOOM)
{
VKBE_RT_Begin(rtscreen);
VK_R_BloomBlend(&rt->q_colour, r_refdef.vrect.x, r_refdef.vrect.y, r_refdef.vrect.width, r_refdef.vrect.height);
rt = rtscreen;
}
}
else if (r_refdef.flags & RDF_RENDERSCALE)
{
@ -1521,8 +1838,9 @@ void VK_R_RenderView (void)
"}\n"
"}\n"
);
VKBE_RT_End(); //WARNING: redundant begin+end renderpasses.
vk.sourcecolour = &rt->q_colour;
rt = rtscreen;
VKBE_RT_Begin(rt);
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();
}
@ -1752,7 +2070,7 @@ static void VK_PaintScreen(void)
// scr_con_forcedraw = true;
nohud = true;
}
}
SCR_DrawTwoDimensional(uimenu, nohud);
@ -1938,6 +2256,9 @@ qboolean VK_SCR_GrabBackBuffer(void)
rpbi.pClearValues = clearvalues;
vkCmdBeginRenderPass(vk.frame->cbuf, &rpbi, VK_SUBPASS_CONTENTS_INLINE);
vk.frame->backbuf->width = vid.pixelwidth;
vk.frame->backbuf->height = vid.pixelheight;
rpbi.clearValueCount = 0;
rpbi.pClearValues = NULL;
rpbi.renderPass = vk.renderpass[0];
@ -2843,7 +3164,9 @@ void VK_Shutdown(void)
VK_DestroySwapChain();
for (i = 0; i < countof(postproc); i++)
VKBE_RT_Destroy(&postproc[i]);
VKBE_RT_Gen(&postproc[i], 0, 0, false);
VKBE_RT_Gen_Cube(&vk_rt_cubemap, 0, false);
VK_R_BloomShutdown();
vkDestroyCommandPool(vk.device, vk.cmdpool, vkallocationcb);
VK_DestroyRenderPass();

View file

@ -201,7 +201,13 @@ struct vk_rendertarg
qboolean depthcleared; //starting a new gameview needs cleared depth relative to other views, but the first probably won't.
VkRenderPassBeginInfo restartinfo;
struct vk_rendertarg *prev;
};
struct vk_rendertarg_cube
{
uint32_t size;
image_t q_colour, q_depth; //extra sillyness...
vk_image_t colour, depth;
struct vk_rendertarg face[6];
};
extern struct vulkaninfo_s
@ -336,6 +342,10 @@ qboolean VK_LoadTextureMips (texid_t tex, struct pendingtextureinfo *mips);
qboolean VK_Init(rendererstate_t *info, const char *sysextname, qboolean (*createSurface)(void));
void VK_Shutdown(void);
void VK_R_BloomBlend (texid_t source, int x, int y, int w, int h);
void VK_R_BloomShutdown(void);
qboolean R_CanBloom(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);
@ -374,9 +384,9 @@ qboolean VKBE_BeginShadowmap(qboolean isspot, uint32_t width, uint32_t height);
void VKBE_BeginShadowmapFace(void);
void VKBE_DoneShadows(void);
void VKBE_RT_Gen(struct vk_rendertarg *targ, uint32_t width, uint32_t height);
void VKBE_RT_Begin(struct vk_rendertarg *targ, uint32_t width, uint32_t height);
void VKBE_RT_End(void);
void VKBE_RT_Gen_Cube(struct vk_rendertarg_cube *targ, uint32_t size, qboolean clear);
void VKBE_RT_Gen(struct vk_rendertarg *targ, uint32_t width, uint32_t height, qboolean clear);
void VKBE_RT_Begin(struct vk_rendertarg *targ);
void VKBE_RT_Destroy(struct vk_rendertarg *targ);

View file

@ -2248,15 +2248,11 @@ qintptr_t IRC_Frame(qintptr_t *args)
{
memmove(ircclient->bufferedoutmessage, ircclient->bufferedoutmessage+flushed, ircclient->bufferedoutammount - flushed);
ircclient->bufferedoutammount -= flushed;
if (!ircclient->bufferedoutammount)
{
pNet_Close(ircclient->socket);
ircclient->socket = 0;
}
}
}
}
if (ircclient->quitting && !ircclient->bufferedoutammount)
stat = IRC_KILL;
if (stat == IRC_KILL)
{
pNet_Close(ircclient->socket);

View file

@ -93,7 +93,7 @@ float (float event, float parama, float paramb, float devid) CSQC_InputEvent =
{
if (!thedesktop)
return event!=IE_KEYUP;
if (items_keypress(thedesktop, event, parama, paramb, devid))
if (items_keypress_(thedesktop, event, parama, paramb, devid))
return TRUE;
return FALSE;

File diff suppressed because it is too large Load diff

View file

@ -71,7 +71,7 @@ void(mitem_desktop desktop) M_Pop =
mitem_desktop desktop;
void() m_shutdown = {};
void() m_draw = {items_draw(desktop);};
void(vector screensize) m_draw = {items_draw(desktop);};
void(float scan, float chr) m_keydown = {items_keypress(desktop, scan, chr, TRUE);};
void(float scan, float chr) m_keyup = {items_keypress(desktop, scan, chr, FALSE);};
void(float mode) m_toggle