diff --git a/src/common/rendering/hwrenderer/data/hw_mesh.cpp b/src/common/rendering/hwrenderer/data/hw_mesh.cpp index fdde561549..1c6f1e6417 100644 --- a/src/common/rendering/hwrenderer/data/hw_mesh.cpp +++ b/src/common/rendering/hwrenderer/data/hw_mesh.cpp @@ -33,23 +33,23 @@ void Mesh::Draw(FRenderState& renderstate) #endif MeshApplyState origState; - origState.RenderStyle = renderstate.mRenderStyle; - origState.SpecialEffect = renderstate.mSpecialEffect; - origState.TextureEnabled = renderstate.mTextureEnabled; - origState.AlphaThreshold = renderstate.mAlphaThreshold; + origState.applyData.RenderStyle = renderstate.mRenderStyle; + origState.applyData.SpecialEffect = renderstate.mSpecialEffect; + origState.applyData.TextureEnabled = renderstate.mTextureEnabled; + origState.applyData.AlphaThreshold = renderstate.mAlphaThreshold; + origState.applyData.FogEnabled = renderstate.mFogEnabled; + origState.applyData.BrightmapEnabled = renderstate.mBrightmapEnabled; + origState.applyData.TextureClamp = renderstate.mTextureClamp; + origState.applyData.TextureMode = renderstate.mTextureMode; + origState.applyData.TextureModeFlags = renderstate.mTextureModeFlags; + origState.applyData.uLightDist = renderstate.mLightParms[0]; + origState.applyData.uLightFactor = renderstate.mLightParms[1]; + origState.applyData.uFogDensity = renderstate.mLightParms[2]; + origState.applyData.uClipSplit[0] = renderstate.mClipSplit[0]; + origState.applyData.uClipSplit[1] = renderstate.mClipSplit[1]; + origState.uLightLevel = renderstate.mLightParms[3]; origState.streamData = renderstate.mStreamData; origState.material = renderstate.mMaterial; - origState.FogEnabled = renderstate.mFogEnabled; - origState.BrightmapEnabled = renderstate.mBrightmapEnabled; - origState.TextureClamp = renderstate.mTextureClamp; - origState.TextureMode = renderstate.mTextureMode; - origState.TextureModeFlags = renderstate.mTextureModeFlags; - origState.uLightDist = renderstate.mLightParms[0]; - origState.uLightFactor = renderstate.mLightParms[1]; - origState.uFogDensity = renderstate.mLightParms[2]; - origState.uLightLevel = renderstate.mLightParms[3]; - origState.uClipSplit[0] = renderstate.mClipSplit[0]; - origState.uClipSplit[1] = renderstate.mClipSplit[1]; int applyIndex = -1; int depthFunc = -1; @@ -58,7 +58,7 @@ void Mesh::Draw(FRenderState& renderstate) bool apply = applyIndex != cmd.ApplyIndex; if (apply) { - int newDepthFunc = mApplys[cmd.ApplyIndex].DepthFunc; + int newDepthFunc = mApplys[cmd.ApplyIndex].applyData.DepthFunc; if (depthFunc != newDepthFunc) { depthFunc = newDepthFunc; @@ -86,7 +86,7 @@ void Mesh::Draw(FRenderState& renderstate) bool apply = applyIndex != cmd.ApplyIndex; if (apply) { - int newDepthFunc = mApplys[cmd.ApplyIndex].DepthFunc; + int newDepthFunc = mApplys[cmd.ApplyIndex].applyData.DepthFunc; if (depthFunc != newDepthFunc) { depthFunc = newDepthFunc; @@ -104,21 +104,21 @@ void Mesh::Draw(FRenderState& renderstate) void Mesh::Apply(FRenderState& renderstate, const MeshApplyState& state) { - renderstate.mRenderStyle = state.RenderStyle; - renderstate.mSpecialEffect = state.SpecialEffect; - renderstate.mTextureEnabled = state.TextureEnabled; - renderstate.mAlphaThreshold = state.AlphaThreshold; + renderstate.mRenderStyle = state.applyData.RenderStyle; + renderstate.mSpecialEffect = state.applyData.SpecialEffect; + renderstate.mTextureEnabled = state.applyData.TextureEnabled; + renderstate.mAlphaThreshold = state.applyData.AlphaThreshold; + renderstate.mFogEnabled = state.applyData.FogEnabled; + renderstate.mBrightmapEnabled = state.applyData.BrightmapEnabled; + renderstate.mTextureClamp = state.applyData.TextureClamp; + renderstate.mTextureMode = state.applyData.TextureMode; + renderstate.mTextureModeFlags = state.applyData.TextureModeFlags; + renderstate.mLightParms[0] = state.applyData.uLightDist; + renderstate.mLightParms[1] = state.applyData.uLightFactor; + renderstate.mLightParms[2] = state.applyData.uFogDensity; + renderstate.mClipSplit[0] = state.applyData.uClipSplit[0]; + renderstate.mClipSplit[1] = state.applyData.uClipSplit[1]; + renderstate.mLightParms[3] = state.uLightLevel; renderstate.mStreamData = state.streamData; renderstate.mMaterial = state.material; - renderstate.mFogEnabled = state.FogEnabled; - renderstate.mBrightmapEnabled = state.BrightmapEnabled; - renderstate.mTextureClamp = state.TextureClamp; - renderstate.mTextureMode = state.TextureMode; - renderstate.mTextureModeFlags = state.TextureModeFlags; - renderstate.mLightParms[0] = state.uLightDist; - renderstate.mLightParms[1] = state.uLightFactor; - renderstate.mLightParms[2] = state.uFogDensity; - renderstate.mLightParms[3] = state.uLightLevel; - renderstate.mClipSplit[0] = state.uClipSplit[0]; - renderstate.mClipSplit[1] = state.uClipSplit[1]; } diff --git a/src/common/rendering/hwrenderer/data/hw_meshbuilder.cpp b/src/common/rendering/hwrenderer/data/hw_meshbuilder.cpp index f9cdd2ddc0..0b9cde55e9 100644 --- a/src/common/rendering/hwrenderer/data/hw_meshbuilder.cpp +++ b/src/common/rendering/hwrenderer/data/hw_meshbuilder.cpp @@ -27,8 +27,8 @@ void MeshBuilder::Draw(int dt, int index, int count, bool apply) command.DrawType = dt; command.Start = index; command.Count = count; - command.ApplyIndex = mApplys.Size() - 1; - mDraws.Push(command); + command.ApplyIndex = -1; + mDrawLists->mDraws.Push(command); } void MeshBuilder::DrawIndexed(int dt, int index, int count, bool apply) @@ -40,8 +40,8 @@ void MeshBuilder::DrawIndexed(int dt, int index, int count, bool apply) command.DrawType = dt; command.Start = index; command.Count = count; - command.ApplyIndex = mApplys.Size() - 1; - mIndexedDraws.Push(command); + command.ApplyIndex = -1; + mDrawLists->mIndexedDraws.Push(command); } void MeshBuilder::SetDepthFunc(int func) @@ -53,45 +53,54 @@ void MeshBuilder::Apply() { MeshApplyState state; - state.RenderStyle = mRenderStyle; - state.SpecialEffect = mSpecialEffect; - state.TextureEnabled = mTextureEnabled; - state.AlphaThreshold = mAlphaThreshold; - state.DepthFunc = mDepthFunc; - + state.applyData.RenderStyle = mRenderStyle; + state.applyData.SpecialEffect = mSpecialEffect; + state.applyData.TextureEnabled = mTextureEnabled; + state.applyData.AlphaThreshold = mAlphaThreshold; + state.applyData.DepthFunc = mDepthFunc; + state.applyData.FogEnabled = mFogEnabled; + state.applyData.BrightmapEnabled = mBrightmapEnabled; + state.applyData.TextureClamp = mTextureClamp; + state.applyData.TextureMode = mTextureMode; + state.applyData.TextureModeFlags = mTextureModeFlags; + state.applyData.uLightDist = mLightParms[0]; + state.applyData.uLightFactor = mLightParms[1]; + state.applyData.uFogDensity = mLightParms[2]; + state.applyData.uClipSplit = { mClipSplit[0], mClipSplit[1] }; + state.uLightLevel = mLightParms[3]; state.streamData = mStreamData; state.material = mMaterial; - state.FogEnabled = mFogEnabled; - state.BrightmapEnabled = mBrightmapEnabled; - state.TextureClamp = mTextureClamp; - state.TextureMode = mTextureMode; - state.TextureModeFlags = mTextureModeFlags; + state.streamData.uVertexNormal = FVector4(0.0f, 0.0f, 0.0f, 0.0f); // Grr, this should be part of the vertex!! - state.uLightDist = mLightParms[0]; - state.uLightFactor = mLightParms[1]; - state.uFogDensity = mLightParms[2]; - state.uLightLevel = mLightParms[3]; - - state.uClipSplit = { mClipSplit[0], mClipSplit[1] }; - - mApplys.Push(state); + mDrawLists = &mSortedLists[state]; } std::unique_ptr MeshBuilder::Create() { - if (mDraws.Size() == 0 && mIndexedDraws.Size() == 0) + if (mSortedLists.empty()) return {}; auto mesh = std::make_unique(); - mesh->mApplys = std::move(mApplys); - mesh->mDraws = std::move(mDraws); - mesh->mIndexedDraws = std::move(mIndexedDraws); - mesh->mVertices = std::move(mVertices); - mApplys.Clear(); - mDraws.Clear(); - mIndexedDraws.Clear(); + int applyIndex = 0; + for (auto& it : mSortedLists) + { + mesh->mApplys.Push(it.first); + for (MeshDrawCommand& command : it.second.mDraws) + { + command.ApplyIndex = applyIndex; + mesh->mDraws.Push(command); + } + for (MeshDrawCommand& command : it.second.mIndexedDraws) + { + command.ApplyIndex = applyIndex; + mesh->mIndexedDraws.Push(command); + } + applyIndex++; + } + + mesh->mVertices = std::move(mVertices); mVertices.Clear(); return mesh; diff --git a/src/common/rendering/hwrenderer/data/hw_meshbuilder.h b/src/common/rendering/hwrenderer/data/hw_meshbuilder.h index fc58255434..46992aac29 100644 --- a/src/common/rendering/hwrenderer/data/hw_meshbuilder.h +++ b/src/common/rendering/hwrenderer/data/hw_meshbuilder.h @@ -3,33 +3,55 @@ #include "hw_renderstate.h" #include "hw_material.h" #include "flatvertices.h" +#include class Mesh; class MeshApplyState { public: - FRenderStyle RenderStyle; - int SpecialEffect; - bool TextureEnabled; - float AlphaThreshold; - int DepthFunc; + struct ApplyData + { + FRenderStyle RenderStyle; + int SpecialEffect; + int TextureEnabled; + float AlphaThreshold; + int DepthFunc; + int FogEnabled; + int BrightmapEnabled; + int TextureClamp; + int TextureMode; + int TextureModeFlags; + float uFogDensity; + float uLightFactor; + float uLightDist; + FVector2 uClipSplit; + }; + float uLightLevel; + + ApplyData applyData; StreamData streamData; FMaterialState material; - uint8_t FogEnabled; - uint8_t BrightmapEnabled; - int TextureClamp; - int TextureMode; - int TextureModeFlags; + bool operator<(const MeshApplyState& other) const + { + if (material.mMaterial != other.material.mMaterial) + return material.mMaterial < other.material.mMaterial; + if (material.mClampMode != other.material.mClampMode) + return material.mClampMode < other.material.mClampMode; + if (material.mTranslation != other.material.mTranslation) + return material.mTranslation < other.material.mTranslation; + if (material.mOverrideShader != other.material.mOverrideShader) + return material.mOverrideShader < other.material.mOverrideShader; - float uLightLevel; - float uFogDensity; - float uLightFactor; - float uLightDist; + int result = memcmp(&applyData, &other.applyData, sizeof(ApplyData)); + if (result != 0) + return result < 0; - FVector2 uClipSplit; + result = memcmp(&streamData, &other.streamData, sizeof(StreamData)); + return result < 0; + } }; class MeshDrawCommand @@ -79,9 +101,14 @@ public: private: void Apply(); - TArray mApplys; - TArray mDraws; - TArray mIndexedDraws; + struct DrawLists + { + TArray mDraws; + TArray mIndexedDraws; + }; + std::map mSortedLists; + DrawLists* mDrawLists = nullptr; + TArray mVertices; int mDepthFunc = 0; }; diff --git a/src/rendering/hwrenderer/scene/hw_drawinfo.cpp b/src/rendering/hwrenderer/scene/hw_drawinfo.cpp index 022bce1d4d..91466e7acd 100644 --- a/src/rendering/hwrenderer/scene/hw_drawinfo.cpp +++ b/src/rendering/hwrenderer/scene/hw_drawinfo.cpp @@ -512,13 +512,9 @@ void HWDrawInfo::RenderScene(FRenderState &state) drawlists[GLDL_PLAINWALLS].DrawWalls(this, state, false); drawlists[GLDL_PLAINFLATS].DrawFlats(this, state, false); - if (gl_meshcache) + if (gl_meshcache && meshcache.Opaque) { - for (HWCachedSector& cachedsector : meshcache.Sectors) - { - if (cachedsector.Opaque) - cachedsector.Opaque->Draw(state); - } + meshcache.Opaque->Draw(state); } // Part 2: masked geometry. This is set up so that only pixels with alpha>gl_mask_threshold will show @@ -526,13 +522,9 @@ void HWDrawInfo::RenderScene(FRenderState &state) drawlists[GLDL_MASKEDWALLS].DrawWalls(this, state, false); drawlists[GLDL_MASKEDFLATS].DrawFlats(this, state, false); - if (gl_meshcache) + if (gl_meshcache && meshcache.Translucent) { - for (HWCachedSector& cachedsector : meshcache.Sectors) - { - if (cachedsector.Translucent) - cachedsector.Translucent->Draw(state); - } + meshcache.Translucent->Draw(state); } // Part 3: masked geometry with polygon offset. This list is empty most of the time so only waste time on it when in use. @@ -543,14 +535,10 @@ void HWDrawInfo::RenderScene(FRenderState &state) state.ClearDepthBias(); } - if (gl_meshcache) + if (gl_meshcache && meshcache.TranslucentDepthBiased) { state.SetDepthBias(-1, -128); - for (HWCachedSector& cachedsector : meshcache.Sectors) - { - if (cachedsector.TranslucentDepthBiased) - cachedsector.TranslucentDepthBiased->Draw(state); - } + meshcache.TranslucentDepthBiased->Draw(state); state.ClearDepthBias(); } diff --git a/src/rendering/hwrenderer/scene/hw_meshcache.cpp b/src/rendering/hwrenderer/scene/hw_meshcache.cpp index abd0f2b1c3..daa7a5d4a3 100644 --- a/src/rendering/hwrenderer/scene/hw_meshcache.cpp +++ b/src/rendering/hwrenderer/scene/hw_meshcache.cpp @@ -16,8 +16,12 @@ HWMeshCache meshcache; void HWMeshCache::Clear() { +#if 0 Sectors.Reset(); - nextRefresh = 0; +#endif + Opaque.reset(); + Translucent.reset(); + TranslucentDepthBiased.reset(); } void HWMeshCache::Update(FRenderViewpoint& vp) @@ -26,6 +30,9 @@ void HWMeshCache::Update(FRenderViewpoint& vp) return; auto level = vp.ViewLevel; + +#if 0 + unsigned int count = level->sectors.Size(); Sectors.Resize(count); @@ -48,19 +55,6 @@ void HWMeshCache::Update(FRenderViewpoint& vp) } } -#if 0 - // Refresh 10 sectors per frame. - for (int i = 0; i < 10; i++) - { - if (nextRefresh < count) - { - Sectors[nextRefresh].NeedsUpdate = true; - } - if (count > 0) - nextRefresh = (nextRefresh + 1) % count; - } -#endif - // Update changed sectors for (unsigned int i = 0; i < count; i++) { @@ -75,87 +69,91 @@ void HWMeshCache::Update(FRenderViewpoint& vp) cacheitem->Update(vp); } } -} -void HWCachedSector::Update(FRenderViewpoint& vp) -{ - Opaque.reset(); - Translucent.reset(); - TranslucentDepthBiased.reset(); +#endif - HWDrawInfo* di = HWDrawInfo::StartDrawInfo(vp.ViewLevel, nullptr, vp, nullptr); - di->MeshBuilding = true; - - // Add to the draw lists - - CheckUpdate(screen->mVertexData, Sector); - std::unordered_set seenSections; - for (int i = 0, count = Sector->subsectorcount; i < count; i++) + if (!Opaque) { - subsector_t* subsector = Sector->subsectors[i]; - if (seenSections.find(subsector->section) == seenSections.end()) + HWDrawInfo* di = HWDrawInfo::StartDrawInfo(vp.ViewLevel, nullptr, vp, nullptr); + di->MeshBuilding = true; + + // Add to the draw lists + + unsigned int count = level->sectors.Size(); + for (unsigned int i = 0; i < count; i++) { - seenSections.insert(subsector->section); + auto sector = &level->sectors[i]; - HWFlat flat; - flat.section = subsector->section; - sector_t* front = hw_FakeFlat(subsector->render_sector, area_default, false); - flat.ProcessSector(di, front); + CheckUpdate(screen->mVertexData, sector); + std::unordered_set seenSections; + for (int i = 0, count = sector->subsectorcount; i < count; i++) + { + subsector_t* subsector = sector->subsectors[i]; + if (seenSections.find(subsector->section) == seenSections.end()) + { + seenSections.insert(subsector->section); + + HWFlat flat; + flat.section = subsector->section; + sector_t* front = hw_FakeFlat(subsector->render_sector, area_default, false); + flat.ProcessSector(di, front); + } + } + + for (line_t* line : sector->Lines) + { + side_t* side = (line->sidedef[0]->sector == sector) ? line->sidedef[0] : line->sidedef[1]; + + HWWall wall; + wall.sub = sector->subsectors[0]; + wall.Process(di, side->segs[0], sector, (line->sidedef[0]->sector == sector) ? line->backsector : line->frontsector); + } } - } - for (line_t* line : Sector->Lines) - { - side_t* side = (line->sidedef[0]->sector == Sector) ? line->sidedef[0] : line->sidedef[1]; + // Convert draw lists to meshes - HWWall wall; - wall.sub = Sector->subsectors[0]; - wall.Process(di, side->segs[0], Sector, (line->sidedef[0]->sector == Sector) ? line->backsector : line->frontsector); - } + MeshBuilder state; - // Convert draw lists to meshes + state.SetDepthMask(true); + state.EnableFog(true); + state.SetRenderStyle(STYLE_Source); - MeshBuilder state; + di->drawlists[GLDL_PLAINWALLS].SortWalls(); + di->drawlists[GLDL_PLAINFLATS].SortFlats(); + di->drawlists[GLDL_MASKEDWALLS].SortWalls(); + di->drawlists[GLDL_MASKEDFLATS].SortFlats(); + di->drawlists[GLDL_MASKEDWALLSOFS].SortWalls(); - state.SetDepthMask(true); - state.EnableFog(true); - state.SetRenderStyle(STYLE_Source); - - di->drawlists[GLDL_PLAINWALLS].SortWalls(); - di->drawlists[GLDL_PLAINFLATS].SortFlats(); - di->drawlists[GLDL_MASKEDWALLS].SortWalls(); - di->drawlists[GLDL_MASKEDFLATS].SortFlats(); - di->drawlists[GLDL_MASKEDWALLSOFS].SortWalls(); - - // Part 1: solid geometry. This is set up so that there are no transparent parts - state.SetDepthFunc(DF_Less); - state.AlphaFunc(Alpha_GEqual, 0.f); - state.ClearDepthBias(); - state.EnableTexture(gl_texture); - state.EnableBrightmap(true); - di->drawlists[GLDL_PLAINWALLS].DrawWalls(di, state, false); - di->drawlists[GLDL_PLAINFLATS].DrawFlats(di, state, false); - Opaque = state.Create(); - - // Part 2: masked geometry. This is set up so that only pixels with alpha>gl_mask_threshold will show - state.AlphaFunc(Alpha_GEqual, gl_mask_threshold); - di->drawlists[GLDL_MASKEDWALLS].DrawWalls(di, state, false); - di->drawlists[GLDL_MASKEDFLATS].DrawFlats(di, state, false); - Translucent = state.Create(); - - // Part 3: masked geometry with polygon offset. This list is empty most of the time so only waste time on it when in use. - if (di->drawlists[GLDL_MASKEDWALLSOFS].Size() > 0) - { - state.SetDepthBias(-1, -128); - di->drawlists[GLDL_MASKEDWALLSOFS].DrawWalls(di, state, false); + // Part 1: solid geometry. This is set up so that there are no transparent parts + state.SetDepthFunc(DF_Less); + state.AlphaFunc(Alpha_GEqual, 0.f); state.ClearDepthBias(); - TranslucentDepthBiased = state.Create(); - } - else - { - TranslucentDepthBiased.reset(); - } + state.EnableTexture(gl_texture); + state.EnableBrightmap(true); + di->drawlists[GLDL_PLAINWALLS].DrawWalls(di, state, false); + di->drawlists[GLDL_PLAINFLATS].DrawFlats(di, state, false); + Opaque = state.Create(); - di->MeshBuilding = false; - di->EndDrawInfo(); + // Part 2: masked geometry. This is set up so that only pixels with alpha>gl_mask_threshold will show + state.AlphaFunc(Alpha_GEqual, gl_mask_threshold); + di->drawlists[GLDL_MASKEDWALLS].DrawWalls(di, state, false); + di->drawlists[GLDL_MASKEDFLATS].DrawFlats(di, state, false); + Translucent = state.Create(); + + // Part 3: masked geometry with polygon offset. This list is empty most of the time so only waste time on it when in use. + if (di->drawlists[GLDL_MASKEDWALLSOFS].Size() > 0) + { + state.SetDepthBias(-1, -128); + di->drawlists[GLDL_MASKEDWALLSOFS].DrawWalls(di, state, false); + state.ClearDepthBias(); + TranslucentDepthBiased = state.Create(); + } + else + { + TranslucentDepthBiased.reset(); + } + + di->MeshBuilding = false; + di->EndDrawInfo(); + } } diff --git a/src/rendering/hwrenderer/scene/hw_meshcache.h b/src/rendering/hwrenderer/scene/hw_meshcache.h index 08d793f668..5ca6bf269e 100644 --- a/src/rendering/hwrenderer/scene/hw_meshcache.h +++ b/src/rendering/hwrenderer/scene/hw_meshcache.h @@ -5,6 +5,7 @@ struct FRenderViewpoint; +#if 0 class HWCachedSector { public: @@ -13,13 +14,8 @@ public: sector_t* Sector = nullptr; secplane_t Floorplane; secplane_t Ceilingplane; - - std::unique_ptr Opaque; - std::unique_ptr Translucent; - std::unique_ptr TranslucentDepthBiased; - - void Update(FRenderViewpoint& vp); }; +#endif class HWMeshCache { @@ -27,10 +23,13 @@ public: void Clear(); void Update(FRenderViewpoint& vp); +#if 0 TArray Sectors; +#endif -private: - unsigned int nextRefresh = 0; + std::unique_ptr Opaque; + std::unique_ptr Translucent; + std::unique_ptr TranslucentDepthBiased; }; extern HWMeshCache meshcache;