NepDisk 2026-03-06 10:43:31 -05:00
parent d0a9f2d9b6
commit c5bc17ff5e
2 changed files with 278 additions and 288 deletions

View file

@ -15,6 +15,19 @@
#include "../i_system.h"
#include "../qs22j.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;
GLMipmap_t *brightmap;
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;
@ -22,23 +35,36 @@ GLMipmap_t *current_brightmap = 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.
@ -48,13 +74,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;
@ -70,9 +96,7 @@ void HWR_SetCurrentTexture(GLMipmap_t *texture)
if (texture != NULL)
{
if (texture->flags & TF_BRIGHTMAP)
{
current_brightmap = texture;
}
else
{
current_texture = texture;
@ -80,14 +104,56 @@ void HWR_SetCurrentTexture(GLMipmap_t *texture)
}
}
else
{
current_texture = current_brightmap = NULL;
}
}
else
{
GL_SetTexture(texture);
}
static void HWR_CollectDrawCallInfo(FSurfaceInfo *pSurf, FUINT iNumPts, FBITFIELD PolyFlags, int shader_target, 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].brightmap = current_brightmap;
drawCalls[drawCallsSize].shader = (shader_target != -1) ? HWR_GetShaderFromTarget(shader_target) : shader_target;
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
@ -98,46 +164,13 @@ void HWR_ProcessPolygon(FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPt
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].brightmap = current_brightmap;
polygonArray[polygonArraySize].shader = (shader_target != -1) ? HWR_GetShaderFromTarget(shader_target) : shader_target;
polygonArray[polygonArraySize].horizonSpecial = horizonSpecial;
polygonArraySize++;
memcpy(&unsortedVertexArray[unsortedVertexArraySize], pOutVerts, iNumPts * sizeof(FOutVector));
unsortedVertexArraySize += iNumPts;
HWR_CollectDrawCallInfo(pSurf, iNumPts, PolyFlags, shader_target, horizonSpecial);
HWR_CollectDrawCallVertices(pOutVerts, iNumPts);
}
else
{
@ -146,12 +179,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;
@ -209,12 +242,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];
DrawCallInfo* poly1 = &drawCalls[index1];
DrawCallInfo* poly2 = &drawCalls[index2];
int diff;
INT64 diff64;
@ -245,60 +278,164 @@ 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;
}
static GLMipmap_t *HWR_GetDrawCallBrightmap(DrawCallInfo *dc)
{
return (dc->polyFlags & PF_NoTexture) ? NULL : dc->brightmap;
}
// 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 = &current->surf;
FSurfaceInfo *nextSI = &next->surf;
// check if a state change is required and flag it to stateChanges
if (current->shader != next->shader && cv_glshaders.value && gl_shadersavailable)
stateChanges |= SHADER_CHANGED;
if (HWR_GetDrawCallTexture(current) != HWR_GetDrawCallTexture(next)
|| HWR_GetDrawCallBrightmap(current) != HWR_GetDrawCallBrightmap(next))
stateChanges |= TEXTURE_CHANGED;
if (current->polyFlags != next->polyFlags)
stateChanges |= POLYFLAGS_CHANGED;
if (cv_glshaders.value && gl_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_glshaders.value && gl_shadersavailable)
{
GL_SetShader(dc->shader);
ps_hw_numshaders++;
}
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
GL_SetTexture(dc->texture);
if (dc->brightmap)
GL_SetTexture(dc->brightmap);
}
ps_hw_numtextures++;
}
// 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++;
if (stateChanges & SURFACEINFO_CHANGED)
ps_hw_numcolors++;
}
static void HWR_InitBatchingStats(void)
{
ps_hw_numpolys = drawCallsSize;
ps_hw_numcalls = ps_hw_numverts
= ps_hw_numshaders = ps_hw_numtextures
= ps_hw_numpolyflags = ps_hw_numcolors = 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 = NULL;
GLMipmap_t *nextTexture = NULL;
GLMipmap_t *currentBrightmap = NULL;
GLMipmap_t *nextBrightmap = NULL;
FBITFIELD currentPolyFlags = 0;
FBITFIELD nextPolyFlags = 0;
FSurfaceInfo currentSurfaceInfo;
FSurfaceInfo nextSurfaceInfo;
int drawCallReadPos = 0; // position in drawCallOrder
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;
nextSurfaceInfo.LightInfo.directional = false;
currently_batching = false; // no longer collecting batches
currently_batching = false;// no longer collecting batches
if (!polygonArraySize)
{
ps_hw_numpolys = ps_hw_numcalls = ps_hw_numshaders = ps_hw_numtextures = ps_hw_numpolyflags = ps_hw_numcolors = 0;
return;// nothing to draw
}
// init stats vars
ps_hw_numpolys = polygonArraySize;
ps_hw_numcalls = ps_hw_numverts = 0;
ps_hw_numshaders = ps_hw_numtextures = ps_hw_numpolyflags = ps_hw_numcolors = 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_hw_batchsorttime = I_GetPreciseTime();
if (cv_glshaders.value && gl_shadersavailable)
qs22j(polygonIndexArray, polygonArraySize, sizeof(unsigned int), comparePolygons);
qs22j(drawCallOrder, drawCallsSize, sizeof(UINT32), compareDrawCalls);
else
qs22j(polygonIndexArray, polygonArraySize, sizeof(unsigned int), comparePolygonsNoShaders);
qs22j(drawCallOrder, drawCallsSize, sizeof(UINT32), compareDrawCallsNoShaders);
ps_hw_batchsorttime = I_GetPreciseTime() - ps_hw_batchsorttime;
// sort order
// sort grouping order
// 1. shader
// 2. texture
// 3. brightmap
@ -308,43 +445,15 @@ void HWR_RenderBatches(void)
ps_hw_batchdrawtime = I_GetPreciseTime();
currentShader = polygonArray[polygonIndexArray[0]].shader;
currentTexture = polygonArray[polygonIndexArray[0]].texture;
currentBrightmap = polygonArray[polygonIndexArray[0]].brightmap;
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_glshaders.value && gl_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)
{
GL_SetShader(currentShader);
}
if (currentPolyFlags & PF_NoTexture)
{
currentTexture = currentBrightmap = NULL;
}
else
{
GL_SetTexture(currentTexture);
if (currentBrightmap)
GL_SetTexture(currentBrightmap);
}
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
@ -357,152 +466,46 @@ void HWR_RenderBatches(void)
// 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++;
}
unsigned int stateChanges = 0; // flags defined above HWR_MarkStateChanges
DrawCallInfo *currentDrawCall = &drawCalls[drawCallOrder[drawCallReadPos++]];
DrawCallInfo *nextDrawCall = NULL;
if (polygonReadPos >= polygonArraySize)
HWR_CollectVerticesIntoBatch(currentDrawCall);
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;
nextBrightmap = polygonArray[nextIndex].brightmap;
nextPolyFlags = polygonArray[nextIndex].polyFlags;
nextSurfaceInfo = polygonArray[nextIndex].surf;
if (nextPolyFlags & PF_NoTexture)
nextTexture = nextBrightmap = 0;
if (currentShader != nextShader && cv_glshaders.value && gl_shadersavailable)
{
changeState = true;
changeShader = true;
}
if (currentTexture != nextTexture || currentBrightmap != nextBrightmap)
{
changeState = true;
changeTexture = true;
}
if (currentPolyFlags != nextPolyFlags)
{
changeState = true;
changePolyFlags = true;
}
if (cv_glshaders.value && gl_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 ||
currentSurfaceInfo.LightInfo.directional != nextSurfaceInfo.LightInfo.directional)
{
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
GL_DrawIndexedTriangles(&currentSurfaceInfo, finalVertexArray, finalIndexWritePos, currentPolyFlags, finalVertexIndexArray);
// execute combined draw call
GL_DrawIndexedTriangles(&currentDrawCall->surf, finalVertices,
finalIndicesSize, currentDrawCall->polyFlags, finalIndices);
// update stats
ps_hw_numcalls++;
ps_hw_numverts += finalIndexWritePos;
// reset write positions
finalVertexWritePos = 0;
finalIndexWritePos = 0;
ps_hw_numverts += 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)
{
GL_SetShader(nextShader);
currentShader = nextShader;
changeShader = false;
ps_hw_numshaders++;
}
if (changeTexture)
{
// texture should be already ready for use from calls to SetTexture during batch collection
GL_SetTexture(nextTexture);
currentTexture = nextTexture;
if (nextBrightmap)
GL_SetTexture(nextBrightmap);
currentBrightmap = nextBrightmap;
changeTexture = false;
ps_hw_numtextures++;
}
if (changePolyFlags)
{
currentPolyFlags = nextPolyFlags;
changePolyFlags = false;
ps_hw_numpolyflags++;
}
if (changeSurfaceInfo)
{
currentSurfaceInfo = nextSurfaceInfo;
changeSurfaceInfo = false;
ps_hw_numcolors++;
}
// 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_hw_batchdrawtime = I_GetPreciseTime() - ps_hw_batchdrawtime;
}

View file

@ -20,19 +20,6 @@
extern "C" {
#endif
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;
GLMipmap_t *brightmap;
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);