- base the viewpoint buffer on IDataBuffer.

This commit is contained in:
Christoph Oelckers 2018-10-28 13:18:13 +01:00
parent 3b26e64404
commit b51cc8b115
9 changed files with 61 additions and 118 deletions

View file

@ -29,17 +29,18 @@
#include "gl_load/gl_interface.h" #include "gl_load/gl_interface.h"
#include "hwrenderer/data/shaderuniforms.h" #include "hwrenderer/data/shaderuniforms.h"
#include "hwrenderer/scene/hw_viewpointuniforms.h" #include "hwrenderer/scene/hw_viewpointuniforms.h"
#include "hwrenderer/scene/hw_drawinfo.h"
#include "gl_viewpointbuffer.h" #include "gl_viewpointbuffer.h"
static const int INITIAL_BUFFER_SIZE = 100; // 100 viewpoints per frame should nearly always be enough static const int INITIAL_BUFFER_SIZE = 100; // 100 viewpoints per frame should nearly always be enough
GLViewpointBuffer::GLViewpointBuffer() GLViewpointBuffer::GLViewpointBuffer()
{ {
mPersistent = screen->BuffersArePersistent();
mBufferSize = INITIAL_BUFFER_SIZE; mBufferSize = INITIAL_BUFFER_SIZE;
mBlockAlign = ((sizeof(HWViewpointUniforms) / gl.uniformblockalignment) + 1) * gl.uniformblockalignment; mBlockAlign = ((sizeof(HWViewpointUniforms) / screen->uniformblockalignment) + 1) * screen->uniformblockalignment;
mByteSize = mBufferSize * mBlockAlign; mByteSize = mBufferSize * mBlockAlign;
Allocate(); mBuffer = screen->CreateDataBuffer(VIEWPOINT_BINDINGPOINT, false);
mBuffer->SetData(mByteSize, nullptr, false);
Clear(); Clear();
mLastMappedIndex = UINT_MAX; mLastMappedIndex = UINT_MAX;
mClipPlaneInfo.Push(0); mClipPlaneInfo.Push(0);
@ -47,98 +48,32 @@ GLViewpointBuffer::GLViewpointBuffer()
GLViewpointBuffer::~GLViewpointBuffer() GLViewpointBuffer::~GLViewpointBuffer()
{ {
glBindBuffer(GL_UNIFORM_BUFFER, 0); delete mBuffer;
glDeleteBuffers(1, &mBufferId);
} }
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() void GLViewpointBuffer::CheckSize()
{ {
if (mUploadIndex >= mBufferSize) if (mUploadIndex >= mBufferSize)
{ {
// reallocate the buffer with twice the size
unsigned int oldbuffer = mBufferId;
mBufferSize *= 2; mBufferSize *= 2;
mByteSize *= 2; mByteSize *= 2;
mBuffer->Resize(mByteSize);
// 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);
} }
} }
void GLViewpointBuffer::Map() int GLViewpointBuffer::Bind(HWDrawInfo *di, unsigned int index)
{
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)
{ {
if (index != mLastMappedIndex) if (index != mLastMappedIndex)
{ {
mLastMappedIndex = index; mLastMappedIndex = index;
glBindBufferRange(GL_UNIFORM_BUFFER, VIEWPOINT_BINDINGPOINT, mBufferId, index * mBlockAlign, mBlockAlign); mBuffer->BindRange(index * mBlockAlign, mBlockAlign);
di->EnableClipDistance(0, mClipPlaneInfo[index]);
// 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);
}
}
} }
return index; return index;
} }
void GLViewpointBuffer::Set2D(int width, int height) void GLViewpointBuffer::Set2D(HWDrawInfo *di, int width, int height)
{ {
if (width != m2DWidth || height != m2DHeight) if (width != m2DWidth || height != m2DHeight)
{ {
@ -146,25 +81,25 @@ void GLViewpointBuffer::Set2D(int width, int height)
matrices.SetDefaults(); matrices.SetDefaults();
matrices.mProjectionMatrix.ortho(0, width, height, 0, -1.0f, 1.0f); matrices.mProjectionMatrix.ortho(0, width, height, 0, -1.0f, 1.0f);
matrices.CalcDependencies(); matrices.CalcDependencies();
Map(); mBuffer->Map();
memcpy(mBufferPointer, &matrices, sizeof(matrices)); memcpy(mBuffer->Memory(), &matrices, sizeof(matrices));
Unmap(); mBuffer->Unmap();
m2DWidth = width; m2DWidth = width;
m2DHeight = height; m2DHeight = height;
mLastMappedIndex = -1; mLastMappedIndex = -1;
} }
Bind(0); Bind(di, 0);
} }
int GLViewpointBuffer::SetViewpoint(HWViewpointUniforms *vp) int GLViewpointBuffer::SetViewpoint(HWDrawInfo *di, HWViewpointUniforms *vp)
{ {
CheckSize(); CheckSize();
Map(); mBuffer->Map();
memcpy(((char*)mBufferPointer) + mUploadIndex * mBlockAlign, vp, sizeof(*vp)); memcpy(((char*)mBuffer->Memory()) + mUploadIndex * mBlockAlign, vp, sizeof(*vp));
Unmap(); mBuffer->Unmap();
mClipPlaneInfo.Push(vp->mClipHeightDirection != 0.f || vp->mClipLine.X > -10000000.0f); mClipPlaneInfo.Push(vp->mClipHeightDirection != 0.f || vp->mClipLine.X > -10000000.0f);
return Bind(mUploadIndex++); return Bind(di, mUploadIndex++);
} }
void GLViewpointBuffer::Clear() void GLViewpointBuffer::Clear()

