diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 86750fc32f..02b810f7a3 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1038,7 +1038,6 @@ set (PCH_SOURCES g_statusbar/sbarinfo.cpp g_statusbar/sbar_mugshot.cpp g_statusbar/shared_sbar.cpp - gl/data/gl_uniformbuffer.cpp gl/data/gl_viewpointbuffer.cpp gl/dynlights/gl_lightbuffer.cpp gl/dynlights/gl_shadowmap.cpp diff --git a/src/gl/data/gl_uniformbuffer.cpp b/src/gl/data/gl_uniformbuffer.cpp deleted file mode 100644 index 010c0aff17..0000000000 --- a/src/gl/data/gl_uniformbuffer.cpp +++ /dev/null @@ -1,84 +0,0 @@ -// -//--------------------------------------------------------------------------- -// -// 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_uniformbuffer.cpp -** Uniform buffer abstraction class. -** -**/ - - -#include "gl_load/gl_system.h" -#include "gl_load/gl_interface.h" -#include "gl_uniformbuffer.h" - - -//========================================================================== -// -// -// -//========================================================================== - -GLUniformBuffer::GLUniformBuffer(size_t size, bool staticdraw) -: IUniformBuffer(size), mStaticDraw(staticdraw) -{ - glGenBuffers(1, &mBufferId); -} - -//========================================================================== -// -// -// -//========================================================================== - -GLUniformBuffer::~GLUniformBuffer() -{ - if (mBufferId != 0) - { - glDeleteBuffers(1, &mBufferId); - } -} - -//========================================================================== -// -// -// -//========================================================================== - -void GLUniformBuffer::SetData(const void *data) -{ - if (mBufferId != 0) - { - glBindBuffer(GL_UNIFORM_BUFFER, mBufferId); - glBufferData(GL_UNIFORM_BUFFER, mSize, data, mStaticDraw? GL_STATIC_DRAW : GL_STREAM_DRAW); - } -} - -//========================================================================== -// -// This needs to go away later. -// -//========================================================================== - -void GLUniformBuffer::Bind(int bindingpoint) -{ - glBindBufferBase(GL_UNIFORM_BUFFER, bindingpoint, mBufferId); -} diff --git a/src/gl/data/gl_uniformbuffer.h b/src/gl/data/gl_uniformbuffer.h deleted file mode 100644 index 64c1831be7..0000000000 --- a/src/gl/data/gl_uniformbuffer.h +++ /dev/null @@ -1,24 +0,0 @@ -#pragma once - -#include -#include "hwrenderer/data/uniformbuffer.h" - - -class GLUniformBuffer : public IUniformBuffer -{ - unsigned mBufferId; - bool mStaticDraw; - -public: - GLUniformBuffer(size_t size, bool staticdraw = false); - ~GLUniformBuffer(); - - void SetData(const void *data) override; - void Bind(int bindingpoint) override; - - unsigned ID() const - { - return mBufferId; - } - -}; diff --git a/src/gl/renderer/gl_renderbuffers.cpp b/src/gl/renderer/gl_renderbuffers.cpp index 48cbd0e754..4946afca1f 100644 --- a/src/gl/renderer/gl_renderbuffers.cpp +++ b/src/gl/renderer/gl_renderbuffers.cpp @@ -966,9 +966,9 @@ void FGLRenderBuffers::RenderEffect(const FString &name) if (step.Uniforms.Size > 0) { if (!shader->Uniforms) - shader->Uniforms.reset(screen->CreateUniformBuffer(step.Uniforms.Size)); - shader->Uniforms->SetData(step.Uniforms.Data); - shader->Uniforms->Bind(POSTPROCESS_BINDINGPOINT); + shader->Uniforms.reset(screen->CreateDataBuffer(POSTPROCESS_BINDINGPOINT, false)); + shader->Uniforms->SetData(step.Uniforms.Size, step.Uniforms.Data); + shader->Uniforms->BindBase(); } // Set shader diff --git a/src/gl/shaders/gl_shaderprogram.h b/src/gl/shaders/gl_shaderprogram.h index c0b8a72195..fb5a117ca3 100644 --- a/src/gl/shaders/gl_shaderprogram.h +++ b/src/gl/shaders/gl_shaderprogram.h @@ -21,7 +21,7 @@ public: GLuint Handle() { return mProgram; } //explicit operator bool() const { return mProgram != 0; } - std::unique_ptr Uniforms; + std::unique_ptr Uniforms; private: FShaderProgram(const FShaderProgram &) = delete; diff --git a/src/gl/system/gl_framebuffer.cpp b/src/gl/system/gl_framebuffer.cpp index 780d494ec1..cceb4a3106 100644 --- a/src/gl/system/gl_framebuffer.cpp +++ b/src/gl/system/gl_framebuffer.cpp @@ -38,7 +38,6 @@ #include "gl/textures/gl_samplers.h" #include "hwrenderer/utility/hw_clock.h" #include "hwrenderer/utility/hw_vrmodes.h" -#include "gl/data/gl_uniformbuffer.h" #include "hwrenderer/models/hw_models.h" #include "gl/shaders/gl_shaderprogram.h" #include "gl_debug.h" @@ -353,11 +352,6 @@ FModelRenderer *OpenGLFrameBuffer::CreateModelRenderer(int mli) return new FGLModelRenderer(nullptr, gl_RenderState, mli); } -IUniformBuffer *OpenGLFrameBuffer::CreateUniformBuffer(size_t size, bool staticuse) -{ - return new GLUniformBuffer(size, staticuse); -} - IShaderProgram *OpenGLFrameBuffer::CreateShaderProgram() { return new FShaderProgram; @@ -373,6 +367,11 @@ IIndexBuffer *OpenGLFrameBuffer::CreateIndexBuffer() return new GLIndexBuffer; } +IDataBuffer *OpenGLFrameBuffer::CreateDataBuffer(int bindingpoint, bool ssbo) +{ + return new GLDataBuffer(bindingpoint, ssbo); +} + void OpenGLFrameBuffer::TextureFilterChanged() { diff --git a/src/gl/system/gl_framebuffer.h b/src/gl/system/gl_framebuffer.h index 2a6ff6457f..9f14bbb5de 100644 --- a/src/gl/system/gl_framebuffer.h +++ b/src/gl/system/gl_framebuffer.h @@ -41,10 +41,10 @@ public: void BeginFrame() override; void SetViewportRects(IntRect *bounds) override; void BlurScene(float amount) override; - IUniformBuffer *CreateUniformBuffer(size_t size, bool staticuse = false) override; - IShaderProgram *CreateShaderProgram() override; + IShaderProgram *CreateShaderProgram() override; IVertexBuffer *CreateVertexBuffer() override; IIndexBuffer *CreateIndexBuffer() override; + IDataBuffer *CreateDataBuffer(int bindingpoint, bool ssbo) override; // Retrieves a buffer containing image data for a screenshot. // Hint: Pitch can be negative for upside-down images, in which case buffer diff --git a/src/gl/system/glsys_vertexbuffer.cpp b/src/gl/system/glsys_vertexbuffer.cpp index c68cad69ae..a6bfd0a953 100644 --- a/src/gl/system/glsys_vertexbuffer.cpp +++ b/src/gl/system/glsys_vertexbuffer.cpp @@ -122,6 +122,32 @@ void GLBuffer::Unlock() gl_RenderState.ResetVertexBuffer(); } +void GLBuffer::Resize(size_t newsize) +{ + assert(!nomap); // only mappable buffers can be resized. + if (newsize > buffersize && !nomap) + { + // reallocate the buffer with twice the size + unsigned int oldbuffer = mBufferId; + + // first unmap the old buffer + Bind(); + glUnmapBuffer(mUseType); + + glGenBuffers(1, &mBufferId); + SetData(newsize, nullptr, false); + glBindBuffer(GL_COPY_READ_BUFFER, oldbuffer); + + // copy contents and delete the old buffer. + glCopyBufferSubData(GL_COPY_READ_BUFFER, mUseType, 0, 0, buffersize); + glBindBuffer(GL_COPY_READ_BUFFER, 0); + glDeleteBuffers(1, &oldbuffer); + buffersize = newsize; + gl_RenderState.ResetVertexBuffer(); + } +} + + //=========================================================================== // // Vertex buffer implementation @@ -171,3 +197,13 @@ void GLVertexBuffer::Bind(int *offsets) } } +void GLDataBuffer::BindRange(size_t start, size_t length) +{ + if (mUseType == GL_UNIFORM_BUFFER) // SSBO's cannot be rebound. + glBindBufferRange(mUseType, mBindingPoint, mBufferId, start, length); +} + +void GLDataBuffer::BindBase() +{ + glBindBufferBase(mUseType, mBindingPoint, mBufferId); +} diff --git a/src/gl/system/glsys_vertexbuffer.h b/src/gl/system/glsys_vertexbuffer.h index 7085bafc50..b76a56eea6 100644 --- a/src/gl/system/glsys_vertexbuffer.h +++ b/src/gl/system/glsys_vertexbuffer.h @@ -10,9 +10,9 @@ class GLBuffer : virtual public IBuffer { +protected: const int mUseType; unsigned int mBufferId; -protected: int mAllocationSize = 0; bool mPersistent = false; bool nomap = true; @@ -22,6 +22,7 @@ protected: void SetData(size_t size, void *data, bool staticdata) override; void Map() override; void Unmap() override; + void Resize(size_t newsize) override; void *Lock(unsigned int size) override; void Unlock() override; public: @@ -56,3 +57,12 @@ public: GLIndexBuffer() : GLBuffer(GL_ELEMENT_ARRAY_BUFFER) {} }; +class GLDataBuffer : public IDataBuffer, public GLBuffer +{ + int mBindingPoint; +public: + GLDataBuffer(int bindingpoint, bool is_ssbo) : GLBuffer(is_ssbo? GL_SHADER_STORAGE_BUFFER : GL_UNIFORM_BUFFER), mBindingPoint(bindingpoint) {} + void BindRange(size_t start, size_t length) override; + void BindBase() override; +}; + diff --git a/src/hwrenderer/data/shaderuniforms.h b/src/hwrenderer/data/shaderuniforms.h index 4ec9c2393d..b375b649e6 100644 --- a/src/hwrenderer/data/shaderuniforms.h +++ b/src/hwrenderer/data/shaderuniforms.h @@ -1,7 +1,7 @@ #pragma once #include -#include "hwrenderer/data/uniformbuffer.h" +#include "hwrenderer/data/vertexbuffer.h" #include "v_video.h" enum @@ -116,17 +116,17 @@ public: void Init() { if (mBuffer == nullptr) - mBuffer = screen->CreateUniformBuffer(sizeof(T)); + mBuffer = screen->CreateDataBuffer(bindingpoint, false); } void Set(bool bind = true) { if (mBuffer != nullptr) - mBuffer->SetData(&Values); + mBuffer->SetData(sizeof(T), &Values); // Let's hope this can be done better when things have moved further ahead. // This really is not the best place to add something that depends on API behavior. - if (bind) mBuffer->Bind(bindingpoint); + if (bind) mBuffer->BindBase(); } T *operator->() { return &Values; } @@ -138,7 +138,7 @@ private: ShaderUniforms(const ShaderUniforms &) = delete; ShaderUniforms &operator=(const ShaderUniforms &) = delete; - IUniformBuffer *mBuffer = nullptr; + IDataBuffer *mBuffer = nullptr; std::vector mFields; }; diff --git a/src/hwrenderer/data/uniformbuffer.h b/src/hwrenderer/data/uniformbuffer.h deleted file mode 100644 index 9aa078d3d8..0000000000 --- a/src/hwrenderer/data/uniformbuffer.h +++ /dev/null @@ -1,18 +0,0 @@ -#pragma once - -#include "zstring.h" - -class IUniformBuffer -{ -protected: - size_t mSize; - - IUniformBuffer(size_t size) : mSize(size) {} - -public: - virtual ~IUniformBuffer() {} - virtual void SetData(const void *data) = 0; - virtual void Bind(int bindingpoint) = 0; // This is only here for OpenGL. Vulkan doesn't need the ability to bind this at run time. - - -}; diff --git a/src/hwrenderer/data/vertexbuffer.h b/src/hwrenderer/data/vertexbuffer.h index ae3883d173..d179d5447e 100644 --- a/src/hwrenderer/data/vertexbuffer.h +++ b/src/hwrenderer/data/vertexbuffer.h @@ -47,6 +47,7 @@ public: virtual void SetData(size_t size, void *data, bool staticdata = true) = 0; virtual void *Lock(unsigned int size) = 0; virtual void Unlock() = 0; + virtual void Resize(size_t newsize) = 0; virtual void Map() {} // Only needed by old OpenGL but this needs to be in the interface. virtual void Unmap() {} void *Memory() { assert(map); return map; } @@ -67,3 +68,11 @@ class IIndexBuffer : virtual public IBuffer // Ob Vulkam, element size is a buffer property and of no concern to the drawing functions (as it should be.) }; +class IDataBuffer : virtual public IBuffer +{ + // Can be either uniform or shader storage buffer, depending on its needs. +public: + virtual void BindRange(size_t start, size_t length) = 0; + virtual void BindBase() = 0; + +}; \ No newline at end of file diff --git a/src/v_video.h b/src/v_video.h index d63c8cbaab..c3c6ebd004 100644 --- a/src/v_video.h +++ b/src/v_video.h @@ -52,6 +52,7 @@ struct FPortalSceneState; class FSkyVertexBuffer; class IIndexBuffer; class IVertexBuffer; +class IDataBuffer; enum EHWCaps { @@ -335,7 +336,6 @@ public: class FUniquePalette; class IHardwareTexture; class FTexture; -class IUniformBuffer; // A canvas that represents the actual display. The video code is responsible // for actually implementing this. Built on top of SimpleCanvas, because it @@ -450,10 +450,10 @@ public: virtual void BlurScene(float amount) {} // Interface to hardware rendering resources - virtual IUniformBuffer *CreateUniformBuffer(size_t size, bool staticuse = false) { return nullptr; } virtual IShaderProgram *CreateShaderProgram() { return nullptr; } virtual IVertexBuffer *CreateVertexBuffer() { return nullptr; } virtual IIndexBuffer *CreateIndexBuffer() { return nullptr; } + virtual IDataBuffer *CreateDataBuffer(int bindingpoint, bool ssbo) { return nullptr; } bool BuffersArePersistent() { return !!(hwcaps & RFL_BUFFER_STORAGE); } // Begin/End 2D drawing operations.