- some cleanup on the OpenGL interface and its flags.

Most importantly, the separate command line options for switching on the legacy buffer handling have been removed.
There's really no need for them anymore, because unlike in earlier versions many of the implementation differences no longer exist - with the exception of where the light and vertex buffer contents are generated.
For testing this, -glversion 3 is sufficient.
This commit is contained in:
Christoph Oelckers 2018-10-20 12:55:25 +02:00
parent 9253118bdc
commit 5f838d52b9
19 changed files with 39 additions and 62 deletions

View file

@ -99,9 +99,10 @@ void FSimpleVertexBuffer::set(FSimpleVertex *verts, int count)
FFlatVertexBuffer::FFlatVertexBuffer(int width, int height)
: FVertexBuffer(true), FFlatVertexGenerator(width, height)
{
mPersistent = screen->BuffersArePersistent();
ibo_id = 0;
glGenBuffers(1, &ibo_id);
if (gl.buffermethod == BM_PERSISTENT)
if (mPersistent)
{
unsigned int bytesize = BUFFER_SIZE * sizeof(FFlatVertex);
glBindBuffer(GL_ARRAY_BUFFER, vbo_id);
@ -165,7 +166,7 @@ void FFlatVertexBuffer::BindVBO()
void FFlatVertexBuffer::Map()
{
if (gl.buffermethod == BM_DEFERRED)
if (!mPersistent)
{
unsigned int bytesize = BUFFER_SIZE * sizeof(FFlatVertex);
glBindBuffer(GL_ARRAY_BUFFER, vbo_id);
@ -176,7 +177,7 @@ void FFlatVertexBuffer::Map()
void FFlatVertexBuffer::Unmap()
{
if (gl.buffermethod == BM_DEFERRED)
if (!mPersistent)
{
unsigned int bytesize = BUFFER_SIZE * sizeof(FFlatVertex);
glBindBuffer(GL_ARRAY_BUFFER, vbo_id);

View file

@ -101,6 +101,7 @@ class FFlatVertexBuffer : public FVertexBuffer, public FFlatVertexGenerator
std::atomic<unsigned int> mCurIndex;
std::mutex mBufferMutex;
unsigned int mNumReserved;
bool mPersistent;
static const unsigned int BUFFER_SIZE = 2000000;

View file

@ -35,6 +35,7 @@ static const int INITIAL_BUFFER_SIZE = 100; // 100 viewpoints per frame should n
GLViewpointBuffer::GLViewpointBuffer()
{
mPersistent = screen->BuffersArePersistent();
mBufferSize = INITIAL_BUFFER_SIZE;
mBlockAlign = ((sizeof(HWViewpointUniforms) / gl.uniformblockalignment) + 1) * gl.uniformblockalignment;
mByteSize = mBufferSize * mBlockAlign;
@ -55,7 +56,7 @@ 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 (gl.flags & RFL_BUFFER_STORAGE)
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);
@ -93,7 +94,7 @@ void GLViewpointBuffer::CheckSize()
void GLViewpointBuffer::Map()
{
if (!(gl.flags & RFL_BUFFER_STORAGE))
if (!mPersistent)
{
glBindBuffer(GL_UNIFORM_BUFFER, mBufferId);
mBufferPointer = (float*)glMapBufferRange(GL_UNIFORM_BUFFER, 0, mByteSize, GL_MAP_WRITE_BIT);
@ -102,7 +103,7 @@ void GLViewpointBuffer::Map()
void GLViewpointBuffer::Unmap()
{
if (!(gl.flags & RFL_BUFFER_STORAGE))
if (!mPersistent)
{
glBindBuffer(GL_UNIFORM_BUFFER, mBufferId);
glUnmapBuffer(GL_UNIFORM_BUFFER);

View file

@ -13,6 +13,7 @@ class GLViewpointBuffer
unsigned int mByteSize;
void * mBufferPointer;
TArray<bool> mClipPlaneInfo;
bool mPersistent;
unsigned int m2DWidth = ~0u, m2DHeight = ~0u;

View file

@ -40,6 +40,7 @@ FLightBuffer::FLightBuffer()
{
int maxNumberOfLights = 40000;
mPersistentBuffer = screen->BuffersArePersistent();
mBufferSize = maxNumberOfLights * ELEMENTS_PER_LIGHT;
mByteSize = mBufferSize * ELEMENT_SIZE;
@ -65,7 +66,7 @@ FLightBuffer::FLightBuffer()
glGenBuffers(1, &mBufferId);
glBindBufferBase(mBufferType, LIGHTBUF_BINDINGPOINT, mBufferId);
glBindBuffer(mBufferType, mBufferId); // Note: Some older AMD drivers don't do that in glBindBufferBase, as they should.
if (gl.lightmethod == LM_DIRECT)
if (mPersistentBuffer)
{
glBufferStorage(mBufferType, mByteSize, NULL, GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT);
mBufferPointer = (float*)glMapBufferRange(mBufferType, 0, mByteSize, GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT);
@ -119,7 +120,7 @@ void FLightBuffer::CheckSize()
}
mBufferSize = mByteSize / ELEMENT_SIZE;
if (gl.lightmethod == LM_DIRECT)
if (mPersistentBuffer)
{
glBufferStorage(mBufferType, mByteSize, NULL, GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT);
mBufferPointer = (float*)glMapBufferRange(mBufferType, 0, mByteSize, GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT);
@ -201,7 +202,7 @@ int FLightBuffer::UploadLights(FDynLightData &data)
void FLightBuffer::Begin()
{
if (gl.lightmethod == LM_DEFERRED)
if (!mPersistentBuffer)
{
glBindBuffer(mBufferType, mBufferId);
mBufferPointer = (float*)glMapBufferRange(mBufferType, 0, mByteSize, GL_MAP_WRITE_BIT);
@ -210,7 +211,7 @@ void FLightBuffer::Begin()
void FLightBuffer::Finish()
{
if (gl.lightmethod == LM_DEFERRED)
if (!mPersistentBuffer)
{
glBindBuffer(mBufferType, mBufferId);
glUnmapBuffer(mBufferType);

View file

@ -19,6 +19,7 @@ class FLightBuffer
unsigned int mBufferSize;
unsigned int mByteSize;
unsigned int mMaxUploadSize;
bool mPersistentBuffer;
std::mutex mBufferMutex;
TArray<float> mBufferedData;

View file

@ -62,7 +62,7 @@ void FDrawInfo::DrawSubsectors(GLFlat *flat, int pass, bool istrans)
auto iboindex = flat->iboindex;
if (screen->hwcaps & RFL_BUFFER_STORAGE)
if (screen->BuffersArePersistent())
{
flat->SetupLights(this, flat->sector->lighthead, lightdata, flat->sector->PortalGroup);
}

View file

@ -246,10 +246,9 @@ void FDrawInfo::DrawSprite(GLSprite *sprite, int pass)
{
gl_RenderState.Apply();
FVector3 v[4];
gl_RenderState.SetNormal(0, 0, 0);
if ((gl.flags & RFL_BUFFER_STORAGE) && sprite->vertexindex == -1)
if (screen->BuffersArePersistent())
{
sprite->CreateVertices(this);
}

View file

@ -239,7 +239,7 @@ void FDrawInfo::RenderTranslucentWall(GLWall *wall)
//==========================================================================
void FDrawInfo::DrawWall(GLWall *wall, int pass)
{
if (screen->hwcaps & RFL_BUFFER_STORAGE)
if (screen->BuffersArePersistent())
{
if (level.HasDynamicLights && !isFullbrightScene() && wall->gltexture != nullptr)
{

View file

@ -168,7 +168,7 @@ bool FShader::Load(const char * name, const char * vert_prog_lump, const char *
FString vp_comb;
assert(GLRenderer->mLights != NULL);
// On the shader side there is no difference between LM_DEFERRED and LM_DIRECT, it only decides how the buffer is initialized.
unsigned int lightbuffertype = GLRenderer->mLights->GetBufferType();
unsigned int lightbuffersize = GLRenderer->mLights->GetBlockSize();
if (lightbuffertype == GL_UNIFORM_BUFFER)
@ -184,7 +184,7 @@ bool FShader::Load(const char * name, const char * vert_prog_lump, const char *
vp_comb = "#version 430 core\n#define SHADER_STORAGE_LIGHTS\n";
}
if (!!(gl.flags & RFL_SHADER_STORAGE_BUFFER))
if (gl.flags & RFL_SHADER_STORAGE_BUFFER)
{
vp_comb << "#define SUPPORTS_SHADOWMAPS\n";
}

View file

@ -75,14 +75,9 @@ OpenGLFrameBuffer::OpenGLFrameBuffer(void *hMonitor, bool fullscreen) :
FHardwareTexture::InitGlobalState();
gl_RenderState.Reset();
GLRenderer = new FGLRenderer(this);
GLRenderer = nullptr;
InitPalette();
InitializeState();
mDebug = std::make_shared<FGLDebug>();
mDebug->Update();
SetGamma();
// Move some state to the framebuffer object for easier access.
hwcaps = gl.flags;
glslversion = gl.glslversion;
@ -90,8 +85,11 @@ OpenGLFrameBuffer::OpenGLFrameBuffer(void *hMonitor, bool fullscreen) :
OpenGLFrameBuffer::~OpenGLFrameBuffer()
{
delete GLRenderer;
GLRenderer = NULL;
if (GLRenderer)
{
delete GLRenderer;
GLRenderer = nullptr;
}
}
//==========================================================================
@ -136,8 +134,12 @@ void OpenGLFrameBuffer::InitializeState()
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
GLRenderer = new FGLRenderer(this);
GLRenderer->Initialize(GetWidth(), GetHeight());
SetViewportRects(nullptr);
mDebug = std::make_shared<FGLDebug>();
mDebug->Update();
}
//==========================================================================

View file

@ -19,7 +19,7 @@ public:
OpenGLFrameBuffer(void *hMonitor, bool fullscreen) ;
~OpenGLFrameBuffer();
void InitializeState();
void InitializeState() override;
void Update() override;
// Color correction

View file

@ -168,8 +168,6 @@ void gl_LoadExtensions()
if (CheckExtension("GL_ARB_texture_compression")) gl.flags |= RFL_TEXTURE_COMPRESSION;
if (CheckExtension("GL_EXT_texture_compression_s3tc")) gl.flags |= RFL_TEXTURE_COMPRESSION_S3TC;
gl.lightmethod = LM_DEFERRED;
gl.buffermethod = BM_DEFERRED;
if (gl_version < 4.f)
{
#ifdef _WIN32
@ -192,16 +190,12 @@ void gl_LoadExtensions()
gl.flags |= RFL_SHADER_STORAGE_BUFFER;
}
gl.flags |= RFL_BUFFER_STORAGE;
gl.lightmethod = LM_DIRECT;
gl.buffermethod = BM_PERSISTENT;
}
}
else
{
// Assume that everything works without problems on GL 4.5 drivers where these things are core features.
gl.flags |= RFL_SHADER_STORAGE_BUFFER | RFL_BUFFER_STORAGE;
gl.lightmethod = LM_DIRECT;
gl.buffermethod = BM_PERSISTENT;
}
// Mesa implements shader storage only for fragment shaders.
@ -215,18 +209,6 @@ void gl_LoadExtensions()
if (gl_version >= 4.3f || CheckExtension("GL_ARB_invalidate_subdata")) gl.flags |= RFL_INVALIDATE_BUFFER;
if (gl_version >= 4.3f || CheckExtension("GL_KHR_debug")) gl.flags |= RFL_DEBUG;
const char *lm = Args->CheckValue("-lightmethod");
if (lm != NULL)
{
if (!stricmp(lm, "deferred") && gl.lightmethod == LM_DIRECT) gl.lightmethod = LM_DEFERRED;
}
lm = Args->CheckValue("-buffermethod");
if (lm != NULL)
{
if (!stricmp(lm, "deferred") && gl.buffermethod == BM_PERSISTENT) gl.buffermethod = BM_DEFERRED;
}
glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS, &v);
gl.maxuniforms = v;
glGetIntegerv(GL_MAX_UNIFORM_BLOCK_SIZE, &v);

View file

@ -16,27 +16,12 @@ enum TexMode
TM_FIXEDCOLORMAP = TM_FOGLAYER, // repurposes the objectcolor uniforms to render a fixed colormap range. (Same constant because they cannot be used in the same context.
};
enum ELightMethod
{
LM_DEFERRED = 1, // calculate lights up front in a separate pass
LM_DIRECT = 2, // calculate lights on the fly along with the render data
};
enum EBufferMethod
{
BM_DEFERRED = 1, // use a temporarily mapped buffer, for GL 3.x core profile
BM_PERSISTENT = 2 // use a persistently mapped buffer
};
struct RenderContext
{
unsigned int flags;
unsigned int maxuniforms;
unsigned int maxuniformblock;
unsigned int uniformblockalignment;
int lightmethod;
int buffermethod;
float glslversion;
int max_texturesize;
char * vendorstring;

View file

@ -186,7 +186,7 @@ inline void GLFlat::PutFlat(HWDrawInfo *di, bool fog)
{
Colormap.Clear();
}
else if (!(screen->hwcaps & RFL_BUFFER_STORAGE))
else if (!screen->BuffersArePersistent())
{
if (level.HasDynamicLights && gltexture != nullptr)
{

View file

@ -230,7 +230,7 @@ inline void GLSprite::PutSprite(HWDrawInfo *di, bool translucent)
dynlightindex = -1;
vertexindex = -1;
if (!(screen->hwcaps & RFL_BUFFER_STORAGE))
if (!screen->BuffersArePersistent())
{
CreateVertices(di);
}

View file

@ -182,7 +182,7 @@ void GLWall::PutWall(HWDrawInfo *di, bool translucent)
if (di->isFullbrightScene() || (Colormap.LightColor.isWhite() && lightlevel == 255))
flags &= ~GLWF_GLOW;
if (!(screen->hwcaps & RFL_BUFFER_STORAGE))
if (!screen->BuffersArePersistent())
{
if (level.HasDynamicLights && !di->isFullbrightScene() && gltexture != nullptr)
{

View file

@ -127,6 +127,7 @@ public:
bool IsFullscreen() { DBGBREAK; return 0; }
int GetClientWidth() { DBGBREAK; return 0; }
int GetClientHeight() { DBGBREAK; return 0; }
void InitializeState() override {}
float Gamma;
};
@ -593,6 +594,7 @@ bool IVideo::SetResolution ()
}
screen = buff;
screen->InitializeState();
screen->SetGamma();
V_UpdateModeSize(screen->GetWidth(), screen->GetHeight());

View file

@ -57,7 +57,6 @@ enum EHWCaps
RFL_SHADER_STORAGE_BUFFER = 4,
RFL_BUFFER_STORAGE = 8,
RFL_NO_LIGHT_PREGENERATE = 16, // delays dynamic light creation until the render pass. With modern OpenGL this is faster because it can make use of the CPU while the GPU is rendering.
RFL_NO_CLIP_PLANES = 32,
@ -373,6 +372,7 @@ public:
public:
DFrameBuffer (int width=1, int height=1);
virtual ~DFrameBuffer() {}
virtual void InitializeState() = 0; // For stuff that needs 'screen' set.
void SetSize(int width, int height);
void SetVirtualSize(int width, int height)
@ -444,6 +444,7 @@ public:
// Interface to hardware rendering resources
virtual IUniformBuffer *CreateUniformBuffer(size_t size, bool staticuse = false) { return nullptr; }
virtual IShaderProgram *CreateShaderProgram() { return nullptr; }
bool BuffersArePersistent() { return !!(hwcaps & RFL_BUFFER_STORAGE); }
// Begin/End 2D drawing operations.
void Begin2D() { isIn2D = true; }