From d5fdd60fed7fd2ef5d2b8b0b3805a304b7f665fd Mon Sep 17 00:00:00 2001 From: Alug Date: Mon, 15 Jan 2024 13:35:17 +0100 Subject: [PATCH 1/8] replace karts batching with srb2s batching currently palette renderer does not work may need to try it with the reworked --- src/Makefile | 2 +- src/hardware/hw_batching.c | 488 +++++++++++++++++++++++ src/hardware/hw_batching.h | 39 ++ src/hardware/hw_cache.c | 26 +- src/hardware/hw_draw.c | 22 +- src/hardware/hw_drv.h | 10 +- src/hardware/hw_main.c | 97 +++-- src/hardware/hw_main.h | 2 + src/hardware/r_opengl/r_opengl.c | 656 +++---------------------------- src/sdl/hwsym_sdl.c | 6 +- src/sdl/i_video.c | 4 +- 11 files changed, 677 insertions(+), 675 deletions(-) create mode 100644 src/hardware/hw_batching.c create mode 100644 src/hardware/hw_batching.h diff --git a/src/Makefile b/src/Makefile index 06567753a..8af668744 100644 --- a/src/Makefile +++ b/src/Makefile @@ -275,7 +275,7 @@ else OPTS+=-DHWRENDER OBJS+=$(OBJDIR)/hw_bsp.o $(OBJDIR)/hw_draw.o $(OBJDIR)/hw_light.o \ $(OBJDIR)/hw_main.o $(OBJDIR)/hw_clip.o $(OBJDIR)/hw_md2.o $(OBJDIR)/hw_cache.o $(OBJDIR)/hw_trick.o \ - $(OBJDIR)/hw_md2load.o $(OBJDIR)/hw_md3load.o $(OBJDIR)/hw_model.o $(OBJDIR)/u_list.o + $(OBJDIR)/hw_md2load.o $(OBJDIR)/hw_md3load.o $(OBJDIR)/hw_model.o $(OBJDIR)/u_list.o $(OBJDIR)/hw_batching.o endif OPTS += -DCOMPVERSION diff --git a/src/hardware/hw_batching.c b/src/hardware/hw_batching.c new file mode 100644 index 000000000..b56278c7d --- /dev/null +++ b/src/hardware/hw_batching.c @@ -0,0 +1,488 @@ +// SONIC ROBO BLAST 2 +//----------------------------------------------------------------------------- +// Copyright (C) 2020-2023 by Sonic Team Junior. +// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. +//----------------------------------------------------------------------------- +/// \file hw_batching.c +/// \brief Draw call batching and related things. + +#ifdef HWRENDER +#include "hw_glob.h" +#include "hw_batching.h" +#include "hw_main.h" +#include "../i_system.h" + +// The texture for the next polygon given to HWR_ProcessPolygon. +// Set with HWR_SetCurrentTexture. +GLMipmap_t *current_texture = NULL; + +boolean currently_batching = false; + +FOutVector* finalVertexArray = NULL;// contains subset of sorted vertices and texture coordinates to be sent to gpu +UINT32* finalVertexIndexArray = NULL;// contains indexes for glDrawElements, taking into account fan->triangles conversion +// NOTE have this alloced as 3x finalVertexArray size +int finalVertexArrayAllocSize = 65536; +//GLubyte* colorArray = NULL;// contains color data to be sent to gpu, if needed +//int colorArrayAllocSize = 65536; +// not gonna use this for now, just sort by color and change state when it changes +// later maybe when using vertex attributes if it's needed + +PolygonArrayEntry* polygonArray = NULL;// contains the polygon data from DrawPolygon, waiting to be processed +int polygonArraySize = 0; +UINT32* polygonIndexArray = NULL;// contains sorting pointers for polygonArray +int polygonArrayAllocSize = 65536; + +FOutVector* unsortedVertexArray = NULL;// contains unsorted vertices and texture coordinates from DrawPolygon +int unsortedVertexArraySize = 0; +int unsortedVertexArrayAllocSize = 65536; + +// Enables batching mode. HWR_ProcessPolygon will collect polygons instead of passing them directly to the rendering backend. +// Call HWR_RenderBatches to render all the collected geometry. +void HWR_StartBatching(void) +{ + if (currently_batching) + I_Error("Repeat call to HWR_StartBatching without HWR_RenderBatches"); + + // init arrays if that has not been done yet + if (!finalVertexArray) + { + finalVertexArray = malloc(finalVertexArrayAllocSize * sizeof(FOutVector)); + finalVertexIndexArray = malloc(finalVertexArrayAllocSize * 3 * sizeof(UINT32)); + polygonArray = malloc(polygonArrayAllocSize * sizeof(PolygonArrayEntry)); + polygonIndexArray = malloc(polygonArrayAllocSize * sizeof(UINT32)); + unsortedVertexArray = malloc(unsortedVertexArrayAllocSize * sizeof(FOutVector)); + } + + currently_batching = true; +} + +// This replaces the direct calls to pfnSetTexture in cases where batching is available. +// The texture selection is saved for the next HWR_ProcessPolygon call. +// Doing this was easier than getting a texture pointer to HWR_ProcessPolygon. +void HWR_SetCurrentTexture(GLMipmap_t *texture) +{ + if (currently_batching) + { + current_texture = texture; + } + else + { + HWD.pfnSetTexture(texture); + } +} + +// If batching is enabled, this function collects the polygon data and the chosen texture +// for later use in HWR_RenderBatches. Otherwise the rendering backend is used to +// render the polygon immediately. +void HWR_ProcessPolygon(FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPts, FBITFIELD PolyFlags, int shader, boolean horizonSpecial) +{ + if (currently_batching) + { + if (!pSurf) + I_Error("Got a null FSurfaceInfo in batching");// nulls should not come in the stuff that batching currently applies to + if (polygonArraySize == polygonArrayAllocSize) + { + PolygonArrayEntry* new_array; + // ran out of space, make new array double the size + polygonArrayAllocSize *= 2; + new_array = malloc(polygonArrayAllocSize * sizeof(PolygonArrayEntry)); + memcpy(new_array, polygonArray, polygonArraySize * sizeof(PolygonArrayEntry)); + free(polygonArray); + polygonArray = new_array; + // also need to redo the index array, dont need to copy it though + free(polygonIndexArray); + polygonIndexArray = malloc(polygonArrayAllocSize * sizeof(UINT32)); + } + + while (unsortedVertexArraySize + (int)iNumPts > unsortedVertexArrayAllocSize) + { + FOutVector* new_array; + // need more space for vertices in unsortedVertexArray + unsortedVertexArrayAllocSize *= 2; + new_array = malloc(unsortedVertexArrayAllocSize * sizeof(FOutVector)); + memcpy(new_array, unsortedVertexArray, unsortedVertexArraySize * sizeof(FOutVector)); + free(unsortedVertexArray); + unsortedVertexArray = new_array; + } + + // add the polygon data to the arrays + + polygonArray[polygonArraySize].surf = *pSurf; + polygonArray[polygonArraySize].vertsIndex = unsortedVertexArraySize; + polygonArray[polygonArraySize].numVerts = iNumPts; + polygonArray[polygonArraySize].polyFlags = PolyFlags; + polygonArray[polygonArraySize].texture = current_texture; + polygonArray[polygonArraySize].shader = shader; + polygonArray[polygonArraySize].horizonSpecial = horizonSpecial; + polygonArraySize++; + + memcpy(&unsortedVertexArray[unsortedVertexArraySize], pOutVerts, iNumPts * sizeof(FOutVector)); + unsortedVertexArraySize += iNumPts; + } + else + { + if (shader) + HWD.pfnSetShader(shader); + HWD.pfnDrawPolygon(pSurf, pOutVerts, iNumPts, PolyFlags); + } +} + +static int comparePolygons(const void *p1, const void *p2) +{ + unsigned int index1 = *(const unsigned int*)p1; + unsigned int index2 = *(const unsigned int*)p2; + PolygonArrayEntry* poly1 = &polygonArray[index1]; + PolygonArrayEntry* poly2 = &polygonArray[index2]; + int diff; + INT64 diff64; + UINT32 downloaded1 = 0; + UINT32 downloaded2 = 0; + + int shader1 = poly1->shader; + int shader2 = poly2->shader; + // make skywalls and horizon lines first in order + if (poly1->polyFlags & PF_NoTexture || poly1->horizonSpecial) + shader1 = -1; + if (poly2->polyFlags & PF_NoTexture || poly2->horizonSpecial) + shader2 = -1; + diff = shader1 - shader2; + if (diff != 0) return diff; + + // skywalls and horizon lines must retain their order for horizon lines to work + if (shader1 == -1 && shader2 == -1) + return index1 - index2; + + if (poly1->texture) + downloaded1 = poly1->texture->downloaded; // there should be a opengl texture name here, usable for comparisons + if (poly2->texture) + downloaded2 = poly2->texture->downloaded; + diff64 = downloaded1 - downloaded2; + if (diff64 != 0) return diff64; + + if (HWR_ShouldUsePaletteRendering()) + { + diff = poly1->surf.LightTableId - poly2->surf.LightTableId; + if (diff != 0) return diff; + } + + diff = poly1->polyFlags - poly2->polyFlags; + if (diff != 0) return diff; + + diff64 = poly1->surf.PolyColor.rgba - poly2->surf.PolyColor.rgba; + if (diff64 < 0) return -1; else if (diff64 > 0) return 1; + diff64 = poly1->surf.TintColor.rgba - poly2->surf.TintColor.rgba; + if (diff64 < 0) return -1; else if (diff64 > 0) return 1; + diff64 = poly1->surf.FadeColor.rgba - poly2->surf.FadeColor.rgba; + if (diff64 < 0) return -1; else if (diff64 > 0) return 1; + + diff = poly1->surf.LightInfo.light_level - poly2->surf.LightInfo.light_level; + if (diff != 0) return diff; + diff = poly1->surf.LightInfo.fade_start - poly2->surf.LightInfo.fade_start; + if (diff != 0) return diff; + diff = poly1->surf.LightInfo.fade_end - poly2->surf.LightInfo.fade_end; + return diff; +} + +static int comparePolygonsNoShaders(const void *p1, const void *p2) +{ + unsigned int index1 = *(const unsigned int*)p1; + unsigned int index2 = *(const unsigned int*)p2; + PolygonArrayEntry* poly1 = &polygonArray[index1]; + PolygonArrayEntry* poly2 = &polygonArray[index2]; + int diff; + INT64 diff64; + + GLMipmap_t *texture1 = poly1->texture; + GLMipmap_t *texture2 = poly2->texture; + UINT32 downloaded1 = 0; + UINT32 downloaded2 = 0; + if (poly1->polyFlags & PF_NoTexture || poly1->horizonSpecial) + texture1 = NULL; + if (poly2->polyFlags & PF_NoTexture || poly2->horizonSpecial) + texture2 = NULL; + if (texture1) + downloaded1 = texture1->downloaded; // there should be a opengl texture name here, usable for comparisons + if (texture2) + downloaded2 = texture2->downloaded; + // skywalls and horizon lines must retain their order for horizon lines to work + if (!texture1 && !texture2) + return index1 - index2; + diff64 = downloaded1 - downloaded2; + if (diff64 != 0) return diff64; + + diff = poly1->polyFlags - poly2->polyFlags; + if (diff != 0) return diff; + + diff64 = poly1->surf.PolyColor.rgba - poly2->surf.PolyColor.rgba; + if (diff64 < 0) return -1; else if (diff64 > 0) return 1; + + return 0; +} + +// This function organizes the geometry collected by HWR_ProcessPolygon calls into batches and uses +// the rendering backend to draw them. +void HWR_RenderBatches(void) +{ + int finalVertexWritePos = 0;// position in finalVertexArray + int finalIndexWritePos = 0;// position in finalVertexIndexArray + + int polygonReadPos = 0;// position in polygonIndexArray + + int currentShader; + int nextShader = 0; + GLMipmap_t *currentTexture; + GLMipmap_t *nextTexture = NULL; + FBITFIELD currentPolyFlags = 0; + FBITFIELD nextPolyFlags = 0; + FSurfaceInfo currentSurfaceInfo; + FSurfaceInfo nextSurfaceInfo; + + int i; + + if (!currently_batching) + I_Error("HWR_RenderBatches called without starting batching"); + + nextSurfaceInfo.LightInfo.fade_end = 0; + nextSurfaceInfo.LightInfo.fade_start = 0; + nextSurfaceInfo.LightInfo.light_level = 0; + + currently_batching = false;// no longer collecting batches + if (!polygonArraySize) + { + ps_hw_numpolys.value.i = ps_hw_numcalls.value.i = ps_hw_numshaders.value.i + = ps_hw_numtextures.value.i = ps_hw_numpolyflags.value.i + = ps_hw_numcolors.value.i = 0; + return;// nothing to draw + } + // init stats vars + ps_hw_numpolys.value.i = polygonArraySize; + ps_hw_numcalls.value.i = ps_hw_numverts.value.i = 0; + ps_hw_numshaders.value.i = ps_hw_numtextures.value.i + = ps_hw_numpolyflags.value.i = ps_hw_numcolors.value.i = 1; + // init polygonIndexArray + for (i = 0; i < polygonArraySize; i++) + { + polygonIndexArray[i] = i; + } + + // sort polygons + PS_START_TIMING(ps_hw_batchsorttime); + if (cv_grshaders.value && gr_shadersavailable) + qsort(polygonIndexArray, polygonArraySize, sizeof(unsigned int), comparePolygons); + else + qsort(polygonIndexArray, polygonArraySize, sizeof(unsigned int), comparePolygonsNoShaders); + PS_STOP_TIMING(ps_hw_batchsorttime); + // sort order + // 1. shader + // 2. texture + // 3. polyflags + // 4. colors + light level + // not sure about what order of the last 2 should be, or if it even matters + + PS_START_TIMING(ps_hw_batchdrawtime); + + currentShader = polygonArray[polygonIndexArray[0]].shader; + currentTexture = polygonArray[polygonIndexArray[0]].texture; + currentPolyFlags = polygonArray[polygonIndexArray[0]].polyFlags; + currentSurfaceInfo = polygonArray[polygonIndexArray[0]].surf; + // For now, will sort and track the colors. Vertex attributes could be used instead of uniforms + // and a color array could replace the color calls. + + // set state for first batch + + if (cv_grshaders.value && gr_shadersavailable) + { + HWD.pfnSetShader(currentShader); + } + + if (currentPolyFlags & PF_NoTexture) + currentTexture = NULL; + else + HWD.pfnSetTexture(currentTexture); + + while (1)// note: remember handling notexture polyflag as having texture number 0 (also in comparePolygons) + { + int firstIndex; + int lastIndex; + + boolean stopFlag = false; + boolean changeState = false; + boolean changeShader = false; + boolean changeTexture = false; + boolean changePolyFlags = false; + boolean changeSurfaceInfo = false; + + // steps: + // write vertices + // check for changes or end, otherwise go back to writing + // changes will affect the next vars and the change bools + // end could set flag for stopping + // execute draw call + // could check ending flag here + // change states according to next vars and change bools, updating the current vars and reseting the bools + // reset write pos + // repeat loop + + int index = polygonIndexArray[polygonReadPos++]; + int numVerts = polygonArray[index].numVerts; + // before writing, check if there is enough room + // using 'while' instead of 'if' here makes sure that there will *always* be enough room. + // probably never will this loop run more than once though + while (finalVertexWritePos + numVerts > finalVertexArrayAllocSize) + { + FOutVector* new_array; + unsigned int* new_index_array; + finalVertexArrayAllocSize *= 2; + new_array = malloc(finalVertexArrayAllocSize * sizeof(FOutVector)); + memcpy(new_array, finalVertexArray, finalVertexWritePos * sizeof(FOutVector)); + free(finalVertexArray); + finalVertexArray = new_array; + // also increase size of index array, 3x of vertex array since + // going from fans to triangles increases vertex count to 3x + new_index_array = malloc(finalVertexArrayAllocSize * 3 * sizeof(UINT32)); + memcpy(new_index_array, finalVertexIndexArray, finalIndexWritePos * sizeof(UINT32)); + free(finalVertexIndexArray); + finalVertexIndexArray = new_index_array; + } + // write the vertices of the polygon + memcpy(&finalVertexArray[finalVertexWritePos], &unsortedVertexArray[polygonArray[index].vertsIndex], + numVerts * sizeof(FOutVector)); + // write the indexes, pointing to the fan vertexes but in triangles format + firstIndex = finalVertexWritePos; + lastIndex = finalVertexWritePos + numVerts; + finalVertexWritePos += 2; + while (finalVertexWritePos < lastIndex) + { + finalVertexIndexArray[finalIndexWritePos++] = firstIndex; + finalVertexIndexArray[finalIndexWritePos++] = finalVertexWritePos - 1; + finalVertexIndexArray[finalIndexWritePos++] = finalVertexWritePos++; + } + + if (polygonReadPos >= polygonArraySize) + { + stopFlag = true; + } + else + { + // check if a state change is required, set the change bools and next vars + int nextIndex = polygonIndexArray[polygonReadPos]; + nextShader = polygonArray[nextIndex].shader; + nextTexture = polygonArray[nextIndex].texture; + nextPolyFlags = polygonArray[nextIndex].polyFlags; + nextSurfaceInfo = polygonArray[nextIndex].surf; + if (nextPolyFlags & PF_NoTexture) + nextTexture = 0; + if (currentShader != nextShader && cv_grshaders.value && gr_shadersavailable) + { + changeState = true; + changeShader = true; + } + if (currentTexture != nextTexture) + { + changeState = true; + changeTexture = true; + } + if (currentPolyFlags != nextPolyFlags) + { + changeState = true; + changePolyFlags = true; + } + if ((cv_grshaders.value && gr_shadersavailable) && (HWR_ShouldUsePaletteRendering())) + { + if (currentSurfaceInfo.PolyColor.rgba != nextSurfaceInfo.PolyColor.rgba || + currentSurfaceInfo.TintColor.rgba != nextSurfaceInfo.TintColor.rgba || + currentSurfaceInfo.FadeColor.rgba != nextSurfaceInfo.FadeColor.rgba || + currentSurfaceInfo.LightInfo.light_level != nextSurfaceInfo.LightInfo.light_level || + currentSurfaceInfo.LightInfo.fade_start != nextSurfaceInfo.LightInfo.fade_start || + currentSurfaceInfo.LightInfo.fade_end != nextSurfaceInfo.LightInfo.fade_end || + currentSurfaceInfo.LightTableId != nextSurfaceInfo.LightTableId) + { + changeState = true; + changeSurfaceInfo = true; + } + } + else if (cv_grshaders.value && gr_shadersavailable) + { + if (currentSurfaceInfo.PolyColor.rgba != nextSurfaceInfo.PolyColor.rgba || + currentSurfaceInfo.TintColor.rgba != nextSurfaceInfo.TintColor.rgba || + currentSurfaceInfo.FadeColor.rgba != nextSurfaceInfo.FadeColor.rgba || + currentSurfaceInfo.LightInfo.light_level != nextSurfaceInfo.LightInfo.light_level || + currentSurfaceInfo.LightInfo.fade_start != nextSurfaceInfo.LightInfo.fade_start || + currentSurfaceInfo.LightInfo.fade_end != nextSurfaceInfo.LightInfo.fade_end) + { + changeState = true; + changeSurfaceInfo = true; + } + } + else + { + if (currentSurfaceInfo.PolyColor.rgba != nextSurfaceInfo.PolyColor.rgba) + { + changeState = true; + changeSurfaceInfo = true; + } + } + } + + if (changeState || stopFlag) + { + // execute draw call + HWD.pfnDrawIndexedTriangles(¤tSurfaceInfo, finalVertexArray, finalIndexWritePos, currentPolyFlags, finalVertexIndexArray); + // update stats + ps_hw_numcalls.value.i++; + ps_hw_numverts.value.i += finalIndexWritePos; + // reset write positions + finalVertexWritePos = 0; + finalIndexWritePos = 0; + } + else continue; + + // if we're here then either its time to stop or time to change state + if (stopFlag) break; + + // change state according to change bools and next vars, update current vars and reset bools + if (changeShader) + { + HWD.pfnSetShader(nextShader); + currentShader = nextShader; + changeShader = false; + + ps_hw_numshaders.value.i++; + } + if (changeTexture) + { + // texture should be already ready for use from calls to SetTexture during batch collection + HWD.pfnSetTexture(nextTexture); + currentTexture = nextTexture; + changeTexture = false; + + ps_hw_numtextures.value.i++; + } + if (changePolyFlags) + { + currentPolyFlags = nextPolyFlags; + changePolyFlags = false; + + ps_hw_numpolyflags.value.i++; + } + if (changeSurfaceInfo) + { + currentSurfaceInfo = nextSurfaceInfo; + changeSurfaceInfo = false; + + ps_hw_numcolors.value.i++; + } + // and that should be it? + } + // reset the arrays (set sizes to 0) + polygonArraySize = 0; + unsortedVertexArraySize = 0; + + PS_STOP_TIMING(ps_hw_batchdrawtime); +} + + +#endif // HWRENDER diff --git a/src/hardware/hw_batching.h b/src/hardware/hw_batching.h new file mode 100644 index 000000000..bf0b7fc94 --- /dev/null +++ b/src/hardware/hw_batching.h @@ -0,0 +1,39 @@ +// SONIC ROBO BLAST 2 +//----------------------------------------------------------------------------- +// Copyright (C) 1998-2000 by DooM Legacy Team. +// Copyright (C) 1999-2020 by Sonic Team Junior. +// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. +//----------------------------------------------------------------------------- +/// \file hw_batching.h +/// \brief Draw call batching and related things. + +#ifndef __HWR_BATCHING_H__ +#define __HWR_BATCHING_H__ + +#include "hw_defs.h" +#include "hw_data.h" +#include "hw_drv.h" + +typedef struct +{ + FSurfaceInfo surf;// surf also has its own polyflags for some reason, but it seems unused + unsigned int vertsIndex;// location of verts in unsortedVertexArray + FUINT numVerts; + FBITFIELD polyFlags; + GLMipmap_t *texture; + int shader; + // this tells batching that the plane belongs to a horizon line and must be drawn in correct order with the skywalls + boolean horizonSpecial; +} PolygonArrayEntry; + +void HWR_StartBatching(void); +void HWR_SetCurrentTexture(GLMipmap_t *texture); +void HWR_ProcessPolygon(FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPts, FBITFIELD PolyFlags, int shader, boolean horizonSpecial); +void HWR_RenderBatches(void); + +extern boolean currently_batching; + +#endif diff --git a/src/hardware/hw_cache.c b/src/hardware/hw_cache.c index 4255475bb..bdcdea1a6 100644 --- a/src/hardware/hw_cache.c +++ b/src/hardware/hw_cache.c @@ -17,6 +17,7 @@ #include "hw_main.h" #include "hw_glob.h" #include "hw_drv.h" +#include "hw_batching.h" #include "../doomstat.h" //gamemode #include "../i_video.h" //rendermode @@ -591,7 +592,11 @@ GLTexture_t *HWR_GetTexture(INT32 tex) if (!grtex->mipmap.grInfo.data && !grtex->mipmap.downloaded) HWR_GenerateTexture(tex, grtex); - HWD.pfnSetTexture(&grtex->mipmap); + // If hardware does not have the texture, then call pfnSetTexture to upload it + if (!grtex->mipmap.downloaded) + HWD.pfnSetTexture(&grtex->mipmap); + + HWR_SetCurrentTexture(&grtex->mipmap); // The system-memory data can be purged now. Z_ChangeTag(grtex->mipmap.grInfo.data, PU_HWRCACHE_UNLOCKED); @@ -675,7 +680,11 @@ void HWR_GetFlat(lumpnum_t flatlumpnum, boolean noencoremap) if (!grmip->downloaded && !grmip->grInfo.data) HWR_CacheFlat(grmip, flatlumpnum); - HWD.pfnSetTexture(grmip); + // If hardware does not have the texture, then call pfnSetTexture to upload it + if (!grmip->downloaded) + HWD.pfnSetTexture(grmip); + + HWR_SetCurrentTexture(grmip); // The system-memory data can be purged now. Z_ChangeTag(grmip->grInfo.data, PU_HWRCACHE_UNLOCKED); @@ -701,8 +710,11 @@ static void HWR_LoadMappedPatch(GLMipmap_t *grmip, GLPatch_t *gpatch) Z_Free(patch); } - - HWD.pfnSetTexture(grmip); + // If hardware does not have the texture, then call pfnSetTexture to upload it + if (!grmip->downloaded) + HWD.pfnSetTexture(grmip); + + HWR_SetCurrentTexture(grmip); // The system-memory data can be purged now. Z_ChangeTag(grmip->grInfo.data, PU_HWRCACHE_UNLOCKED); @@ -732,7 +744,11 @@ void HWR_GetPatch(GLPatch_t *gpatch) Z_Free(ptr); } - HWD.pfnSetTexture(gpatch->mipmap); + // If hardware does not have the texture, then call pfnSetTexture to upload it + if (!gpatch->mipmap->downloaded) + HWD.pfnSetTexture(gpatch->mipmap); + + HWR_SetCurrentTexture(gpatch->mipmap); // The system-memory patch data can be purged now. Z_ChangeTag(gpatch->mipmap->grInfo.data, PU_HWRCACHE_UNLOCKED); diff --git a/src/hardware/hw_draw.c b/src/hardware/hw_draw.c index 8feb7c050..8c309f020 100644 --- a/src/hardware/hw_draw.c +++ b/src/hardware/hw_draw.c @@ -122,7 +122,7 @@ void HWR_DrawPatch(GLPatch_t *gpatch, INT32 x, INT32 y, INT32 option) flags |= PF_ForceWrapY; // clip it since it is used for bunny scroll in doom I - HWD.pfnDrawPolygon(NULL, v, 4, flags, false); + HWD.pfnDrawPolygon(NULL, v, 4, flags); } void HWR_DrawStretchyFixedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale, fixed_t vscale, INT32 option, const UINT8 *colormap) @@ -300,10 +300,10 @@ void HWR_DrawStretchyFixedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t else if (alphalevel == 15) Surf.PolyColor.s.alpha = softwaretranstogl_hi[hudtrans]; else Surf.PolyColor.s.alpha = softwaretranstogl[10-alphalevel]; flags |= PF_Modulated; - HWD.pfnDrawPolygon(&Surf, v, 4, flags, false); + HWD.pfnDrawPolygon(&Surf, v, 4, flags); } else - HWD.pfnDrawPolygon(NULL, v, 4, flags, false); + HWD.pfnDrawPolygon(NULL, v, 4, flags); } void HWR_DrawCroppedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale, INT32 option, fixed_t sx, fixed_t sy, fixed_t w, fixed_t h) @@ -454,10 +454,10 @@ void HWR_DrawCroppedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscal else if (alphalevel == 15) Surf.PolyColor.s.alpha = softwaretranstogl_hi[cv_translucenthud.value]; else Surf.PolyColor.s.alpha = softwaretranstogl[10-alphalevel]; flags |= PF_Modulated; - HWD.pfnDrawPolygon(&Surf, v, 4, flags, false); + HWD.pfnDrawPolygon(&Surf, v, 4, flags); } else - HWD.pfnDrawPolygon(NULL, v, 4, flags, false); + HWD.pfnDrawPolygon(NULL, v, 4, flags); } // ========================================================================== @@ -533,7 +533,7 @@ void HWR_DrawFlatFill (INT32 x, INT32 y, INT32 w, INT32 h, lumpnum_t flatlumpnum // BTW, I see we put 0 for PFs, and If I'm right, that // means we take the previous PFs as default // how can we be sure they are ok? - HWD.pfnDrawPolygon(NULL, v, 4, PF_NoDepthTest, false); //PF_Translucent); + HWD.pfnDrawPolygon(NULL, v, 4, PF_NoDepthTest); //PF_Translucent); } @@ -575,7 +575,7 @@ void HWR_FadeScreenMenuBack(UINT16 color, UINT8 strength) Surf.PolyColor.s.alpha = (UINT8)(strength*25.5f); } - HWD.pfnDrawPolygon(&Surf, v, 4, PF_NoTexture|PF_Modulated|PF_Translucent|PF_NoDepthTest, false); + HWD.pfnDrawPolygon(&Surf, v, 4, PF_NoTexture|PF_Modulated|PF_Translucent|PF_NoDepthTest); } // Draw the console background with translucency support @@ -602,7 +602,7 @@ void HWR_DrawConsoleBack(UINT32 color, INT32 height) Surf.PolyColor.rgba = UINT2RGBA(color); Surf.PolyColor.s.alpha = 0x80; - HWD.pfnDrawPolygon(&Surf, v, 4, PF_NoTexture|PF_Modulated|PF_Translucent|PF_NoDepthTest, false); + HWD.pfnDrawPolygon(&Surf, v, 4, PF_NoTexture|PF_Modulated|PF_Translucent|PF_NoDepthTest); } @@ -851,7 +851,7 @@ void HWR_DrawDiag(INT32 x, INT32 y, INT32 wh, INT32 color) Surf.PolyColor = V_GetColor(color); HWD.pfnDrawPolygon(&Surf, v, 4, - PF_Modulated|PF_NoTexture|PF_NoDepthTest, false); + PF_Modulated|PF_NoTexture|PF_NoDepthTest); } // -------------------+ @@ -959,7 +959,7 @@ void HWR_DrawConsoleFill(INT32 x, INT32 y, INT32 w, INT32 h, UINT32 color, INT32 Surf.PolyColor.rgba = UINT2RGBA(color); Surf.PolyColor.s.alpha = 0x80; - HWD.pfnDrawPolygon(&Surf, v, 4, PF_NoTexture|PF_Modulated|PF_Translucent|PF_NoDepthTest, false); + HWD.pfnDrawPolygon(&Surf, v, 4, PF_NoTexture|PF_Modulated|PF_Translucent|PF_NoDepthTest); } // -----------------+ @@ -1076,7 +1076,7 @@ void HWR_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 color) else Surf.PolyColor.s.alpha = softwaretranstogl[10-alphalevel]; } - HWD.pfnDrawPolygon(&Surf, v, 4, PF_NoTexture|PF_Modulated|PF_Translucent|PF_NoDepthTest, false); + HWD.pfnDrawPolygon(&Surf, v, 4, PF_NoTexture|PF_Modulated|PF_Translucent|PF_NoDepthTest); } #ifdef HAVE_PNG diff --git a/src/hardware/hw_drv.h b/src/hardware/hw_drv.h index b231e76c4..f7441204f 100644 --- a/src/hardware/hw_drv.h +++ b/src/hardware/hw_drv.h @@ -36,7 +36,8 @@ EXPORT void HWRAPI(SetPalette) (RGBA_t *ppal, RGBA_t *pgamma); #endif EXPORT void HWRAPI(FinishUpdate) (INT32 waitvbl); EXPORT void HWRAPI(Draw2DLine) (F2DCoord *v1, F2DCoord *v2, RGBA_t Color); -EXPORT void HWRAPI(DrawPolygon) (FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPts, FBITFIELD PolyFlags, boolean horizonSpecial); +EXPORT void HWRAPI(DrawPolygon) (FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPts, FBITFIELD PolyFlags); +EXPORT void HWRAPI(DrawIndexedTriangles) (FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPts, FBITFIELD PolyFlags, unsigned int *IndexArray); EXPORT void HWRAPI(SetBlend) (FBITFIELD PolyFlags); EXPORT void HWRAPI(ClearBuffer) (FBOOLEAN ColorMask, FBOOLEAN DepthMask, FBOOLEAN StencilMask, FRGBAFloat *ClearColor); EXPORT void HWRAPI(SetTexture) (FTextureInfo *TexInfo); @@ -81,9 +82,6 @@ EXPORT void HWRAPI(SetShaderInfo) (hwdshaderinfo_t info, INT32 value); EXPORT void HWRAPI(LoadCustomShader) (int number, char *shader, size_t size, boolean fragment); EXPORT boolean HWRAPI(InitCustomShaders) (void); -EXPORT void HWRAPI(StartBatching) (void); -EXPORT void HWRAPI(RenderBatches) (precise_t *sSortTime, precise_t *sDrawTime, int *sNumPolys, int *sNumVerts, int *sNumCalls, int *sNumShaders, int *sNumTextures, int *sNumPolyFlags, int *sNumColors); - EXPORT void HWRAPI(InitPalette) (int flashnum, boolean skiplut); EXPORT UINT32 HWRAPI(AddLightTable) (UINT8 *lighttable); EXPORT void HWRAPI(ClearLightTableCache) (void); @@ -102,6 +100,7 @@ struct hwdriver_s FinishUpdate pfnFinishUpdate; Draw2DLine pfnDraw2DLine; DrawPolygon pfnDrawPolygon; + DrawIndexedTriangles pfnDrawIndexedTriangles; SetBlend pfnSetBlend; ClearBuffer pfnClearBuffer; SetTexture pfnSetTexture; @@ -136,9 +135,6 @@ struct hwdriver_s LoadCustomShader pfnLoadCustomShader; InitCustomShaders pfnInitCustomShaders; - StartBatching pfnStartBatching; - RenderBatches pfnRenderBatches; - InitPalette pfnInitPalette; AddLightTable pfnAddLightTable; ClearLightTableCache pfnClearLightTableCache; diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index b2a4bdde8..bf733b637 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -19,6 +19,7 @@ #include "hw_main.h" #include "hw_glob.h" #include "hw_drv.h" +#include "hw_batching.h" #include "hw_md2.h" #include "hw_clip.h" #include "hw_light.h" @@ -682,6 +683,8 @@ void HWR_RenderPlane(subsector_t *subsector, extrasubsector_t *xsub, boolean isc static FOutVector *planeVerts = NULL; static UINT16 numAllocedPlaneVerts = 0; + + INT32 shader = 0; // no convex poly were generated for this subsector if (!xsub->planepoly) @@ -859,16 +862,16 @@ void HWR_RenderPlane(subsector_t *subsector, extrasubsector_t *xsub, boolean isc if (HWR_UseShader()) { if (PolyFlags & PF_Fog) - HWD.pfnSetShader(6); // fog shader + shader = 6; // fog shader else if (PolyFlags & PF_Ripple) - HWD.pfnSetShader(HWR_ShouldUsePaletteRendering() ? 11 : 5); // water shader + shader = (HWR_ShouldUsePaletteRendering() ? 11 : 5); // water shader else - HWD.pfnSetShader(HWR_ShouldUsePaletteRendering() ? 9 : 1); // floor shader + shader = (HWR_ShouldUsePaletteRendering() ? 9 : 1); // floor shader PolyFlags |= PF_ColorMapped; } - HWD.pfnDrawPolygon(&Surf, planeVerts, nrPlaneVerts, PolyFlags, false); + HWR_ProcessPolygon(&Surf, planeVerts, nrPlaneVerts, PolyFlags, shader, false); if (subsector) { @@ -953,7 +956,7 @@ void HWR_RenderPlane(subsector_t *subsector, extrasubsector_t *xsub, boolean isc horizonpts[4].y = gr_viewz; // Draw - HWD.pfnDrawPolygon(&Surf, horizonpts, 6, PolyFlags, true); + HWR_ProcessPolygon(&Surf, horizonpts, 6, PolyFlags, shader, true); } } } @@ -969,6 +972,8 @@ static void HWR_DrawSegsSplats(FSurfaceInfo * pSurf) fixed_t i; // seg bbox fixed_t segbbox[4]; + + INT32 shader = 0; M_ClearBox(segbbox); M_AddToBox(segbbox, @@ -1022,10 +1027,10 @@ static void HWR_DrawSegsSplats(FSurfaceInfo * pSurf) if (HWR_UseShader()) { - HWD.pfnSetShader(HWR_ShouldUsePaletteRendering() ? 10 : 2); // wall shader + shader = (HWR_ShouldUsePaletteRendering() ? 10 : 2); // wall shader } - HWD.pfnDrawPolygon(&pSurf, wallVerts, 4, i|PF_Modulated|PF_Decal, false); + HWD.HWR_ProcessPolygon(&pSurf, wallVerts, 4, i|PF_Modulated|PF_Decal, shader, false); } } #endif @@ -1056,11 +1061,13 @@ FBITFIELD HWR_TranstableToAlpha(INT32 transtablenum, FSurfaceInfo *pSurf) // void HWR_ProjectWall(FOutVector *wallVerts, FSurfaceInfo *pSurf, FBITFIELD blendmode, INT32 lightlevel, extracolormap_t *wallcolormap) { + INT32 shader = 0; + HWR_Lighting(pSurf, lightlevel, wallcolormap); if (HWR_UseShader()) { - HWD.pfnSetShader(HWR_ShouldUsePaletteRendering() ? 10 : 2); // wall shader + shader = (HWR_ShouldUsePaletteRendering() ? 10 : 2); // wall shader blendmode |= PF_ColorMapped; } @@ -1071,7 +1078,7 @@ void HWR_ProjectWall(FOutVector *wallVerts, FSurfaceInfo *pSurf, FBITFIELD blend blendmode &= ~PF_Masked; } - HWD.pfnDrawPolygon(pSurf, wallVerts, 4, blendmode|PF_Modulated|PF_Occlude, false); + HWR_ProcessPolygon(pSurf, wallVerts, 4, blendmode|PF_Modulated|PF_Occlude, shader, false); // wall shader #ifdef WALLSPLATS if (gr_curline->linedef->splats && cv_splats.value) @@ -1427,11 +1434,11 @@ static void HWR_DrawSkyWallList(void) surf.PolyColor.rgba = 0xFFFFFFFF; - HWD.pfnSetTexture(NULL); + HWR_SetCurrentTexture(NULL); HWD.pfnUnSetShader(); for (i = 0; i < skyWallVertexArraySize; i++) { - HWD.pfnDrawPolygon(&surf, skyWallVertexArray + i * 4, 4, PF_Occlude|PF_Invisible|PF_NoTexture, false); + HWD.pfnDrawPolygon(&surf, skyWallVertexArray + i * 4, 4, PF_Occlude|PF_Invisible|PF_NoTexture); } } @@ -1452,7 +1459,7 @@ void HWR_DrawSkyWall(FOutVector *wallVerts, FSurfaceInfo *Surf) } else { - HWD.pfnSetTexture(NULL); + HWR_SetCurrentTexture(NULL); HWR_ProjectWall(wallVerts, Surf, PF_Invisible|PF_NoTexture, 255, NULL); } // PF_Invisible so it's not drawn into the colour buffer @@ -3147,6 +3154,8 @@ void HWR_RenderPolyObjectPlane(polyobj_t *polysector, boolean isceiling, fixed_t static FOutVector *planeVerts = NULL; static UINT16 numAllocedPlaneVerts = 0; + + INT32 shader = 0; nrPlaneVerts = polysector->numVertices; @@ -3292,11 +3301,11 @@ void HWR_RenderPolyObjectPlane(polyobj_t *polysector, boolean isceiling, fixed_t if (HWR_UseShader()) { - HWD.pfnSetShader(HWR_ShouldUsePaletteRendering() ? 9 : 1); // floor shader + shader = (HWR_ShouldUsePaletteRendering() ? 9 : 1); // floor shader blendmode |= PF_ColorMapped; } - HWD.pfnDrawPolygon(&Surf, planeVerts, nrPlaneVerts, blendmode, false); + HWR_ProcessPolygon(&Surf, planeVerts, nrPlaneVerts, blendmode, shader, false); // floor shader } void HWR_AddPolyObjectPlanes(void) @@ -3952,6 +3961,8 @@ static void HWR_DrawSpriteShadow(gr_vissprite_t *spr, GLPatch_t *gpatch, float t fixed_t slopez; float offset = 0; + INT32 shader = 0; + R_GetShadowZ(spr->mobj, &floorslope); mobjfloor = HWR_OpaqueFloorAtPos( @@ -4101,10 +4112,10 @@ static void HWR_DrawSpriteShadow(gr_vissprite_t *spr, GLPatch_t *gpatch, float t if (HWR_UseShader()) { - HWD.pfnSetShader(HWR_ShouldUsePaletteRendering() ? 9 : 1); // floor shader + shader = (HWR_ShouldUsePaletteRendering() ? 9 : 1); // floor shader } - - HWD.pfnDrawPolygon(&sSurf, swallVerts, 4, PF_Translucent|PF_Modulated, false); + + HWR_ProcessPolygon(&sSurf, swallVerts, 4, PF_Translucent|PF_Modulated, shader, false); } } @@ -4200,6 +4211,8 @@ static void HWR_SplitSprite(gr_vissprite_t *spr) fixed_t v1x, v1y, v2x, v2y; #endif + INT32 shader = 0; + this_scale = FIXED_TO_FLOAT(spr->mobj->scale); if (hires) @@ -4473,11 +4486,11 @@ static void HWR_SplitSprite(gr_vissprite_t *spr) if (HWR_UseShader()) { - HWD.pfnSetShader(HWR_ShouldUsePaletteRendering() ? 10 : 3); // sprite shader + shader = (HWR_ShouldUsePaletteRendering() ? 10 : 3); // sprite shader blend |= PF_ColorMapped; } - HWD.pfnDrawPolygon(&Surf, wallVerts, 4, blend|PF_Modulated, false); + HWR_ProcessPolygon(&Surf, wallVerts, 4, blend|PF_Modulated, shader, false); // sprite shader top = bot; #ifdef ESLOPE @@ -4518,11 +4531,11 @@ static void HWR_SplitSprite(gr_vissprite_t *spr) if (HWR_UseShader()) { - HWD.pfnSetShader(HWR_ShouldUsePaletteRendering() ? 10 : 3); // sprite shader + shader = (HWR_ShouldUsePaletteRendering() ? 10 : 3); // sprite shader blend |= PF_ColorMapped; } - HWD.pfnDrawPolygon(&Surf, wallVerts, 4, blend|PF_Modulated, false); + HWR_ProcessPolygon(&Surf, wallVerts, 4, blend|PF_Modulated, shader, false); // sprite shader } // -----------------+ @@ -4536,6 +4549,9 @@ static void HWR_DrawSprite(gr_vissprite_t *spr) FOutVector wallVerts[4]; GLPatch_t *gpatch; // sprite patch converted to hardware FSurfaceInfo Surf; + + INT32 shader = 0; + const boolean hires = (spr->mobj && spr->mobj->skin && ((skin_t *)( (spr->mobj->localskin) ? spr->mobj->localskin : spr->mobj->skin ))->flags & SF_HIRES); if (spr->mobj) this_scale = FIXED_TO_FLOAT(spr->mobj->scale); @@ -4676,11 +4692,11 @@ static void HWR_DrawSprite(gr_vissprite_t *spr) if (HWR_UseShader()) { - HWD.pfnSetShader(HWR_ShouldUsePaletteRendering() ? 10 : 3); // sprite shader + shader = (HWR_ShouldUsePaletteRendering() ? 10 : 3); // sprite shader blend |= PF_ColorMapped; } - HWD.pfnDrawPolygon(&Surf, wallVerts, 4, blend|PF_Modulated, false); + HWR_ProcessPolygon(&Surf, wallVerts, 4, blend|PF_Modulated, shader, false); } } @@ -4691,6 +4707,8 @@ static inline void HWR_DrawPrecipitationSprite(gr_vissprite_t *spr) FOutVector wallVerts[4]; GLPatch_t *gpatch; // sprite patch converted to hardware FSurfaceInfo Surf; + + INT32 shader = 0; if (!spr->mobj) return; @@ -4775,11 +4793,11 @@ static inline void HWR_DrawPrecipitationSprite(gr_vissprite_t *spr) if (HWR_UseShader()) { - HWD.pfnSetShader(HWR_ShouldUsePaletteRendering() ? 10 : 3); // sprite shader + shader = (HWR_ShouldUsePaletteRendering() ? 10 : 3); // sprite shader blend |= PF_ColorMapped; } - HWD.pfnDrawPolygon(&Surf, wallVerts, 4, blend|PF_Modulated, false); + HWR_ProcessPolygon(&Surf, wallVerts, 4, blend|PF_Modulated, shader, false); } // -------------------------------------------------------------------------- @@ -5945,8 +5963,8 @@ static void HWR_PortalClipping(gl_portal_t *portal) line_t *line = &lines[portal->clipline]; - angle1 = R_PointToAngleEx64(viewx, viewy, line->v1->x, line->v1->y); - angle2 = R_PointToAngleEx64(viewx, viewy, line->v2->x, line->v2->y); + angle1 = R_PointToAngleEx(viewx, viewy, line->v1->x, line->v1->y); + angle2 = R_PointToAngleEx(viewx, viewy, line->v2->x, line->v2->y); // clip things that are not inside the portal window from our viewpoint gld_clipper_SafeAddClipRange(angle2, angle1); @@ -6076,8 +6094,9 @@ static void HWR_RenderViewpoint(gl_portal_t *rootportal, const float fpov, playe } //drawcount = 0; validcount++; + if (cv_grbatching.value) - HWD.pfnStartBatching(); + HWR_StartBatching(); ps_numbspcalls.value.i = 0; ps_numpolyobjects.value.i = 0; @@ -6098,14 +6117,10 @@ static void HWR_RenderViewpoint(gl_portal_t *rootportal, const float fpov, playe gr_portal = oldgl_portal_state; PS_STOP_TIMING(ps_bsptime); - + if (cv_grbatching.value) - { - HWD.pfnRenderBatches(&ps_hw_batchsorttime.value.p, &ps_hw_batchdrawtime.value.p, - &ps_hw_numpolys.value.i, &ps_hw_numverts.value.i, &ps_hw_numcalls.value.i, - &ps_hw_numshaders.value.i, &ps_hw_numtextures.value.i, &ps_hw_numpolyflags.value.i, - &ps_hw_numcolors.value.i); - } + HWR_RenderBatches(); + if (skyWallVertexArraySize)// if there are skywalls to draw using the alternate method { HWR_SetStencilState(HWR_STENCIL_SKY, -1); @@ -6353,7 +6368,7 @@ void HWR_AddCommands(void) CV_RegisterVar(&cv_granisotropicmode); CV_RegisterVar(&cv_grcorrecttricks); CV_RegisterVar(&cv_grsolvetjoin); - + CV_RegisterVar(&cv_grbatching); CV_RegisterVar(&cv_grfofcut); CV_RegisterVar(&cv_fofzfightfix); @@ -6444,6 +6459,8 @@ void HWR_RenderWall(FOutVector *wallVerts, FSurfaceInfo *pSurf, FBITFIELD blend, { FBITFIELD blendmode = blend; UINT8 alpha = pSurf->PolyColor.s.alpha; // retain the alpha + + INT32 shader = 0; // Lighting is done here instead so that fog isn't drawn incorrectly on transparent walls after sorting HWR_Lighting(pSurf, lightlevel, wallcolormap); @@ -6456,7 +6473,7 @@ void HWR_RenderWall(FOutVector *wallVerts, FSurfaceInfo *pSurf, FBITFIELD blend, if (fogwall) { blendmode |= PF_Fog; - HWD.pfnSetShader(6); // fog shader + shader = 6; // fog shader } blendmode |= PF_Modulated; // No PF_Occlude means overlapping (incorrect) transparency @@ -6465,12 +6482,12 @@ void HWR_RenderWall(FOutVector *wallVerts, FSurfaceInfo *pSurf, FBITFIELD blend, { if (HWR_UseShader()) { - HWD.pfnSetShader(HWR_ShouldUsePaletteRendering() ? 10 : 2); // wall shader + shader = (HWR_ShouldUsePaletteRendering() ? 10 : 2); // wall shader blendmode |= PF_ColorMapped; } } - HWD.pfnDrawPolygon(pSurf, wallVerts, 4, blendmode, false); + HWR_ProcessPolygon(pSurf, wallVerts, 4, blendmode, shader, false); #ifdef WALLSPLATS if (gr_curline->linedef->splats && cv_splats.value) @@ -6521,7 +6538,7 @@ void HWR_DoPostProcessor(player_t *player) Surf.PolyColor.s.alpha = 0xc0; // match software mode - HWD.pfnDrawPolygon(&Surf, v, 4, PF_Modulated|PF_Translucent|PF_NoTexture|PF_NoDepthTest, false); + HWD.pfnDrawPolygon(&Surf, v, 4, PF_Modulated|PF_Translucent|PF_NoTexture|PF_NoDepthTest); } if (!cv_grscreentextures.value) // screen textures are needed for the rest of the effects diff --git a/src/hardware/hw_main.h b/src/hardware/hw_main.h index 6a62295f8..23d93e8ce 100644 --- a/src/hardware/hw_main.h +++ b/src/hardware/hw_main.h @@ -64,6 +64,8 @@ extern ps_metric_t ps_hw_numcolors; extern ps_metric_t ps_hw_batchsorttime; extern ps_metric_t ps_hw_batchdrawtime; +extern boolean gr_shadersavailable; + // hw_draw.c void HWR_DrawPatch(GLPatch_t *gpatch, INT32 x, INT32 y, INT32 option); void HWR_DrawStretchyFixedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale, fixed_t vscale, INT32 option, const UINT8 *colormap); diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c index 2fbd9071e..681c42005 100644 --- a/src/hardware/r_opengl/r_opengl.c +++ b/src/hardware/r_opengl/r_opengl.c @@ -34,6 +34,7 @@ #include "../../i_system.h" // for I_GetPreciseTime (batching time measurements) #include "../hw_main.h" +#include "../hw_batching.h" // Eeeeh not sure is this right way, but it works < sry :c extern consvar_t cv_grusecustomshaders; @@ -638,8 +639,6 @@ static boolean gl_shadersenabled = false; static GLuint gl_currentshaderprogram = 0; static boolean gl_shaderprogramchanged = true; -static boolean gl_batching = false;// are we currently collecting batches? - static GLint gl_palette[768]; boolean gl_palette_initialized = false; static boolean gl_palshader = false; @@ -1464,7 +1463,7 @@ EXPORT void HWRAPI(InitPalette) (int flashnum, boolean skiplut) static void SetNoTexture(void) { // Disable texture. - if (tex_downloaded != NOTEXTURE_NUM && !gl_batching) + if (tex_downloaded != NOTEXTURE_NUM) { pglBindTexture(GL_TEXTURE_2D, NOTEXTURE_NUM); tex_downloaded = NOTEXTURE_NUM; @@ -1685,7 +1684,7 @@ EXPORT UINT32 HWRAPI(AddLightTable) (UINT8 *lighttable) pglTexImage2D(GL_TEXTURE_2D, 0, internalFormat, 256, 32, 0, GL_RED, GL_UNSIGNED_BYTE, lighttable); // restore previously bound texture - if (!gl_batching) + if (!cv_grbatching.value) pglBindTexture(GL_TEXTURE_2D, tex_downloaded); return ltcachetail->id; @@ -2362,628 +2361,77 @@ static void Shader_SetUniforms(FSurfaceInfo *Surface, GLRGBAFloat *poly, GLRGBAF #endif } - -// unfinished draw call batching - -// Note: could use realloc in the array reallocation code - -typedef struct +// code that is common between DrawPolygon and DrawIndexedTriangles +// the corona thing is there too, i have no idea if that stuff works with DrawIndexedTriangles and batching +static void PreparePolygon(FSurfaceInfo *pSurf, FOutVector *pOutVerts, FBITFIELD PolyFlags) { - FSurfaceInfo surf;// surf also has its own polyflags for some reason, but it seems unused - unsigned int vertsIndex;// location of verts in unsortedVertexArray - FUINT numVerts; - FBITFIELD polyFlags; - GLuint texNum; - GLuint shader; - // this tells batching that the plane belongs to a horizon line and must be drawn in correct order with the skywalls - boolean horizonSpecial; -} PolygonArrayEntry; + static GLRGBAFloat poly = {0,0,0,0}; + static GLRGBAFloat tint = {0,0,0,0}; + static GLRGBAFloat fade = {0,0,0,0}; -FOutVector* finalVertexArray = NULL;// contains subset of sorted vertices and texture coordinates to be sent to gpu -UINT32* finalVertexIndexArray = NULL;// contains indexes for glDrawElements, taking into account fan->triangles conversion -// NOTE have this alloced as 3x finalVertexArray size -int finalVertexArrayAllocSize = 65536; -//GLubyte* colorArray = NULL;// contains color data to be sent to gpu, if needed -//int colorArrayAllocSize = 65536; -// not gonna use this for now, just sort by color and change state when it changes -// later maybe when using vertex attributes if it's needed + SetBlend(PolyFlags); //TODO: inline (#pragma..) -PolygonArrayEntry* polygonArray = NULL;// contains the polygon data from DrawPolygon, waiting to be processed -int polygonArraySize = 0; -UINT32* polygonIndexArray = NULL;// contains sorting pointers for polygonArray -int polygonArrayAllocSize = 65536; - -FOutVector* unsortedVertexArray = NULL;// contains unsorted vertices and texture coordinates from DrawPolygon -int unsortedVertexArraySize = 0; -int unsortedVertexArrayAllocSize = 65536; - -EXPORT void HWRAPI(StartBatching) (void) -{ - //CONS_Printf("StartBatching begin\n"); - // init arrays if that has not been done yet - if (!finalVertexArray) + // PolyColor + if (pSurf) { - finalVertexArray = malloc(finalVertexArrayAllocSize * sizeof(FOutVector)); - finalVertexIndexArray = malloc(finalVertexArrayAllocSize * 3 * sizeof(UINT32)); - polygonArray = malloc(polygonArrayAllocSize * sizeof(PolygonArrayEntry)); - polygonIndexArray = malloc(polygonArrayAllocSize * sizeof(UINT32)); - unsortedVertexArray = malloc(unsortedVertexArrayAllocSize * sizeof(FOutVector)); - } - // drawing functions will now collect the drawing data instead of passing it to opengl - gl_batching = true; - //CONS_Printf("StartBatching end\n"); -} + // If Modulated, mix the surface colour to the texture + if (CurrentPolyFlags & PF_Modulated) + { + // Poly color + poly.red = byte2float[pSurf->PolyColor.s.red]; + poly.green = byte2float[pSurf->PolyColor.s.green]; + poly.blue = byte2float[pSurf->PolyColor.s.blue]; + poly.alpha = byte2float[pSurf->PolyColor.s.alpha]; -static int comparePolygons(const void *p1, const void *p2) -{ - unsigned int index1 = *(const unsigned int*)p1; - unsigned int index2 = *(const unsigned int*)p2; - PolygonArrayEntry* poly1 = &polygonArray[index1]; - PolygonArrayEntry* poly2 = &polygonArray[index2]; - int diff; - INT64 diff64; + pglColor4ubv((GLubyte*)&pSurf->PolyColor.s); + } - int shader1 = poly1->shader; - int shader2 = poly2->shader; - // make skywalls and horizon lines first in order - if (poly1->polyFlags & PF_NoTexture || poly1->horizonSpecial) - shader1 = -1; - if (poly2->polyFlags & PF_NoTexture || poly2->horizonSpecial) - shader2 = -1; - diff = shader1 - shader2; - if (diff != 0) return diff; + // Tint color + tint.red = byte2float[pSurf->TintColor.s.red]; + tint.green = byte2float[pSurf->TintColor.s.green]; + tint.blue = byte2float[pSurf->TintColor.s.blue]; + tint.alpha = byte2float[pSurf->TintColor.s.alpha]; - // skywalls and horizon lines must retain their order for horizon lines to work - if (shader1 == -1 && shader2 == -1) - return index1 - index2; - - diff = poly1->texNum - poly2->texNum; - if (diff != 0) return diff; - - if (gl_palshader) - { - diff = poly1->surf.LightTableId - poly2->surf.LightTableId; - if (diff != 0) return diff; + // Fade color + fade.red = byte2float[pSurf->FadeColor.s.red]; + fade.green = byte2float[pSurf->FadeColor.s.green]; + fade.blue = byte2float[pSurf->FadeColor.s.blue]; + fade.alpha = byte2float[pSurf->FadeColor.s.alpha]; } - diff = poly1->polyFlags - poly2->polyFlags; - if (diff != 0) return diff; - - diff64 = poly1->surf.PolyColor.rgba - poly2->surf.PolyColor.rgba; - if (diff64 < 0) return -1; else if (diff64 > 0) return 1; - diff64 = poly1->surf.TintColor.rgba - poly2->surf.TintColor.rgba; - if (diff64 < 0) return -1; else if (diff64 > 0) return 1; - diff64 = poly1->surf.FadeColor.rgba - poly2->surf.FadeColor.rgba; - if (diff64 < 0) return -1; else if (diff64 > 0) return 1; - - diff = poly1->surf.LightInfo.light_level - poly2->surf.LightInfo.light_level; - if (diff != 0) return diff; - diff = poly1->surf.LightInfo.fade_start - poly2->surf.LightInfo.fade_start; - if (diff != 0) return diff; - diff = poly1->surf.LightInfo.fade_end - poly2->surf.LightInfo.fade_end; - return diff; -} - -static int comparePolygonsNoShaders(const void *p1, const void *p2) -{ - unsigned int index1 = *(const unsigned int*)p1; - unsigned int index2 = *(const unsigned int*)p2; - PolygonArrayEntry* poly1 = &polygonArray[index1]; - PolygonArrayEntry* poly2 = &polygonArray[index2]; - int diff; - INT64 diff64; - - GLuint texNum1 = poly1->texNum; - GLuint texNum2 = poly2->texNum; - if (poly1->polyFlags & PF_NoTexture || poly1->horizonSpecial) - texNum1 = 0; - if (poly2->polyFlags & PF_NoTexture || poly2->horizonSpecial) - texNum2 = 0; - diff = texNum1 - texNum2; - if (diff != 0) return diff; - - // skywalls and horizon lines must retain their order for horizon lines to work - if (texNum1 == 0 && texNum2 == 0) - return index1 - index2; - - diff = poly1->polyFlags - poly2->polyFlags; - if (diff != 0) return diff; - - diff64 = poly1->surf.PolyColor.rgba - poly2->surf.PolyColor.rgba; - if (diff64 < 0) return -1; else if (diff64 > 0) return 1; - - return 0; -} - -// the parameters for this functions (numPolys etc.) are used to return rendering stats -EXPORT void HWRAPI(RenderBatches) (precise_t *sSortTime, precise_t *sDrawTime, int *sNumPolys, int *sNumVerts, int *sNumCalls, int *sNumShaders, int *sNumTextures, int *sNumPolyFlags, int *sNumColors) -{ - int finalVertexWritePos = 0;// position in finalVertexArray - int finalIndexWritePos = 0;// position in finalVertexIndexArray - - int polygonReadPos = 0;// position in polygonIndexArray - - GLuint currentShader; - GLuint currentTexture; - FBITFIELD currentPolyFlags; - FSurfaceInfo currentSurfaceInfo; - - GLRGBAFloat firstPoly = {0,0,0,0}; // may be misleading but this means first PolyColor - GLRGBAFloat firstTint = {0,0,0,0}; - GLRGBAFloat firstFade = {0,0,0,0}; - - boolean needRebind = false; - - int i; - - //CONS_Printf("RenderBatches\n"); - gl_batching = false;// no longer collecting batches - if (!polygonArraySize) - { - *sSortTime = *sDrawTime = *sNumPolys = *sNumCalls = *sNumShaders = *sNumTextures = *sNumPolyFlags = *sNumColors = 0; - return;// nothing to draw - } - // init stats vars - *sNumPolys = polygonArraySize; - *sNumCalls = *sNumVerts = 0; - *sNumShaders = *sNumTextures = *sNumPolyFlags = *sNumColors = 1; - // init polygonIndexArray - for (i = 0; i < polygonArraySize; i++) - { - polygonIndexArray[i] = i; - } - - // sort polygons - //CONS_Printf("qsort polys\n"); - *sSortTime = I_GetPreciseTime(); - if (gl_allowshaders) - qsort(polygonIndexArray, polygonArraySize, sizeof(unsigned int), comparePolygons); - else - qsort(polygonIndexArray, polygonArraySize, sizeof(unsigned int), comparePolygonsNoShaders); - *sSortTime = I_GetPreciseTime() - *sSortTime; - //CONS_Printf("sort done\n"); - // sort order - // 1. shader - // 2. texture - // 3. polyflags - // 4. colors + light level - // not sure about order of last 2, or if it even matters - - *sDrawTime = I_GetPreciseTime(); - - currentShader = polygonArray[polygonIndexArray[0]].shader; - currentTexture = polygonArray[polygonIndexArray[0]].texNum; - currentPolyFlags = polygonArray[polygonIndexArray[0]].polyFlags; - currentSurfaceInfo = polygonArray[polygonIndexArray[0]].surf; - // For now, will sort and track the colors. Vertex attributes could be used instead of uniforms - // and a color array could replace the color calls. - - // set state for first batch - //CONS_Printf("set first state\n"); - gl_currentshaderprogram = currentShader; - gl_shaderprogramchanged = true; - if (currentPolyFlags & PF_Modulated) - { - // Poly color - firstPoly.red = byte2float[currentSurfaceInfo.PolyColor.s.red]; - firstPoly.green = byte2float[currentSurfaceInfo.PolyColor.s.green]; - firstPoly.blue = byte2float[currentSurfaceInfo.PolyColor.s.blue]; - firstPoly.alpha = byte2float[currentSurfaceInfo.PolyColor.s.alpha]; - pglColor4ubv((GLubyte*)¤tSurfaceInfo.PolyColor.s); - } - // Tint color - firstTint.red = byte2float[currentSurfaceInfo.TintColor.s.red]; - firstTint.green = byte2float[currentSurfaceInfo.TintColor.s.green]; - firstTint.blue = byte2float[currentSurfaceInfo.TintColor.s.blue]; - firstTint.alpha = byte2float[currentSurfaceInfo.TintColor.s.alpha]; - // Fade color - firstFade.red = byte2float[currentSurfaceInfo.FadeColor.s.red]; - firstFade.green = byte2float[currentSurfaceInfo.FadeColor.s.green]; - firstFade.blue = byte2float[currentSurfaceInfo.FadeColor.s.blue]; - firstFade.alpha = byte2float[currentSurfaceInfo.FadeColor.s.alpha]; - - if (gl_allowshaders) - { - Shader_Load(¤tSurfaceInfo, &firstPoly, &firstTint, &firstFade); - if (gl_palshader) - { - pglActiveTexture(GL_TEXTURE2);// this stuff could be done better but gonna do it quick like this for now - pglBindTexture(GL_TEXTURE_2D, currentSurfaceInfo.LightTableId); - pglActiveTexture(GL_TEXTURE0); - } - } - - if (currentPolyFlags & PF_NoTexture) - currentTexture = 0; - pglBindTexture(GL_TEXTURE_2D, currentTexture); - tex_downloaded = currentTexture; - - SetBlend(currentPolyFlags); - - //CONS_Printf("first pointers to ogl\n"); - pglVertexPointer(3, GL_FLOAT, sizeof(FOutVector), &finalVertexArray[0].x); - pglTexCoordPointer(2, GL_FLOAT, sizeof(FOutVector), &finalVertexArray[0].s); - - while (1)// note: remember handling notexture polyflag as having texture number 0 (also in comparePolygons) - { - int firstIndex; - int lastIndex; - - boolean stopFlag = false; - boolean changeState = false; - boolean changeShader = false; - GLuint nextShader = 0U; - boolean changeTexture = false; - GLuint nextTexture = 0U; - boolean changePolyFlags = false; - FBITFIELD nextPolyFlags = 0U; - boolean changeSurfaceInfo = false; - FSurfaceInfo nextSurfaceInfo; - - //CONS_Printf("loop iter start\n"); - // new try: - // write vertices - // check for changes or end, otherwise go back to writing - // changes will affect the next vars and the change bools - // end could set flag for stopping - // execute draw call - // could check ending flag here - // change states according to next vars and change bools, updating the current vars and reseting the bools - // reset write pos - // repeat loop - - int index = polygonIndexArray[polygonReadPos++]; - int numVerts = polygonArray[index].numVerts; - // before writing, check if there is enough room - // using 'while' instead of 'if' here makes sure that there will *always* be enough room. - // probably never will this loop run more than once though - while (finalVertexWritePos + numVerts > finalVertexArrayAllocSize) - { - FOutVector* new_array; - unsigned int* new_index_array; - //CONS_Printf("final vert realloc\n"); - finalVertexArrayAllocSize *= 2; - new_array = malloc(finalVertexArrayAllocSize * sizeof(FOutVector)); - memcpy(new_array, finalVertexArray, finalVertexWritePos * sizeof(FOutVector)); - free(finalVertexArray); - finalVertexArray = new_array; - // also increase size of index array, 3x of vertex array since - // going from fans to triangles increases vertex count to 3x - new_index_array = malloc(finalVertexArrayAllocSize * 3 * sizeof(UINT32)); - memcpy(new_index_array, finalVertexIndexArray, finalIndexWritePos * sizeof(UINT32)); - free(finalVertexIndexArray); - finalVertexIndexArray = new_index_array; - // if vertex buffers are reallocated then opengl needs to know too - needRebind = true; - } - //CONS_Printf("write verts to final\n"); - // write the vertices of the polygon - memcpy(&finalVertexArray[finalVertexWritePos], &unsortedVertexArray[polygonArray[index].vertsIndex], - numVerts * sizeof(FOutVector)); - // write the indexes, pointing to the fan vertexes but in triangles format - firstIndex = finalVertexWritePos; - lastIndex = finalVertexWritePos + numVerts; - finalVertexWritePos += 2; - //CONS_Printf("write final vert indices\n"); - while (finalVertexWritePos < lastIndex) - { - finalVertexIndexArray[finalIndexWritePos++] = firstIndex; - finalVertexIndexArray[finalIndexWritePos++] = finalVertexWritePos - 1; - finalVertexIndexArray[finalIndexWritePos++] = finalVertexWritePos++; - } - - if (polygonReadPos >= polygonArraySize) - { - stopFlag = true; - } - else - { - //CONS_Printf("state change check\n"); - // check if a state change is required, set the change bools and next vars - int nextIndex = polygonIndexArray[polygonReadPos]; - nextShader = polygonArray[nextIndex].shader; - nextTexture = polygonArray[nextIndex].texNum; - nextPolyFlags = polygonArray[nextIndex].polyFlags; - nextSurfaceInfo = polygonArray[nextIndex].surf; - if (nextPolyFlags & PF_NoTexture) - nextTexture = 0; - if (currentShader != nextShader) - { - changeState = true; - changeShader = true; - } - if (currentTexture != nextTexture) - { - changeState = true; - changeTexture = true; - } - if (currentPolyFlags != nextPolyFlags) - { - changeState = true; - changePolyFlags = true; - } - if (gl_allowshaders && gl_palshader) - { - if (currentSurfaceInfo.PolyColor.rgba != nextSurfaceInfo.PolyColor.rgba || - currentSurfaceInfo.TintColor.rgba != nextSurfaceInfo.TintColor.rgba || - currentSurfaceInfo.FadeColor.rgba != nextSurfaceInfo.FadeColor.rgba || - currentSurfaceInfo.LightInfo.light_level != nextSurfaceInfo.LightInfo.light_level || - currentSurfaceInfo.LightInfo.fade_start != nextSurfaceInfo.LightInfo.fade_start || - currentSurfaceInfo.LightInfo.fade_end != nextSurfaceInfo.LightInfo.fade_end || - currentSurfaceInfo.LightTableId != nextSurfaceInfo.LightTableId) - { - changeState = true; - changeSurfaceInfo = true; - } - } - else if ((gl_allowshaders) && (!gl_palshader)) - { - if (currentSurfaceInfo.PolyColor.rgba != nextSurfaceInfo.PolyColor.rgba || - currentSurfaceInfo.TintColor.rgba != nextSurfaceInfo.TintColor.rgba || - currentSurfaceInfo.FadeColor.rgba != nextSurfaceInfo.FadeColor.rgba || - currentSurfaceInfo.LightInfo.light_level != nextSurfaceInfo.LightInfo.light_level || - currentSurfaceInfo.LightInfo.fade_start != nextSurfaceInfo.LightInfo.fade_start || - currentSurfaceInfo.LightInfo.fade_end != nextSurfaceInfo.LightInfo.fade_end) - { - changeState = true; - changeSurfaceInfo = true; - } - } - else - { - if (currentSurfaceInfo.PolyColor.rgba != nextSurfaceInfo.PolyColor.rgba) - { - changeState = true; - changeSurfaceInfo = true; - } - } - } - - if (changeState || stopFlag) - { - if (needRebind) - { - //CONS_Printf("rebind\n"); - pglVertexPointer(3, GL_FLOAT, sizeof(FOutVector), &finalVertexArray[0].x); - pglTexCoordPointer(2, GL_FLOAT, sizeof(FOutVector), &finalVertexArray[0].s); - needRebind = false; - } - //CONS_Printf("exec draw call\n"); - // execute draw call - pglDrawElements(GL_TRIANGLES, finalIndexWritePos, GL_UNSIGNED_INT, finalVertexIndexArray); - //CONS_Printf("draw call done\n"); - // update stats - (*sNumCalls)++; - *sNumVerts += finalIndexWritePos; - // reset write positions - finalVertexWritePos = 0; - finalIndexWritePos = 0; - } - else continue; - - // if we're here then either its time to stop or time to change state - if (stopFlag) break; - - //CONS_Printf("state change\n"); - - // change state according to change bools and next vars, update current vars and reset bools - if (changeShader) - { - GLRGBAFloat poly = {0,0,0,0}; - GLRGBAFloat tint = {0,0,0,0}; - GLRGBAFloat fade = {0,0,0,0}; - gl_currentshaderprogram = nextShader; - gl_shaderprogramchanged = true; - if (nextPolyFlags & PF_Modulated) - { - // Poly color - poly.red = byte2float[nextSurfaceInfo.PolyColor.s.red]; - poly.green = byte2float[nextSurfaceInfo.PolyColor.s.green]; - poly.blue = byte2float[nextSurfaceInfo.PolyColor.s.blue]; - poly.alpha = byte2float[nextSurfaceInfo.PolyColor.s.alpha]; - } - // Tint color - tint.red = byte2float[nextSurfaceInfo.TintColor.s.red]; - tint.green = byte2float[nextSurfaceInfo.TintColor.s.green]; - tint.blue = byte2float[nextSurfaceInfo.TintColor.s.blue]; - tint.alpha = byte2float[nextSurfaceInfo.TintColor.s.alpha]; - // Fade color - fade.red = byte2float[nextSurfaceInfo.FadeColor.s.red]; - fade.green = byte2float[nextSurfaceInfo.FadeColor.s.green]; - fade.blue = byte2float[nextSurfaceInfo.FadeColor.s.blue]; - fade.alpha = byte2float[nextSurfaceInfo.FadeColor.s.alpha]; - - Shader_Load(&nextSurfaceInfo, &poly, &tint, &fade); - currentShader = nextShader; - changeShader = false; - - (*sNumShaders)++; - } - if (changeTexture) - { - // texture should be already ready for use from calls to SetTexture during batch collection - pglBindTexture(GL_TEXTURE_2D, nextTexture); - tex_downloaded = nextTexture; - currentTexture = nextTexture; - changeTexture = false; - - (*sNumTextures)++; - } - if (changePolyFlags) - { - SetBlend(nextPolyFlags); - currentPolyFlags = nextPolyFlags; - changePolyFlags = false; - - (*sNumPolyFlags)++; - } - if (changeSurfaceInfo) - { - GLRGBAFloat poly = {0,0,0,0}; - GLRGBAFloat tint = {0,0,0,0}; - GLRGBAFloat fade = {0,0,0,0}; - gl_shaderprogramchanged = false; - if (nextPolyFlags & PF_Modulated) - { - // Poly color - poly.red = byte2float[nextSurfaceInfo.PolyColor.s.red]; - poly.green = byte2float[nextSurfaceInfo.PolyColor.s.green]; - poly.blue = byte2float[nextSurfaceInfo.PolyColor.s.blue]; - poly.alpha = byte2float[nextSurfaceInfo.PolyColor.s.alpha]; - pglColor4ubv((GLubyte*)&nextSurfaceInfo.PolyColor.s); - } - if (gl_allowshaders) - { - // Tint color - tint.red = byte2float[nextSurfaceInfo.TintColor.s.red]; - tint.green = byte2float[nextSurfaceInfo.TintColor.s.green]; - tint.blue = byte2float[nextSurfaceInfo.TintColor.s.blue]; - tint.alpha = byte2float[nextSurfaceInfo.TintColor.s.alpha]; - // Fade color - fade.red = byte2float[nextSurfaceInfo.FadeColor.s.red]; - fade.green = byte2float[nextSurfaceInfo.FadeColor.s.green]; - fade.blue = byte2float[nextSurfaceInfo.FadeColor.s.blue]; - fade.alpha = byte2float[nextSurfaceInfo.FadeColor.s.alpha]; - - Shader_Load(&nextSurfaceInfo, &poly, &tint, &fade); - - if (gl_palshader) - { - pglActiveTexture(GL_TEXTURE2);// this stuff could be done better but gonna do it quick like this for now - pglBindTexture(GL_TEXTURE_2D, nextSurfaceInfo.LightTableId); - pglActiveTexture(GL_TEXTURE0); - } - } - - currentSurfaceInfo = nextSurfaceInfo; - changeSurfaceInfo = false; - - (*sNumColors)++; - } - // and that should be it? - } - // reset the arrays (set sizes to 0) - polygonArraySize = 0; - unsortedVertexArraySize = 0; - - *sDrawTime = I_GetPreciseTime() - *sDrawTime; + Shader_Load(pSurf, &poly, &tint, &fade); } // -----------------+ // DrawPolygon : Render a polygon, set the texture, set render mode // -----------------+ -EXPORT void HWRAPI(DrawPolygon) (FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPts, FBITFIELD PolyFlags, boolean horizonSpecial) +EXPORT void HWRAPI(DrawPolygon) (FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPts, FBITFIELD PolyFlags) { - if (gl_batching) - { - //CONS_Printf("Batched DrawPolygon\n"); - if (!pSurf) - I_Error("Got a null FSurfaceInfo in batching");// nulls should only come in sky background pic drawing - if (polygonArraySize == polygonArrayAllocSize) - { - PolygonArrayEntry* new_array; - // ran out of space, make new array double the size - polygonArrayAllocSize *= 2; - new_array = malloc(polygonArrayAllocSize * sizeof(PolygonArrayEntry)); - memcpy(new_array, polygonArray, polygonArraySize * sizeof(PolygonArrayEntry)); - free(polygonArray); - polygonArray = new_array; - // also need to redo the index array, dont need to copy it though - free(polygonIndexArray); - polygonIndexArray = malloc(polygonArrayAllocSize * sizeof(unsigned int)); - } + PreparePolygon(pSurf, pOutVerts, PolyFlags); - while (unsortedVertexArraySize + (int)iNumPts > unsortedVertexArrayAllocSize) - { - FOutVector* new_array; - // need more space for vertices in unsortedVertexArray - unsortedVertexArrayAllocSize *= 2; - new_array = malloc(unsortedVertexArrayAllocSize * sizeof(FOutVector)); - memcpy(new_array, unsortedVertexArray, unsortedVertexArraySize * sizeof(FOutVector)); - free(unsortedVertexArray); - unsortedVertexArray = new_array; - } + pglVertexPointer(3, GL_FLOAT, sizeof(FOutVector), &pOutVerts[0].x); + pglTexCoordPointer(2, GL_FLOAT, sizeof(FOutVector), &pOutVerts[0].s); + pglDrawArrays(GL_TRIANGLE_FAN, 0, iNumPts); - // add the polygon data to the arrays + if (PolyFlags & PF_RemoveYWrap) + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); - polygonArray[polygonArraySize].surf = *pSurf; - polygonArray[polygonArraySize].vertsIndex = unsortedVertexArraySize; - polygonArray[polygonArraySize].numVerts = iNumPts; - polygonArray[polygonArraySize].polyFlags = PolyFlags; - polygonArray[polygonArraySize].texNum = tex_downloaded; - polygonArray[polygonArraySize].shader = gl_currentshaderprogram; - polygonArray[polygonArraySize].horizonSpecial = horizonSpecial; - polygonArraySize++; + if (PolyFlags & PF_ForceWrapX) + Clamp2D(GL_TEXTURE_WRAP_S); - memcpy(&unsortedVertexArray[unsortedVertexArraySize], pOutVerts, iNumPts * sizeof(FOutVector)); - unsortedVertexArraySize += iNumPts; - } - else - { - static GLRGBAFloat poly = {0,0,0,0}; - static GLRGBAFloat tint = {0,0,0,0}; - static GLRGBAFloat fade = {0,0,0,0}; + if (PolyFlags & PF_ForceWrapY) + Clamp2D(GL_TEXTURE_WRAP_T); +} - SetBlend(PolyFlags); //TODO: inline (#pragma..) +EXPORT void HWRAPI(DrawIndexedTriangles) (FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPts, FBITFIELD PolyFlags, unsigned int *IndexArray) +{ + PreparePolygon(pSurf, pOutVerts, PolyFlags); - if (gl_portal_mode == HWD_PORTAL_NORMAL) - { - // PolyColor - if (pSurf) - { - // If modulated, mix the surface colour to the texture - if (CurrentPolyFlags & PF_Modulated) - pglColor4ubv((GLubyte*)&pSurf->PolyColor.s); + pglVertexPointer(3, GL_FLOAT, sizeof(FOutVector), &pOutVerts[0].x); + pglTexCoordPointer(2, GL_FLOAT, sizeof(FOutVector), &pOutVerts[0].s); + pglDrawElements(GL_TRIANGLES, iNumPts, GL_UNSIGNED_INT, IndexArray); - // If the surface is either modulated or colormapped, or both - if (CurrentPolyFlags & (PF_Modulated | PF_ColorMapped)) - { - poly.red = byte2float[pSurf->PolyColor.s.red]; - poly.green = byte2float[pSurf->PolyColor.s.green]; - poly.blue = byte2float[pSurf->PolyColor.s.blue]; - poly.alpha = byte2float[pSurf->PolyColor.s.alpha]; - } - - // Only if the surface is colormapped - if (CurrentPolyFlags & PF_ColorMapped) - { - tint.red = byte2float[pSurf->TintColor.s.red]; - tint.green = byte2float[pSurf->TintColor.s.green]; - tint.blue = byte2float[pSurf->TintColor.s.blue]; - tint.alpha = byte2float[pSurf->TintColor.s.alpha]; - - fade.red = byte2float[pSurf->FadeColor.s.red]; - fade.green = byte2float[pSurf->FadeColor.s.green]; - fade.blue = byte2float[pSurf->FadeColor.s.blue]; - fade.alpha = byte2float[pSurf->FadeColor.s.alpha]; - } - - if (gl_palshader && gl_allowshaders) - { - pglActiveTexture(GL_TEXTURE2); - pglBindTexture(GL_TEXTURE_2D, pSurf->LightTableId); - pglActiveTexture(GL_TEXTURE0); - } - } - - Shader_Load(pSurf, &poly, &tint, &fade); - } - else - UnSetShader(); - - pglVertexPointer(3, GL_FLOAT, sizeof(FOutVector), &pOutVerts[0].x); - pglTexCoordPointer(2, GL_FLOAT, sizeof(FOutVector), &pOutVerts[0].s); - pglDrawArrays(GL_TRIANGLE_FAN, 0, iNumPts); - - if (PolyFlags & PF_RemoveYWrap) - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); - - if (PolyFlags & PF_ForceWrapX) - Clamp2D(GL_TEXTURE_WRAP_S); - - if (PolyFlags & PF_ForceWrapY) - Clamp2D(GL_TEXTURE_WRAP_T); - } + // the DrawPolygon variant of this has some code about polyflags and wrapping here but havent noticed any problems from omitting it? } // Sky dome code, taken/backported from SRB2 diff --git a/src/sdl/hwsym_sdl.c b/src/sdl/hwsym_sdl.c index 96b7b0679..181866443 100644 --- a/src/sdl/hwsym_sdl.c +++ b/src/sdl/hwsym_sdl.c @@ -81,6 +81,7 @@ void *hwSym(const char *funcName,void *handle) GETFUNC(SetupGLInfo); GETFUNC(Draw2DLine); GETFUNC(DrawPolygon); + GETFUNC(DrawIndexedTriangles); GETFUNC(SetBlend); GETFUNC(ClearBuffer); GETFUNC(SetTexture); @@ -114,10 +115,7 @@ void *hwSym(const char *funcName,void *handle) GETFUNC(SetShaderInfo); GETFUNC(LoadCustomShader); GETFUNC(InitCustomShaders); - - GETFUNC(StartBatching); - GETFUNC(RenderBatches); - + GETFUNC(InitPalette); GETFUNC(AddLightTable); GETFUNC(ClearLightTableCache); diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c index dd2953716..9011c333d 100644 --- a/src/sdl/i_video.c +++ b/src/sdl/i_video.c @@ -2113,6 +2113,7 @@ void I_StartupGraphics(void) HWD.pfnFinishUpdate = NULL; HWD.pfnDraw2DLine = hwSym("Draw2DLine",NULL); HWD.pfnDrawPolygon = hwSym("DrawPolygon",NULL); + HWD.pfnDrawIndexedTriangles = hwSym("DrawIndexedTriangles",NULL); HWD.pfnSetBlend = hwSym("SetBlend",NULL); HWD.pfnClearBuffer = hwSym("ClearBuffer",NULL); HWD.pfnSetTexture = hwSym("SetTexture",NULL); @@ -2148,9 +2149,6 @@ void I_StartupGraphics(void) HWD.pfnLoadCustomShader = hwSym("LoadCustomShader",NULL); HWD.pfnInitCustomShaders = hwSym("InitCustomShaders",NULL); - HWD.pfnStartBatching = hwSym("StartBatching",NULL); - HWD.pfnRenderBatches = hwSym("RenderBatches",NULL); - HWD.pfnInitPalette = hwSym("InitPalette",NULL); HWD.pfnAddLightTable = hwSym("AddLightTable",NULL); HWD.pfnClearLightTableCache = hwSym("ClearLightTableCache",NULL); -- 2.54.0 From 08e5b4844e00590e5718ef4770c02ce821baeca3 Mon Sep 17 00:00:00 2001 From: Alug Date: Mon, 15 Jan 2024 13:59:43 +0100 Subject: [PATCH 2/8] fix palshader --- src/hardware/r_opengl/r_opengl.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c index 681c42005..5a3ea3360 100644 --- a/src/hardware/r_opengl/r_opengl.c +++ b/src/hardware/r_opengl/r_opengl.c @@ -2397,6 +2397,13 @@ static void PreparePolygon(FSurfaceInfo *pSurf, FOutVector *pOutVerts, FBITFIELD fade.green = byte2float[pSurf->FadeColor.s.green]; fade.blue = byte2float[pSurf->FadeColor.s.blue]; fade.alpha = byte2float[pSurf->FadeColor.s.alpha]; + + if (HWR_ShouldUsePaletteRendering && gl_allowshaders) + { + pglActiveTexture(GL_TEXTURE2); + pglBindTexture(GL_TEXTURE_2D, pSurf->LightTableId); + pglActiveTexture(GL_TEXTURE0); + } } Shader_Load(pSurf, &poly, &tint, &fade); -- 2.54.0 From 35e8d54fc4ba74c7e4b3440e6afb16fd04e479cc Mon Sep 17 00:00:00 2001 From: Alug Date: Mon, 15 Jan 2024 14:21:38 +0100 Subject: [PATCH 3/8] oopsie --- src/hardware/r_opengl/r_opengl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c index 5a3ea3360..418967bf3 100644 --- a/src/hardware/r_opengl/r_opengl.c +++ b/src/hardware/r_opengl/r_opengl.c @@ -2398,7 +2398,7 @@ static void PreparePolygon(FSurfaceInfo *pSurf, FOutVector *pOutVerts, FBITFIELD fade.blue = byte2float[pSurf->FadeColor.s.blue]; fade.alpha = byte2float[pSurf->FadeColor.s.alpha]; - if (HWR_ShouldUsePaletteRendering && gl_allowshaders) + if (HWR_ShouldUsePaletteRendering() && gl_allowshaders) { pglActiveTexture(GL_TEXTURE2); pglBindTexture(GL_TEXTURE_2D, pSurf->LightTableId); -- 2.54.0 From 5e0fe497f516808fe4e928f0263db56ba3e6faba Mon Sep 17 00:00:00 2001 From: Alug Date: Mon, 15 Jan 2024 14:27:01 +0100 Subject: [PATCH 4/8] add stuff here too --- src/CMakeLists.txt | 2 ++ src/sdl/Srb2SDL-vc10.vcxproj | 2 ++ src/sdl/Srb2SDL-vc10.vcxproj.filters | 6 ++++++ 3 files changed, 10 insertions(+) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 8f6a56235..d2985dc21 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -452,6 +452,7 @@ endif() if(${SRB2_CONFIG_HWRENDER}) add_definitions(-DHWRENDER) set(SRB2_HWRENDER_SOURCES + ${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_batching.c ${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_bsp.c ${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_cache.c ${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_clip.c @@ -467,6 +468,7 @@ if(${SRB2_CONFIG_HWRENDER}) ) set (SRB2_HWRENDER_HEADERS + ${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_batching.h ${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_clip.h ${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_data.h ${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_defs.h diff --git a/src/sdl/Srb2SDL-vc10.vcxproj b/src/sdl/Srb2SDL-vc10.vcxproj index 813e31a98..e51799314 100644 --- a/src/sdl/Srb2SDL-vc10.vcxproj +++ b/src/sdl/Srb2SDL-vc10.vcxproj @@ -218,6 +218,7 @@ + @@ -364,6 +365,7 @@ + diff --git a/src/sdl/Srb2SDL-vc10.vcxproj.filters b/src/sdl/Srb2SDL-vc10.vcxproj.filters index f197a394b..2234d7620 100644 --- a/src/sdl/Srb2SDL-vc10.vcxproj.filters +++ b/src/sdl/Srb2SDL-vc10.vcxproj.filters @@ -215,6 +215,9 @@ Hw_Hardware + + + Hw_Hardware Hw_Hardware @@ -617,6 +620,9 @@ Hw_Hardware + + + Hw_Hardware Hw_Hardware -- 2.54.0 From 3eb8886890076baad71917f1b6d3dd3299abe3de Mon Sep 17 00:00:00 2001 From: Alug Date: Mon, 15 Jan 2024 15:10:02 +0100 Subject: [PATCH 5/8] remove Shader_Load as Shader_SetUniforms literally did the same thing --- src/hardware/r_opengl/r_opengl.c | 59 ++++++++++++++------------------ 1 file changed, 25 insertions(+), 34 deletions(-) diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c index 418967bf3..5f03a2995 100644 --- a/src/hardware/r_opengl/r_opengl.c +++ b/src/hardware/r_opengl/r_opengl.c @@ -128,9 +128,10 @@ static GLuint endScreenWipe = 0; static GLuint finalScreenTexture = 0; // Lactozilla: Set shader programs and uniforms -static void *Shader_Load(FSurfaceInfo *Surface, GLRGBAFloat *poly, GLRGBAFloat *tint, GLRGBAFloat *fade); static void Shader_SetUniforms(FSurfaceInfo *Surface, GLRGBAFloat *poly, GLRGBAFloat *tint, GLRGBAFloat *fade); +static GLRGBAFloat shader_defaultcolor = {1.0f, 1.0f, 1.0f, 1.0f}; + // shortcut for ((float)1/i) static const GLfloat byte2float[256] = { 0.000000f, 0.003922f, 0.007843f, 0.011765f, 0.015686f, 0.019608f, 0.023529f, 0.027451f, @@ -2282,43 +2283,33 @@ EXPORT void HWRAPI(SetTexture) (FTextureInfo *pTexInfo) } } - -static void *Shader_Load(FSurfaceInfo *Surface, GLRGBAFloat *poly, GLRGBAFloat *tint, GLRGBAFloat *fade) -{ -#ifdef GL_SHADERS - if (gl_shadersenabled && pglUseProgram) - { - gl_shaderprogram_t *shader = &gl_shaderprograms[gl_currentshaderprogram]; - if (shader->program) - { - if (gl_shaderprogramchanged) - { - pglUseProgram(gl_shaderprograms[gl_currentshaderprogram].program); - gl_shaderprogramchanged = false; - } - Shader_SetUniforms(Surface, poly, tint, fade); - return shader; - } - else - pglUseProgram(0); - } -#else - (void)Surface; - (void)poly; - (void)tint; - (void)fade; -#endif - return NULL; -} - static void Shader_SetUniforms(FSurfaceInfo *Surface, GLRGBAFloat *poly, GLRGBAFloat *tint, GLRGBAFloat *fade) { + gl_shaderprogram_t *shader = &gl_shaderprograms[gl_currentshaderprogram]; + #ifdef GL_SHADERS - if (gl_shadersenabled) + if (gl_shadersenabled && (shader != NULL) && pglUseProgram) { - gl_shaderprogram_t *shader = &gl_shaderprograms[gl_currentshaderprogram]; + if (!shader->program) + { + pglUseProgram(0); return; + } + + if (gl_shaderprogramchanged) + { + pglUseProgram(gl_shaderprograms[gl_currentshaderprogram].program); + gl_shaderprogramchanged = false; + } + + // Color uniforms can be left NULL and will be set to white (1.0f, 1.0f, 1.0f, 1.0f) + if (poly == NULL) + poly = &shader_defaultcolor; + if (tint == NULL) + tint = &shader_defaultcolor; + if (fade == NULL) + fade = &shader_defaultcolor; #define UNIFORM_1(uniform, a, function) \ if (uniform != -1) \ @@ -2406,7 +2397,7 @@ static void PreparePolygon(FSurfaceInfo *pSurf, FOutVector *pOutVerts, FBITFIELD } } - Shader_Load(pSurf, &poly, &tint, &fade); + Shader_SetUniforms(pSurf, &poly, &tint, &fade); } // -----------------+ @@ -3182,7 +3173,7 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, float duration, float fade.blue = byte2float[Surface->FadeColor.s.blue]; fade.alpha = byte2float[Surface->FadeColor.s.alpha]; - Shader_Load(Surface, &poly, &tint, &fade); + Shader_SetUniforms(Surface, &poly, &tint, &fade); pglEnable(GL_CULL_FACE); pglEnable(GL_NORMALIZE); -- 2.54.0 From d071f52707bc1194fa7a611194e0f72b6aa33218 Mon Sep 17 00:00:00 2001 From: Alug Date: Wed, 17 Jan 2024 18:15:54 +0100 Subject: [PATCH 6/8] fix typo --- src/hardware/hw_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index bf733b637..56b72eae7 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -1030,7 +1030,7 @@ static void HWR_DrawSegsSplats(FSurfaceInfo * pSurf) shader = (HWR_ShouldUsePaletteRendering() ? 10 : 2); // wall shader } - HWD.HWR_ProcessPolygon(&pSurf, wallVerts, 4, i|PF_Modulated|PF_Decal, shader, false); + HWR_ProcessPolygon(&pSurf, wallVerts, 4, i|PF_Modulated|PF_Decal, shader, false); } } #endif -- 2.54.0 From 3dcf4f6f6472b76fe8cd124c52ee5c35c3bac8e4 Mon Sep 17 00:00:00 2001 From: Alug Date: Wed, 17 Jan 2024 18:31:36 +0100 Subject: [PATCH 7/8] Refactor Batching code from Hannu Hanhi https://git.do.srb2.org/STJr/SRB2/-/commit/707687beea50a2bfcc14638e923ac516195351b1?merge_request_iid=1774 --- src/hardware/hw_batching.c | 569 ++++++++++++++++++------------------- src/hardware/hw_batching.h | 12 - 2 files changed, 275 insertions(+), 306 deletions(-) diff --git a/src/hardware/hw_batching.c b/src/hardware/hw_batching.c index b56278c7d..bbb228367 100644 --- a/src/hardware/hw_batching.c +++ b/src/hardware/hw_batching.c @@ -15,29 +15,54 @@ #include "hw_main.h" #include "../i_system.h" +typedef struct +{ + FSurfaceInfo surf; // surf also has its own polyflags for some reason, but it seems unused + unsigned int vertsIndex; // location of verts in unsortedVertices + FUINT numVerts; + FBITFIELD polyFlags; + GLMipmap_t *texture; + int shader; + // this tells batching that the plane belongs to a horizon line and must be drawn in correct order with the skywalls + boolean horizonSpecial; +} DrawCallInfo; + // The texture for the next polygon given to HWR_ProcessPolygon. // Set with HWR_SetCurrentTexture. GLMipmap_t *current_texture = NULL; boolean currently_batching = false; -FOutVector* finalVertexArray = NULL;// contains subset of sorted vertices and texture coordinates to be sent to gpu -UINT32* finalVertexIndexArray = NULL;// contains indexes for glDrawElements, taking into account fan->triangles conversion -// NOTE have this alloced as 3x finalVertexArray size -int finalVertexArrayAllocSize = 65536; -//GLubyte* colorArray = NULL;// contains color data to be sent to gpu, if needed -//int colorArrayAllocSize = 65536; -// not gonna use this for now, just sort by color and change state when it changes -// later maybe when using vertex attributes if it's needed +// Dynamic arrays for: +// - unsorted draw calls +// - sorted order of draw calls +// - unsorted vertices +// - final (sorted) vertices +// - vertex indices for sorted vertices -PolygonArrayEntry* polygonArray = NULL;// contains the polygon data from DrawPolygon, waiting to be processed -int polygonArraySize = 0; -UINT32* polygonIndexArray = NULL;// contains sorting pointers for polygonArray -int polygonArrayAllocSize = 65536; +// contains the draw calls from DrawPolygon, waiting to be processed +DrawCallInfo* drawCalls = NULL; +int drawCallsSize = 0; +int drawCallsCapacity = 65536; -FOutVector* unsortedVertexArray = NULL;// contains unsorted vertices and texture coordinates from DrawPolygon -int unsortedVertexArraySize = 0; -int unsortedVertexArrayAllocSize = 65536; +// contains sorted order (array indices) for drawCalls +// (therefore size and capacity shared with it) +UINT32* drawCallOrder = NULL; + +// contains unsorted vertices and texture coordinates from DrawPolygon +FOutVector* unsortedVertices = NULL; +int unsortedVerticesSize = 0; +int unsortedVerticesCapacity = 65536; + +// contains subset of sorted vertices and texture coordinates to be sent to gpu +FOutVector* finalVertices = NULL; +int finalVerticesSize = 0; +int finalVerticesCapacity = 65536; + +// contains vertex indices into finalVertices for glDrawElements, +// taking into account fan->triangles conversion +UINT32* finalIndices = NULL; // this is alloced with 3x finalVertices size +int finalIndicesSize = 0; // Enables batching mode. HWR_ProcessPolygon will collect polygons instead of passing them directly to the rendering backend. // Call HWR_RenderBatches to render all the collected geometry. @@ -47,13 +72,13 @@ void HWR_StartBatching(void) I_Error("Repeat call to HWR_StartBatching without HWR_RenderBatches"); // init arrays if that has not been done yet - if (!finalVertexArray) + if (!finalVertices) { - finalVertexArray = malloc(finalVertexArrayAllocSize * sizeof(FOutVector)); - finalVertexIndexArray = malloc(finalVertexArrayAllocSize * 3 * sizeof(UINT32)); - polygonArray = malloc(polygonArrayAllocSize * sizeof(PolygonArrayEntry)); - polygonIndexArray = malloc(polygonArrayAllocSize * sizeof(UINT32)); - unsortedVertexArray = malloc(unsortedVertexArrayAllocSize * sizeof(FOutVector)); + finalVertices = malloc(finalVerticesCapacity * sizeof(FOutVector)); + finalIndices = malloc(finalVerticesCapacity * 3 * sizeof(UINT32)); + drawCalls = malloc(drawCallsCapacity * sizeof(DrawCallInfo)); + drawCallOrder = malloc(drawCallsCapacity * sizeof(UINT32)); + unsortedVertices = malloc(unsortedVerticesCapacity * sizeof(FOutVector)); } currently_batching = true; @@ -64,14 +89,55 @@ void HWR_StartBatching(void) // Doing this was easier than getting a texture pointer to HWR_ProcessPolygon. void HWR_SetCurrentTexture(GLMipmap_t *texture) { - if (currently_batching) - { - current_texture = texture; - } - else - { - HWD.pfnSetTexture(texture); - } + if (currently_batching) + current_texture = texture; + else + HWD.pfnSetTexture(texture); +} + +static void HWR_CollectDrawCallInfo(FSurfaceInfo *pSurf, FUINT iNumPts, FBITFIELD PolyFlags, int shader, boolean horizonSpecial) +{ + // make sure dynamic array has capacity + if (drawCallsSize == drawCallsCapacity) + { + DrawCallInfo* new_array; + // ran out of space, make new array double the size + drawCallsCapacity *= 2; + new_array = malloc(drawCallsCapacity * sizeof(DrawCallInfo)); + memcpy(new_array, drawCalls, drawCallsSize * sizeof(DrawCallInfo)); + free(drawCalls); + drawCalls = new_array; + // also need to redo the index array, dont need to copy it though + free(drawCallOrder); + drawCallOrder = malloc(drawCallsCapacity * sizeof(UINT32)); + } + // add entry to array + drawCalls[drawCallsSize].surf = *pSurf; + drawCalls[drawCallsSize].vertsIndex = unsortedVerticesSize; + drawCalls[drawCallsSize].numVerts = iNumPts; + drawCalls[drawCallsSize].polyFlags = PolyFlags; + drawCalls[drawCallsSize].texture = current_texture; + drawCalls[drawCallsSize].shader = shader; + drawCalls[drawCallsSize].horizonSpecial = horizonSpecial; + drawCallsSize++; +} + +static void HWR_CollectDrawCallVertices(FOutVector *pOutVerts, FUINT iNumPts) +{ + // make sure dynamic array has capacity + while (unsortedVerticesSize + (int)iNumPts > unsortedVerticesCapacity) + { + FOutVector* new_array; + // need more space for vertices in unsortedVertices + unsortedVerticesCapacity *= 2; + new_array = malloc(unsortedVerticesCapacity * sizeof(FOutVector)); + memcpy(new_array, unsortedVertices, unsortedVerticesSize * sizeof(FOutVector)); + free(unsortedVertices); + unsortedVertices = new_array; + } + // add vertices to array + memcpy(&unsortedVertices[unsortedVerticesSize], pOutVerts, iNumPts * sizeof(FOutVector)); + unsortedVerticesSize += iNumPts; } // If batching is enabled, this function collects the polygon data and the chosen texture @@ -79,48 +145,16 @@ void HWR_SetCurrentTexture(GLMipmap_t *texture) // render the polygon immediately. void HWR_ProcessPolygon(FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPts, FBITFIELD PolyFlags, int shader, boolean horizonSpecial) { - if (currently_batching) + if (currently_batching) { if (!pSurf) - I_Error("Got a null FSurfaceInfo in batching");// nulls should not come in the stuff that batching currently applies to - if (polygonArraySize == polygonArrayAllocSize) { - PolygonArrayEntry* new_array; - // ran out of space, make new array double the size - polygonArrayAllocSize *= 2; - new_array = malloc(polygonArrayAllocSize * sizeof(PolygonArrayEntry)); - memcpy(new_array, polygonArray, polygonArraySize * sizeof(PolygonArrayEntry)); - free(polygonArray); - polygonArray = new_array; - // also need to redo the index array, dont need to copy it though - free(polygonIndexArray); - polygonIndexArray = malloc(polygonArrayAllocSize * sizeof(UINT32)); + // handling null FSurfaceInfo is not implemented + I_Error("Got a null FSurfaceInfo in batching"); } - while (unsortedVertexArraySize + (int)iNumPts > unsortedVertexArrayAllocSize) - { - FOutVector* new_array; - // need more space for vertices in unsortedVertexArray - unsortedVertexArrayAllocSize *= 2; - new_array = malloc(unsortedVertexArrayAllocSize * sizeof(FOutVector)); - memcpy(new_array, unsortedVertexArray, unsortedVertexArraySize * sizeof(FOutVector)); - free(unsortedVertexArray); - unsortedVertexArray = new_array; - } - - // add the polygon data to the arrays - - polygonArray[polygonArraySize].surf = *pSurf; - polygonArray[polygonArraySize].vertsIndex = unsortedVertexArraySize; - polygonArray[polygonArraySize].numVerts = iNumPts; - polygonArray[polygonArraySize].polyFlags = PolyFlags; - polygonArray[polygonArraySize].texture = current_texture; - polygonArray[polygonArraySize].shader = shader; - polygonArray[polygonArraySize].horizonSpecial = horizonSpecial; - polygonArraySize++; - - memcpy(&unsortedVertexArray[unsortedVertexArraySize], pOutVerts, iNumPts * sizeof(FOutVector)); - unsortedVertexArraySize += iNumPts; + HWR_CollectDrawCallInfo(pSurf, iNumPts, PolyFlags, shader, horizonSpecial); + HWR_CollectDrawCallVertices(pOutVerts, iNumPts); } else { @@ -130,12 +164,12 @@ void HWR_ProcessPolygon(FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPt } } -static int comparePolygons(const void *p1, const void *p2) +static int compareDrawCalls(const void *p1, const void *p2) { - unsigned int index1 = *(const unsigned int*)p1; - unsigned int index2 = *(const unsigned int*)p2; - PolygonArrayEntry* poly1 = &polygonArray[index1]; - PolygonArrayEntry* poly2 = &polygonArray[index2]; + UINT32 index1 = *(const UINT32*)p1; + UINT32 index2 = *(const UINT32*)p2; + DrawCallInfo* poly1 = &drawCalls[index1]; + DrawCallInfo* poly2 = &drawCalls[index2]; int diff; INT64 diff64; UINT32 downloaded1 = 0; @@ -186,12 +220,12 @@ static int comparePolygons(const void *p1, const void *p2) return diff; } -static int comparePolygonsNoShaders(const void *p1, const void *p2) +static int compareDrawCallsNoShaders(const void *p1, const void *p2) { - unsigned int index1 = *(const unsigned int*)p1; - unsigned int index2 = *(const unsigned int*)p2; - PolygonArrayEntry* poly1 = &polygonArray[index1]; - PolygonArrayEntry* poly2 = &polygonArray[index2]; + UINT32 index1 = *(const UINT32*)p1; + UINT32 index2 = *(const UINT32*)p2; + DrawCallInfo* poly1 = &drawCalls[index1]; + DrawCallInfo* poly2 = &drawCalls[index2]; int diff; INT64 diff64; @@ -222,60 +256,155 @@ static int comparePolygonsNoShaders(const void *p1, const void *p2) return 0; } -// This function organizes the geometry collected by HWR_ProcessPolygon calls into batches and uses -// the rendering backend to draw them. +static void HWR_CollectVerticesIntoBatch(DrawCallInfo *drawCall) +{ + int firstVIndex; + int lastVIndex; + int numVerts = drawCall->numVerts; + // before writing, check if there is enough room + // using 'while' instead of 'if' here makes sure that there will *always* be enough room. + // probably never will this loop run more than once though + while (finalVerticesSize + numVerts > finalVerticesCapacity) + { + FOutVector* new_array; + UINT32* new_index_array; + finalVerticesCapacity *= 2; + new_array = malloc(finalVerticesCapacity * sizeof(FOutVector)); + memcpy(new_array, finalVertices, finalVerticesSize * sizeof(FOutVector)); + free(finalVertices); + finalVertices = new_array; + // also increase size of index array, 3x of vertex array since + // going from fans to triangles increases vertex count to 3x + new_index_array = malloc(finalVerticesCapacity * 3 * sizeof(UINT32)); + memcpy(new_index_array, finalIndices, finalIndicesSize * sizeof(UINT32)); + free(finalIndices); + finalIndices = new_index_array; + } + // write the vertices of the polygon + memcpy(&finalVertices[finalVerticesSize], &unsortedVertices[drawCall->vertsIndex], + numVerts * sizeof(FOutVector)); + // write the indexes, pointing to the fan vertexes but in triangles format + firstVIndex = finalVerticesSize; + lastVIndex = finalVerticesSize + numVerts; + finalVerticesSize += 2; + while (finalVerticesSize < lastVIndex) + { + finalIndices[finalIndicesSize++] = firstVIndex; + finalIndices[finalIndicesSize++] = finalVerticesSize - 1; + finalIndices[finalIndicesSize++] = finalVerticesSize++; + } +} + +static GLMipmap_t *HWR_GetDrawCallTexture(DrawCallInfo *dc) +{ + return (dc->polyFlags & PF_NoTexture) ? NULL : dc->texture; +} + +// flags returned by HWR_MarkStateChanges +#define SHADER_CHANGED 1 +#define TEXTURE_CHANGED 2 +#define POLYFLAGS_CHANGED 4 +#define SURFACEINFO_CHANGED 8 + +static unsigned int HWR_MarkStateChanges(DrawCallInfo *current, DrawCallInfo *next) +{ + unsigned int stateChanges = 0; + FSurfaceInfo *currentSI = ¤t->surf; + FSurfaceInfo *nextSI = &next->surf; + + // check if a state change is required and flag it to stateChanges + + if (current->shader != next->shader && cv_grshaders.value && gr_shadersavailable) + stateChanges |= SHADER_CHANGED; + if (HWR_GetDrawCallTexture(current) != HWR_GetDrawCallTexture(next)) + stateChanges |= TEXTURE_CHANGED; + if (current->polyFlags != next->polyFlags) + stateChanges |= POLYFLAGS_CHANGED; + if (cv_grshaders.value && gr_shadersavailable) + { + if (currentSI->PolyColor.rgba != nextSI->PolyColor.rgba || + currentSI->TintColor.rgba != nextSI->TintColor.rgba || + currentSI->FadeColor.rgba != nextSI->FadeColor.rgba || + currentSI->LightInfo.light_level != nextSI->LightInfo.light_level || + currentSI->LightInfo.fade_start != nextSI->LightInfo.fade_start || + currentSI->LightInfo.fade_end != nextSI->LightInfo.fade_end) + { + stateChanges |= SURFACEINFO_CHANGED; + } + } + else + { + if (currentSI->PolyColor.rgba != nextSI->PolyColor.rgba) + stateChanges |= SURFACEINFO_CHANGED; + } + + return stateChanges; +} + +static void HWR_ExecuteStateChanges(unsigned int stateChanges, DrawCallInfo *dc) +{ + if ((stateChanges & SHADER_CHANGED) && cv_grshaders.value && gr_shadersavailable) + { + HWD.pfnSetShader(dc->shader); + ps_hw_numshaders.value.i++; + } + if (stateChanges & TEXTURE_CHANGED) + { + // for PF_NoTexture the texture is set in DrawIndexedTriangles + if (!(dc->polyFlags & PF_NoTexture)) + { + // texture should be already ready for use from calls to + // SetTexture during batch collection + HWD.pfnSetTexture(dc->texture); + } + ps_hw_numtextures.value.i++; + } + // these two are just parameters to DrawIndexedTriangles + // (changes to polyflags states are tracked in r_opengl.c though) + if (stateChanges & POLYFLAGS_CHANGED) + ps_hw_numpolyflags.value.i++; + if (stateChanges & SURFACEINFO_CHANGED) + ps_hw_numcolors.value.i++; +} + + +static void HWR_InitBatchingStats(void) +{ + ps_hw_numpolys.value.i = drawCallsSize; + ps_hw_numcalls.value.i = ps_hw_numverts.value.i + = ps_hw_numshaders.value.i = ps_hw_numtextures.value.i + = ps_hw_numpolyflags.value.i = ps_hw_numcolors.value.i = 0; +} + +// This function organizes the geometry and draw calls collected by HWR_ProcessPolygon +// calls into batches and uses the rendering backend to draw them. void HWR_RenderBatches(void) { - int finalVertexWritePos = 0;// position in finalVertexArray - int finalIndexWritePos = 0;// position in finalVertexIndexArray - - int polygonReadPos = 0;// position in polygonIndexArray - - int currentShader; - int nextShader = 0; - GLMipmap_t *currentTexture; - GLMipmap_t *nextTexture = NULL; - FBITFIELD currentPolyFlags = 0; - FBITFIELD nextPolyFlags = 0; - FSurfaceInfo currentSurfaceInfo; - FSurfaceInfo nextSurfaceInfo; - + int drawCallReadPos = 0; // position in drawCallOrder int i; - if (!currently_batching) + if (!currently_batching) I_Error("HWR_RenderBatches called without starting batching"); - nextSurfaceInfo.LightInfo.fade_end = 0; - nextSurfaceInfo.LightInfo.fade_start = 0; - nextSurfaceInfo.LightInfo.light_level = 0; + currently_batching = false; // no longer collecting batches - currently_batching = false;// no longer collecting batches - if (!polygonArraySize) - { - ps_hw_numpolys.value.i = ps_hw_numcalls.value.i = ps_hw_numshaders.value.i - = ps_hw_numtextures.value.i = ps_hw_numpolyflags.value.i - = ps_hw_numcolors.value.i = 0; - return;// nothing to draw - } - // init stats vars - ps_hw_numpolys.value.i = polygonArraySize; - ps_hw_numcalls.value.i = ps_hw_numverts.value.i = 0; - ps_hw_numshaders.value.i = ps_hw_numtextures.value.i - = ps_hw_numpolyflags.value.i = ps_hw_numcolors.value.i = 1; - // init polygonIndexArray - for (i = 0; i < polygonArraySize; i++) - { - polygonIndexArray[i] = i; - } + HWR_InitBatchingStats(); - // sort polygons + if (!drawCallsSize) + return; // nothing to draw + + // init drawCallOrder + for (i = 0; i < drawCallsSize; i++) + drawCallOrder[i] = i; + + // sort the draw calls PS_START_TIMING(ps_hw_batchsorttime); if (cv_grshaders.value && gr_shadersavailable) - qsort(polygonIndexArray, polygonArraySize, sizeof(unsigned int), comparePolygons); + qsort(drawCallOrder, drawCallsSize, sizeof(UINT32), compareDrawCalls); else - qsort(polygonIndexArray, polygonArraySize, sizeof(unsigned int), comparePolygonsNoShaders); + qsort(drawCallOrder, drawCallsSize, sizeof(UINT32), compareDrawCallsNoShaders); PS_STOP_TIMING(ps_hw_batchsorttime); - // sort order + // sort grouping order // 1. shader // 2. texture // 3. polyflags @@ -284,205 +413,57 @@ void HWR_RenderBatches(void) PS_START_TIMING(ps_hw_batchdrawtime); - currentShader = polygonArray[polygonIndexArray[0]].shader; - currentTexture = polygonArray[polygonIndexArray[0]].texture; - currentPolyFlags = polygonArray[polygonIndexArray[0]].polyFlags; - currentSurfaceInfo = polygonArray[polygonIndexArray[0]].surf; - // For now, will sort and track the colors. Vertex attributes could be used instead of uniforms - // and a color array could replace the color calls. - // set state for first batch + HWR_ExecuteStateChanges(0xFFFF, &drawCalls[drawCallOrder[0]]); - if (cv_grshaders.value && gr_shadersavailable) + // - iterate through draw calls + // - accumulate converted vertices and indices into finalVertices and finalIndices + // and send them as a combined draw call when a state change occurs + while (1) { - HWD.pfnSetShader(currentShader); - } - - if (currentPolyFlags & PF_NoTexture) - currentTexture = NULL; - else - HWD.pfnSetTexture(currentTexture); - - while (1)// note: remember handling notexture polyflag as having texture number 0 (also in comparePolygons) - { - int firstIndex; - int lastIndex; - boolean stopFlag = false; - boolean changeState = false; - boolean changeShader = false; - boolean changeTexture = false; - boolean changePolyFlags = false; - boolean changeSurfaceInfo = false; + unsigned int stateChanges = 0; // flags defined above HWR_MarkStateChanges + DrawCallInfo *currentDrawCall = &drawCalls[drawCallOrder[drawCallReadPos++]]; + DrawCallInfo *nextDrawCall = NULL; - // steps: - // write vertices - // check for changes or end, otherwise go back to writing - // changes will affect the next vars and the change bools - // end could set flag for stopping - // execute draw call - // could check ending flag here - // change states according to next vars and change bools, updating the current vars and reseting the bools - // reset write pos - // repeat loop + HWR_CollectVerticesIntoBatch(currentDrawCall); - int index = polygonIndexArray[polygonReadPos++]; - int numVerts = polygonArray[index].numVerts; - // before writing, check if there is enough room - // using 'while' instead of 'if' here makes sure that there will *always* be enough room. - // probably never will this loop run more than once though - while (finalVertexWritePos + numVerts > finalVertexArrayAllocSize) - { - FOutVector* new_array; - unsigned int* new_index_array; - finalVertexArrayAllocSize *= 2; - new_array = malloc(finalVertexArrayAllocSize * sizeof(FOutVector)); - memcpy(new_array, finalVertexArray, finalVertexWritePos * sizeof(FOutVector)); - free(finalVertexArray); - finalVertexArray = new_array; - // also increase size of index array, 3x of vertex array since - // going from fans to triangles increases vertex count to 3x - new_index_array = malloc(finalVertexArrayAllocSize * 3 * sizeof(UINT32)); - memcpy(new_index_array, finalVertexIndexArray, finalIndexWritePos * sizeof(UINT32)); - free(finalVertexIndexArray); - finalVertexIndexArray = new_index_array; - } - // write the vertices of the polygon - memcpy(&finalVertexArray[finalVertexWritePos], &unsortedVertexArray[polygonArray[index].vertsIndex], - numVerts * sizeof(FOutVector)); - // write the indexes, pointing to the fan vertexes but in triangles format - firstIndex = finalVertexWritePos; - lastIndex = finalVertexWritePos + numVerts; - finalVertexWritePos += 2; - while (finalVertexWritePos < lastIndex) - { - finalVertexIndexArray[finalIndexWritePos++] = firstIndex; - finalVertexIndexArray[finalIndexWritePos++] = finalVertexWritePos - 1; - finalVertexIndexArray[finalIndexWritePos++] = finalVertexWritePos++; - } - - if (polygonReadPos >= polygonArraySize) + if (drawCallReadPos >= drawCallsSize) // was that the last draw call? { stopFlag = true; } else { - // check if a state change is required, set the change bools and next vars - int nextIndex = polygonIndexArray[polygonReadPos]; - nextShader = polygonArray[nextIndex].shader; - nextTexture = polygonArray[nextIndex].texture; - nextPolyFlags = polygonArray[nextIndex].polyFlags; - nextSurfaceInfo = polygonArray[nextIndex].surf; - if (nextPolyFlags & PF_NoTexture) - nextTexture = 0; - if (currentShader != nextShader && cv_grshaders.value && gr_shadersavailable) - { - changeState = true; - changeShader = true; - } - if (currentTexture != nextTexture) - { - changeState = true; - changeTexture = true; - } - if (currentPolyFlags != nextPolyFlags) - { - changeState = true; - changePolyFlags = true; - } - if ((cv_grshaders.value && gr_shadersavailable) && (HWR_ShouldUsePaletteRendering())) - { - if (currentSurfaceInfo.PolyColor.rgba != nextSurfaceInfo.PolyColor.rgba || - currentSurfaceInfo.TintColor.rgba != nextSurfaceInfo.TintColor.rgba || - currentSurfaceInfo.FadeColor.rgba != nextSurfaceInfo.FadeColor.rgba || - currentSurfaceInfo.LightInfo.light_level != nextSurfaceInfo.LightInfo.light_level || - currentSurfaceInfo.LightInfo.fade_start != nextSurfaceInfo.LightInfo.fade_start || - currentSurfaceInfo.LightInfo.fade_end != nextSurfaceInfo.LightInfo.fade_end || - currentSurfaceInfo.LightTableId != nextSurfaceInfo.LightTableId) - { - changeState = true; - changeSurfaceInfo = true; - } - } - else if (cv_grshaders.value && gr_shadersavailable) - { - if (currentSurfaceInfo.PolyColor.rgba != nextSurfaceInfo.PolyColor.rgba || - currentSurfaceInfo.TintColor.rgba != nextSurfaceInfo.TintColor.rgba || - currentSurfaceInfo.FadeColor.rgba != nextSurfaceInfo.FadeColor.rgba || - currentSurfaceInfo.LightInfo.light_level != nextSurfaceInfo.LightInfo.light_level || - currentSurfaceInfo.LightInfo.fade_start != nextSurfaceInfo.LightInfo.fade_start || - currentSurfaceInfo.LightInfo.fade_end != nextSurfaceInfo.LightInfo.fade_end) - { - changeState = true; - changeSurfaceInfo = true; - } - } - else - { - if (currentSurfaceInfo.PolyColor.rgba != nextSurfaceInfo.PolyColor.rgba) - { - changeState = true; - changeSurfaceInfo = true; - } - } + nextDrawCall = &drawCalls[drawCallOrder[drawCallReadPos]]; + stateChanges = HWR_MarkStateChanges(currentDrawCall, nextDrawCall); } - if (changeState || stopFlag) + if (stateChanges || stopFlag) { - // execute draw call - HWD.pfnDrawIndexedTriangles(¤tSurfaceInfo, finalVertexArray, finalIndexWritePos, currentPolyFlags, finalVertexIndexArray); + // execute combined draw call + HWD.pfnDrawIndexedTriangles(¤tDrawCall->surf, finalVertices, + finalIndicesSize, currentDrawCall->polyFlags, finalIndices); // update stats ps_hw_numcalls.value.i++; - ps_hw_numverts.value.i += finalIndexWritePos; - // reset write positions - finalVertexWritePos = 0; - finalIndexWritePos = 0; + ps_hw_numverts.value.i += finalIndicesSize; + // reset final geometry collection arrays + finalVerticesSize = 0; + finalIndicesSize = 0; } - else continue; + else + continue; // if we're here then either its time to stop or time to change state - if (stopFlag) break; - - // change state according to change bools and next vars, update current vars and reset bools - if (changeShader) - { - HWD.pfnSetShader(nextShader); - currentShader = nextShader; - changeShader = false; - - ps_hw_numshaders.value.i++; - } - if (changeTexture) - { - // texture should be already ready for use from calls to SetTexture during batch collection - HWD.pfnSetTexture(nextTexture); - currentTexture = nextTexture; - changeTexture = false; - - ps_hw_numtextures.value.i++; - } - if (changePolyFlags) - { - currentPolyFlags = nextPolyFlags; - changePolyFlags = false; - - ps_hw_numpolyflags.value.i++; - } - if (changeSurfaceInfo) - { - currentSurfaceInfo = nextSurfaceInfo; - changeSurfaceInfo = false; - - ps_hw_numcolors.value.i++; - } - // and that should be it? + if (stopFlag) + break; + else + HWR_ExecuteStateChanges(stateChanges, nextDrawCall); } // reset the arrays (set sizes to 0) - polygonArraySize = 0; - unsortedVertexArraySize = 0; + drawCallsSize = 0; + unsortedVerticesSize = 0; PS_STOP_TIMING(ps_hw_batchdrawtime); } - #endif // HWRENDER diff --git a/src/hardware/hw_batching.h b/src/hardware/hw_batching.h index bf0b7fc94..b4e4bd9e3 100644 --- a/src/hardware/hw_batching.h +++ b/src/hardware/hw_batching.h @@ -17,18 +17,6 @@ #include "hw_data.h" #include "hw_drv.h" -typedef struct -{ - FSurfaceInfo surf;// surf also has its own polyflags for some reason, but it seems unused - unsigned int vertsIndex;// location of verts in unsortedVertexArray - FUINT numVerts; - FBITFIELD polyFlags; - GLMipmap_t *texture; - int shader; - // this tells batching that the plane belongs to a horizon line and must be drawn in correct order with the skywalls - boolean horizonSpecial; -} PolygonArrayEntry; - void HWR_StartBatching(void); void HWR_SetCurrentTexture(GLMipmap_t *texture); void HWR_ProcessPolygon(FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPts, FBITFIELD PolyFlags, int shader, boolean horizonSpecial); -- 2.54.0 From 5cec34e8d9c4fadea4ee4be1c1fb5dd8bde3d324 Mon Sep 17 00:00:00 2001 From: Alug Date: Thu, 18 Jan 2024 16:56:59 +0100 Subject: [PATCH 8/8] fix lighttable batching for new batching and palshader code --- src/hardware/hw_batching.c | 6 ------ src/hardware/r_opengl/r_opengl.c | 20 ++++++++++++-------- 2 files changed, 12 insertions(+), 14 deletions(-) diff --git a/src/hardware/hw_batching.c b/src/hardware/hw_batching.c index bbb228367..e3d02c4b4 100644 --- a/src/hardware/hw_batching.c +++ b/src/hardware/hw_batching.c @@ -195,12 +195,6 @@ static int compareDrawCalls(const void *p1, const void *p2) downloaded2 = poly2->texture->downloaded; diff64 = downloaded1 - downloaded2; if (diff64 != 0) return diff64; - - if (HWR_ShouldUsePaletteRendering()) - { - diff = poly1->surf.LightTableId - poly2->surf.LightTableId; - if (diff != 0) return diff; - } diff = poly1->polyFlags - poly2->polyFlags; if (diff != 0) return diff; diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c index 68619d4e0..581fa8625 100644 --- a/src/hardware/r_opengl/r_opengl.c +++ b/src/hardware/r_opengl/r_opengl.c @@ -79,10 +79,7 @@ static float NEAR_CLIPPING_PLANE = NZCLIP_PLANE; // ************************************************************************** static GLuint tex_downloaded = 0; -// these didnt work with karts batching system, hope this is not an issue -//static GLuint lt_downloaded = 0; // currently bound lighttable texture - currentSurfaceInfo -//static GLuint lt_downloaded2 = 0; // currently bound lighttable texture - nextSurfaceInfo -//static GLuint lt_downloaded3 = 0; // currently bound lighttable texture - pSurf +static GLuint lt_downloaded = 0; // currently bound lighttable texture static GLfloat fov = 90.0f; static FBITFIELD CurrentPolyFlags; @@ -2211,11 +2208,12 @@ static void PreparePolygon(FSurfaceInfo *pSurf, FOutVector *pOutVerts, FBITFIELD fade.blue = byte2float[pSurf->FadeColor.s.blue]; fade.alpha = byte2float[pSurf->FadeColor.s.alpha]; - if (HWR_ShouldUsePaletteRendering() && gl_allowshaders) + if (pSurf->LightTableId && pSurf->LightTableId != lt_downloaded) { pglActiveTexture(GL_TEXTURE2); pglBindTexture(GL_TEXTURE_2D, pSurf->LightTableId); pglActiveTexture(GL_TEXTURE0); + lt_downloaded = pSurf->LightTableId; } } @@ -2990,6 +2988,14 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, float duration, float fade.green = byte2float[Surface->FadeColor.s.green]; fade.blue = byte2float[Surface->FadeColor.s.blue]; fade.alpha = byte2float[Surface->FadeColor.s.alpha]; + + if (Surface->LightTableId && Surface->LightTableId != lt_downloaded) + { + pglActiveTexture(GL_TEXTURE2); + pglBindTexture(GL_TEXTURE_2D, Surface->LightTableId); + pglActiveTexture(GL_TEXTURE0); + lt_downloaded = Surface->LightTableId; + } Shader_SetUniforms(Surface, &poly, &tint, &fade); @@ -3856,9 +3862,7 @@ EXPORT void HWRAPI(ClearLightTables)(void) LightTablesTail = NULL; // we no longer have a bound light table (if we had one), we just deleted it! - //lt_downloaded = 0; - //lt_downloaded2 = 0; - //lt_downloaded3 = 0; + lt_downloaded = 0; } // This palette is used for the palette rendering postprocessing step. -- 2.54.0