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