diff --git a/src/gl/data/gl_viewpointbuffer.cpp b/src/gl/data/gl_viewpointbuffer.cpp index 8f74d4eadf..f109355d65 100644 --- a/src/gl/data/gl_viewpointbuffer.cpp +++ b/src/gl/data/gl_viewpointbuffer.cpp @@ -29,17 +29,18 @@ #include "gl_load/gl_interface.h" #include "hwrenderer/data/shaderuniforms.h" #include "hwrenderer/scene/hw_viewpointuniforms.h" +#include "hwrenderer/scene/hw_drawinfo.h" #include "gl_viewpointbuffer.h" static const int INITIAL_BUFFER_SIZE = 100; // 100 viewpoints per frame should nearly always be enough GLViewpointBuffer::GLViewpointBuffer() { - mPersistent = screen->BuffersArePersistent(); mBufferSize = INITIAL_BUFFER_SIZE; - mBlockAlign = ((sizeof(HWViewpointUniforms) / gl.uniformblockalignment) + 1) * gl.uniformblockalignment; + mBlockAlign = ((sizeof(HWViewpointUniforms) / screen->uniformblockalignment) + 1) * screen->uniformblockalignment; mByteSize = mBufferSize * mBlockAlign; - Allocate(); + mBuffer = screen->CreateDataBuffer(VIEWPOINT_BINDINGPOINT, false); + mBuffer->SetData(mByteSize, nullptr, false); Clear(); mLastMappedIndex = UINT_MAX; mClipPlaneInfo.Push(0); @@ -47,98 +48,32 @@ GLViewpointBuffer::GLViewpointBuffer() GLViewpointBuffer::~GLViewpointBuffer() { - glBindBuffer(GL_UNIFORM_BUFFER, 0); - glDeleteBuffers(1, &mBufferId); + delete mBuffer; } -void GLViewpointBuffer::Allocate() -{ - glGenBuffers(1, &mBufferId); - glBindBufferBase(GL_UNIFORM_BUFFER, VIEWPOINT_BINDINGPOINT, mBufferId); - glBindBuffer(GL_UNIFORM_BUFFER, mBufferId); // Note: Some older AMD drivers don't do that in glBindBufferBase, as they should. - if (mPersistent) - { - glBufferStorage(GL_UNIFORM_BUFFER, mByteSize, NULL, GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT); - mBufferPointer = glMapBufferRange(GL_UNIFORM_BUFFER, 0, mByteSize, GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT); - } - else - { - glBufferData(GL_UNIFORM_BUFFER, mByteSize, NULL, GL_STATIC_DRAW); - mBufferPointer = NULL; - } -} void GLViewpointBuffer::CheckSize() { if (mUploadIndex >= mBufferSize) { - // reallocate the buffer with twice the size - unsigned int oldbuffer = mBufferId; - mBufferSize *= 2; mByteSize *= 2; - - // first unmap the old buffer - glBindBuffer(GL_UNIFORM_BUFFER, mBufferId); - glUnmapBuffer(GL_UNIFORM_BUFFER); - - Allocate(); - glBindBuffer(GL_COPY_READ_BUFFER, oldbuffer); - - // copy contents and delete the old buffer. - glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_UNIFORM_BUFFER, 0, 0, mByteSize / 2); // old size is half of the current one. - glBindBuffer(GL_COPY_READ_BUFFER, 0); - glDeleteBuffers(1, &oldbuffer); + mBuffer->Resize(mByteSize); } } -void GLViewpointBuffer::Map() -{ - if (!mPersistent) - { - glBindBuffer(GL_UNIFORM_BUFFER, mBufferId); - mBufferPointer = (float*)glMapBufferRange(GL_UNIFORM_BUFFER, 0, mByteSize, GL_MAP_WRITE_BIT); - } -} - -void GLViewpointBuffer::Unmap() -{ - if (!mPersistent) - { - glBindBuffer(GL_UNIFORM_BUFFER, mBufferId); - glUnmapBuffer(GL_UNIFORM_BUFFER); - mBufferPointer = nullptr; - } - else - { - glMemoryBarrier(GL_CLIENT_MAPPED_BUFFER_BARRIER_BIT); - } -} - -int GLViewpointBuffer::Bind(unsigned int index) +int GLViewpointBuffer::Bind(HWDrawInfo *di, unsigned int index) { if (index != mLastMappedIndex) { mLastMappedIndex = index; - glBindBufferRange(GL_UNIFORM_BUFFER, VIEWPOINT_BINDINGPOINT, mBufferId, index * mBlockAlign, mBlockAlign); - - // Update the viewpoint-related clip plane setting. - if (!(gl.flags & RFL_NO_CLIP_PLANES)) - { - if (mClipPlaneInfo[index]) - { - glEnable(GL_CLIP_DISTANCE0); - } - else - { - glDisable(GL_CLIP_DISTANCE0); - } - } + mBuffer->BindRange(index * mBlockAlign, mBlockAlign); + di->EnableClipDistance(0, mClipPlaneInfo[index]); } return index; } -void GLViewpointBuffer::Set2D(int width, int height) +void GLViewpointBuffer::Set2D(HWDrawInfo *di, int width, int height) { if (width != m2DWidth || height != m2DHeight) { @@ -146,25 +81,25 @@ void GLViewpointBuffer::Set2D(int width, int height) matrices.SetDefaults(); matrices.mProjectionMatrix.ortho(0, width, height, 0, -1.0f, 1.0f); matrices.CalcDependencies(); - Map(); - memcpy(mBufferPointer, &matrices, sizeof(matrices)); - Unmap(); + mBuffer->Map(); + memcpy(mBuffer->Memory(), &matrices, sizeof(matrices)); + mBuffer->Unmap(); m2DWidth = width; m2DHeight = height; mLastMappedIndex = -1; } - Bind(0); + Bind(di, 0); } -int GLViewpointBuffer::SetViewpoint(HWViewpointUniforms *vp) +int GLViewpointBuffer::SetViewpoint(HWDrawInfo *di, HWViewpointUniforms *vp) { CheckSize(); - Map(); - memcpy(((char*)mBufferPointer) + mUploadIndex * mBlockAlign, vp, sizeof(*vp)); - Unmap(); + mBuffer->Map(); + memcpy(((char*)mBuffer->Memory()) + mUploadIndex * mBlockAlign, vp, sizeof(*vp)); + mBuffer->Unmap(); mClipPlaneInfo.Push(vp->mClipHeightDirection != 0.f || vp->mClipLine.X > -10000000.0f); - return Bind(mUploadIndex++); + return Bind(di, mUploadIndex++); } void GLViewpointBuffer::Clear() diff --git a/src/gl/data/gl_viewpointbuffer.h b/src/gl/data/gl_viewpointbuffer.h index a904875a75..44afdda3bd 100644 --- a/src/gl/data/gl_viewpointbuffer.h +++ b/src/gl/data/gl_viewpointbuffer.h @@ -1,37 +1,35 @@ #include "tarray.h" +#include "hwrenderer/data/buffers.h" struct HWViewpointUniforms; +struct HWDrawInfo; class GLViewpointBuffer { - unsigned int mBufferId; + IDataBuffer *mBuffer; + unsigned int mBufferSize; unsigned int mBlockAlign; unsigned int mUploadIndex; unsigned int mLastMappedIndex; unsigned int mByteSize; - void * mBufferPointer; TArray mClipPlaneInfo; - bool mPersistent; unsigned int m2DWidth = ~0u, m2DHeight = ~0u; unsigned int mBlockSize; void CheckSize(); - void Allocate(); public: GLViewpointBuffer(); ~GLViewpointBuffer(); void Clear(); - void Map(); - void Unmap(); - int Bind(unsigned int index); - void Set2D(int width, int height); - int SetViewpoint(HWViewpointUniforms *vp); + int Bind(HWDrawInfo *di, unsigned int index); + void Set2D(HWDrawInfo *di, int width, int height); + int SetViewpoint(HWDrawInfo *di, HWViewpointUniforms *vp); unsigned int GetBlockSize() const { return mBlockSize; } }; diff --git a/src/gl/renderer/gl_renderer.cpp b/src/gl/renderer/gl_renderer.cpp index c31c22b428..4dfd98c470 100644 --- a/src/gl/renderer/gl_renderer.cpp +++ b/src/gl/renderer/gl_renderer.cpp @@ -418,9 +418,11 @@ void FGLRenderer::Draw2D(F2DDrawer *drawer) FGLDebug::PushGroup("Draw2D"); if (VRMode::GetVRMode(true)->mEyeCount == 1) mBuffers->BindCurrentFB(); + + FDrawInfo di; // For access to the virtual interface. This should be placed elsewhere... const auto &mScreenViewport = screen->mScreenViewport; glViewport(mScreenViewport.left, mScreenViewport.top, mScreenViewport.width, mScreenViewport.height); - GLRenderer->mViewpoints->Set2D(screen->GetWidth(), screen->GetHeight()); + GLRenderer->mViewpoints->Set2D(&di, screen->GetWidth(), screen->GetHeight()); glDisable(GL_DEPTH_TEST); diff --git a/src/gl/scene/gl_drawinfo.cpp b/src/gl/scene/gl_drawinfo.cpp index e096b3e4ab..7cf1f24ecd 100644 --- a/src/gl/scene/gl_drawinfo.cpp +++ b/src/gl/scene/gl_drawinfo.cpp @@ -263,7 +263,7 @@ void FDrawInfo::RenderPortal(HWPortal *p, bool usestencil) gp->DrawContents(new_di, gl_RenderState); new_di->EndDrawInfo(); GLRenderer->mVBO->Bind(gl_RenderState); - GLRenderer->mViewpoints->Bind(vpIndex); + GLRenderer->mViewpoints->Bind(this, vpIndex); gp->RemoveStencil(this, gl_RenderState, usestencil); } @@ -320,6 +320,21 @@ void FDrawInfo::SetCulling(int mode) } } +void FDrawInfo::EnableClipDistance(int num, bool state) +{ + // Update the viewpoint-related clip plane setting. + if (!(gl.flags & RFL_NO_CLIP_PLANES)) + { + if (state) + { + glEnable(GL_CLIP_DISTANCE0+num); + } + else + { + glDisable(GL_CLIP_DISTANCE0+num); + } + } +} //========================================================================== // @@ -330,7 +345,7 @@ void FDrawInfo::ClearScreen() { bool multi = !!glIsEnabled(GL_MULTISAMPLE); - GLRenderer->mViewpoints->Set2D(SCREENWIDTH, SCREENHEIGHT); + GLRenderer->mViewpoints->Set2D(this, SCREENWIDTH, SCREENHEIGHT); gl_RenderState.SetColor(0, 0, 0); gl_RenderState.Apply(); diff --git a/src/gl/scene/gl_drawinfo.h b/src/gl/scene/gl_drawinfo.h index d280cc39b6..a1a1a110c3 100644 --- a/src/gl/scene/gl_drawinfo.h +++ b/src/gl/scene/gl_drawinfo.h @@ -54,12 +54,12 @@ struct FDrawInfo : public HWDrawInfo void EnableDrawBufferAttachments(bool on) override; void SetStencil(int offs, int op, int flags) override; void SetCulling(int mode) override; + void EnableClipDistance(int num, bool state) override; void StartScene(); void DrawSorted(int listindex); - // These two may be moved to the API independent part of the renderer later. void AddSubsectorToPortal(FSectorPortalGroup *portal, subsector_t *sub) override; void CreateScene(); @@ -74,16 +74,5 @@ struct FDrawInfo : public HWDrawInfo static FDrawInfo *StartDrawInfo(FRenderViewpoint &parentvp, HWViewpointUniforms *uniforms); FDrawInfo *EndDrawInfo(); - - void SetColor(int light, int rellight, const FColormap &cm, float alpha, bool weapon = false) - { - gl_RenderState.SetColor(light, rellight, isFullbrightScene(), cm, alpha, weapon); - } - - void SetFog(int lightlevel, int rellight, const FColormap *cmap, bool isadditive) - { - gl_RenderState.SetFog(lightlevel, rellight, isFullbrightScene(), cmap, isadditive); - } - }; #endif diff --git a/src/gl/scene/gl_scene.cpp b/src/gl/scene/gl_scene.cpp index 13e39d14a9..dc2bcfde4c 100644 --- a/src/gl/scene/gl_scene.cpp +++ b/src/gl/scene/gl_scene.cpp @@ -78,7 +78,7 @@ EXTERN_CVAR (Bool, r_drawvoxels) void FDrawInfo::ApplyVPUniforms() { VPUniforms.CalcDependencies(); - vpIndex = GLRenderer->mViewpoints->SetViewpoint(&VPUniforms); + vpIndex = GLRenderer->mViewpoints->SetViewpoint(this, &VPUniforms); } @@ -280,7 +280,7 @@ void FDrawInfo::DrawScene(int drawmode) GLRenderer->mBuffers->BindSceneFB(true); gl_RenderState.EnableDrawBuffers(gl_RenderState.GetPassDrawBufferCount()); gl_RenderState.Apply(); - GLRenderer->mViewpoints->Bind(vpIndex); + GLRenderer->mViewpoints->Bind(this, vpIndex); } // Handle all portals after rendering the opaque objects but before @@ -329,7 +329,7 @@ void FDrawInfo::DrawEndScene2D(sector_t * viewsector) HWViewpointUniforms vp = VPUniforms; vp.mViewMatrix.loadIdentity(); vp.mProjectionMatrix = vrmode->GetHUDSpriteProjection(); - GLRenderer->mViewpoints->SetViewpoint(&vp); + GLRenderer->mViewpoints->SetViewpoint(this, &vp); glDisable(GL_DEPTH_TEST); glDisable(GL_MULTISAMPLE); diff --git a/src/gl/system/gl_framebuffer.cpp b/src/gl/system/gl_framebuffer.cpp index 1916bc8922..8ab7aae058 100644 --- a/src/gl/system/gl_framebuffer.cpp +++ b/src/gl/system/gl_framebuffer.cpp @@ -112,6 +112,7 @@ void OpenGLFrameBuffer::InitializeState() // Move some state to the framebuffer object for easier access. hwcaps = gl.flags; glslversion = gl.glslversion; + uniformblockalignment = gl.uniformblockalignment; if (first) { diff --git a/src/hwrenderer/scene/hw_drawinfo.h b/src/hwrenderer/scene/hw_drawinfo.h index 2de7d19b71..d98a7eec36 100644 --- a/src/hwrenderer/scene/hw_drawinfo.h +++ b/src/hwrenderer/scene/hw_drawinfo.h @@ -362,6 +362,7 @@ public: virtual void EnableDrawBufferAttachments(bool on) = 0; virtual void SetStencil(int offs, int op, int flags) = 0; virtual void SetCulling(int mode) = 0; + virtual void EnableClipDistance(int num, bool state) = 0; }; diff --git a/src/v_video.h b/src/v_video.h index c3c6ebd004..3487a9c9bf 100644 --- a/src/v_video.h +++ b/src/v_video.h @@ -365,13 +365,15 @@ protected: PalEntry SourcePalette[256]; // This is where unpaletted textures get their palette from public: - int hwcaps = 0; - float glslversion = 0; // This is here so that the differences between old OpenGL and new OpenGL/Vulkan can be handled by platform independent code. - int instack[2] = { 0,0 }; // this is globally maintained state for portal recursion avoidance. - int stencilValue = 0; // Global stencil test value - bool enable_quadbuffered = false; - FPortalSceneState *mPortalState; // global portal state. - FSkyVertexBuffer *mSkyData; // we need access to this in the device independent part, but cannot depend on how the renderer manages it internally. + // Hardware render state that needs to be exposed to the API independent part of the renderer. For ease of access this is stored in the base class. + int hwcaps = 0; // Capability flags + float glslversion = 0; // This is here so that the differences between old OpenGL and new OpenGL/Vulkan can be handled by platform independent code. + int instack[2] = { 0,0 }; // this is globally maintained state for portal recursion avoidance. + int stencilValue = 0; // Global stencil test value + bool enable_quadbuffered = false; // Quad-buffered stereo available? + unsigned int uniformblockalignment = 256; // Hardware dependent uniform buffer alignment. + FPortalSceneState *mPortalState; // global portal state. + FSkyVertexBuffer *mSkyData; // we need access to this in the device independent part, but cannot depend on how the renderer manages it internally. IntRect mScreenViewport; IntRect mSceneViewport;