View file

@ -1,37 +1,35 @@
#include "tarray.h" #include "tarray.h"
#include "hwrenderer/data/buffers.h"
struct HWViewpointUniforms; struct HWViewpointUniforms;
struct HWDrawInfo;
class GLViewpointBuffer class GLViewpointBuffer
{ {
unsigned int mBufferId; IDataBuffer *mBuffer;
unsigned int mBufferSize; unsigned int mBufferSize;
unsigned int mBlockAlign; unsigned int mBlockAlign;
unsigned int mUploadIndex; unsigned int mUploadIndex;
unsigned int mLastMappedIndex; unsigned int mLastMappedIndex;
unsigned int mByteSize; unsigned int mByteSize;
void * mBufferPointer;
TArray<bool> mClipPlaneInfo; TArray<bool> mClipPlaneInfo;
bool mPersistent;
unsigned int m2DWidth = ~0u, m2DHeight = ~0u; unsigned int m2DWidth = ~0u, m2DHeight = ~0u;
unsigned int mBlockSize; unsigned int mBlockSize;
void CheckSize(); void CheckSize();
void Allocate();
public: public:
GLViewpointBuffer(); GLViewpointBuffer();
~GLViewpointBuffer(); ~GLViewpointBuffer();
void Clear(); void Clear();
void Map(); int Bind(HWDrawInfo *di, unsigned int index);
void Unmap(); void Set2D(HWDrawInfo *di, int width, int height);
int Bind(unsigned int index); int SetViewpoint(HWDrawInfo *di, HWViewpointUniforms *vp);
void Set2D(int width, int height);
int SetViewpoint(HWViewpointUniforms *vp);
unsigned int GetBlockSize() const { return mBlockSize; } unsigned int GetBlockSize() const { return mBlockSize; }
}; };

View file

@ -418,9 +418,11 @@ void FGLRenderer::Draw2D(F2DDrawer *drawer)
FGLDebug::PushGroup("Draw2D"); FGLDebug::PushGroup("Draw2D");
if (VRMode::GetVRMode(true)->mEyeCount == 1) if (VRMode::GetVRMode(true)->mEyeCount == 1)
mBuffers->BindCurrentFB(); mBuffers->BindCurrentFB();
FDrawInfo di; // For access to the virtual interface. This should be placed elsewhere...
const auto &mScreenViewport = screen->mScreenViewport; const auto &mScreenViewport = screen->mScreenViewport;
glViewport(mScreenViewport.left, mScreenViewport.top, mScreenViewport.width, mScreenViewport.height); 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); glDisable(GL_DEPTH_TEST);

View file

@ -263,7 +263,7 @@ void FDrawInfo::RenderPortal(HWPortal *p, bool usestencil)
gp->DrawContents(new_di, gl_RenderState); gp->DrawContents(new_di, gl_RenderState);
new_di->EndDrawInfo(); new_di->EndDrawInfo();
GLRenderer->mVBO->Bind(gl_RenderState); GLRenderer->mVBO->Bind(gl_RenderState);
GLRenderer->mViewpoints->Bind(vpIndex); GLRenderer->mViewpoints->Bind(this, vpIndex);
gp->RemoveStencil(this, gl_RenderState, usestencil); 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); bool multi = !!glIsEnabled(GL_MULTISAMPLE);
GLRenderer->mViewpoints->Set2D(SCREENWIDTH, SCREENHEIGHT); GLRenderer->mViewpoints->Set2D(this, SCREENWIDTH, SCREENHEIGHT);
gl_RenderState.SetColor(0, 0, 0); gl_RenderState.SetColor(0, 0, 0);
gl_RenderState.Apply(); gl_RenderState.Apply();

