Skip to content

Commit

Permalink
- generalization of the texture matrix class to handle other type of …
Browse files Browse the repository at this point in the history
…data as well.
  • Loading branch information
coelckers committed Aug 19, 2018
1 parent 68bbf4e commit c3cc79f
Show file tree
Hide file tree
Showing 10 changed files with 122 additions and 120 deletions.
2 changes: 1 addition & 1 deletion src/CMakeLists.txt
Expand Up @@ -1047,7 +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/data/gl_dynamicuniformbuffer.cpp
gl/dynlights/gl_lightbuffer.cpp
gl/dynlights/gl_shadowmap.cpp
gl/models/gl_models.cpp
Expand Down
Expand Up @@ -20,25 +20,27 @@
//--------------------------------------------------------------------------
//
/*
** gl_viewpointbuffer.cpp
** Buffer data maintenance for per viewpoint uniform data
** gl_dynamicuniformbuffer.cpp
** Buffer class for semi-static map data (i.e. the size is constant, but content may change occasionally)
**
**/

#include "gl_load/gl_system.h"
#include "gl_load/gl_interface.h"
#include "hwrenderer/data/shaderuniforms.h"
#include "gl_texturematrixbuffer.h"
#include "gl_dynamicuniformbuffer.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()
GLDynamicUniformBuffer::GLDynamicUniformBuffer(int bindingpoint, unsigned int elementsize, unsigned int reserved, unsigned forstreaming, void (*staticinitfunc)(char *buffer))
{
mSectorCount = INITIAL_SECTOR_COUNT;
mElementCount = reserved + forstreaming;
mReservedCount = reserved;
mStreamCount = forstreaming;
mElementSize = elementsize;
mLastBoundIndex = UINT_MAX;
mBufferId = 0;
mUploadIndex = reserved;
mStaticInitFunc = staticinitfunc;

if (gl.flags & RFL_SHADER_STORAGE_BUFFER && !strstr(gl.vendorstring, "Intel"))
{
Expand All @@ -49,30 +51,26 @@ GLTextureMatrixBuffer::GLTextureMatrixBuffer()
else
{
mBufferType = GL_UNIFORM_BUFFER;
// A matrix is always 64 bytes.
if (gl.maxuniformblock % sizeof(VSMatrix) == 0)
if (gl.maxuniformblock % elementsize == 0)
{
mBlockAlign = gl.maxuniformblock;
}
else
{
mBlockAlign = gl.uniformblockalignment; // this should really never happen.
mBlockAlign = gl.uniformblockalignment;
}
mBlockSize = mBlockAlign / sizeof(VSMatrix);
mBlockSize = mBlockAlign / elementsize;
}

mBufferId = 0;
mUploadIndex = 2;
Allocate();
mLastMappedIndex = UINT_MAX;
}

GLTextureMatrixBuffer::~GLTextureMatrixBuffer()
GLDynamicUniformBuffer::~GLDynamicUniformBuffer()
{
Unload();
}

void GLTextureMatrixBuffer::Unload()
void GLDynamicUniformBuffer::Unload()
{
if (mBufferId != 0)
{
Expand All @@ -84,19 +82,18 @@ void GLTextureMatrixBuffer::Unload()
mBufferId = 0;
}

void GLTextureMatrixBuffer::Allocate()
void GLDynamicUniformBuffer::Allocate()
{
Unload();

mBufferSize = mSectorCount * 2 + ADDITIONAL_ENTRIES;
mByteSize = mBufferSize * sizeof(VSMatrix);
mByteSize = mElementCount * mElementSize;
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);
mBufferPointer = (char*)glMapBufferRange(mBufferType, 0, mByteSize, GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT);
mPersistent = true;
}
else
Expand All @@ -105,44 +102,33 @@ void GLTextureMatrixBuffer::Allocate()
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();
if (mStaticInitFunc != nullptr)
{
Map();
mStaticInitFunc(mBufferPointer);
Unmap();
}
}

