From 5f838d52b9cebb707241a53bc4f2ccb0efd3710a Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 20 Oct 2018 12:55:25 +0200 Subject: [PATCH] - 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. --- src/gl/data/gl_vertexbuffer.cpp | 7 ++++--- src/gl/data/gl_vertexbuffer.h | 1 + src/gl/data/gl_viewpointbuffer.cpp | 7 ++++--- src/gl/data/gl_viewpointbuffer.h | 1 + src/gl/dynlights/gl_lightbuffer.cpp | 9 +++++---- src/gl/dynlights/gl_lightbuffer.h | 1 + src/gl/scene/gl_flats.cpp | 2 +- src/gl/scene/gl_sprite.cpp | 3 +-- src/gl/scene/gl_walls_draw.cpp | 2 +- src/gl/shaders/gl_shader.cpp | 4 ++-- src/gl/system/gl_framebuffer.cpp | 18 ++++++++++-------- src/gl/system/gl_framebuffer.h | 2 +- src/gl_load/gl_interface.cpp | 18 ------------------ src/gl_load/gl_interface.h | 15 --------------- src/hwrenderer/scene/hw_flats.cpp | 2 +- src/hwrenderer/scene/hw_sprites.cpp | 2 +- src/hwrenderer/scene/hw_walls.cpp | 2 +- src/v_video.cpp | 2 ++ src/v_video.h | 3 ++- 19 files changed, 39 insertions(+), 62 deletions(-) diff --git a/src/gl/data/gl_vertexbuffer.cpp b/src/gl/data/gl_vertexbuffer.cpp index f9fe4a667..27ab11198 100644 --- a/src/gl/data/gl_vertexbuffer.cpp +++ b/src/gl/data/gl_vertexbuffer.cpp @@ -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); diff --git a/src/gl/data/gl_vertexbuffer.h b/src/gl/data/gl_vertexbuffer.h index 7c54b1916..c93b77c2d 100644 --- a/src/gl/data/gl_vertexbuffer.h +++ b/src/gl/data/gl_vertexbuffer.h @@ -101,6 +101,7 @@ class FFlatVertexBuffer : public FVertexBuffer, public FFlatVertexGenerator std::atomic mCurIndex; std::mutex mBufferMutex; unsigned int mNumReserved; + bool mPersistent; static const unsigned int BUFFER_SIZE = 2000000; diff --git a/src/gl/data/gl_viewpointbuffer.cpp b/src/gl/data/gl_viewpointbuffer.cpp index 611db9e40..8f74d4ead 100644 --- a/src/gl/data/gl_viewpointbuffer.cpp +++ b/src/gl/data/gl_viewpointbuffer.cpp @@ -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); diff --git a/src/gl/data/gl_viewpointbuffer.h b/src/gl/data/gl_viewpointbuffer.h index 3ec1093df..a904875a7 100644 --- a/src/gl/data/gl_viewpointbuffer.h +++ b/src/gl/data/gl_viewpointbuffer.h @@ -13,6 +13,7 @@ class GLViewpointBuffer unsigned int mByteSize; void * mBufferPointer; TArray mClipPlaneInfo; + bool mPersistent; unsigned int m2DWidth = ~0u, m2DHeight = ~0u; diff --git a/src/gl/dynlights/gl_lightbuffer.cpp b/src/gl/dynlights/gl_lightbuffer.cpp index 2265f58f0..0c98d601e 100644 --- a/src/gl/dynlights/gl_lightbuffer.cpp +++ b/src/gl/dynlights/gl_lightbuffer.cpp @@ -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); diff --git a/src/gl/dynlights/gl_lightbuffer.h b/src/gl/dynlights/gl_lightbuffer.h index c77d1ce71..2a5cedbf0 100644 --- a/src/gl/dynlights/gl_lightbuffer.h +++ b/src/gl/dynlights/gl_lightbuffer.h @@ -19,6 +19,7 @@ class FLightBuffer unsigned int mBufferSize; unsigned int mByteSize; unsigned int mMaxUploadSize; + bool mPersistentBuffer; std::mutex mBufferMutex; TArray mBufferedData; diff --git a/src/gl/scene/gl_flats.cpp b/src/gl/scene/gl_flats.cpp index 04771dd56..331acdcad 100644 --- a/src/gl/scene/gl_flats.cpp +++ b/src/gl/scene/gl_flats.cpp @@ -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); } diff --git a/src/gl/scene/gl_sprite.cpp b/src/gl/scene/gl_sprite.cpp index ebf29e3ca..42d3c9e28 100644 --- a/src/gl/scene/gl_sprite.cpp +++ b/src/gl/scene/gl_sprite.cpp @@ -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); } diff --git a/src/gl/scene/gl_walls_draw.cpp b/src/gl/scene/gl_walls_draw.cpp index 61f51a1d5..d6d102d0f 100644 --- a/src/gl/scene/gl_walls_draw.cpp +++ b/src/gl/scene/gl_walls_draw.cpp @@ -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) { diff --git a/src/gl/shaders/gl_shader.cpp b/src/gl/shaders/gl_shader.cpp index d61a962c1..a572a126b 100644 --- a/src/gl/shaders/gl_shader.cpp +++ b/src/gl/shaders/gl_shader.cpp @@ -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"; } diff --git a/src/gl/system/gl_framebuffer.cpp b/src/gl/system/gl_framebuffer.cpp index 729ecad1f..b3ce1023b 100644 --- a/src/gl/system/gl_framebuffer.cpp +++ b/src/gl/system/gl_framebuffer.cpp @@ -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(); - 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(); + mDebug->Update(); } //========================================================================== diff --git a/src/gl/system/gl_framebuffer.h b/src/gl/system/gl_framebuffer.h index 44a380b3a..4c1c59ce1 100644 --- a/src/gl/system/gl_framebuffer.h +++ b/src/gl/system/gl_framebuffer.h @@ -19,7 +19,7 @@ public: OpenGLFrameBuffer(void *hMonitor, bool fullscreen) ; ~OpenGLFrameBuffer(); - void InitializeState(); + void InitializeState() override; void Update() override; // Color correction diff --git a/src/gl_load/gl_interface.cpp b/src/gl_load/gl_interface.cpp index c9423b15f..af1077700 100644 --- a/src/gl_load/gl_interface.cpp +++ b/src/gl_load/gl_interface.cpp @@ -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); diff --git a/src/gl_load/gl_interface.h b/src/gl_load/gl_interface.h index f12e21fe4..682be7e77 100644 --- a/src/gl_load/gl_interface.h +++ b/src/gl_load/gl_interface.h @@ -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; diff --git a/src/hwrenderer/scene/hw_flats.cpp b/src/hwrenderer/scene/hw_flats.cpp index 6c28d5636..e1580caca 100644 --- a/src/hwrenderer/scene/hw_flats.cpp +++ b/src/hwrenderer/scene/hw_flats.cpp @@ -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) { diff --git a/src/hwrenderer/scene/hw_sprites.cpp b/src/hwrenderer/scene/hw_sprites.cpp index 99d5d691a..e8917745a 100644 --- a/src/hwrenderer/scene/hw_sprites.cpp +++ b/src/hwrenderer/scene/hw_sprites.cpp @@ -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); } diff --git a/src/hwrenderer/scene/hw_walls.cpp b/src/hwrenderer/scene/hw_walls.cpp index d164aaf31..87fbf38ea 100644 --- a/src/hwrenderer/scene/hw_walls.cpp +++ b/src/hwrenderer/scene/hw_walls.cpp @@ -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) { diff --git a/src/v_video.cpp b/src/v_video.cpp index 76b8770dc..19d24297d 100644 --- a/src/v_video.cpp +++ b/src/v_video.cpp @@ -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()); diff --git a/src/v_video.h b/src/v_video.h index 6908dfd57..1e29ff473 100644 --- a/src/v_video.h +++ b/src/v_video.h @@ -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; }