From 17813b4556e506cd67793fcebcc44ddce208c5e3 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 18 Aug 2018 22:14:30 +0200 Subject: [PATCH] - use a uniform / shader storage buffer to handle the texture matrices. Since these are relatively constant data, holding them in a buffer and only updating when needed will save some processing time. It also removes 16 uniform values from the main attribute set which needs to be brought down to 32 for the Vulkan renderer. With the texture matrix removed there are currently 55 uniforms in this set, i.e. 23 more still need to be refactored into buffers. --- src/CMakeLists.txt | 1 + src/gl/data/gl_modelbuffer.cpp | 4 +- src/gl/data/gl_texturematrixbuffer.cpp | 192 +++++++++++++++++++++++++ src/gl/data/gl_texturematrixbuffer.h | 48 +++++++ src/gl/data/gl_viewpointbuffer.cpp | 4 +- src/gl/models/gl_models.cpp | 4 - src/gl/renderer/gl_renderer.cpp | 11 +- src/gl/renderer/gl_renderer.h | 2 + src/gl/renderer/gl_renderstate.cpp | 17 +-- src/gl/renderer/gl_renderstate.h | 18 +-- src/gl/scene/gl_drawinfo.cpp | 6 + src/gl/scene/gl_drawinfo.h | 1 + src/gl/scene/gl_flats.cpp | 7 +- src/gl/scene/gl_portal.cpp | 4 +- src/gl/scene/gl_skydome.cpp | 11 +- src/gl/shaders/gl_shader.cpp | 49 ++++--- src/gl/shaders/gl_shader.h | 10 +- src/hwrenderer/data/shaderuniforms.h | 3 +- src/hwrenderer/scene/hw_drawinfo.h | 1 + src/hwrenderer/scene/hw_drawstructs.h | 3 +- src/hwrenderer/scene/hw_flats.cpp | 12 ++ src/r_defs.h | 20 +-- wadsrc/static/shaders/glsl/main.vp | 2 +- 23 files changed, 339 insertions(+), 91 deletions(-) create mode 100644 src/gl/data/gl_texturematrixbuffer.cpp create mode 100644 src/gl/data/gl_texturematrixbuffer.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index de580c8214c..d6a16a1d6a1 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1047,6 +1047,7 @@ set (PCH_SOURCES gl/data/gl_uniformbuffer.cpp gl/data/gl_viewpointbuffer.cpp gl/data/gl_modelbuffer.cpp + gl/data/gl_texturematrixbuffer.cpp gl/dynlights/gl_lightbuffer.cpp gl/dynlights/gl_shadowmap.cpp gl/models/gl_models.cpp diff --git a/src/gl/data/gl_modelbuffer.cpp b/src/gl/data/gl_modelbuffer.cpp index d6074ed0f11..b15058cd778 100644 --- a/src/gl/data/gl_modelbuffer.cpp +++ b/src/gl/data/gl_modelbuffer.cpp @@ -57,6 +57,8 @@ GLModelBuffer::GLModelBuffer() GLModelBuffer::~GLModelBuffer() { + glBindBuffer(GL_UNIFORM_BUFFER, mBufferId); + glUnmapBuffer(GL_UNIFORM_BUFFER); glBindBuffer(mBufferType, 0); glDeleteBuffers(1, &mBufferId); } @@ -132,7 +134,7 @@ void GLModelBuffer::Map() void GLModelBuffer::Unmap() { - if (!mPersistent) + if (!mPersistent && mBufferPointer) { glBindBuffer(mBufferType, mBufferId); glUnmapBuffer(mBufferType); diff --git a/src/gl/data/gl_texturematrixbuffer.cpp b/src/gl/data/gl_texturematrixbuffer.cpp new file mode 100644 index 00000000000..307cee43ea3 --- /dev/null +++ b/src/gl/data/gl_texturematrixbuffer.cpp @@ -0,0 +1,192 @@ +// +//--------------------------------------------------------------------------- +// +// Copyright(C) 2018 Christoph Oelckers +// All rights reserved. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this program. If not, see http://www.gnu.org/licenses/ +// +//-------------------------------------------------------------------------- +// +/* +** gl_viewpointbuffer.cpp +** Buffer data maintenance for per viewpoint uniform data +** +**/ + +#include "gl_load/gl_system.h" +#include "gl_load/gl_interface.h" +#include "hwrenderer/data/shaderuniforms.h" +#include "gl_texturematrixbuffer.h" +#include "templates.h" +#include "g_levellocals.h" +#include "r_data/matrix.h" + +static const int INITIAL_SECTOR_COUNT = 1024; +static const int ADDITIONAL_ENTRIES = 50; // for skyboxes + +GLTextureMatrixBuffer::GLTextureMatrixBuffer() +{ + mSectorCount = INITIAL_SECTOR_COUNT; + + if (gl.flags & RFL_SHADER_STORAGE_BUFFER && !strstr(gl.vendorstring, "Intel")) + { + mBufferType = GL_SHADER_STORAGE_BUFFER; + mBlockAlign = 0; + mBlockSize = 0; + } + else + { + mBufferType = GL_UNIFORM_BUFFER; + // A matrix is always 64 bytes. + if (gl.maxuniformblock % sizeof(VSMatrix) == 0) + { + mBlockAlign = gl.maxuniformblock; + } + else + { + mBlockAlign = gl.uniformblockalignment; // this should really never happen. + } + mBlockSize = mBlockAlign / sizeof(VSMatrix); + } + + mBufferId = 0; + mUploadIndex = 2; + Allocate(); + mLastMappedIndex = UINT_MAX; + + // Initialize the identity rotation. + Map(); +} + +GLTextureMatrixBuffer::~GLTextureMatrixBuffer() +{ + Unload(); +} + +void GLTextureMatrixBuffer::Unload() +{ + if (mBufferId != 0) + { + glBindBuffer(mBufferType, mBufferId); + glUnmapBuffer(mBufferType); + glBindBuffer(mBufferType, 0); + glDeleteBuffers(1, &mBufferId); + } + mBufferId = 0; +} + +void GLTextureMatrixBuffer::Allocate() +{ + Unload(); + + mBufferSize = mSectorCount * 2 + ADDITIONAL_ENTRIES; + mByteSize = mBufferSize * sizeof(VSMatrix); + glGenBuffers(1, &mBufferId); + glBindBufferBase(mBufferType, TEXMATRIX_BINDINGPOINT, mBufferId); + glBindBuffer(mBufferType, mBufferId); + if (gl.buffermethod == BM_PERSISTENT) + { + glBufferStorage(mBufferType, mByteSize, NULL, GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT); + mBufferPointer = (VSMatrix*)glMapBufferRange(mBufferType, 0, mByteSize, GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT); + mPersistent = true; + } + else + { + glBufferData(mBufferType, mByteSize, NULL, GL_DYNAMIC_DRAW); + mBufferPointer = nullptr; + mPersistent = false; + } + Map(); + // Index #0 is the identity matrix. + // Index #1 is a y-flip matrix for camera textures. + VSMatrix mat; + mat.loadIdentity(); + mBufferPointer[0] = mat; + mat.scale(1.f, -1.f, 1.f); + mat.translate(0.f, 1.f, 0.0f); + mBufferPointer[1] = mat; + Unmap(); +} + +void GLTextureMatrixBuffer::ValidateSize(int numsectors) +{ + if (mSectorCount < numsectors) + { + mSectorCount = MAX(mSectorCount*2, numsectors); + Allocate(); + } + // Mark all indices as uninitialized. + int tmindex = -ADDITIONAL_ENTRIES; + for (auto &sec : level.sectors) + { + sec.planes[sector_t::floor].ubIndexMatrix = tmindex--; + sec.planes[sector_t::ceiling].ubIndexMatrix = tmindex--; + } +} + +void GLTextureMatrixBuffer::Map() +{ + if (!mPersistent) + { + glBindBuffer(mBufferType, mBufferId); + mBufferPointer = (VSMatrix*)glMapBufferRange(mBufferType, 0, mByteSize, GL_MAP_WRITE_BIT); + } +} + +void GLTextureMatrixBuffer::Unmap() +{ + if (!mPersistent && mBufferPointer) + { + glBindBuffer(mBufferType, mBufferId); + glUnmapBuffer(mBufferType); + mBufferPointer = nullptr; + } +} + +int GLTextureMatrixBuffer::Upload(const VSMatrix &mat, int index) +{ + assert(mBufferPointer != nullptr); // May only be called when the buffer is mapped. + if (mBufferPointer == nullptr) return 0; + + if (index == -1) // dynamic case for sky domes. + { + // The dynamic case for sky domes uses a simple circular buffer. 48 sky domes in a single map are highly unlikely and due to the serial nature of portal rendering + // even then has little chance on stomping on data still in flight. + // This can only happen in non-multithreaded parts right now so no synchronization is needed here. + index = mUploadIndex++; + if (index >= 50) + { + index = 2; + } + } + + mBufferPointer[index] = mat; + return index; +} + +// When this gets called we already have ruled out the case where rebinding is not needed. +int GLTextureMatrixBuffer::DoBind(unsigned int index) +{ + unsigned int offset = (index*sizeof(VSMatrix) / mBlockAlign) * mBlockAlign; + + if (offset != mLastMappedIndex) + { + mLastMappedIndex = offset; + glBindBufferRange(GL_UNIFORM_BUFFER, TEXMATRIX_BINDINGPOINT, mBufferId, offset, MIN(mBlockAlign, mByteSize - offset)); + } + return index - (offset/sizeof(VSMatrix)); +} + + diff --git a/src/gl/data/gl_texturematrixbuffer.h b/src/gl/data/gl_texturematrixbuffer.h new file mode 100644 index 00000000000..2d0eacda299 --- /dev/null +++ b/src/gl/data/gl_texturematrixbuffer.h @@ -0,0 +1,48 @@ +#pragma once + +#include +#include +#include "hwrenderer/data/shaderuniforms.h" +#include "r_data/matrix.h" + +class VSMatrix; + +class GLTextureMatrixBuffer +{ + bool mPersistent; + unsigned int mBufferId; + unsigned int mBufferType; + unsigned int mBufferSize; + unsigned int mBlockAlign; + unsigned int mUploadIndex; + unsigned int mLastMappedIndex; + VSMatrix * mBufferPointer; + + unsigned int mBlockSize; + unsigned int mByteSize; + unsigned int mSectorCount; + + void Allocate(); + int DoBind(unsigned index); + void Unload(); + +public: + + GLTextureMatrixBuffer(); + ~GLTextureMatrixBuffer(); + void ValidateSize(int numsectors); + int Upload(const VSMatrix &mat, int index); + void Map(); + void Unmap(); + int Bind(unsigned int index) + { + if (mBlockAlign > 0) return DoBind(index); + return index; + } + unsigned int GetBlockSize() const + { + return mBlockSize; + } + +}; + diff --git a/src/gl/data/gl_viewpointbuffer.cpp b/src/gl/data/gl_viewpointbuffer.cpp index 06cf28f204d..23f96d8d782 100644 --- a/src/gl/data/gl_viewpointbuffer.cpp +++ b/src/gl/data/gl_viewpointbuffer.cpp @@ -45,6 +45,8 @@ GLViewpointBuffer::GLViewpointBuffer() GLViewpointBuffer::~GLViewpointBuffer() { + glBindBuffer(GL_UNIFORM_BUFFER, mBufferId); + glUnmapBuffer(GL_UNIFORM_BUFFER); glBindBuffer(GL_UNIFORM_BUFFER, 0); glDeleteBuffers(1, &mBufferId); } @@ -103,7 +105,7 @@ void GLViewpointBuffer::Map() void GLViewpointBuffer::Unmap() { - if (!mPersistent) + if (!mPersistent && mBufferPointer) { glBindBuffer(GL_UNIFORM_BUFFER, mBufferId); glUnmapBuffer(GL_UNIFORM_BUFFER); diff --git a/src/gl/models/gl_models.cpp b/src/gl/models/gl_models.cpp index 13645a7362e..f6667172200 100644 --- a/src/gl/models/gl_models.cpp +++ b/src/gl/models/gl_models.cpp @@ -70,8 +70,6 @@ void FGLModelRenderer::BeginDrawModel(AActor *actor, FSpriteModelFrame *smf, con void FGLModelRenderer::EndDrawModel(AActor *actor, FSpriteModelFrame *smf) { - gl_RenderState.EnableModelMatrix(false); - glDepthFunc(GL_LESS); if (!(actor->RenderStyle == LegacyRenderStyles[STYLE_Normal]) && !(smf->flags & MDL_DONTCULLBACKFACES)) glDisable(GL_CULL_FACE); @@ -94,8 +92,6 @@ void FGLModelRenderer::BeginDrawHUDModel(AActor *actor, const VSMatrix *objectTo void FGLModelRenderer::EndDrawHUDModel(AActor *actor) { - gl_RenderState.EnableModelMatrix(false); - glDepthFunc(GL_LESS); if (!(actor->RenderStyle == LegacyRenderStyles[STYLE_Normal])) glDisable(GL_CULL_FACE); diff --git a/src/gl/renderer/gl_renderer.cpp b/src/gl/renderer/gl_renderer.cpp index da49a95fc43..a327c6bd537 100644 --- a/src/gl/renderer/gl_renderer.cpp +++ b/src/gl/renderer/gl_renderer.cpp @@ -58,6 +58,7 @@ #include "gl/dynlights/gl_lightbuffer.h" #include "gl/data/gl_viewpointbuffer.h" #include "gl/data/gl_modelbuffer.h" +#include "gl/data/gl_texturematrixbuffer.h" #include "r_videoscale.h" EXTERN_CVAR(Int, screenblocks) @@ -106,6 +107,7 @@ void FGLRenderer::Initialize(int width, int height) mLights = new FLightBuffer(); mViewpoints = new GLViewpointBuffer; mModelMatrix = new GLModelBuffer; + mTextureMatrices = new GLTextureMatrixBuffer; gl_RenderState.SetVertexBuffer(mVBO); mFBID = 0; mOldFBID = 0; @@ -127,6 +129,7 @@ FGLRenderer::~FGLRenderer() if (mLights != nullptr) delete mLights; if (mViewpoints != nullptr) delete mViewpoints; if (mModelMatrix != nullptr) delete mModelMatrix; + if (mTextureMatrices != nullptr) delete mTextureMatrices; if (mFBID != 0) glDeleteFramebuffers(1, &mFBID); if (mVAOID != 0) { @@ -161,6 +164,7 @@ void FGLRenderer::ResetSWScene() void FGLRenderer::SetupLevel() { mVBO->CreateVBO(); + mTextureMatrices->ValidateSize(level.sectors.Size()); } //=========================================================================== @@ -509,10 +513,7 @@ void FGLRenderer::Draw2D(F2DDrawer *drawer) // Canvas textures are stored upside down if (cmd.mTexture->bHasCanvas) { - gl_RenderState.mTextureMatrix.loadIdentity(); - gl_RenderState.mTextureMatrix.scale(1.f, -1.f, 1.f); - gl_RenderState.mTextureMatrix.translate(0.f, 1.f, 0.0f); - gl_RenderState.EnableTextureMatrix(true); + gl_RenderState.SetTexMatrixIndex(1); } } else @@ -538,7 +539,7 @@ void FGLRenderer::Draw2D(F2DDrawer *drawer) } gl_RenderState.SetObjectColor(0xffffffff); gl_RenderState.SetObjectColor2(0); - gl_RenderState.EnableTextureMatrix(false); + gl_RenderState.SetTexMatrixIndex(0); } glDisable(GL_SCISSOR_TEST); diff --git a/src/gl/renderer/gl_renderer.h b/src/gl/renderer/gl_renderer.h index 11aa795d03e..9b16dc1bae6 100644 --- a/src/gl/renderer/gl_renderer.h +++ b/src/gl/renderer/gl_renderer.h @@ -37,6 +37,7 @@ class FCustomPostProcessShaders; class SWSceneDrawer; class GLViewpointBuffer; class GLModelBuffer; +class GLTextureMatrixBuffer; struct FRenderViewpoint; #define NOQUEUE nullptr // just some token to be used as a placeholder @@ -82,6 +83,7 @@ class FGLRenderer FLightBuffer *mLights = nullptr; GLViewpointBuffer *mViewpoints = nullptr; GLModelBuffer *mModelMatrix = nullptr; + GLTextureMatrixBuffer *mTextureMatrices = nullptr; SWSceneDrawer *swdrawer = nullptr; FPortalSceneState mPortalState; diff --git a/src/gl/renderer/gl_renderstate.cpp b/src/gl/renderer/gl_renderstate.cpp index 58792c39445..009891b8fd3 100644 --- a/src/gl/renderer/gl_renderstate.cpp +++ b/src/gl/renderer/gl_renderstate.cpp @@ -37,6 +37,7 @@ #include "gl/dynlights//gl_lightbuffer.h" #include "gl/renderer/gl_renderbuffers.h" #include "gl/textures/gl_hwtexture.h" +#include "gl/data/gl_texturematrixbuffer.h" void gl_SetTextureMode(int type); @@ -72,8 +73,6 @@ void FRenderState::Reset() mDstBlend = GL_ONE_MINUS_SRC_ALPHA; mAlphaThreshold = 0.5f; mBlendEquation = GL_FUNC_ADD; - mModelMatrixEnabled = false; - mTextureMatrixEnabled = false; mObjectColor = 0xffffffff; mObjectColor2 = 0; mVertexBuffer = mCurrentVertexBuffer = NULL; @@ -84,6 +83,7 @@ void FRenderState::Reset() mGlossiness = 0.0f; mSpecularLevel = 0.0f; mShaderTimer = 0.0f; + mTexMatrixIndex = 0; ClearClipSplit(); stSrcBlend = stDstBlend = -1; @@ -166,6 +166,7 @@ bool FRenderState::ApplyShader() activeShader->muLightIndex.Set(-1); activeShader->muClipSplit.Set(mClipSplit); activeShader->muSpecularMaterial.Set(mGlossiness, mSpecularLevel); + activeShader->muTexMatrixIndex.Set(GLRenderer->mTextureMatrices->Bind(mTexMatrixIndex)); if (mGlowEnabled) { @@ -198,18 +199,6 @@ bool FRenderState::ApplyShader() activeShader->muSplitBottomPlane.Set(nulvec); activeShader->currentsplitstate = 0; } - - if (mTextureMatrixEnabled) - { - matrixToGL(mTextureMatrix, activeShader->texturematrix_index); - activeShader->currentTextureMatrixState = true; - } - else if (activeShader->currentTextureMatrixState) - { - activeShader->currentTextureMatrixState = false; - matrixToGL(identityMatrix, activeShader->texturematrix_index); - } - return true; } diff --git a/src/gl/renderer/gl_renderstate.h b/src/gl/renderer/gl_renderstate.h index 43adc6097ca..eef18db0eb1 100644 --- a/src/gl/renderer/gl_renderstate.h +++ b/src/gl/renderer/gl_renderstate.h @@ -90,11 +90,10 @@ class FRenderState int mSrcBlend, mDstBlend; float mAlphaThreshold; int mBlendEquation; - bool mModelMatrixEnabled; - bool mTextureMatrixEnabled; bool mLastDepthClamp; float mGlossiness, mSpecularLevel; float mShaderTimer; + int mTexMatrixIndex; FVertexBuffer *mVertexBuffer, *mCurrentVertexBuffer; FStateVec4 mNormal; @@ -270,14 +269,9 @@ class FRenderState mBrightmapEnabled = on; } - void EnableModelMatrix(bool on) + void SetTexMatrixIndex(int index) { - mModelMatrixEnabled = on; - } - - void EnableTextureMatrix(bool on) - { - mTextureMatrixEnabled = on; + mTexMatrixIndex = index; } void SetGlowParams(float *t, float *b) @@ -436,10 +430,7 @@ class FRenderState return mPassType == GBUFFER_PASS ? 3 : 1; } - // Backwards compatibility crap follows - void ApplyFixedFunction(); - void DrawColormapOverlay(); - + /* void SetPlaneTextureRotation(GLSectorPlane *plane, FMaterial *texture) { if (hw_SetPlaneTextureRotation(plane, texture, mTextureMatrix)) @@ -447,6 +438,7 @@ class FRenderState EnableTextureMatrix(true); } } + */ }; diff --git a/src/gl/scene/gl_drawinfo.cpp b/src/gl/scene/gl_drawinfo.cpp index 982d66343b8..98f52404f5b 100644 --- a/src/gl/scene/gl_drawinfo.cpp +++ b/src/gl/scene/gl_drawinfo.cpp @@ -37,6 +37,7 @@ #include "gl/data/gl_vertexbuffer.h" #include "gl/data/gl_modelbuffer.h" +#include "gl/data/gl_texturematrixbuffer.h" #include "gl/scene/gl_drawinfo.h" #include "hwrenderer/scene/hw_clipper.h" #include "gl/scene/gl_portal.h" @@ -268,6 +269,11 @@ int FDrawInfo::UploadModelMatrix(VSMatrix &data, float ifactor) return GLRenderer->mModelMatrix->Upload(&data, ifactor); } +int FDrawInfo::UploadTextureMatrix(const VSMatrix &data, int bufferindex) +{ + return GLRenderer->mTextureMatrices->Upload(data, bufferindex); +} + bool FDrawInfo::SetDepthClamp(bool on) { return gl_RenderState.SetDepthClamp(on); diff --git a/src/gl/scene/gl_drawinfo.h b/src/gl/scene/gl_drawinfo.h index 04d7abe0877..e93d138f8ef 100644 --- a/src/gl/scene/gl_drawinfo.h +++ b/src/gl/scene/gl_drawinfo.h @@ -52,6 +52,7 @@ struct FDrawInfo : public HWDrawInfo std::pair AllocVertices(unsigned int count) override; int UploadLights(FDynLightData &data) override; int UploadModelMatrix(VSMatrix &data, float ifactor) override; + int UploadTextureMatrix(const VSMatrix &data, int bufferindex) override; void DrawDecal(GLDecal *gldecal); void DrawDecals(); diff --git a/src/gl/scene/gl_flats.cpp b/src/gl/scene/gl_flats.cpp index 6da7c84f900..b4bb24451c8 100644 --- a/src/gl/scene/gl_flats.cpp +++ b/src/gl/scene/gl_flats.cpp @@ -219,10 +219,9 @@ void FDrawInfo::DrawFlat(GLFlat *flat, int pass, bool trans) // trans only has m gl_RenderState.SetObjectColor(flat->FlatColor | 0xff000000); if (flat->sector->special != GLSector_Skybox) { + gl_RenderState.SetTexMatrixIndex(flat->plane.ubIndexMatrix); gl_RenderState.SetMaterial(flat->gltexture, CLAMP_NONE, 0, -1, false); - gl_RenderState.SetPlaneTextureRotation(&plane, flat->gltexture); DrawSubsectors(flat, pass, false); - gl_RenderState.EnableTextureMatrix(false); } else { @@ -252,15 +251,15 @@ void FDrawInfo::DrawFlat(GLFlat *flat, int pass, bool trans) // trans only has m { if (!flat->gltexture->tex->GetTranslucency()) gl_RenderState.AlphaFunc(GL_GEQUAL, gl_mask_threshold); else gl_RenderState.AlphaFunc(GL_GEQUAL, 0.f); + gl_RenderState.SetTexMatrixIndex(flat->plane.ubIndexMatrix); gl_RenderState.SetMaterial(flat->gltexture, CLAMP_NONE, 0, -1, false); - gl_RenderState.SetPlaneTextureRotation(&plane, flat->gltexture); DrawSubsectors(flat, pass, true); - gl_RenderState.EnableTextureMatrix(false); } if (flat->renderstyle==STYLE_Add) gl_RenderState.BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); gl_RenderState.SetObjectColor(0xffffffff); break; } + gl_RenderState.SetTexMatrixIndex(0); } //========================================================================== diff --git a/src/gl/scene/gl_portal.cpp b/src/gl/scene/gl_portal.cpp index 823b85c3131..54ed0a948f4 100644 --- a/src/gl/scene/gl_portal.cpp +++ b/src/gl/scene/gl_portal.cpp @@ -428,7 +428,7 @@ void GLHorizonPortal::DrawContents(HWDrawInfo *hwdi) gl_RenderState.SetMaterial(gltexture, CLAMP_NONE, 0, -1, false); gl_RenderState.SetObjectColor(origin->specialcolor); - gl_RenderState.SetPlaneTextureRotation(sp, gltexture); + gl_RenderState.SetTexMatrixIndex(sp->ubIndexMatrix); gl_RenderState.AlphaFunc(GL_GEQUAL, 0.f); gl_RenderState.BlendFunc(GL_ONE,GL_ZERO); gl_RenderState.Apply(); @@ -440,7 +440,7 @@ void GLHorizonPortal::DrawContents(HWDrawInfo *hwdi) } GLRenderer->mVBO->RenderArray(GL_TRIANGLE_STRIP, voffset + vcount, 10); - gl_RenderState.EnableTextureMatrix(false); + gl_RenderState.SetTexMatrixIndex(0); } diff --git a/src/gl/scene/gl_skydome.cpp b/src/gl/scene/gl_skydome.cpp index f071c2affe4..2f23535fedb 100644 --- a/src/gl/scene/gl_skydome.cpp +++ b/src/gl/scene/gl_skydome.cpp @@ -32,6 +32,7 @@ #include "gl_load/gl_interface.h" #include "gl/data/gl_vertexbuffer.h" #include "gl/data/gl_modelbuffer.h" +#include "gl/data/gl_texturematrixbuffer.h" #include "gl/renderer/gl_lightdata.h" #include "gl/renderer/gl_renderer.h" #include "gl/renderer/gl_renderstate.h" @@ -123,18 +124,20 @@ void RenderDome(FMaterial * tex, float x_offset, float y_offset, bool mirror, in if (tex) { gl_RenderState.SetMaterial(tex, CLAMP_NONE, 0, -1, false); - gl_RenderState.EnableTextureMatrix(true); - VSMatrix modelmatrix; - GLRenderer->mSkyVBO->SetupMatrices(tex, x_offset, y_offset, mirror, mode, modelmatrix, gl_RenderState.mTextureMatrix); + VSMatrix modelmatrix, texturematrix; + GLRenderer->mSkyVBO->SetupMatrices(tex, x_offset, y_offset, mirror, mode, modelmatrix, texturematrix); GLRenderer->mModelMatrix->Map(); auto ndx = GLRenderer->mModelMatrix->Upload(&modelmatrix, 0); GLRenderer->mModelMatrix->Unmap(); GLRenderer->mModelMatrix->Bind(ndx); + GLRenderer->mTextureMatrices->Map(); + gl_RenderState.SetTexMatrixIndex(GLRenderer->mTextureMatrices->Upload(texturematrix, -1)); + GLRenderer->mTextureMatrices->Unmap(); } GLRenderer->mSkyVBO->RenderDome(tex, mode); - gl_RenderState.EnableTextureMatrix(false); + gl_RenderState.SetTexMatrixIndex(0); GLRenderer->mModelMatrix->Bind(0); } diff --git a/src/gl/shaders/gl_shader.cpp b/src/gl/shaders/gl_shader.cpp index 317d8613e2f..14e712e1852 100644 --- a/src/gl/shaders/gl_shader.cpp +++ b/src/gl/shaders/gl_shader.cpp @@ -43,6 +43,7 @@ #include "gl/renderer/gl_renderstate.h" #include "gl/shaders/gl_shader.h" #include "gl/dynlights/gl_lightbuffer.h" +#include "gl/data/gl_texturematrixbuffer.h" bool FShader::Load(const char * name, const char * vert_prog_lump, const char * frag_prog_lump, const char * proc_prog_lump, const char * light_fragprog, const char * defines) { @@ -76,41 +77,51 @@ bool FShader::Load(const char * name, const char * vert_prog_lump, const char * }; - #ifdef SHADER_STORAGE_LIGHTS + #ifdef USE_SHADER_STORAGE layout(std430, binding = 1) buffer LightBufferSSO { vec4 lights[]; }; - #elif defined NUM_UBO_LIGHTS + + layout(std430, binding = 5) buffer TexMatrixSSO + { + mat4 TextureMatrices[]; + }; + #else uniform LightBufferUBO { vec4 lights[NUM_UBO_LIGHTS]; }; + + uniform TexMatrixUBO + { + mat4 TextureMatrices[NUM_TEXMATRICES]; + }; #endif )"; // Base - i_data += "uniform mat4 TextureMatrix;\n"; // 16, 8 i_data += "uniform vec4 uObjectColor;\n"; i_data += "uniform vec4 uObjectColor2;\n"; i_data += "uniform vec4 uGlowTopPlane;\n"; - i_data += "uniform vec4 uGlowTopColor;\n"; // 32, 24 + i_data += "uniform vec4 uGlowTopColor;\n"; // 16 i_data += "uniform vec4 uGlowBottomPlane;\n"; i_data += "uniform vec4 uGlowBottomColor;\n"; i_data += "uniform vec4 uSplitTopPlane;\n"; - i_data += "uniform vec4 uSplitBottomPlane;\n"; // 48, 40 + i_data += "uniform vec4 uSplitBottomPlane;\n"; // 32 i_data += "uniform vec4 uFogColor;\n"; i_data += "uniform vec4 uDynLightColor;\n"; - i_data += "uniform vec4 uLightAttr;\n"; + i_data += "uniform vec4 uLightAttr;\n"; i_data += "uniform vec2 uClipSplit;\n"; i_data += "uniform float uDesaturationFactor;\n"; - i_data += "uniform float timer;\n"; // 64, 56 + i_data += "uniform float timer;\n"; // 48 i_data += "uniform float uAlphaThreshold;\n"; i_data += "uniform int uTextureMode;\n"; i_data += "uniform int uFogEnabled;\n"; - i_data += "uniform int uLightIndex;\n"; - i_data += "uniform vec2 uSpecularMaterial;\n"; // 70, 62 + i_data += "uniform int uLightIndex;\n"; + i_data += "uniform int uTexMatrixIndex;\n"; // 53 + i_data += "uniform vec2 uSpecularMaterial;\n"; // textures i_data += "uniform sampler2D tex;\n"; @@ -161,6 +172,7 @@ bool FShader::Load(const char * name, const char * vert_prog_lump, const char * assert(GLRenderer->mLights != NULL); unsigned int lightbuffertype = GLRenderer->mLights->GetBufferType(); unsigned int lightbuffersize = GLRenderer->mLights->GetBlockSize(); + unsigned int tmatbuffersize = GLRenderer->mTextureMatrices->GetBlockSize(); if (lightbuffertype == GL_UNIFORM_BUFFER) { vp_comb.Format("#version 330 core\n#define NUM_UBO_LIGHTS %d\n", lightbuffersize); @@ -169,9 +181,9 @@ bool FShader::Load(const char * name, const char * vert_prog_lump, const char * { // This differentiation is for Intel which do not seem to expose the full extension, even if marked as required. if (gl.glslversion < 4.3f) - vp_comb = "#version 400 core\n#extension GL_ARB_shader_storage_buffer_object : require\n#define SHADER_STORAGE_LIGHTS\n"; + vp_comb = "#version 400 core\n#extension GL_ARB_shader_storage_buffer_object : require\n#define USE_SHADER_STORAGE\n"; else - vp_comb = "#version 430 core\n#define SHADER_STORAGE_LIGHTS\n"; + vp_comb = "#version 430 core\n#define USE_SHADER_STORAGE\n"; } if (gl.flags & RFL_SHADER_STORAGE_BUFFER) @@ -319,27 +331,28 @@ bool FShader::Load(const char * name, const char * vert_prog_lump, const char * muSplitTopPlane.Init(hShader, "uSplitTopPlane"); muAlphaThreshold.Init(hShader, "uAlphaThreshold"); muSpecularMaterial.Init(hShader, "uSpecularMaterial"); + muTexMatrixIndex.Init(hShader, "uTexMatrixIndex"); muTimer.Init(hShader, "timer"); lights_index = glGetUniformLocation(hShader, "lights"); - texturematrix_index = glGetUniformLocation(hShader, "TextureMatrix"); - vertexmatrix_index = glGetUniformLocation(hShader, "uQuadVertices"); - texcoordmatrix_index = glGetUniformLocation(hShader, "uQuadTexCoords"); - quadmode_index = glGetUniformLocation(hShader, "uQuadMode"); + int tempindex; if (lightbuffertype == GL_UNIFORM_BUFFER) { - int tempindex = glGetUniformBlockIndex(hShader, "LightBufferUBO"); + tempindex = glGetUniformBlockIndex(hShader, "LightBufferUBO"); if (tempindex != -1) glUniformBlockBinding(hShader, tempindex, LIGHTBUF_BINDINGPOINT); + + tempindex = glGetUniformBlockIndex(hShader, "TexMatrixUBO"); + if (tempindex != -1) glUniformBlockBinding(hShader, tempindex, TEXMATRIX_BINDINGPOINT); + } - int tempindex = glGetUniformBlockIndex(hShader, "ViewpointUBO"); + tempindex = glGetUniformBlockIndex(hShader, "ViewpointUBO"); if (tempindex != -1) glUniformBlockBinding(hShader, tempindex, VIEWPOINT_BINDINGPOINT); tempindex = glGetUniformBlockIndex(hShader, "ModelUBO"); if (tempindex != -1) glUniformBlockBinding(hShader, tempindex, MODELBUF_BINDINGPOINT); glUseProgram(hShader); - if (quadmode_index > 0) glUniform1i(quadmode_index, 0); // set up other texture units (if needed by the shader) for (int i = 2; i<16; i++) diff --git a/src/gl/shaders/gl_shader.h b/src/gl/shaders/gl_shader.h index d8da3ccdca4..2d3fa59e8e2 100644 --- a/src/gl/shaders/gl_shader.h +++ b/src/gl/shaders/gl_shader.h @@ -260,21 +260,13 @@ class FShader FBufferedUniform1f muAlphaThreshold; FBufferedUniform2f muSpecularMaterial; FBufferedUniform1f muTimer; + FBufferedUniform1i muTexMatrixIndex; int lights_index; - int texturematrix_index; -public: - int vertexmatrix_index; - int texcoordmatrix_index; - int quadmode_index; private: int currentglowstate = 0; int currentsplitstate = 0; - int currentcliplinestate = 0; - int currentfixedcolormap = 0; - bool currentTextureMatrixState = true;// by setting the matrix state to 'true' it is guaranteed to be set the first time the render state gets applied. - bool currentModelMatrixState = true; public: FShader(const char *name) diff --git a/src/hwrenderer/data/shaderuniforms.h b/src/hwrenderer/data/shaderuniforms.h index edb8930d1ab..656dca3c4e8 100644 --- a/src/hwrenderer/data/shaderuniforms.h +++ b/src/hwrenderer/data/shaderuniforms.h @@ -9,7 +9,8 @@ enum LIGHTBUF_BINDINGPOINT = 1, POSTPROCESS_BINDINGPOINT = 2, VIEWPOINT_BINDINGPOINT = 3, - MODELBUF_BINDINGPOINT = 4 + MODELBUF_BINDINGPOINT = 4, + TEXMATRIX_BINDINGPOINT = 5, }; enum class UniformType diff --git a/src/hwrenderer/scene/hw_drawinfo.h b/src/hwrenderer/scene/hw_drawinfo.h index 5f703441c3d..55a816ed846 100644 --- a/src/hwrenderer/scene/hw_drawinfo.h +++ b/src/hwrenderer/scene/hw_drawinfo.h @@ -286,6 +286,7 @@ struct HWDrawInfo virtual int UploadLights(FDynLightData &data) = 0; virtual int UploadModelMatrix(VSMatrix &data, float ifactor) = 0; + virtual int UploadTextureMatrix(const VSMatrix &data, int bufferindex) = 0; virtual void ApplyVPUniforms() = 0; virtual bool SetDepthClamp(bool on) = 0; diff --git a/src/hwrenderer/scene/hw_drawstructs.h b/src/hwrenderer/scene/hw_drawstructs.h index d2b2ae5c1eb..505dadcc25a 100644 --- a/src/hwrenderer/scene/hw_drawstructs.h +++ b/src/hwrenderer/scene/hw_drawstructs.h @@ -74,6 +74,7 @@ struct GLSectorPlane float Angle; FVector2 Offs; FVector2 Scale; + int ubIndexMatrix; void GetFromSector(sector_t * sec, int ceiling) { @@ -85,6 +86,7 @@ struct GLSectorPlane texture = sec->GetTexture(ceiling); plane = sec->GetSecPlane(ceiling); Texheight = (float)((ceiling == sector_t::ceiling)? plane.fD() : -plane.fD()); + ubIndexMatrix = sec->planes[ceiling].ubIndexMatrix; } }; @@ -308,7 +310,6 @@ class GLFlat bool ceiling; uint8_t renderflags; int iboindex; - //int vboheight; int dynlightindex; diff --git a/src/hwrenderer/scene/hw_flats.cpp b/src/hwrenderer/scene/hw_flats.cpp index 78ac79ee3c8..214bd71e78a 100644 --- a/src/hwrenderer/scene/hw_flats.cpp +++ b/src/hwrenderer/scene/hw_flats.cpp @@ -84,6 +84,7 @@ bool hw_SetPlaneTextureRotation(const GLSectorPlane * secplane, FMaterial * glte dest.rotate(angle, 0.0f, 0.0f, 1.0f); return true; } + dest.loadIdentity(); return false; } @@ -221,6 +222,17 @@ void GLFlat::Process(HWDrawInfo *di, sector_t * model, int whichplane, bool fog) Colormap.MakeWhite(); lightlevel=255; } + + if (plane.ubIndexMatrix < 0) + { + // Need to recalculate the texture matrix. + // (Note that theoretically two threads can do this at the same time, but since they'd create the same data this isn't critical.) + VSMatrix mat; + plane.ubIndexMatrix = -plane.ubIndexMatrix; + model->planes[whichplane].ubIndexMatrix = plane.ubIndexMatrix; + hw_SetPlaneTextureRotation(&plane, gltexture, mat); + di->UploadTextureMatrix(mat, plane.ubIndexMatrix); + } } else { diff --git a/src/r_defs.h b/src/r_defs.h index 411bb57f490..c463d439170 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -696,26 +696,20 @@ struct sector_t int ubIndexMatrix; // index in uniform buffer for texture matrix data }; - splane planes[2]; // never write directly to this. Always use the access functions! - - enum - { - INV_FLOORPLANE = 1, - INV_CEILINGPLANE = 2, - INV_FLOORMATRIX = 4, - INV_CEILINGMATRIX = 8 - }; - - int invalidflags; + splane planes[2]; void InvalidateMatrix(int pos) { - invalidflags |= pos == sector_t::ceiling ? INV_CEILINGMATRIX : INV_FLOORMATRIX; + // negate the buffer index to mark it as invalid. + auto & p = planes[pos].ubIndexMatrix; + if (p > 0) p = -p; } void InvalidatePlane(int pos) { - invalidflags |= pos == sector_t::ceiling ? INV_CEILINGPLANE : INV_FLOORPLANE; + // negate the buffer index to mark it as invalid. + auto & p = planes[pos].ubIndexPlane; + if (p > 0) p = -p; } void SetXOffset(int pos, double o) diff --git a/wadsrc/static/shaders/glsl/main.vp b/wadsrc/static/shaders/glsl/main.vp index 1b96d7ae034..b0720b80a9c 100644 --- a/wadsrc/static/shaders/glsl/main.vp +++ b/wadsrc/static/shaders/glsl/main.vp @@ -72,7 +72,7 @@ void main() vec2 sst = vec2(r.x/m + 0.5, r.y/m + 0.5); vTexCoord.xy = sst; #else - vTexCoord = TextureMatrix * vec4(parmTexCoord, 0.0, 1.0); + vTexCoord = TextureMatrices[uTexMatrixIndex] * vec4(parmTexCoord, 0.0, 1.0); #endif gl_Position = ProjectionMatrix * eyeCoordPos;