void GLTextureMatrixBuffer::ValidateSize(int numsectors)
void GLDynamicUniformBuffer::ValidateSize(int newnumelements) // that is 'new elements plus the reserved items'
{
if (mSectorCount < numsectors)
if (mElementCount < newnumelements)
{
mSectorCount = MAX<unsigned>(mSectorCount*2, numsectors);
mElementCount = newnumelements;
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()
void GLDynamicUniformBuffer::Map()
{
if (!mPersistent)
{
glBindBuffer(mBufferType, mBufferId);
mBufferPointer = (VSMatrix*)glMapBufferRange(mBufferType, 0, mByteSize, GL_MAP_WRITE_BIT);
mBufferPointer = (char*)glMapBufferRange(mBufferType, 0, mByteSize, GL_MAP_WRITE_BIT);
}
}

void GLTextureMatrixBuffer::Unmap()
void GLDynamicUniformBuffer::Unmap()
{
if (!mPersistent && mBufferPointer)
{
Expand All @@ -152,38 +138,36 @@ void GLTextureMatrixBuffer::Unmap()
}
}

int GLTextureMatrixBuffer::Upload(const VSMatrix &mat, int index)
int GLDynamicUniformBuffer::Upload(const void *data, int index, unsigned int count)
{
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.
if (index == -1) // dynamic case. Currently only used by the texture matrix for the 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.
if (mStreamCount == 0) return 0; // don't do this!
index = mUploadIndex++;
if (index >= 50)
if (index >= mReservedCount + mStreamCount)
{
index = 2;
index = mReservedCount;
}
}

mBufferPointer[index] = mat;
memcpy(mBufferPointer + index * mElementSize, data, count * mElementSize);
return index;
}

// When this gets called we already have ruled out the case where rebinding is not needed.
int GLTextureMatrixBuffer::DoBind(unsigned int index)
int GLDynamicUniformBuffer::DoBind(unsigned int index)
{
unsigned int offset = (index*sizeof(VSMatrix) / mBlockAlign) * mBlockAlign;
unsigned int offset = ((index*mElementSize) / mBlockAlign) * mBlockAlign;

if (offset != mLastMappedIndex)
if (offset != mLastBoundIndex)
{
mLastMappedIndex = offset;
mLastBoundIndex = offset;
glBindBufferRange(GL_UNIFORM_BUFFER, TEXMATRIX_BINDINGPOINT, mBufferId, offset, MIN(mBlockAlign, mByteSize - offset));
}
return index - (offset/sizeof(VSMatrix));
return index - offset / mElementSize;
}


50 changes: 50 additions & 0 deletions src/gl/data/gl_dynamicuniformbuffer.h
@@ -0,0 +1,50 @@
#pragma once


class GLDynamicUniformBuffer
{
bool mPersistent;
unsigned int mBufferId;
unsigned int mBufferType;

unsigned int mByteSize; // size of buffer in bytes
unsigned int mElementSize; // size of one element in bytes
unsigned int mElementCount; // number of elements in the buffer
unsigned int mReservedCount; // number of reserved elements (will not be used for other things.)
unsigned int mStreamCount; // number of elements for streaming data (used as a ring buffer.)
unsigned int mBlockAlign; // binding alignment in bytes
unsigned int mBlockSize; // how many element fit in one bindable block.
unsigned int mUploadIndex; // upload index for next streamable element
unsigned int mLastBoundIndex; // last active binding index
char *mBufferPointer;
void (*mStaticInitFunc)(char *buffer);

void Allocate();
int DoBind(unsigned index);
void Unload();

public:

// Init is a function because it may have to be called again upon reallocation.
GLDynamicUniformBuffer(int bindingpoint, unsigned int elementsize, unsigned int reserved, unsigned forstreaming, void (*staticinitfunc)(char *buffer));
~GLDynamicUniformBuffer();
void ValidateSize(int numelements);
int Upload(const void *src, int index, unsigned int count);
void Map();
void Unmap();
int Bind(unsigned int index)
{
if (mBlockAlign > 0) return DoBind(index);
return index;
}
unsigned int GetBlockSize() const
{
return mBlockSize;
}
unsigned int DynamicStart() const
{
return mReservedCount + mStreamCount;
}

};

48 changes: 0 additions & 48 deletions src/gl/data/gl_texturematrixbuffer.h

This file was deleted.

21 changes: 18 additions & 3 deletions src/gl/renderer/gl_renderer.cpp
Expand Up @@ -58,7 +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 "gl/data/gl_dynamicuniformbuffer.h"
#include "r_videoscale.h"

EXTERN_CVAR(Int, screenblocks)
Expand Down Expand Up @@ -107,7 +107,14 @@ void FGLRenderer::Initialize(int width, int height)
mLights = new FLightBuffer();
mViewpoints = new GLViewpointBuffer;
mModelMatrix = new GLModelBuffer;
mTextureMatrices = new GLTextureMatrixBuffer;
mTextureMatrices = new GLDynamicUniformBuffer(TEXMATRIX_BINDINGPOINT, sizeof(VSMatrix), 2, 50, [](char *buffer) {
VSMatrix mat[2];
mat[0].loadIdentity();
mat[1].loadIdentity();
mat[1].scale(1.f, -1.f, 1.f);
mat[1].translate(0.f, 1.f, 0.0f);
memcpy(buffer, mat, sizeof(mat));
});
gl_RenderState.SetVertexBuffer(mVBO);
mFBID = 0;
mOldFBID = 0;
Expand Down Expand Up @@ -164,7 +171,15 @@ void FGLRenderer::ResetSWScene()
void FGLRenderer::SetupLevel()
{
mVBO->CreateVBO();
mTextureMatrices->ValidateSize(level.sectors.Size());
mTextureMatrices->ValidateSize(level.sectors.Size()*2);
// Mark all indices as uninitialized.
int tmindex = -(int)mTextureMatrices->DynamicStart();

for (auto &sec : level.sectors)
{
sec.planes[sector_t::floor].ubIndexMatrix = tmindex--;
sec.planes[sector_t::ceiling].ubIndexMatrix = tmindex--;
}
}

//===========================================================================
Expand Down
4 changes: 2 additions & 2 deletions src/gl/renderer/gl_renderer.h
Expand Up @@ -37,7 +37,7 @@ class FCustomPostProcessShaders;
class SWSceneDrawer;
class GLViewpointBuffer;
class GLModelBuffer;
class GLTextureMatrixBuffer;
class GLDynamicUniformBuffer;
struct FRenderViewpoint;
#define NOQUEUE nullptr // just some token to be used as a placeholder

Expand Down Expand Up @@ -83,7 +83,7 @@ class FGLRenderer
FLightBuffer *mLights = nullptr;
GLViewpointBuffer *mViewpoints = nullptr;
GLModelBuffer *mModelMatrix = nullptr;
GLTextureMatrixBuffer *mTextureMatrices = nullptr;
GLDynamicUniformBuffer *mTextureMatrices = nullptr;
SWSceneDrawer *swdrawer = nullptr;

FPortalSceneState mPortalState;
Expand Down
2 changes: 1 addition & 1 deletion src/gl/renderer/gl_renderstate.cpp
Expand Up @@ -37,7 +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"
#include "gl/data/gl_dynamicuniformbuffer.h"

void gl_SetTextureMode(int type);

Expand Down
4 changes: 2 additions & 2 deletions src/gl/scene/gl_drawinfo.cpp
Expand Up @@ -37,7 +37,7 @@

#include "gl/data/gl_vertexbuffer.h"
#include "gl/data/gl_modelbuffer.h"
#include "gl/data/gl_texturematrixbuffer.h"
#include "gl/data/gl_dynamicuniformbuffer.h"
#include "gl/scene/gl_drawinfo.h"
#include "hwrenderer/scene/hw_clipper.h"
#include "gl/scene/gl_portal.h"
Expand Down Expand Up @@ -271,7 +271,7 @@ int FDrawInfo::UploadModelMatrix(VSMatrix &data, float ifactor)

int FDrawInfo::UploadTextureMatrix(const VSMatrix &data, int bufferindex)
{
return GLRenderer->mTextureMatrices->Upload(data, bufferindex);
return GLRenderer->mTextureMatrices->Upload(&data, bufferindex, 1);
}

bool FDrawInfo::SetDepthClamp(bool on)
Expand Down

0 comments on commit c3cc79f

Please sign in to comment.