From 3e204080ae3b2459e16d956b37d71a61adb64c2d Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 19 May 2018 15:20:46 +0200 Subject: [PATCH] - render sector planes in one draw call. On a fast and modern graphics card this is a lot faster than doing it per subsector but it may not be without drawbacks on older hardware so it will require some testing on older hardware. For me Frozen Time's view over the bridge went from 46 fps to 51 fps with this change, the time saved was roughly 2 ms. --- src/gl/scene/gl_drawinfo.h | 1 + src/gl/scene/gl_flats.cpp | 60 ++++++++++++++++++++++--- src/hwrenderer/data/flatvertices.cpp | 1 + src/hwrenderer/scene/hw_drawstructs.h | 2 + src/hwrenderer/scene/hw_flats.cpp | 16 +++++-- src/hwrenderer/scene/hw_renderhacks.cpp | 2 + 6 files changed, 72 insertions(+), 10 deletions(-) diff --git a/src/gl/scene/gl_drawinfo.h b/src/gl/scene/gl_drawinfo.h index 05ca3dd8d..1add3bf4d 100644 --- a/src/gl/scene/gl_drawinfo.h +++ b/src/gl/scene/gl_drawinfo.h @@ -121,6 +121,7 @@ struct FDrawInfo : public HWDrawInfo void ProcessLights(GLFlat *flat, bool istrans); void DrawSubsector(GLFlat *flat, subsector_t * sub); void SetupSubsectorLights(GLFlat *flat, int pass, subsector_t * sub, int *dli); + void SetupSectorLights(GLFlat *flat, int pass, int *dli); // Sprite drawer void DrawSprite(GLSprite *sprite, int pass); diff --git a/src/gl/scene/gl_flats.cpp b/src/gl/scene/gl_flats.cpp index ac6415b43..d4105c569 100644 --- a/src/gl/scene/gl_flats.cpp +++ b/src/gl/scene/gl_flats.cpp @@ -62,7 +62,35 @@ void FDrawInfo::SetupSubsectorLights(GLFlat *flat, int pass, subsector_t * sub, (*dli)++; return; } - if (flat->SetupSubsectorLights(pass, sub, lightdata)) + if (flat->SetupSectorLights(pass, flat->sector, lightdata)) + { + int d = GLRenderer->mLights->UploadLights(lightdata); + if (pass == GLPASS_LIGHTSONLY) + { + GLRenderer->mLights->StoreIndex(d); + } + else + { + gl_RenderState.ApplyLightIndex(d); + } + } +} + +//========================================================================== +// +// +// +//========================================================================== + +void FDrawInfo::SetupSectorLights(GLFlat *flat, int pass, int *dli) +{ + if (dli != NULL && *dli != -1) + { + gl_RenderState.ApplyLightIndex(GLRenderer->mLights->GetIndex(*dli)); + (*dli)++; + return; + } + if (flat->SetupSectorLights(pass, flat->sector, lightdata)) { int d = GLRenderer->mLights->UploadLights(lightdata); if (pass == GLPASS_LIGHTSONLY) @@ -137,13 +165,20 @@ void FDrawInfo::ProcessLights(GLFlat *flat, bool istrans) { flat->dynlightindex = GLRenderer->mLights->GetIndexPtr(); - // Draw the subsectors belonging to this sector - for (int i=0; i< flat->sector->subsectorcount; i++) + if (flat->sector->ibocount > 0) { - subsector_t * sub = flat->sector->subsectors[i]; - if (gl_drawinfo->ss_renderflags[sub->Index()]& flat->renderflags || istrans) + SetupSectorLights(flat, GLPASS_LIGHTSONLY, nullptr); + } + else + { + // Draw the subsectors belonging to this sector + for (int i = 0; i < flat->sector->subsectorcount; i++) { - SetupSubsectorLights(flat, GLPASS_LIGHTSONLY, sub, nullptr); + subsector_t * sub = flat->sector->subsectors[i]; + if (gl_drawinfo->ss_renderflags[sub->Index()] & flat->renderflags || istrans) + { + SetupSubsectorLights(flat, GLPASS_LIGHTSONLY, sub, nullptr); + } } } @@ -175,7 +210,18 @@ void FDrawInfo::DrawSubsectors(GLFlat *flat, int pass, bool processlights, bool gl_RenderState.Apply(); if (gl.legacyMode) processlights = false; - if (flat->vboindex >= 0) + + auto vcount = flat->sector->ibocount; + if (vcount > 0) + { + if (processlights) SetupSectorLights(flat, GLPASS_ALL, &dli); + drawcalls.Clock(); + glDrawElements(GL_TRIANGLES, vcount, GL_UNSIGNED_INT, GLRenderer->mVBO->GetIndexPointer() + flat->vboindex); + drawcalls.Unclock(); + flatvertices += vcount; + flatprimitives++; + } + else if (flat->vboindex >= 0) { int index = flat->vboindex; for (int i=0; isector->subsectorcount; i++) diff --git a/src/hwrenderer/data/flatvertices.cpp b/src/hwrenderer/data/flatvertices.cpp index 0fba9a50f..cba80b11a 100644 --- a/src/hwrenderer/data/flatvertices.cpp +++ b/src/hwrenderer/data/flatvertices.cpp @@ -165,6 +165,7 @@ int FFlatVertexGenerator::CreateIndexedSectorVertices(sector_t *sec, const secpl subsector_t *sub = sec->subsectors[j]; CreateIndexedSubsectorVertices(sub, plane, floor, vi, gen); } + sec->ibocount = ibo_data.Size() - rt; return rt; } diff --git a/src/hwrenderer/scene/hw_drawstructs.h b/src/hwrenderer/scene/hw_drawstructs.h index 7aa7e0b7d..56c74a8f7 100644 --- a/src/hwrenderer/scene/hw_drawstructs.h +++ b/src/hwrenderer/scene/hw_drawstructs.h @@ -311,7 +311,9 @@ public: int dynlightindex; + bool SetupLights(int pass, FLightNode *head, FDynLightData &lightdata, int portalgroup); bool SetupSubsectorLights(int pass, subsector_t * sub, FDynLightData &lightdata); + bool SetupSectorLights(int pass, sector_t * sec, FDynLightData &lightdata); void PutFlat(HWDrawInfo *di, bool fog = false); void Process(HWDrawInfo *di, sector_t * model, int whichplane, bool notexture); diff --git a/src/hwrenderer/scene/hw_flats.cpp b/src/hwrenderer/scene/hw_flats.cpp index dabee535d..0aafadc26 100644 --- a/src/hwrenderer/scene/hw_flats.cpp +++ b/src/hwrenderer/scene/hw_flats.cpp @@ -92,14 +92,13 @@ bool hw_SetPlaneTextureRotation(const GLSectorPlane * secplane, FMaterial * glte // //========================================================================== -bool GLFlat::SetupSubsectorLights(int pass, subsector_t * sub, FDynLightData &lightdata) +bool GLFlat::SetupLights(int pass, FLightNode * node, FDynLightData &lightdata, int portalgroup) { Plane p; if (renderstyle == STYLE_Add && !level.lightadditivesurfaces) return false; // no lights on additively blended surfaces. lightdata.Clear(); - FLightNode * node = sub->lighthead; while (node) { ADynamicLight * light = node->lightsource; @@ -121,13 +120,23 @@ bool GLFlat::SetupSubsectorLights(int pass, subsector_t * sub, FDynLightData &li } p.Set(plane.plane.Normal(), plane.plane.fD()); - lightdata.GetLight(sub->sector->PortalGroup, p, light, false); + lightdata.GetLight(portalgroup, p, light, false); node = node->nextLight; } return true; } +bool GLFlat::SetupSubsectorLights(int pass, subsector_t * sub, FDynLightData &lightdata) +{ + return SetupLights(pass, sub->lighthead, lightdata, sub->sector->PortalGroup); +} + +bool GLFlat::SetupSectorLights(int pass, sector_t * sec, FDynLightData &lightdata) +{ + return SetupLights(pass, sec->lighthead, lightdata, sec->PortalGroup); +} + //========================================================================== // // GLFlat::PutFlat @@ -252,6 +261,7 @@ void GLFlat::ProcessSector(HWDrawInfo *di, sector_t * frontsector) sector = &level.sectors[frontsector->sectornum]; extsector_t::xfloor &x = sector->e->XFloor; dynlightindex = -1; + vertexcount = sector->ibocount; uint8_t &srf = di->sectorrenderflags[sector->sectornum]; diff --git a/src/hwrenderer/scene/hw_renderhacks.cpp b/src/hwrenderer/scene/hw_renderhacks.cpp index 5eacd9dfc..bfc7b38d3 100644 --- a/src/hwrenderer/scene/hw_renderhacks.cpp +++ b/src/hwrenderer/scene/hw_renderhacks.cpp @@ -1077,6 +1077,7 @@ void HWDrawInfo::ProcessSectorStacks(area_t in_area) { subsector_t *sub = HandledSubsectors[j]; ss_renderflags[sub->Index()] &= ~SSRF_RENDERCEILING; + sub->sector->ibocount = -1; // cannot render this sector in one go. if (sub->portalcoverage[sector_t::ceiling].subsectors == NULL) { @@ -1122,6 +1123,7 @@ void HWDrawInfo::ProcessSectorStacks(area_t in_area) { subsector_t *sub = HandledSubsectors[j]; ss_renderflags[sub->Index()] &= ~SSRF_RENDERFLOOR; + sub->sector->ibocount = -1; // cannot render this sector in one go. if (sub->portalcoverage[sector_t::floor].subsectors == NULL) {