From 45b4659de6b315afba7288159e33d88ec81c36fa Mon Sep 17 00:00:00 2001 From: Spoike Date: Sat, 27 Oct 2018 04:32:18 +0000 Subject: [PATCH] Fix vulkan lag issue with vk_busywait. Separate lightmap formats, to fix deluxemapping-with-hdr-lightmaps. Fix decals lingering on removed bmodels. git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@5326 fc73d0e0-1445-4013-8a0c-d673dee63da5 --- engine/Makefile | 2 +- engine/client/cl_ents.c | 1 - engine/client/cl_main.c | 14 +- engine/client/cl_pred.c | 1 - engine/client/m_items.c | 8 +- engine/client/menu.c | 20 +- engine/client/menu.h | 10 +- engine/client/p_script.c | 2 + engine/client/r_surf.c | 570 +++++++++++---------------- engine/client/render.h | 17 +- engine/client/textedit.c | 12 + engine/gl/gl_alias.c | 3 +- engine/gl/gl_backend.c | 12 +- engine/gl/gl_heightmap.c | 85 ++-- engine/gl/gl_rsurf.c | 10 +- engine/gl/gl_terrain.h | 2 +- engine/gl/r_bishaders.h | 1 + engine/server/pr_cmds.c | 7 +- engine/server/sv_ccmds.c | 2 +- engine/server/sv_send.c | 1 + engine/server/sv_user.c | 7 +- engine/shaders/glsl/defaultwall.glsl | 1 + engine/vk/vk_backend.c | 8 +- engine/vk/vk_init.c | 36 +- engine/vk/vkrenderer.h | 2 +- 25 files changed, 398 insertions(+), 436 deletions(-) diff --git a/engine/Makefile b/engine/Makefile index aef92f4d..1cfd9d83 100644 --- a/engine/Makefile +++ b/engine/Makefile @@ -31,7 +31,7 @@ OGGVER=1.3.3 VORBISVER=1.3.6 SDL2VER=2.0.7 SCINTILLAVER=373 -OPUSVER=1.2.1 +OPUSVER=1.3 SPEEXVER=1.2.0 SPEEXDSPVER=1.2rc3 FREETYPEVER=2.9 diff --git a/engine/client/cl_ents.c b/engine/client/cl_ents.c index c263aa05..a6d8ecad 100644 --- a/engine/client/cl_ents.c +++ b/engine/client/cl_ents.c @@ -63,7 +63,6 @@ static struct predicted_player } predicted_players[MAX_CLIENTS]; static void CL_LerpNetFrameState(framestate_t *fs, lerpents_t *le); -qboolean CL_PredictPlayer(lerpents_t *le, entity_state_t *state, int sequence); void CL_PlayerFrameUpdated(player_state_t *plstate, entity_state_t *state, int sequence); void CL_AckedInputFrame(int inseq, int outseq, qboolean worldstateokay); diff --git a/engine/client/cl_main.c b/engine/client/cl_main.c index f817a892..b5a04e5a 100644 --- a/engine/client/cl_main.c +++ b/engine/client/cl_main.c @@ -5670,17 +5670,13 @@ double Host_Frame (double time) if (cl.paused) cl.gametimemark += time; - idle = (cls.state == ca_disconnected) || + //if we're at a menu/console/thing + idle = Key_Dest_Has_Higher(kdm_gmenu); #ifdef VM_UI - UI_MenuState() != 0 || + idle |= UI_MenuState() != 0; #endif - Key_Dest_Has(kdm_gmenu) || - Key_Dest_Has(kdm_emenu) || - Key_Dest_Has(kdm_editor) || - !vid.activeapp || - cl.paused - ; - // TODO: check if minimized or unfocused + idle = ((cls.state == ca_disconnected) || cl.paused) && !idle; //idle if we're disconnected/paused and not at a menu + idle |= !vid.activeapp; //always idle when tabbed out //read packets early and always, so we don't have stuff waiting for reception quite so often. //should smooth out a few things, and increase download speeds. diff --git a/engine/client/cl_pred.c b/engine/client/cl_pred.c index cc9b5583..fd577296 100644 --- a/engine/client/cl_pred.c +++ b/engine/client/cl_pred.c @@ -1166,7 +1166,6 @@ void CL_PredictMovePNum (int seat) } if (i == pe->num_entities && pv->nolocalplayer) { - return; fromstate = &nullstate; nopred = true; } diff --git a/engine/client/m_items.c b/engine/client/m_items.c index d16956c5..2b4e6162 100644 --- a/engine/client/m_items.c +++ b/engine/client/m_items.c @@ -692,7 +692,7 @@ static void MenuDraw(menu_t *menu) } -menutext_t *MC_AddWhiteText(menu_t *menu, int lhs, int rhs, int y, const char *text, qboolean rightalign) +menutext_t *MC_AddWhiteText(menu_t *menu, int lhs, int rhs, int y, const char *text, int rightalign) { menutext_t *n = Z_Malloc(sizeof(menutext_t) + (text?strlen(text):0)+1); n->common.type = mt_text; @@ -712,7 +712,7 @@ menutext_t *MC_AddWhiteText(menu_t *menu, int lhs, int rhs, int y, const char *t return n; } -menutext_t *MC_AddBufferedText(menu_t *menu, int lhs, int rhs, int y, const char *text, qboolean rightalign, qboolean red) +menutext_t *MC_AddBufferedText(menu_t *menu, int lhs, int rhs, int y, const char *text, int rightalign, qboolean red) { menutext_t *n = Z_Malloc(sizeof(menutext_t) + strlen(text)+1); n->common.type = mt_text; @@ -732,7 +732,7 @@ menutext_t *MC_AddBufferedText(menu_t *menu, int lhs, int rhs, int y, const char return n; } -menutext_t *MC_AddRedText(menu_t *menu, int lhs, int rhs, int y, const char *text, qboolean rightalign) +menutext_t *MC_AddRedText(menu_t *menu, int lhs, int rhs, int y, const char *text, int rightalign) { menutext_t *n; n = MC_AddWhiteText(menu, lhs, rhs, y, text, rightalign); @@ -1329,7 +1329,7 @@ menubutton_t *MC_AddCommand(menu_t *menu, int lhs, int rhs, int y, char *text, q return n; } -menubutton_t *VARGS MC_AddConsoleCommandf(menu_t *menu, int lhs, int rhs, int y, qboolean rightalign, const char *text, char *command, ...) +menubutton_t *VARGS MC_AddConsoleCommandf(menu_t *menu, int lhs, int rhs, int y, int rightalign, const char *text, char *command, ...) { va_list argptr; static char string[1024]; diff --git a/engine/client/menu.c b/engine/client/menu.c index 98012e96..0ed7614e 100644 --- a/engine/client/menu.c +++ b/engine/client/menu.c @@ -1136,9 +1136,9 @@ void M_Menu_Quit_f (void) quitmenu = M_CreateMenuInfront(0); quitmenu->key = MC_SaveQuit_Key; - MC_AddWhiteText(quitmenu, 64, 0, 84, "You have unsaved settings ", false); - MC_AddWhiteText(quitmenu, 64, 0, 92, " Would you like to ", false); - MC_AddWhiteText(quitmenu, 64, 0, 100, " save them now? ", false); + MC_AddWhiteText(quitmenu, 64, 256, 84, "You have unsaved settings ", 2); + MC_AddWhiteText(quitmenu, 64, 256, 92, " Would you like to ", 2); + MC_AddWhiteText(quitmenu, 64, 256, 100, " save them now? ", 2); quitmenu->selecteditem = (menuoption_t *) #ifdef FTE_TARGET_WEB @@ -1162,19 +1162,19 @@ void M_Menu_Quit_f (void) #ifdef FTE_TARGET_WEB -// MC_AddWhiteText(quitmenu, 64, 0, 84, " ", false); - MC_AddWhiteText(quitmenu, 64, 0, 92, " There is nothing to save ", false); -// MC_AddWhiteText(quitmenu, 64, 0, 100, " ", false); +// MC_AddWhiteText(quitmenu, 64, 256, 84, " ", 2); + MC_AddWhiteText(quitmenu, 64, 256, 92, " There is nothing to save ", 2); +// MC_AddWhiteText(quitmenu, 64, 256, 100, " ", 2); quitmenu->selecteditem = (menuoption_t *) MC_AddConsoleCommand (quitmenu, 120, 0, 116, "Oh", "menupop\n"); #else { int i = rand()&7; - MC_AddWhiteText(quitmenu, 64, 0, 84, quitMessage[i*4+0], false); - MC_AddWhiteText(quitmenu, 64, 0, 92, quitMessage[i*4+1], false); - MC_AddWhiteText(quitmenu, 64, 0, 100, quitMessage[i*4+2], false); - MC_AddWhiteText(quitmenu, 64, 0, 108, quitMessage[i*4+3], false); + MC_AddWhiteText(quitmenu, 64, 256, 84, quitMessage[i*4+0], 2); + MC_AddWhiteText(quitmenu, 64, 256, 92, quitMessage[i*4+1], 2); + MC_AddWhiteText(quitmenu, 64, 256, 100, quitMessage[i*4+2], 2); + MC_AddWhiteText(quitmenu, 64, 256, 108, quitMessage[i*4+3], 2); } quitmenu->selecteditem = (menuoption_t *) diff --git a/engine/client/menu.h b/engine/client/menu.h index 32a94de6..bd4b3e78 100644 --- a/engine/client/menu.h +++ b/engine/client/menu.h @@ -201,7 +201,7 @@ typedef struct menucheck_s { typedef struct { menucommon_t common; const char *text; - qboolean rightalign; + int rightalign; qboolean isred; } menutext_t; @@ -302,9 +302,9 @@ typedef struct menu_s { menuoption_t *cursoritem; } menu_t; -menutext_t *MC_AddBufferedText(menu_t *menu, int lhs, int rhs, int y, const char *text, qboolean rightalign, qboolean red); -menutext_t *MC_AddRedText(menu_t *menu, int lhs, int rhs, int y, const char *text, qboolean rightalign); -menutext_t *MC_AddWhiteText(menu_t *menu, int lhs, int rhs, int y, const char *text, qboolean rightalign); +menutext_t *MC_AddBufferedText(menu_t *menu, int lhs, int rhs, int y, const char *text, int rightalign, qboolean red); +menutext_t *MC_AddRedText(menu_t *menu, int lhs, int rhs, int y, const char *text, int rightalign); +menutext_t *MC_AddWhiteText(menu_t *menu, int lhs, int rhs, int y, const char *text, int rightalign); menubind_t *MC_AddBind(menu_t *menu, int cx, int bx, int y, const char *caption, char *command, char *tooltip); menubox_t *MC_AddBox(menu_t *menu, int x, int y, int width, int height); menupicture_t *MC_AddPicture(menu_t *menu, int x, int y, int width, int height, char *picname); @@ -319,7 +319,7 @@ menubutton_t *MC_AddConsoleCommand(menu_t *menu, int lhs, int rhs, int y, const menubutton_t *MC_AddConsoleCommandQBigFont(menu_t *menu, int x, int y, const char *text, const char *command); mpic_t *QBigFontWorks(void); menubutton_t *MC_AddConsoleCommandHexen2BigFont(menu_t *menu, int x, int y, const char *text, const char *command); -menubutton_t *VARGS MC_AddConsoleCommandf(menu_t *menu, int lhs, int rhs, int y, qboolean rightalign, const char *text, char *command, ...); +menubutton_t *VARGS MC_AddConsoleCommandf(menu_t *menu, int lhs, int rhs, int y, int rightalign, const char *text, char *command, ...); menubutton_t *MC_AddCommand(menu_t *menu, int lhs, int rhs, int y, char *text, qboolean (*command) (union menuoption_s *,struct menu_s *,int)); menucombo_t *MC_AddCombo(menu_t *menu, int tx, int cx, int y, const char *caption, const char **ops, int initialvalue); menucombo_t *MC_AddCvarCombo(menu_t *menu, int tx, int cx, int y, const char *caption, cvar_t *cvar, const char **ops, const char **values); diff --git a/engine/client/p_script.c b/engine/client/p_script.c index 28393be5..d9d83c58 100644 --- a/engine/client/p_script.c +++ b/engine/client/p_script.c @@ -6489,6 +6489,8 @@ static void R_AddClippedDecal(scenetris_t *t, clippeddecal_t *d, plooks_t *type) if (d->entity > 0) { lerpents_t *le = cl.lerpents+d->entity; + if (le->sequence != cl.lerpentssequence) + return; //hide until its visible again. if (le->angles[0] || le->angles[1] || le->angles[2]) { //FIXME: deal with rotated entities. d->die = -1; diff --git a/engine/client/r_surf.c b/engine/client/r_surf.c index 3bbe8209..cc2f796a 100644 --- a/engine/client/r_surf.c +++ b/engine/client/r_surf.c @@ -40,9 +40,6 @@ static vec3_t modelorg; /*set before recursively entering the visible surface model_t *currentmodel; -uploadfmt_t lightmap_fmt; //bgra32, rgba32, rgb24, lum8 -int lightmap_bytes; // 1, 3 or 4 - size_t maxblocksize; vec3_t *blocknormals; unsigned *blocklights; @@ -597,7 +594,7 @@ static void Surf_AddDynamicLightsColours (msurface_t *surf) -static void Surf_BuildDeluxMap (model_t *wmodel, msurface_t *surf, qbyte *dest, unsigned int lmwidth, vec3_t *blocknormals) +static void Surf_BuildDeluxMap (model_t *wmodel, msurface_t *surf, qbyte *dest, lightmapinfo_t *lm, vec3_t *blocknormals) { int smax, tmax; int i, j, size; @@ -609,7 +606,7 @@ static void Surf_BuildDeluxMap (model_t *wmodel, msurface_t *surf, qbyte *dest, vec_t *bnorm; vec3_t temp; - int stride = lmwidth*lightmap_bytes; + int stride = lm->width*lm->pixbytes; if (!dest) return; @@ -645,7 +642,7 @@ static void Surf_BuildDeluxMap (model_t *wmodel, msurface_t *surf, qbyte *dest, switch(wmodel->lightmaps.fmt) { case LM_E5BGR9: - deluxmap = surf->samples - wmodel->lightdata + wmodel->deluxdata; + deluxmap = ((surf->samples - wmodel->lightdata)/4)*3 + wmodel->deluxdata; for (maps = 0 ; maps < MAXQ1LIGHTMAPS && surf->styles[maps] != 255 ; maps++) { scale = d_lightstylevalue[surf->styles[maps]]; @@ -703,7 +700,7 @@ store: // bound, invert, and shift - stride -= smax*lightmap_bytes; + stride -= smax*lm->pixbytes; bnorm = blocknormals[0]; for (i=0 ; ipixbytes; bnorm+=3; } } @@ -803,19 +800,19 @@ static void Surf_PackRGB32F(void *result, int r, int g, int b, int one) just unpacks the internal lightmap block into texture info ready for upload merges stains and oversaturates overbrights. */ -static void Surf_StoreLightmap_RGB(qbyte *dest, unsigned int *bl, int smax, int tmax, unsigned int shift, stmap *stainsrc, unsigned int lmwidth) +static void Surf_StoreLightmap_RGB(qbyte *dest, unsigned int *bl, int smax, int tmax, unsigned int shift, stmap *stainsrc, lightmapinfo_t *lm) { int r, g, b, m; unsigned int i, j; int stride; - switch(lightmap_fmt) + switch(lm->fmt) { default: Sys_Error("Bad lightmap_fmt\n"); break; case PTI_A2BGR10: - stride = (lmwidth-smax)<<2; + stride = (lm->width-smax)<<2; shift -= 2; @@ -848,11 +845,11 @@ static void Surf_StoreLightmap_RGB(qbyte *dest, unsigned int *bl, int smax, int dest += 4; } if (stainsrc) - stainsrc += (lmwidth - smax)*3; + stainsrc += (lm->width - smax)*3; } break; case PTI_E5BGR9: - stride = (lmwidth-smax)<<2; + stride = (lm->width-smax)<<2; //5bit shared exponent, with bias of 15. for (i=0 ; iwidth - smax)*3; } break; case PTI_RGBA16F: - stride = (lmwidth-smax)<<3; + stride = (lm->width-smax)<<3; for (i=0 ; iwidth - smax)*3; } break; case PTI_RGBA32F: - stride = (lmwidth-smax)<<4; + stride = (lm->width-smax)<<4; for (i=0 ; iwidth - smax)*3; } break; case PTI_RGBX8: case PTI_RGBA8: - stride = (lmwidth-smax)<<2; + stride = (lm->width-smax)<<2; for (i=0 ; iwidth - smax)*3; } break; case PTI_BGRX8: case PTI_BGRA8: - stride = (lmwidth-smax)<<2; + stride = (lm->width-smax)<<2; for (i=0 ; iwidth - smax)*3; } break; /* case PTI_BGRX8: case PTI_BGRA8: - stride = (lmwidth-smax)<<2; + stride = (lm->width-smax)<<2; bl = blocklights; @@ -1057,7 +1054,7 @@ static void Surf_StoreLightmap_RGB(qbyte *dest, unsigned int *bl, int smax, int break; */ case PTI_RGB565: - stride = (lmwidth-smax)<<1; + stride = (lm->width-smax)<<1; for (i=0 ; iwidth - smax)*3; } break; case PTI_RGBA4444: - stride = (lmwidth-smax)<<1; + stride = (lm->width-smax)<<1; for (i=0 ; iwidth - smax)*3; } break; case PTI_RGBA5551: - stride = (lmwidth-smax)<<1; + stride = (lm->width-smax)<<1; for (i=0 ; iwidth - smax)*3; } break; case PTI_ARGB4444: - stride = (lmwidth-smax)<<1; + stride = (lm->width-smax)<<1; for (i=0 ; iwidth - smax)*3; } break; case PTI_ARGB1555: - stride = (lmwidth-smax)<<1; + stride = (lm->width-smax)<<1; for (i=0 ; iwidth - smax)*3; } break; case PTI_RGB8: - stride = lmwidth*3 - (smax*3); + stride = lm->width*3 - (smax*3); for (i=0 ; iwidth - smax)*3; } break; } @@ -1295,29 +1292,30 @@ R_BuildLightMap Combine and scale multiple lightmaps into the 8.8 format in blocklights =============== */ -static void Surf_BuildLightMap (model_t *currentmodel, msurface_t *surf, qbyte *dest, qbyte *deluxdest, stmap *stainsrc, int shift, int ambient, unsigned int lmwidth, int *d_lightstylevalue) +static void Surf_BuildLightMap (model_t *currentmodel, msurface_t *surf, int map, int shift, int ambient, int *d_lightstylevalue) { - int smax, tmax; + int smax = (surf->extents[0]>>surf->lmshift)+1; + int tmax = (surf->extents[1]>>surf->lmshift)+1; int t; int i; - size_t size; - qbyte *lightmap; + size_t size = (size_t)smax*tmax; unsigned scalergb[3]; unsigned scale; int maps; unsigned *bl; + glRect_t *theRect; + void *dest; + void *deluxedest; + void *stainsrc; + lightmapinfo_t *lm = lightmap[surf->lightmaptexturenums[map]]; + qbyte *src = surf->samples; shift += 7; // increase to base value surf->cached_dlight = (surf->dlightframe == r_framecount); - smax = (surf->extents[0]>>surf->lmshift)+1; - tmax = (surf->extents[1]>>surf->lmshift)+1; - size = (size_t)smax*tmax; - lightmap = surf->samples; - if (size > maxblocksize) { //fixme: fill in? - //Threading: this should not be a problem, all surfaces should have been built from the main thead at map load so it should have maxed it there. + //Threading: this should not be a problem, all surfaces should have been built from the main thread at map load so it should have maxed it there. BZ_Free(blocklights); BZ_Free(blocknormals); @@ -1326,10 +1324,44 @@ static void Surf_BuildLightMap (model_t *currentmodel, msurface_t *surf, qbyte * blocklights = BZ_Malloc(maxblocksize * 3*sizeof(*blocklights)); } - if (currentmodel->deluxdata) - Surf_BuildDeluxMap(currentmodel, surf, deluxdest, lmwidth, blocknormals); + //make sure we flag the output rect properly. + theRect = &lm->rectchange; + if (theRect->t > surf->light_t[map]) + theRect->t = surf->light_t[map]; + if (theRect->l > surf->light_s[map]) + theRect->l = surf->light_s[map]; + if (theRect->r < surf->light_s[map]+smax) + theRect->r = surf->light_s[map]+smax; + if (theRect->b < surf->light_t[map]+tmax) + theRect->b = surf->light_t[map]+tmax; - if (lightmap_fmt != PTI_L8) + dest = lm->lightmaps + (surf->light_t[map] * lm->width + surf->light_s[map]) * lm->pixbytes; + if (!r_stains.value || !surf->stained) + stainsrc = NULL; + else + stainsrc = lm->stainmaps + (surf->light_t[map] * lm->width + surf->light_s[map]) * 3; + + lm->modified = true; + if (lm->hasdeluxe && currentmodel->deluxdata) + { + lightmapinfo_t *dlm = lightmap[surf->lightmaptexturenums[map]+1]; + dlm->modified = true; + theRect = &dlm->rectchange; + if (theRect->t > surf->light_t[map]) + theRect->t = surf->light_t[map]; + if (theRect->l > surf->light_s[map]) + theRect->l = surf->light_s[map]; + if (theRect->r < surf->light_s[map]+smax) + theRect->r = surf->light_s[map]+smax; + if (theRect->b < surf->light_t[map]+tmax) + theRect->b = surf->light_t[map]+tmax; + + deluxedest = dlm->lightmaps + (surf->light_t[map] * dlm->width + surf->light_s[map]) * dlm->pixbytes; + + Surf_BuildDeluxMap(currentmodel, surf, deluxedest, lm, blocknormals); + } + + if (lm->fmt != PTI_L8) { // set to full bright if no light data if (ambient < 0) @@ -1377,7 +1409,7 @@ static void Surf_BuildLightMap (model_t *currentmodel, msurface_t *surf, qbyte * } // add all the lightmaps - if (lightmap) + if (src) { if (currentmodel->fromgame == fg_quake3) Sys_Error("Surf_BuildLightMap: q3bsp"); @@ -1393,14 +1425,14 @@ static void Surf_BuildLightMap (model_t *currentmodel, msurface_t *surf, qbyte * VectorScale(cl_lightstyle[surf->styles[maps]].colours, scale, scalergb); for (i=0 ; i>27]*(1<<7); blocklights[i*3+0] += scalergb[0] * e * ((l>> 0)&0x1ff); blocklights[i*3+1] += scalergb[1] * e * ((l>> 9)&0x1ff); blocklights[i*3+2] += scalergb[2] * e * ((l>>18)&0x1ff); } } - lightmap += size*4; // skip to next lightmap + src += size*4; // skip to next lightmap } break; case LM_RGB8: @@ -1414,13 +1446,13 @@ static void Surf_BuildLightMap (model_t *currentmodel, msurface_t *surf, qbyte * bl = blocklights; for (i=0 ; idlightframe == r_framecount) Surf_AddDynamicLightsColours (surf); - if (!r_stains.value || !surf->stained) - stainsrc = NULL; - - Surf_StoreLightmap_RGB(dest, blocklights, smax, tmax, shift, stainsrc, lmwidth); + Surf_StoreLightmap_RGB(dest, blocklights, smax, tmax, shift, stainsrc, lm); } else { @@ -1502,7 +1531,7 @@ static void Surf_BuildLightMap (model_t *currentmodel, msurface_t *surf, qbyte * blocklights[i] = 0; // add all the lightmaps - if (lightmap) + if (src) { switch(currentmodel->lightmaps.fmt) { @@ -1514,10 +1543,10 @@ static void Surf_BuildLightMap (model_t *currentmodel, msurface_t *surf, qbyte * surf->cached_colour[maps] = cl_lightstyle[surf->styles[maps]].colourkey; for (i=0 ; i>0)&0x1ff),((lm>>9)&0x1ff),((lm>>18)&0x1ff)) * scale * (rgb9e5tab[lm>>27]*(1<<7)); } - lightmap += size*4; // skip to next lightmap + src += size*4; // skip to next lightmap } break; case LM_RGB8: @@ -1527,8 +1556,8 @@ static void Surf_BuildLightMap (model_t *currentmodel, msurface_t *surf, qbyte * surf->cached_light[maps] = scale; // 8.8 fraction surf->cached_colour[maps] = cl_lightstyle[surf->styles[maps]].colourkey; for (i=0 ; icached_light[maps] = scale; // 8.8 fraction surf->cached_colour[maps] = cl_lightstyle[surf->styles[maps]].colourkey; for (i=0 ; iwidth); } } #if defined(THREADEDWORLD) && (defined(Q1BSPS)||defined(Q2BSPS)) -static void Surf_BuildLightMap_Worker (model_t *wmodel, msurface_t *surf, qbyte *dest, qbyte *deluxdest, stmap *stainsrc, int shift, int ambient, unsigned int lmwidth, int *d_lightstylevalue) +static void Surf_BuildLightMap_Worker (model_t *wmodel, msurface_t *surf, int shift, int ambient, int *d_lightstylevalue) { int smax, tmax; int t; int i, j; size_t size; - qbyte *lightmap; + lightmapinfo_t *lm = lightmap[surf->lightmaptexturenums[0]]; + qbyte *src; unsigned scalergb[3]; unsigned scale; int maps; unsigned *bl; + qbyte *dest; + qbyte *deluxedest; + stmap *stainsrc; + glRect_t *theRect; static size_t maxblocksize; static vec3_t *blocknormals; @@ -1576,7 +1610,7 @@ static void Surf_BuildLightMap_Worker (model_t *wmodel, msurface_t *surf, qbyte smax = (surf->extents[0]>>surf->lmshift)+1; tmax = (surf->extents[1]>>surf->lmshift)+1; size = (size_t)smax*tmax; - lightmap = surf->samples; + src = surf->samples; if (size > maxblocksize) { //fixme: fill in? @@ -1585,10 +1619,21 @@ static void Surf_BuildLightMap_Worker (model_t *wmodel, msurface_t *surf, qbyte blocklights = BZ_Realloc(blocklights, maxblocksize * 3*sizeof(*blocklights)); } - if (wmodel->deluxdata) - Surf_BuildDeluxMap(wmodel, surf, deluxdest, lmwidth, blocknormals); + dest = lm->lightmaps + (surf->light_t[0] * lm->width + surf->light_s[0]) * lm->pixbytes; + if (!r_stains.value || !surf->stained) + stainsrc = NULL; + else + stainsrc = lm->stainmaps + (surf->light_t[0] * lm->width + surf->light_s[0]) * 3; - if (lightmap_fmt != PTI_L8) + if (lm->hasdeluxe) + { + lightmapinfo_t *dlm = lightmap[surf->lightmaptexturenums[0]+1]; + deluxedest = dlm->lightmaps + (surf->light_t[0] * dlm->width + surf->light_s[0]) * dlm->pixbytes; + + Surf_BuildDeluxMap(wmodel, surf, deluxedest, lm, blocknormals); + } + + if (lm->fmt != PTI_L8) { // set to full bright if no light data if (ambient < 0) @@ -1645,21 +1690,22 @@ static void Surf_BuildLightMap_Worker (model_t *wmodel, msurface_t *surf, qbyte } // add all the lightmaps - if (lightmap) + if (src) { if (wmodel->fromgame == fg_quake3) //rgb { /*q3 lightmaps are meant to be pre-built this code is misguided, and ought never be executed anyway. */ + int pixbytes = lm->pixbytes; bl = blocklights; for (i = 0; i < tmax; i++) { for (j = 0; j < smax; j++) { - bl[0] = 255*lightmap[(i*lmwidth+j)*3]; - bl[1] = 255*lightmap[(i*lmwidth+j)*3+1]; - bl[2] = 255*lightmap[(i*lmwidth+j)*3+2]; + bl[0] = 255*src[(i*pixbytes+j)*3]; + bl[1] = 255*src[(i*pixbytes+j)*3+1]; + bl[2] = 255*src[(i*pixbytes+j)*3+2]; bl+=3; } } @@ -1676,14 +1722,14 @@ static void Surf_BuildLightMap_Worker (model_t *wmodel, msurface_t *surf, qbyte VectorScale(cl_lightstyle[surf->styles[maps]].colours, scale, scalergb); for (i=0 ; i>27]*(1<<7); blocklights[i*3+0] += scalergb[0] * e * ((l>> 0)&0x1ff); blocklights[i*3+1] += scalergb[1] * e * ((l>> 9)&0x1ff); blocklights[i*3+2] += scalergb[2] * e * ((l>>18)&0x1ff); } } - lightmap += size*4; // skip to next lightmap + src += size*4; // skip to next lightmap } break; case LM_RGB8: @@ -1697,13 +1743,13 @@ static void Surf_BuildLightMap_Worker (model_t *wmodel, msurface_t *surf, qbyte bl = blocklights; for (i=0 ; istained) stainsrc = NULL; - Surf_StoreLightmap_RGB(dest, blocklights, smax, tmax, shift, stainsrc, lmwidth); + Surf_StoreLightmap_RGB(dest, blocklights, smax, tmax, shift, stainsrc, lm); } else { @@ -1767,7 +1813,7 @@ static void Surf_BuildLightMap_Worker (model_t *wmodel, msurface_t *surf, qbyte blocklights[i] = 0; // add all the lightmaps - if (lightmap) + if (src) { switch(cl.worldmodel->lightmaps.fmt) { @@ -1792,8 +1838,8 @@ static void Surf_BuildLightMap_Worker (model_t *wmodel, msurface_t *surf, qbyte surf->cached_light[maps] = scale; // 8.8 fraction surf->cached_colour[maps] = cl_lightstyle[surf->styles[maps]].colourkey; for (i=0 ; icached_light[maps] = scale; // 8.8 fraction surf->cached_colour[maps] = cl_lightstyle[surf->styles[maps]].colourkey; for (i=0 ; iwidth); + } + + //make sure we flag the output rect properly. + theRect = &lm->rectchange; + if (theRect->t > surf->light_t[0]) + theRect->t = surf->light_t[0]; + if (theRect->l > surf->light_s[0]) + theRect->l = surf->light_s[0]; + if (theRect->r < surf->light_s[0]+smax) + theRect->r = surf->light_s[0]+smax; + if (theRect->b < surf->light_t[0]+tmax) + theRect->b = surf->light_t[0]+tmax; + lm->modified = true; + + if (lm->hasdeluxe) + { + lightmapinfo_t *dlm = lm+1; + theRect = &dlm->rectchange; + if (theRect->t > surf->light_t[0]) + theRect->t = surf->light_t[0]; + if (theRect->l > surf->light_s[0]) + theRect->l = surf->light_s[0]; + if (theRect->r < surf->light_s[0]+smax) + theRect->r = surf->light_s[0]+smax; + if (theRect->b < surf->light_t[0]+tmax) + theRect->b = surf->light_t[0]+tmax; + dlm->modified = true; } } #endif @@ -1832,12 +1905,7 @@ Multitexture */ void Surf_RenderDynamicLightmaps (msurface_t *fa) { - qbyte *base, *luxbase; - stmap *stainbase; int maps; - glRect_t *theRect; - int smax, tmax; - lightmapinfo_t *lm, *dlm; //surfaces without lightmaps if (fa->lightmaptexturenums[0]<0 || !lightmap) @@ -1871,49 +1939,7 @@ dynamic: Sys_Error("Invalid lightmap index\n"); #endif - lm = lightmap[fa->lightmaptexturenums[0]]; - - lm->modified = true; - - smax = (fa->extents[0]>>fa->lmshift)+1; - tmax = (fa->extents[1]>>fa->lmshift)+1; - - theRect = &lm->rectchange; - if (theRect->t > fa->light_t[0]) - theRect->t = fa->light_t[0]; - if (theRect->b < fa->light_t[0]+tmax) - theRect->b = fa->light_t[0]+tmax; - if (theRect->l > fa->light_s[0]) - theRect->l = fa->light_s[0]; - if (theRect->r < fa->light_s[0]+smax) - theRect->r = fa->light_s[0]+smax; - - if (lm->hasdeluxe) - { - dlm = lightmap[fa->lightmaptexturenums[0]+1]; - dlm->modified = true; - theRect = &dlm->rectchange; - if (theRect->t > fa->light_t[0]) - theRect->t = fa->light_t[0]; - if (theRect->b < fa->light_t[0]+tmax) - theRect->b = fa->light_t[0]+tmax; - if (theRect->l > fa->light_s[0]) - theRect->l = fa->light_s[0]; - if (theRect->r < fa->light_s[0]+smax) - theRect->r = fa->light_s[0]+smax; - - luxbase = dlm->lightmaps; - luxbase += (fa->light_t[0] * dlm->width + fa->light_s[0]) * lightmap_bytes; - } - else - luxbase = NULL; - - - base = lm->lightmaps; - base += (fa->light_t[0] * lm->width + fa->light_s[0]) * lightmap_bytes; - stainbase = lm->stainmaps; - stainbase += (fa->light_t[0] * lm->width + fa->light_s[0]) * 3; - Surf_BuildLightMap (currentmodel, fa, base, luxbase, stainbase, lightmap_shift, r_ambient.value*255, lm->width, d_lightstylevalue); + Surf_BuildLightMap (currentmodel, fa, 0, lightmap_shift, r_ambient.value*255, d_lightstylevalue); RSpeedEnd(RSPEED_DYNAMIC); } @@ -1922,12 +1948,7 @@ dynamic: #if defined(THREADEDWORLD) && (defined(Q1BSPS)||defined(Q2BSPS)) static void Surf_RenderDynamicLightmaps_Worker (model_t *wmodel, msurface_t *fa, int *d_lightstylevalue) { - qbyte *base, *luxbase; - stmap *stainbase; int maps; - glRect_t *lmr, *dlmr = NULL; - int smax, tmax; - lightmapinfo_t *lm, *dlm = NULL; //surfaces without lightmaps if (fa->lightmaptexturenums[0]<0 || !lightmap) @@ -1958,61 +1979,13 @@ dynamic: Sys_Error("Invalid lightmap index\n"); #endif - lm = lightmap[fa->lightmaptexturenums[0]]; - smax = (fa->extents[0]>>fa->lmshift)+1; - tmax = (fa->extents[1]>>fa->lmshift)+1; - - lmr = &lm->rectchange; - if (lm->hasdeluxe) - { - dlm = lightmap[fa->lightmaptexturenums[0]+1]; - dlmr = &dlm->rectchange; - - luxbase = dlm->lightmaps; - luxbase += (fa->light_t[0] * dlm->width + fa->light_s[0]) * lightmap_bytes; - } - else - luxbase = NULL; - - base = lm->lightmaps; - base += (fa->light_t[0] * lm->width + fa->light_s[0]) * lightmap_bytes; - stainbase = lm->stainmaps; - stainbase += (fa->light_t[0] * lm->width + fa->light_s[0]) * 3; - Surf_BuildLightMap_Worker (wmodel, fa, base, luxbase, stainbase, lightmap_shift, r_ambient.value*255, lm->width, d_lightstylevalue); - - if (dlm) - { - if (dlmr->t > fa->light_t[0]) - dlmr->t = fa->light_t[0]; - if (dlmr->b < fa->light_t[0]+tmax) - dlmr->b = fa->light_t[0]+tmax; - if (dlmr->l > fa->light_s[0]) - dlmr->l = fa->light_s[0]; - if (dlmr->r < fa->light_s[0]+smax) - dlmr->r = fa->light_s[0]+smax; - dlm->modified = true; - } - if (lmr->t > fa->light_t[0]) - lmr->t = fa->light_t[0]; - if (lmr->b < fa->light_t[0]+tmax) - lmr->b = fa->light_t[0]+tmax; - if (lmr->l > fa->light_s[0]) - lmr->l = fa->light_s[0]; - if (lmr->r < fa->light_s[0]+smax) - lmr->r = fa->light_s[0]+smax; - lm->modified = true; + Surf_BuildLightMap_Worker (wmodel, fa, lightmap_shift, r_ambient.value*255, d_lightstylevalue); } #endif //THREADEDWORLD void Surf_RenderAmbientLightmaps (msurface_t *fa, int ambient) { - qbyte *base, *luxbase; - stmap *stainbase; - glRect_t *theRect; - int smax, tmax; - lightmapinfo_t *lm, *dlm; - if (!fa->mesh) return; @@ -2030,49 +2003,7 @@ void Surf_RenderAmbientLightmaps (msurface_t *fa, int ambient) dynamic: RSpeedRemark(); - lm = lightmap[fa->lightmaptexturenums[0]]; - - lm->modified = true; - - smax = (fa->extents[0]>>fa->lmshift)+1; - tmax = (fa->extents[1]>>fa->lmshift)+1; - - theRect = &lm->rectchange; - if (theRect->t > fa->light_t[0]) - theRect->t = fa->light_t[0]; - if (theRect->l > fa->light_s[0]) - theRect->l = fa->light_s[0]; - if (theRect->r < fa->light_s[0]+smax) - theRect->r = fa->light_s[0]+smax; - if (theRect->b < fa->light_t[0]+tmax) - theRect->b = fa->light_t[0]+tmax; - - if (lm->hasdeluxe) - { - dlm = lightmap[fa->lightmaptexturenums[0]+1]; - lm->modified = true; - theRect = &lm->rectchange; - if (theRect->t > fa->light_t[0]) - theRect->t = fa->light_t[0]; - if (theRect->l > fa->light_s[0]) - theRect->l = fa->light_s[0]; - if (theRect->r < fa->light_s[0]+smax) - theRect->r = fa->light_s[0]+smax; - if (theRect->b < fa->light_t[0]+tmax) - theRect->b = fa->light_t[0]+tmax; - - luxbase = dlm->lightmaps; - luxbase += (fa->light_t[0] * dlm->width + fa->light_s[0]) * lightmap_bytes; - } - else - luxbase = NULL; - - - base = lm->lightmaps; - base += (fa->light_t[0] * lm->width + fa->light_s[0]) * lightmap_bytes; - stainbase = lm->stainmaps; - stainbase += (fa->light_t[0] * lm->width + fa->light_s[0]) * 3; - Surf_BuildLightMap (currentmodel, fa, base, luxbase, stainbase, lightmap_shift, -1-ambient, lm->width, d_lightstylevalue); + Surf_BuildLightMap (currentmodel, fa, 0, lightmap_shift, -1-ambient, d_lightstylevalue); RSpeedEnd(RSPEED_DYNAMIC); } @@ -3678,19 +3609,19 @@ uploadfmt_t Surf_NameToFormat(const char *nam) return tab[idx]; if (!Q_strcasecmp(nam, "e5bgr9") || !Q_strcasecmp(nam, "rgb9e5")) - return PTI_E5BGR9; + return PTI_E5BGR9; //prefered hdr format, for some reason. if (!Q_strcasecmp(nam, "a2bgr10") || !Q_strcasecmp(nam, "rgb10a2") || !Q_strcasecmp(nam, "rgb10")) - return PTI_A2BGR10; + return PTI_A2BGR10; //prefered ldr format. hurrah for 10 bits. if (!Q_strcasecmp(nam, "rgba32f")) - return PTI_RGBA32F; + return PTI_RGBA32F; //big bulky hdr format if (!Q_strcasecmp(nam, "rgba16f")) - return PTI_RGBA16F; + return PTI_RGBA16F; //tolerable hdr format // if (!Q_strcasecmp(nam, "rgba8s")) // return PTI_RGBA8_SIGNED; if (!Q_strcasecmp(nam, "rgb565") || !Q_strcasecmp(nam, "rgb5")) - return PTI_RGB565; + return PTI_RGB565; //boo hiss if (!Q_strcasecmp(nam, "rgba4444") || !Q_strcasecmp(nam, "rgba4")) - return PTI_RGBA4444; + return PTI_RGBA4444; //erk if (!Q_strcasecmp(nam, "rgba5551") || !Q_strcasecmp(nam, "rgba51")) return PTI_RGBA5551; if (!Q_strcasecmp(nam, "argb4444")) @@ -3698,30 +3629,30 @@ uploadfmt_t Surf_NameToFormat(const char *nam) if (!Q_strcasecmp(nam, "argb1555")) return PTI_ARGB1555; if (!Q_strcasecmp(nam, "rgbx8") || !Q_strcasecmp(nam, "bgrx8") || !Q_strcasecmp(nam, "rgba8") || !Q_strcasecmp(nam, "bgra8")) - return PTI_BGRX8; + return PTI_BGRX8; //most common formats... if (!Q_strcasecmp(nam, "rgb8") || !Q_strcasecmp(nam, "bgr8")) - return PTI_RGB8; + return PTI_RGB8; //generally not recommended if (!Q_strcasecmp(nam, "l8")) return PTI_L8; if (*nam) Con_Printf("Unknown lightmap format: %s\n", nam); - return TF_INVALID; + return PTI_INVALID; } //pick fastest mode for lightmap data -void Surf_LightmapMode(void) +uploadfmt_t Surf_LightmapMode(model_t *model) { - lightmap_fmt = Surf_NameToFormat(r_lightmap_format.string); - if (!sh_config.texfmt[lightmap_fmt]) + uploadfmt_t fmt = Surf_NameToFormat(r_lightmap_format.string); + if (!sh_config.texfmt[fmt]) { qboolean hdr = (vid.flags&VID_SRGBAWARE), rgb = false; - if (lightmap_fmt != TF_INVALID) + if (fmt != PTI_INVALID) Con_Printf("lightmap format %s not supported by renderer\n", r_lightmap_format.string); - if (cl.worldmodel) + if (model) { - switch (cl.worldmodel->lightmaps.fmt) + switch (model->lightmaps.fmt) { case LM_E5BGR9: hdr = rgb = true; @@ -3732,74 +3663,45 @@ void Surf_LightmapMode(void) case LM_L8: break; } - if (cl.worldmodel->deluxdata) + if (model->deluxdata) rgb = true; - if (cl.worldmodel->terrain) //the terrain code can't deal with extended lightmap formats. + if (model->terrain) //the terrain code requires rgba8. hdr = false; } if (sh_config.texfmt[PTI_E5BGR9] && hdr) - lightmap_fmt = PTI_E5BGR9; + fmt = PTI_E5BGR9; else if (sh_config.texfmt[PTI_RGBA16F] && hdr) - lightmap_fmt = PTI_RGBA16F; + fmt = PTI_RGBA16F; else if (sh_config.texfmt[PTI_RGBA32F] && hdr) - lightmap_fmt = PTI_RGBA32F; + fmt = PTI_RGBA32F; else if (sh_config.texfmt[PTI_A2BGR10] && rgb) - lightmap_fmt = PTI_A2BGR10; - else if (sh_config.texfmt[PTI_L8] && !rgb) - lightmap_fmt = PTI_L8; + fmt = PTI_A2BGR10; + else if (sh_config.texfmt[PTI_L8] && !rgb && !r_deluxemapping) + fmt = PTI_L8; else if (sh_config.texfmt[PTI_BGRX8]) - lightmap_fmt = PTI_BGRX8; + fmt = PTI_BGRX8; else if (sh_config.texfmt[PTI_RGB8]) - lightmap_fmt = PTI_RGB8; + fmt = PTI_RGB8; else - lightmap_fmt = PTI_RGBX8; + fmt = PTI_RGBX8; } - Con_DPrintf("Using lightmap format %s\n", Image_FormatName(lightmap_fmt)); + Con_DPrintf("%s: Using lightmap format %s\n", model->name, Image_FormatName(fmt)); - switch(lightmap_fmt) - { - case PTI_RGBA32F: - lightmap_bytes = 4*sizeof(float); - break; - case PTI_RGBA16F: - lightmap_bytes = 4*sizeof(short); - break; - default: - case PTI_A2BGR10: - case PTI_E5BGR9: - case PTI_RGBA8: - case PTI_RGBX8: - case PTI_BGRA8: - case PTI_BGRX8: - lightmap_bytes = 4*sizeof(qbyte); - break; - case PTI_RGB8: - case PTI_BGR8: - lightmap_bytes = 3*sizeof(qbyte); - break; - case PTI_RGB565: - case PTI_RGBA4444: - case PTI_RGBA5551: - case PTI_ARGB4444: - case PTI_ARGB1555: - lightmap_bytes = sizeof(short); - break; - case PTI_L8: - lightmap_bytes = 1*sizeof(qbyte); - break; - } + return fmt; } //needs to be followed by a BE_UploadAllLightmaps at some point -int Surf_NewLightmaps(int count, int width, int height, qboolean deluxe) +int Surf_NewLightmaps(int count, int width, int height, uploadfmt_t fmt, qboolean deluxe) { int first = numlightmaps; int i; + unsigned int pixbytes, pixw, pixh; + if (!count) return -1; @@ -3809,6 +3711,10 @@ int Surf_NewLightmaps(int count, int width, int height, qboolean deluxe) Con_Print("WARNING: Deluxemapping with odd number of lightmaps\n"); } + Image_BlockSizeForEncoding(fmt, &pixbytes, &pixw, &pixh); + if (pixw != 1 || pixh != 1) + return -1; //compressed formats are unsupported + Sys_LockMutex(com_resourcemutex); i = numlightmaps + count; @@ -3818,22 +3724,28 @@ int Surf_NewLightmaps(int count, int width, int height, qboolean deluxe) i--; if (deluxe && ((i - numlightmaps)&1)) - { - lightmap[i] = Z_Malloc(sizeof(*lightmap[i]) + (sizeof(qbyte)*lightmap_bytes)*width*height); + { //deluxemaps always use a specific format. + int pixbytes = 4; + uploadfmt_t fmt = PTI_BGRX8; //deluxemaps have limited format choices. we should probably use RG textures or something, but mneh. + lightmap[i] = Z_Malloc(sizeof(*lightmap[i]) + (sizeof(qbyte)*pixbytes)*width*height); lightmap[i]->width = width; lightmap[i]->height = height; lightmap[i]->lightmaps = (qbyte*)(lightmap[i]+1); lightmap[i]->stainmaps = NULL; lightmap[i]->hasdeluxe = false; + lightmap[i]->pixbytes = pixbytes; + lightmap[i]->fmt = fmt; } else { - lightmap[i] = Z_Malloc(sizeof(*lightmap[i]) + (sizeof(qbyte)*lightmap_bytes + sizeof(stmap)*3)*width*height); + lightmap[i] = Z_Malloc(sizeof(*lightmap[i]) + (sizeof(qbyte)*pixbytes + sizeof(stmap)*3)*width*height); lightmap[i]->width = width; lightmap[i]->height = height; lightmap[i]->lightmaps = (qbyte*)(lightmap[i]+1); - lightmap[i]->stainmaps = (stmap*)(lightmap[i]->lightmaps+lightmap_bytes*width*height); + lightmap[i]->stainmaps = (stmap*)(lightmap[i]->lightmaps+pixbytes*width*height); lightmap[i]->hasdeluxe = deluxe; + lightmap[i]->pixbytes = pixbytes; + lightmap[i]->fmt = fmt; } lightmap[i]->rectchange.l = 0; @@ -3902,6 +3814,7 @@ int Surf_NewExternalLightmaps(int count, char *filepattern, qboolean deluxe) } lightmap[i]->width = lightmap[i]->lightmap_texture->width; lightmap[i]->height = lightmap[i]->lightmap_texture->height; + lightmap[i]->fmt = lightmap[i]->lightmap_texture->format; } if (odd) @@ -3928,13 +3841,11 @@ void Surf_BuildModelLightmaps (model_t *m) batch_t *batch; int sortid; int newfirst; + uploadfmt_t fmt; if (m->loadstate != MLS_LOADED) return; - if (!lightmap_bytes) - return; - #ifdef TERRAIN //easiest way to deal with heightmap lightmaps is to just purge the entire thing. if (m->terrain) @@ -3950,6 +3861,14 @@ void Surf_BuildModelLightmaps (model_t *m) currentmodel = m; shift = Surf_LightmapShift(currentmodel); + fmt = Surf_LightmapMode(m); + +#ifdef THREADEDWORLD + //make sure nothing is poking the lightmaps while we're rewriting them + while(webogenerating) + COM_WorkerPartialSync(webogenerating, &webogeneratingstate, true); +#endif + if (m->submodelof && m->fromgame == fg_quake3) //FIXME: should be all bsp formats { if (m->submodelof->loadstate != MLS_LOADED) @@ -3967,7 +3886,7 @@ void Surf_BuildModelLightmaps (model_t *m) m->lightmaps.count = numlightmaps - newfirst; } else - newfirst = Surf_NewLightmaps(m->lightmaps.count, m->lightmaps.width, m->lightmaps.height, m->lightmaps.deluxemapping); + newfirst = Surf_NewLightmaps(m->lightmaps.count, m->lightmaps.width, m->lightmaps.height, fmt, m->lightmaps.deluxemapping); } //fixup batch lightmaps @@ -4022,7 +3941,7 @@ void Surf_BuildModelLightmaps (model_t *m) stop = m->lightdata + m->lightdatasize; if (m->lightdata) { - switch(lightmap_fmt) + switch(lightmap[newfirst+i]->fmt) { default: Sys_Error("Bad lightmap_fmt\n"); @@ -4083,8 +4002,6 @@ void Surf_BuildModelLightmaps (model_t *m) else { int j; - lightmapinfo_t *lm, *dlm; - qbyte *deluxemap; // if (*m->name == '*') // { @@ -4107,22 +4024,9 @@ void Surf_BuildModelLightmaps (model_t *m) surf->lightmaptexturenums[j] = -1; continue; } - surf->lightmaptexturenums[j] = surf->lightmaptexturenums[0] - m->lightmaps.first + newfirst; + surf->lightmaptexturenums[j] = surf->lightmaptexturenums[j] - m->lightmaps.first + newfirst; - lm = lightmap[surf->lightmaptexturenums[j]]; - if (lm->hasdeluxe) - { - dlm = lightmap[surf->lightmaptexturenums[j]+1]; - deluxemap = dlm->lightmaps + (surf->light_t[j] * dlm->width + surf->light_s[j]) * lightmap_bytes; - } - else - deluxemap = NULL; - - Surf_BuildLightMap (currentmodel, surf, - lm->lightmaps + (surf->light_t[j] * lm->width + surf->light_s[j]) * lightmap_bytes, - deluxemap, - lm->stainmaps + (surf->light_t[j] * lm->width + surf->light_s[j]) * 3, - shift, r_ambient.value*255, lm->width, d_lightstylevalue); + Surf_BuildLightMap (m, surf, j, shift, r_ambient.value*255, d_lightstylevalue); } } } @@ -4131,8 +4035,6 @@ void Surf_BuildModelLightmaps (model_t *m) void Surf_ClearLightmaps(void) { - lightmap_bytes = 0; - #ifdef THREADEDWORLD while(webogenerating) COM_WorkerPartialSync(webogenerating, &webogeneratingstate, true); @@ -4179,8 +4081,6 @@ void Surf_BuildLightmaps (void) lightmap[numlightmaps] = NULL; } - Surf_LightmapMode(); - r_oldviewcluster = -1; r_oldviewcluster2 = -1; diff --git a/engine/client/render.h b/engine/client/render.h index 7e88c3d0..6b91a0bf 100644 --- a/engine/client/render.h +++ b/engine/client/render.h @@ -358,22 +358,19 @@ typedef unsigned char stmap; struct mesh_s; typedef struct { texid_t lightmap_texture; - qboolean modified; - qboolean external; - qboolean hasdeluxe; - uploadfmt_t fmt; + qboolean modified; //data was changed. consult rectchange to see the bounds. + qboolean external; //the data was loaded from a file (q3bsp feature where we shouldn't be blending lightmaps at all) + qboolean hasdeluxe; //says that the next lightmap index contains deluxemap info + uploadfmt_t fmt; //texture format that we're using + qbyte pixbytes; //yes, this means no compressed formats. int width; int height; glRect_t rectchange; - qbyte *lightmaps;//[4*LMBLOCK_WIDTH*LMBLOCK_HEIGHT]; - stmap *stainmaps;//[3*LMBLOCK_WIDTH*LMBLOCK_HEIGHT]; //rgb no a. added to lightmap for added (hopefully) speed. + qbyte *lightmaps; //[pixbytes*LMBLOCK_WIDTH*LMBLOCK_HEIGHT]; + stmap *stainmaps; //[3*LMBLOCK_WIDTH*LMBLOCK_HEIGHT]; //rgb no a. added to lightmap for added (hopefully) speed. } lightmapinfo_t; extern lightmapinfo_t **lightmap; extern int numlightmaps; -//extern texid_t *lightmap_textures; -//extern texid_t *deluxmap_textures; -extern int lightmap_bytes; // 1, 3, or 4 -extern uploadfmt_t lightmap_fmt; //bgra32, rgba32, rgb24, lum8 void QDECL Surf_RebuildLightmap_Callback (struct cvar_s *var, char *oldvalue); diff --git a/engine/client/textedit.c b/engine/client/textedit.c index cc1c9989..49a06c11 100644 --- a/engine/client/textedit.c +++ b/engine/client/textedit.c @@ -465,9 +465,21 @@ static void Con_Editor_LineChanged_Shader(conline_t *line) flocation_t loc; unsigned int flags; image_t img; + memset(&img, 0, sizeof(img)); img.ident = mapname; COM_DeFunString(n, end, mapname, sizeof(mapname), true, true); + while(*img.ident == '$') + { + if (!Q_strncasecmp(img.ident, "$lightmap", 9)) + return; //lightmaps don't need to load from disk + if (!Q_strncasecmp(img.ident, "$rt:", 4)) + return; //render targets never come from disk + if (!Q_strncasecmp(img.ident, "$clamp:", 7) || !Q_strncasecmp(img.ident, "$3d:", 4) || !Q_strncasecmp(img.ident, "$cube:", 6) || !Q_strncasecmp(img.ident, "$nearest:", 9) || !Q_strncasecmp(img.ident, "$linear:", 8)) + img.ident = strchr(img.ident, ':')+1; + else + break; + } if (!Image_LocateHighResTexture(&img, &loc, fname, sizeof(fname), &flags)) line->flags |= CONL_BREAKPOINT; return; diff --git a/engine/gl/gl_alias.c b/engine/gl/gl_alias.c index 916dddad..3f8db643 100644 --- a/engine/gl/gl_alias.c +++ b/engine/gl/gl_alias.c @@ -1499,8 +1499,9 @@ qboolean R_CalcModelLighting(entity_t *e, model_t *clmodel) } } - switch(lightmap_fmt) + switch(PTI_E5BGR9)//lightmap_fmt) { + //don't clamp model lighting if we're not clamping world lighting either. case PTI_E5BGR9: case PTI_RGBA16F: case PTI_RGBA32F: diff --git a/engine/gl/gl_backend.c b/engine/gl/gl_backend.c index 0c5052cd..734dd818 100644 --- a/engine/gl/gl_backend.c +++ b/engine/gl/gl_backend.c @@ -5445,20 +5445,20 @@ static void BE_UpdateLightmaps(void) GL_MTBind(0, GL_TEXTURE_2D, lm->lightmap_texture); qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - qglTexImage2D(GL_TEXTURE_2D, 0, gl_config.formatinfo[lightmap_fmt].internalformat, lm->width, lm->height, 0, gl_config.formatinfo[lightmap_fmt].format, gl_config.formatinfo[lightmap_fmt].type, lm->lightmaps); + qglTexImage2D(GL_TEXTURE_2D, 0, gl_config.formatinfo[lm->fmt].internalformat, lm->width, lm->height, 0, gl_config.formatinfo[lm->fmt].format, gl_config.formatinfo[lm->fmt].type, lm->lightmaps); if (gl_config.glversion >= (gl_config.gles?3.0:3.3)) { - qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, gl_config.formatinfo[lightmap_fmt].swizzle_r); - qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_G, gl_config.formatinfo[lightmap_fmt].swizzle_g); - qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, gl_config.formatinfo[lightmap_fmt].swizzle_b); - qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_A, gl_config.formatinfo[lightmap_fmt].swizzle_a); + qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, gl_config.formatinfo[lm->fmt].swizzle_r); + qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_G, gl_config.formatinfo[lm->fmt].swizzle_g); + qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, gl_config.formatinfo[lm->fmt].swizzle_b); + qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_A, gl_config.formatinfo[lm->fmt].swizzle_a); } } else { GL_MTBind(0, GL_TEXTURE_2D, lm->lightmap_texture); - qglTexSubImage2D(GL_TEXTURE_2D, 0, 0, t, lm->width, b-t, gl_config.formatinfo[lightmap_fmt].format, gl_config.formatinfo[lightmap_fmt].type, lm->lightmaps+t*lm->width*lightmap_bytes); + qglTexSubImage2D(GL_TEXTURE_2D, 0, 0, t, lm->width, b-t, gl_config.formatinfo[lm->fmt].format, gl_config.formatinfo[lm->fmt].type, lm->lightmaps+t*lm->width*lm->pixbytes); } lm->modified = false; lm->rectchange.l = lm->width; diff --git a/engine/gl/gl_heightmap.c b/engine/gl/gl_heightmap.c index 4d58c9f8..422b81a5 100644 --- a/engine/gl/gl_heightmap.c +++ b/engine/gl/gl_heightmap.c @@ -72,8 +72,6 @@ void validatelinks2(link_t *firstnode, link_t *panic) return;*/ } -//FIXME -int Surf_NewLightmaps(int count, int width, int height, qboolean deluxe); #ifndef SERVERONLY static void ted_dorelight(heightmap_t *hm); @@ -164,7 +162,7 @@ static qboolean QDECL Terr_InitLightmap(hmsection_t *s, qboolean initialise) int lm; int i; Sys_UnlockMutex(com_resourcemutex); - lm = Surf_NewLightmaps(1, SECTTEXSIZE*LMCHUNKS, SECTTEXSIZE*LMCHUNKS, false); + lm = Surf_NewLightmaps(1, SECTTEXSIZE*LMCHUNKS, SECTTEXSIZE*LMCHUNKS, PTI_BGRA8, false); Sys_LockMutex(com_resourcemutex); for (i = 0; i < LMCHUNKS*LMCHUNKS; i++) { @@ -196,9 +194,9 @@ static qboolean QDECL Terr_InitLightmap(hmsection_t *s, qboolean initialise) if (initialise && s->lightmap >= 0) { int x, y; - unsigned char *lm; - lm = lightmap[s->lightmap]->lightmaps; - lm += (s->lmy * HMLMSTRIDE + s->lmx) * lightmap_bytes; + unsigned char *lm = lightmap[s->lightmap]->lightmaps; + unsigned int pixbytes = lightmap[s->lightmap]->pixbytes; + lm += (s->lmy * HMLMSTRIDE + s->lmx) * pixbytes; for (y = 0; y < SECTTEXSIZE; y++) { for (x = 0; x < SECTTEXSIZE; x++) @@ -208,7 +206,7 @@ static qboolean QDECL Terr_InitLightmap(hmsection_t *s, qboolean initialise) lm[x*4+2] = 0; lm[x*4+3] = 255; } - lm += (HMLMSTRIDE)*lightmap_bytes; + lm += (HMLMSTRIDE)*pixbytes; } } @@ -803,6 +801,7 @@ static void Terr_SaveV2(heightmap_t *hm, hmsection_t *s, vfsfile_t *f, int sx, i unsigned int flags = s->flags; int i, j, x, y; struct hmwater_s *w; + unsigned int pixbytes; flags &= ~(TSF_INTERNAL); flags &= ~(TSF_HASCOLOURS|TSF_HASHEIGHTS|TSF_HASSHADOW); @@ -824,8 +823,9 @@ static void Terr_SaveV2(heightmap_t *hm, hmsection_t *s, vfsfile_t *f, int sx, i } } + pixbytes = lightmap[s->lightmap]->pixbytes; lm = lightmap[s->lightmap]->lightmaps; - lm += (s->lmy * HMLMSTRIDE + s->lmx) * lightmap_bytes; + lm += (s->lmy * HMLMSTRIDE + s->lmx) * pixbytes; for (y = 0; y < SECTTEXSIZE; y++) { for (x = 0; x < SECTTEXSIZE; x++) @@ -837,7 +837,7 @@ static void Terr_SaveV2(heightmap_t *hm, hmsection_t *s, vfsfile_t *f, int sx, i break; } } - lm += (HMLMSTRIDE)*lightmap_bytes; + lm += (HMLMSTRIDE)*pixbytes; } //write the flags so the loader knows what to load @@ -927,8 +927,9 @@ static void Terr_SaveV2(heightmap_t *hm, hmsection_t *s, vfsfile_t *f, int sx, i //write the channel last = 0; + pixbytes = lightmap[s->lightmap]->pixbytes; lm = lightmap[s->lightmap]->lightmaps; - lm += (s->lmy * HMLMSTRIDE + s->lmx) * lightmap_bytes; + lm += (s->lmy * HMLMSTRIDE + s->lmx) * pixbytes; for (y = 0; y < SECTTEXSIZE; y++) { for (x = 0; x < SECTTEXSIZE; x++) @@ -937,7 +938,7 @@ static void Terr_SaveV2(heightmap_t *hm, hmsection_t *s, vfsfile_t *f, int sx, i last = lm[x*4+j]; Terr_Write_Byte(&strm, delta); } - lm += (HMLMSTRIDE)*lightmap_bytes; + lm += (HMLMSTRIDE)*pixbytes; } } @@ -994,15 +995,16 @@ static void Terr_WorkerLoadedSectionLightmap(void *ctx, void *data, size_t a, si int y; if (s) - if (lightmap_bytes == 4 && Terr_InitLightmap(s, false)) + if (Terr_InitLightmap(s, false)) { + int pixbytes = lightmap[s->lightmap]->pixbytes; outlm = lightmap[s->lightmap]->lightmaps; - outlm += (s->lmy * HMLMSTRIDE + s->lmx) * lightmap_bytes; + outlm += (s->lmy * HMLMSTRIDE + s->lmx) * pixbytes; for (y = 0; y < SECTTEXSIZE; y++) { memcpy(outlm, inlm, SECTTEXSIZE*4); inlm += SECTTEXSIZE*4; - outlm += (HMLMSTRIDE)*lightmap_bytes; + outlm += (HMLMSTRIDE)*pixbytes; } } @@ -1220,10 +1222,9 @@ static void Terr_GenerateDefault(heightmap_t *hm, hmsection_t *s) if (s->lightmap >= 0) { int j; - qbyte *lm; - - lm = lightmap[s->lightmap]->lightmaps; - lm += (s->lmy * HMLMSTRIDE + s->lmx) * lightmap_bytes; + qbyte *lm = lightmap[s->lightmap]->lightmaps; + int pixbytes = lightmap[s->lightmap]->pixbytes; + lm += (s->lmy * HMLMSTRIDE + s->lmx) * pixbytes; for (i = 0; i < SECTTEXSIZE; i++) { for (j = 0; j < SECTTEXSIZE; j++) @@ -1233,7 +1234,7 @@ static void Terr_GenerateDefault(heightmap_t *hm, hmsection_t *s) lm[j*4+0] = 0; lm[j*4+3] = 255; } - lm += (HMLMSTRIDE)*lightmap_bytes; + lm += (HMLMSTRIDE)*pixbytes; } lightmap[s->lightmap]->modified = true; lightmap[s->lightmap]->rectchange.l = 0; @@ -1557,6 +1558,7 @@ static void Terr_SaveV1(heightmap_t *hm, hmsection_t *s, vfsfile_t *f, int sx, i vec4_t dcolours[SECTHEIGHTSIZE*SECTHEIGHTSIZE]; int nothing = 0; struct hmwater_s *w = s->water; + int pixbytes; memset(&ds, 0, sizeof(ds)); memset(&dm, 0, sizeof(dm)); @@ -1595,12 +1597,13 @@ static void Terr_SaveV1(heightmap_t *hm, hmsection_t *s, vfsfile_t *f, int sx, i } s->flags |= TSF_DIRTY; + pixbytes = lightmap[s->lightmap]->pixbytes; lm = lightmap[s->lightmap]->lightmaps; - lm += (s->lmy * HMLMSTRIDE + s->lmx) * lightmap_bytes; + lm += (s->lmy * HMLMSTRIDE + s->lmx) * pixbytes; for (i = 0; i < SECTTEXSIZE; i++) { memcpy(ds.texmap + i, lm, sizeof(ds.texmap[0])); - lm += (HMLMSTRIDE)*lightmap_bytes; + lm += (HMLMSTRIDE)*pixbytes; } for (i = 0; i < SECTHEIGHTSIZE*SECTHEIGHTSIZE; i++) @@ -4349,7 +4352,6 @@ int Heightmap_ClusterForPoint (model_t *model, vec3_t point) #ifndef SERVERONLY static unsigned char *QDECL Terr_GetLightmap(hmsection_t *s, int idx, qboolean edit) { - unsigned char *lm; int x = idx % SECTTEXSIZE, y = idx / SECTTEXSIZE; if (s->lightmap < 0) { @@ -4369,9 +4371,7 @@ static unsigned char *QDECL Terr_GetLightmap(hmsection_t *s, int idx, qboolean e lightmap[s->lightmap]->rectchange.r = HMLMSTRIDE; lightmap[s->lightmap]->rectchange.b = HMLMSTRIDE; } - lm = lightmap[s->lightmap]->lightmaps; - lm += ((s->lmy+y) * HMLMSTRIDE + (s->lmx+x)) * lightmap_bytes; - return lm; + return lightmap[s->lightmap]->lightmaps + ((s->lmy+y) * HMLMSTRIDE + (s->lmx+x)) * lightmap[s->lightmap]->pixbytes; } static void ted_dorelight(heightmap_t *hm) { @@ -5588,7 +5588,7 @@ void Terr_Brush_Draw(heightmap_t *hm, batch_t **batches, entity_t *e) { int first; hm->brushlmremaps = BZ_Realloc(hm->brushlmremaps, sizeof(*hm->brushlmremaps) * lmcount); - first = Surf_NewLightmaps(lmcount - hm->brushmaxlms, hm->brushlmalloc.width, hm->brushlmalloc.height, hm->brushlmalloc.deluxe); + first = Surf_NewLightmaps(lmcount - hm->brushmaxlms, hm->brushlmalloc.width, hm->brushlmalloc.height, PTI_BGRA8, hm->brushlmalloc.deluxe); while(hm->brushmaxlms < lmcount) hm->brushlmremaps[hm->brushmaxlms++] = first++; @@ -5642,11 +5642,11 @@ void Terr_Brush_Draw(heightmap_t *hm, batch_t **batches, entity_t *e) lm->rectchange.b = lm->height; in = br->faces[j].lightdata; - out = lm->lightmaps + (br->faces[j].lmbase[1] * lm->width + br->faces[j].lmbase[0]) * lightmap_bytes; - switch(lightmap_fmt) + out = lm->lightmaps + (br->faces[j].lmbase[1] * lm->width + br->faces[j].lmbase[0]) * lm->pixbytes; + switch(lm->fmt) { default: - Sys_Error("Bad lightmap_fmt\n"); + Sys_Error("Bad terrain lightmap format %i\n", lm->fmt); break; case PTI_BGRA8: case PTI_BGRX8: @@ -5741,8 +5741,33 @@ void Terr_Brush_Draw(heightmap_t *hm, batch_t **batches, entity_t *e) out += (lm->width - br->faces[j].lmextents[0]); } break; - case PTI_RGBA16F: case PTI_RGBA32F: + for (t = 0; t < br->faces[j].lmextents[1]; t++) + { + for (s = 0; s < br->faces[j].lmextents[0]; s++) + { + ((float*)out)[0] = in[0]/255.0; + ((float*)out)[1] = in[1]/255.0; + ((float*)out)[2] = in[2]/255.0; + ((float*)out)[3] = 1.0; + out+=16; + in+=3; + } + out += (lm->width - br->faces[j].lmextents[0]) * 16; + } + break; + /*case PTI_RGBA16F: + for (t = 0; t < br->faces[j].lmextents[1]; t++) + { + for (s = 0; s < br->faces[j].lmextents[0]; s++) + { + Surf_PackRGB16F(in[0], in[1], in[2], 255); + out+=8; + in+=3; + } + out += (lm->width - br->faces[j].lmextents[0]) * 8; + } + break;*/ case PTI_RGB565: case PTI_RGBA4444: case PTI_RGBA5551: diff --git a/engine/gl/gl_rsurf.c b/engine/gl/gl_rsurf.c index a536ed45..bbf89755 100644 --- a/engine/gl/gl_rsurf.c +++ b/engine/gl/gl_rsurf.c @@ -567,14 +567,14 @@ void GLBE_UploadAllLightmaps(void) qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); } - qglTexImage2D(GL_TEXTURE_2D, 0, gl_config.formatinfo[lightmap_fmt].internalformat, lm->width, lm->height, 0, gl_config.formatinfo[lightmap_fmt].format, gl_config.formatinfo[lightmap_fmt].type, lightmap[i]->lightmaps); + qglTexImage2D(GL_TEXTURE_2D, 0, gl_config.formatinfo[lm->fmt].internalformat, lm->width, lm->height, 0, gl_config.formatinfo[lm->fmt].format, gl_config.formatinfo[lm->fmt].type, lightmap[i]->lightmaps); if (gl_config.glversion >= (gl_config.gles?3.0:3.3)) { - qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, gl_config.formatinfo[lightmap_fmt].swizzle_r); - qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_G, gl_config.formatinfo[lightmap_fmt].swizzle_g); - qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, gl_config.formatinfo[lightmap_fmt].swizzle_b); - qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_A, gl_config.formatinfo[lightmap_fmt].swizzle_a); + qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, gl_config.formatinfo[lm->fmt].swizzle_r); + qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_G, gl_config.formatinfo[lm->fmt].swizzle_g); + qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, gl_config.formatinfo[lm->fmt].swizzle_b); + qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_A, gl_config.formatinfo[lm->fmt].swizzle_a); } //for completeness. diff --git a/engine/gl/gl_terrain.h b/engine/gl/gl_terrain.h index 58c2d877..25612058 100644 --- a/engine/gl/gl_terrain.h +++ b/engine/gl/gl_terrain.h @@ -30,7 +30,7 @@ cluster: internal concept to avoid a single pointer array of 16 million entries per terrain. */ -int Surf_NewLightmaps(int count, int width, int height, qboolean deluxe); +int Surf_NewLightmaps(int count, int width, int height, uploadfmt_t fmt, qboolean deluxe); #define MAXCLUSTERS 64 #define MAXSECTIONS 64 //this many sections within each cluster in each direction diff --git a/engine/gl/r_bishaders.h b/engine/gl/r_bishaders.h index 08552292..18e31220 100644 --- a/engine/gl/r_bishaders.h +++ b/engine/gl/r_bishaders.h @@ -5490,6 +5490,7 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND "#ifdef BUMPMODELSPACE\n" "deluxe = normalize(deluxe*invsurface);\n" "#else\n" +"deluxe = normalize(deluxe);\n" "lightmaps *= 2.0 / max(0.25, deluxe.z); //counter the darkening from deluxemaps\n" "#endif\n" "lightmaps *= dot(norm, deluxe);\n" diff --git a/engine/server/pr_cmds.c b/engine/server/pr_cmds.c index 83bbe86f..848daa59 100644 --- a/engine/server/pr_cmds.c +++ b/engine/server/pr_cmds.c @@ -9772,7 +9772,10 @@ static void QCBUILTIN PF_runclientphys(pubprogfuncs_t *prinst, struct globalvars movevars.maxspeed *= ent->xv->hasted; #endif if (client) + { movevars.coordsize = client->netchan.netprim.coordsize; + client->lastruncmd = sv.time*1000; + } else movevars.coordsize = svs.netprim.coordsize; @@ -10869,8 +10872,8 @@ BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs {"getlocalinfo", PF_getlocalinfo,0, 0, 0, 0, D("int(string keyname, optional void *outptr, int size)", "Obtains a copy of the full data blob. Will write up to size bytes and return the actual size. Does not null terminate (but memalloc(ret+1) will, if you want to cast the buffer to a string), and the blob may contain embedded nulls. Ignores all special keys, returning only what is actually there.")}, {"setlocalinfo", PF_setlocalinfo,0, 0, 0, 0, D("void(string keyname, optional void *outptr, int size)", "Changes the server's localinfo. This data will be available for the following map, and will *usually* reload with saved games.")}, - {"isdemo", PF_Fixme, 0, 0, 0, 349, D("float()", "Returns if the client is currently playing a demo or not")},// (EXT_CSQC) - {"isserver", PF_Fixme, 0, 0, 0, 350, D("float()", "Returns if the client is acting as the server (aka: listen server)")},//(EXT_CSQC) + {"isdemo", PF_Fixme, 0, 0, 0, 349, D("float()", "Returns if the client is currently playing a demo or not. Returns 2 when playing an mvd (where other player's stats can be queried, or the pov can be changed freely).")},// (EXT_CSQC) + {"isserver", PF_Fixme, 0, 0, 0, 350, D("float()", "Returns non-zero whenever the local console can directly affect the server (ie: listen servers or single-player). Compat note: DP returns 0 for single-player.")},//(EXT_CSQC) {"SetListener", PF_Fixme, 0, 0, 0, 351, D("void(vector origin, vector forward, vector right, vector up, optional float reverbtype)", "Sets the position of the view, as far as the audio subsystem is concerned. This should be called once per CSQC_UpdateView as it will otherwise revert to default. For reverbtype, see setup_reverb or treat as 'underwater'.")},// (EXT_CSQC) {"setup_reverb", PF_Fixme, 0, 0, 0, 0, D("typedef struct {\n\tfloat flDensity;\n\tfloat flDiffusion;\n\tfloat flGain;\n\tfloat flGainHF;\n\tfloat flGainLF;\n\tfloat flDecayTime;\n\tfloat flDecayHFRatio;\n\tfloat flDecayLFRatio;\n\tfloat flReflectionsGain;\n\tfloat flReflectionsDelay;\n\tvector flReflectionsPan;\n\tfloat flLateReverbGain;\n\tfloat flLateReverbDelay;\n\tvector flLateReverbPan;\n\tfloat flEchoTime;\n\tfloat flEchoDepth;\n\tfloat flModulationTime;\n\tfloat flModulationDepth;\n\tfloat flAirAbsorptionGainHF;\n\tfloat flHFReference;\n\tfloat flLFReference;\n\tfloat flRoomRolloffFactor;\n\tint iDecayHFLimit;\n} reverbinfo_t;\nvoid(float reverbslot, reverbinfo_t *reverbinfo, int sizeofreverinfo_t)", "Reconfigures a reverb slot for weird effects. Slot 0 is reserved for no effects. Slot 1 is reserved for underwater effects. Reserved slots will be reinitialised on snd_restart, but can otherwise be changed. These reverb slots can be activated with SetListener. Note that reverb will currently only work when using OpenAL.")}, {"registercommand", PF_Fixme, 0, 0, 0, 352, D("void(string cmdname)", "Register the given console command, for easy console use.\nConsole commands that are later used will invoke CSQC_ConsoleCommand.")},//(EXT_CSQC) diff --git a/engine/server/sv_ccmds.c b/engine/server/sv_ccmds.c index 10f4c958..88ac665c 100644 --- a/engine/server/sv_ccmds.c +++ b/engine/server/sv_ccmds.c @@ -682,7 +682,7 @@ void SV_Map_f (void) else #endif { - char *exts[] = {"maps/%s", "maps/%s.bsp", "maps/%s.cm", "maps/%s.hmp", /*"maps/%s.map",*/ NULL}; + char *exts[] = {"maps/%s", "maps/%s.bsp", "maps/%s.cm", "maps/%s.hmp", /*"maps/%s.map",*/ /*"maps/%s.ent",*/ NULL}; int i, j; for (i = 0; exts[i]; i++) diff --git a/engine/server/sv_send.c b/engine/server/sv_send.c index 4fff703d..02bb3a10 100644 --- a/engine/server/sv_send.c +++ b/engine/server/sv_send.c @@ -3536,6 +3536,7 @@ void SV_SendClientMessages (void) cmd.buttons = c->lastcmd.buttons; SV_RunCmd (&cmd, true); SV_PostRunCmd(); + c->lastruncmd = sv.time*1000; if (stepmsec > c->msecs) c->msecs = 0; else diff --git a/engine/server/sv_user.c b/engine/server/sv_user.c index 321d3644..33912952 100644 --- a/engine/server/sv_user.c +++ b/engine/server/sv_user.c @@ -2139,10 +2139,9 @@ void SV_Begin_Core(client_t *split) SV_RunCmd(&cmd, false); } SV_PostRunCmd(); + split->lastruncmd = sv.time*1000; host_client = oh; sv_player = oh?oh->edict:NULL; - - host_client->lastruncmd = sv.time*1000; } } } @@ -5658,6 +5657,7 @@ static void SVNQ_Begin_f (void) host_client->lastcmd.msec = 0; SV_RunCmd (&host_client->lastcmd, false); SV_PostRunCmd(); + host_client->lastruncmd = sv.time*1000; } static void SVNQ_PreSpawn_f (void) { @@ -6810,7 +6810,6 @@ size_t playertouchmax; void SV_PreRunCmd(void) { size_t max = MAX_EDICTS;//(sv.world.num_edicts+7)&~7; - host_client->lastruncmd = sv.time*1000; if (max > playertouchmax) { playertouchmax = max; @@ -7868,6 +7867,7 @@ void SV_ExecuteClientMessage (client_t *cl) if (!SV_PlayerPhysicsQC || host_client->spectator) SV_PostRunCmd(); + host_client->lastruncmd = sv.time*1000; } } @@ -8320,6 +8320,7 @@ void SVNQ_ReadClientMove (usercmd_t *move, qboolean forceangle16) SV_RunCmd (move, false); SV_PostRunCmd(); move->impulse = 0; + host_client->lastruncmd = sv.time*1000; } else { diff --git a/engine/shaders/glsl/defaultwall.glsl b/engine/shaders/glsl/defaultwall.glsl index eba9fe51..55b1b2ea 100644 --- a/engine/shaders/glsl/defaultwall.glsl +++ b/engine/shaders/glsl/defaultwall.glsl @@ -295,6 +295,7 @@ void main () #ifdef BUMPMODELSPACE deluxe = normalize(deluxe*invsurface); #else + deluxe = normalize(deluxe); lightmaps *= 2.0 / max(0.25, deluxe.z); //counter the darkening from deluxemaps #endif lightmaps *= dot(norm, deluxe); diff --git a/engine/vk/vk_backend.c b/engine/vk/vk_backend.c index 3a8b76db..0a6b3e90 100644 --- a/engine/vk/vk_backend.c +++ b/engine/vk/vk_backend.c @@ -4137,7 +4137,7 @@ void VK_UploadLightmap(lightmapinfo_t *lm) mips.mip[0].width = lm->width; mips.mip[0].height = lm->height; mips.mip[0].depth = 1; - switch(lightmap_fmt) + switch(lm->fmt) { default: case PTI_A2BGR10: @@ -4145,7 +4145,7 @@ void VK_UploadLightmap(lightmapinfo_t *lm) case PTI_RGBA16F: case PTI_RGBA32F: case PTI_L8: - mips.encoding = lightmap_fmt; + mips.encoding = lm->fmt; break; case PTI_BGRA8: mips.encoding = PTI_BGRX8; @@ -5957,7 +5957,9 @@ qboolean VKBE_BeginShadowmap(qboolean isspot, uint32_t width, uint32_t height) VkMemoryAllocateInfo memAllocInfo = {VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO}; vkGetImageMemoryRequirements(vk.device, shad->image, &mem_reqs); memAllocInfo.allocationSize = mem_reqs.size; - memAllocInfo.memoryTypeIndex = vk_find_memory_require(mem_reqs.memoryTypeBits, 0); + memAllocInfo.memoryTypeIndex = vk_find_memory_try(mem_reqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); + if (memAllocInfo.memoryTypeIndex == ~0) + memAllocInfo.memoryTypeIndex = vk_find_memory_require(mem_reqs.memoryTypeBits, 0); VkAssert(vkAllocateMemory(vk.device, &memAllocInfo, vkallocationcb, &shad->memory)); VkAssert(vkBindImageMemory(vk.device, shad->image, shad->memory, 0)); } diff --git a/engine/vk/vk_init.c b/engine/vk/vk_init.c index f35fc29f..cb0eff08 100644 --- a/engine/vk/vk_init.c +++ b/engine/vk/vk_init.c @@ -2969,8 +2969,23 @@ qboolean VK_SCR_GrabBackBuffer(void) //wait for the queued acquire to actually finish if (vk_busywait.ival) { //busy wait, to try to get the highest fps possible - while (VK_TIMEOUT == vkGetFenceStatus(vk.device, vk.acquirefences[vk.aquirenext%ACQUIRELIMIT])) - ; + for (;;) + { + switch(vkGetFenceStatus(vk.device, vk.acquirefences[vk.aquirenext%ACQUIRELIMIT])) + { + case VK_SUCCESS: + break; //hurrah + case VK_NOT_READY: + continue; //keep going until its actually signaled. submission thread is probably just slow. + case VK_TIMEOUT: + continue; //erk? this isn't a documented result here. + case VK_ERROR_DEVICE_LOST: + Sys_Error("Vulkan device lost"); + default: + return false; + } + break; + } } else { @@ -3616,17 +3631,24 @@ void VK_Submit_Work(VkCommandBuffer cmdbuf, VkSemaphore semwait, VkPipelineStage work->fencedwork = fencedwork; Sys_LockConditional(vk.submitcondition); + +#ifdef MULTITHREAD + if (vk.neednewswapchain && vk.submitthread) + { //if we're trying to kill the submission thread, don't post work to it - instead wait for it to die cleanly then do it ourselves. + Sys_ConditionSignal(vk.submitcondition); + Sys_UnlockConditional(vk.submitcondition); + Sys_WaitOnThread(vk.submitthread); + vk.submitthread = NULL; + Sys_LockConditional(vk.submitcondition); //annoying, but required for it to be reliable with respect to other things. + } +#endif + //add it on the end in a lazy way. for (link = &vk.work; *link; link = &(*link)->next) ; *link = work; #ifdef MULTITHREAD - if (vk.neednewswapchain && vk.submitthread) - { //if we're trying to kill the submission thread, don't post work to it - instead wait for it to die cleanly then do it ourselves. - Sys_WaitOnThread(vk.submitthread); - vk.submitthread = NULL; - } if (vk.submitthread) Sys_ConditionSignal(vk.submitcondition); else diff --git a/engine/vk/vkrenderer.h b/engine/vk/vkrenderer.h index 3f05c412..8fc94c60 100644 --- a/engine/vk/vkrenderer.h +++ b/engine/vk/vkrenderer.h @@ -289,7 +289,7 @@ extern struct vulkaninfo_s VkCommandPool cmdpool; VkPhysicalDeviceLimits limits; -#define ACQUIRELIMIT 8 +#define ACQUIRELIMIT 8 //don't run more than this many frames behind VkSemaphore acquiresemaphores[ACQUIRELIMIT]; VkFence acquirefences[ACQUIRELIMIT]; uint32_t acquirebufferidx[ACQUIRELIMIT];