- replaced IUniformBuffer with IDataBuffer, which reuses the code for the other buffer types and is more flexible.

This commit is contained in:
Christoph Oelckers 2018-10-28 11:54:26 +01:00
parent 8abf09afe2
commit a1fb1f60f4
13 changed files with 74 additions and 147 deletions

View file

@ -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

View file

@ -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);
}

View file

@ -1,24 +0,0 @@
#pragma once
#include <stdlib.h>
#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;
}
};

View file

@ -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

View file

@ -21,7 +21,7 @@ public:
GLuint Handle() { return mProgram; }
//explicit operator bool() const { return mProgram != 0; }
std::unique_ptr<IUniformBuffer> Uniforms;
std::unique_ptr<IDataBuffer> Uniforms;
private:
FShaderProgram(const FShaderProgram &) = delete;

View file

@ -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()
{

View file

@ -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

View file

@ -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);
}

View file

@ -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;
};

View file

@ -1,7 +1,7 @@
#pragma once
#include <vector>
#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<UniformFieldDesc> mFields;
};

View file

@ -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.
};

View file

@ -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;
};

View file

@ -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.