View file

@ -54,12 +54,12 @@ struct FDrawInfo : public HWDrawInfo
void EnableDrawBufferAttachments(bool on) override; void EnableDrawBufferAttachments(bool on) override;
void SetStencil(int offs, int op, int flags) override; void SetStencil(int offs, int op, int flags) override;
void SetCulling(int mode) override; void SetCulling(int mode) override;
void EnableClipDistance(int num, bool state) override;
void StartScene(); void StartScene();
void DrawSorted(int listindex); 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 AddSubsectorToPortal(FSectorPortalGroup *portal, subsector_t *sub) override;
void CreateScene(); void CreateScene();
@ -74,16 +74,5 @@ struct FDrawInfo : public HWDrawInfo
static FDrawInfo *StartDrawInfo(FRenderViewpoint &parentvp, HWViewpointUniforms *uniforms); static FDrawInfo *StartDrawInfo(FRenderViewpoint &parentvp, HWViewpointUniforms *uniforms);
FDrawInfo *EndDrawInfo(); 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 #endif

View file

@ -78,7 +78,7 @@ EXTERN_CVAR (Bool, r_drawvoxels)
void FDrawInfo::ApplyVPUniforms() void FDrawInfo::ApplyVPUniforms()
{ {
VPUniforms.CalcDependencies(); 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); GLRenderer->mBuffers->BindSceneFB(true);
gl_RenderState.EnableDrawBuffers(gl_RenderState.GetPassDrawBufferCount()); gl_RenderState.EnableDrawBuffers(gl_RenderState.GetPassDrawBufferCount());
gl_RenderState.Apply(); gl_RenderState.Apply();
GLRenderer->mViewpoints->Bind(vpIndex); GLRenderer->mViewpoints->Bind(this, vpIndex);
} }
// Handle all portals after rendering the opaque objects but before // Handle all portals after rendering the opaque objects but before
@ -329,7 +329,7 @@ void FDrawInfo::DrawEndScene2D(sector_t * viewsector)
HWViewpointUniforms vp = VPUniforms; HWViewpointUniforms vp = VPUniforms;
vp.mViewMatrix.loadIdentity(); vp.mViewMatrix.loadIdentity();
vp.mProjectionMatrix = vrmode->GetHUDSpriteProjection(); vp.mProjectionMatrix = vrmode->GetHUDSpriteProjection();
GLRenderer->mViewpoints->SetViewpoint(&vp); GLRenderer->mViewpoints->SetViewpoint(this, &vp);
glDisable(GL_DEPTH_TEST); glDisable(GL_DEPTH_TEST);
glDisable(GL_MULTISAMPLE); glDisable(GL_MULTISAMPLE);

View file

@ -112,6 +112,7 @@ void OpenGLFrameBuffer::InitializeState()
// Move some state to the framebuffer object for easier access. // Move some state to the framebuffer object for easier access.
hwcaps = gl.flags; hwcaps = gl.flags;
glslversion = gl.glslversion; glslversion = gl.glslversion;
uniformblockalignment = gl.uniformblockalignment;
if (first) if (first)
{ {

View file

@ -362,6 +362,7 @@ public:
virtual void EnableDrawBufferAttachments(bool on) = 0; virtual void EnableDrawBufferAttachments(bool on) = 0;
virtual void SetStencil(int offs, int op, int flags) = 0; virtual void SetStencil(int offs, int op, int flags) = 0;
virtual void SetCulling(int mode) = 0; virtual void SetCulling(int mode) = 0;
virtual void EnableClipDistance(int num, bool state) = 0;
}; };

View file

@ -365,11 +365,13 @@ protected:
PalEntry SourcePalette[256]; // This is where unpaletted textures get their palette from PalEntry SourcePalette[256]; // This is where unpaletted textures get their palette from
public: public:
int hwcaps = 0; // 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. 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 instack[2] = { 0,0 }; // this is globally maintained state for portal recursion avoidance.
int stencilValue = 0; // Global stencil test value int stencilValue = 0; // Global stencil test value
bool enable_quadbuffered = false; bool enable_quadbuffered = false; // Quad-buffered stereo available?
unsigned int uniformblockalignment = 256; // Hardware dependent uniform buffer alignment.
FPortalSceneState *mPortalState; // global portal state. 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. FSkyVertexBuffer *mSkyData; // we need access to this in the device independent part, but cannot depend on how the renderer manages it internally.