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;