- use uniform buffers for dynamic lights everywhere.

Branching on SSBO content does not work that well on NVidia so it is better disabled.
So far only implemented for OpenGL - Vulkan needs more work.
This commit is contained in:
Christoph Oelckers 2023-02-18 12:22:26 +01:00
parent b84bf176e1
commit 087050c201
8 changed files with 37 additions and 50 deletions

View file

@ -391,25 +391,17 @@ bool FShader::Load(const char * name, const char * vert_prog_lump, const char *
assert(screen->mLights != NULL); assert(screen->mLights != NULL);
assert(screen->mBones != NULL); assert(screen->mBones != NULL);
bool lightbuffertype = screen->mLights->GetBufferType();
unsigned int lightbuffersize = screen->mLights->GetBlockSize();
if (!lightbuffertype)
{
vp_comb.Format("#version 330 core\n#define NUM_UBO_LIGHTS %d\n#define NUM_UBO_BONES %d\n", lightbuffersize, screen->mBones->GetBlockSize());
}
else
{
// This differentiation is for Intel which do not seem to expose the full extension, even if marked as required.
if (gl.glslversion < 4.3f)
vp_comb = "#version 400 core\n#extension GL_ARB_shader_storage_buffer_object : require\n#define SHADER_STORAGE_LIGHTS\n#define SHADER_STORAGE_BONES\n";
else
vp_comb = "#version 430 core\n#define SHADER_STORAGE_LIGHTS\n#define SHADER_STORAGE_BONES\n";
}
if ((gl.flags & RFL_SHADER_STORAGE_BUFFER) && screen->allowSSBO()) if ((gl.flags & RFL_SHADER_STORAGE_BUFFER) && screen->allowSSBO())
{ vp_comb << "#version 430 core\n#define SUPPORTS_SHADOWMAPS\n";
vp_comb << "#define SUPPORTS_SHADOWMAPS\n"; else
} vp_comb << "#version 330 core\n";
bool lightbuffertype = screen->mLights->GetBufferType();
if (!lightbuffertype)
vp_comb.AppendFormat("#define NUM_UBO_LIGHTS %d\n#define NUM_UBO_BONES %d\n", screen->mLights->GetBlockSize(), screen->mBones->GetBlockSize());
else
vp_comb << "#define SHADER_STORAGE_LIGHTS\n#define SHADER_STORAGE_BONES\n";
FString fp_comb = vp_comb; FString fp_comb = vp_comb;
vp_comb << defines << i_data.GetChars(); vp_comb << defines << i_data.GetChars();

View file

@ -108,6 +108,8 @@ static void InitContext()
void gl_LoadExtensions() void gl_LoadExtensions()
{ {
int v = 0;
InitContext(); InitContext();
CollectExtensions(); CollectExtensions();
@ -162,32 +164,18 @@ void gl_LoadExtensions()
#endif #endif
gl.glslversion = 3.31f; // Force GLSL down to 3.3. gl.glslversion = 3.31f; // Force GLSL down to 3.3.
} }
else if (gl_version < 4.5f) else if (gl_version >= 4.5f)
{
// don't use GL 4.x features when running a GL 3.x context.
if (CheckExtension("GL_ARB_buffer_storage"))
{
// work around a problem with older AMD drivers: Their implementation of shader storage buffer objects is piss-poor and does not match uniform buffers even closely.
// Recent drivers, GL 4.4 don't have this problem, these can easily be recognized by also supporting the GL_ARB_buffer_storage extension.
if (CheckExtension("GL_ARB_shader_storage_buffer_object"))
{
gl.flags |= RFL_SHADER_STORAGE_BUFFER;
}
gl.flags |= RFL_BUFFER_STORAGE;
}
}
else
{ {
// Assume that everything works without problems on GL 4.5 drivers where these things are core features. // 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.flags |= RFL_SHADER_STORAGE_BUFFER | RFL_BUFFER_STORAGE;
// Mesa implements shader storage only for fragment shaders.
// Just disable the feature there. The light buffer may just use a uniform buffer without any adverse effects.
glGetIntegerv(GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS, &v);
if (v == 0)
gl.flags &= ~RFL_SHADER_STORAGE_BUFFER;
} }
// Mesa implements shader storage only for fragment shaders.
// Just disable the feature there. The light buffer may just use a uniform buffer without any adverse effects.
int v = 0;
glGetIntegerv(GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS, &v);
if (v == 0)
gl.flags &= ~RFL_SHADER_STORAGE_BUFFER;
if (gl_version >= 4.3f || CheckExtension("GL_ARB_invalidate_subdata")) gl.flags |= RFL_INVALIDATE_BUFFER; if (gl_version >= 4.3f || CheckExtension("GL_ARB_invalidate_subdata")) gl.flags |= RFL_INVALIDATE_BUFFER;

View file

@ -33,10 +33,7 @@ BoneBuffer::BoneBuffer(int pipelineNbr) : mPipelineNbr(pipelineNbr)
mBufferSize = maxNumberOfBones; mBufferSize = maxNumberOfBones;
mByteSize = mBufferSize * BONE_SIZE; mByteSize = mBufferSize * BONE_SIZE;
// Hack alert: On Intel's GL driver SSBO's perform quite worse than UBOs. if (screen->useSSBO())
// We only want to disable using SSBOs for bones but not disable the feature entirely.
// Note that using an uniform buffer here will limit the number of bones per model so it isn't done for NVidia and AMD.
if (screen->IsVulkan() || screen->IsPoly() || ((screen->hwcaps & RFL_SHADER_STORAGE_BUFFER) && screen->allowSSBO() && !strstr(screen->vendorstring, "Intel")))
{ {
mBufferType = true; mBufferType = true;
mBlockAlign = 0; mBlockAlign = 0;

View file

@ -41,10 +41,7 @@ FLightBuffer::FLightBuffer(int pipelineNbr):
mBufferSize = maxNumberOfLights * ELEMENTS_PER_LIGHT; mBufferSize = maxNumberOfLights * ELEMENTS_PER_LIGHT;
mByteSize = mBufferSize * ELEMENT_SIZE; mByteSize = mBufferSize * ELEMENT_SIZE;
// Hack alert: On Intel's GL driver SSBO's perform quite worse than UBOs. if (screen->useSSBO())
// We only want to disable using SSBOs for lights but not disable the feature entirely.
// Note that using an uniform buffer here will limit the number of lights per surface so it isn't done for NVidia and AMD.
if (screen->IsVulkan() || screen->IsPoly() || ((screen->hwcaps & RFL_SHADER_STORAGE_BUFFER) && screen->allowSSBO() && !strstr(screen->vendorstring, "Intel")))
{ {
mBufferType = true; mBufferType = true;
mBlockAlign = 0; mBlockAlign = 0;

View file

@ -170,7 +170,7 @@ public:
mShadowMap.SetAABBTree(tree); mShadowMap.SetAABBTree(tree);
} }
virtual void SetLevelMesh(hwrenderer::LevelMesh *mesh) { } virtual void SetLevelMesh(hwrenderer::LevelMesh *mesh) { }
bool allowSSBO() bool allowSSBO() const
{ {
#ifndef HW_BLOCK_SSBO #ifndef HW_BLOCK_SSBO
return true; return true;
@ -179,6 +179,14 @@ public:
#endif #endif
} }
// Hack alert: On Intel's GL driver SSBO's perform quite worse than UBOs.
// We only want to disable using SSBOs for lights but not disable the feature entirely.
// Note that using an uniform buffer here will limit the number of lights per surface so it isn't done for NVidia and AMD.
bool useSSBO()
{
return IsVulkan();// || ((hwcaps & RFL_SHADER_STORAGE_BUFFER) && allowSSBO() && !strstr(vendorstring, "Intel"));
}
virtual DCanvas* GetCanvas() { return nullptr; } virtual DCanvas* GetCanvas() { return nullptr; }
void SetSize(int width, int height); void SetSize(int width, int height);

View file

@ -249,6 +249,7 @@ enum
BCOMPATF_FLOATBOB = 1 << 8, // Use Hexen's original method of preventing floatbobbing items from falling down BCOMPATF_FLOATBOB = 1 << 8, // Use Hexen's original method of preventing floatbobbing items from falling down
BCOMPATF_NOSLOPEID = 1 << 9, // disable line IDs on slopes. BCOMPATF_NOSLOPEID = 1 << 9, // disable line IDs on slopes.
BCOMPATF_CLIPMIDTEX = 1 << 10, // Always Clip midtex's in the software renderer (required to run certain GZDoom maps, has no effect in the hardware renderer) BCOMPATF_CLIPMIDTEX = 1 << 10, // Always Clip midtex's in the software renderer (required to run certain GZDoom maps, has no effect in the hardware renderer)
BCOMPATF_NOSECTIONMERGE = 1 << 11, // (for IWAD maps) keep separate sections for sectors with intra-sector linedefs.
}; };
// phares 3/20/98: // phares 3/20/98:

View file

@ -126,6 +126,8 @@ static FCompatOption Options[] =
{ "floatbob", BCOMPATF_FLOATBOB, SLOT_BCOMPAT }, { "floatbob", BCOMPATF_FLOATBOB, SLOT_BCOMPAT },
{ "noslopeid", BCOMPATF_NOSLOPEID, SLOT_BCOMPAT }, { "noslopeid", BCOMPATF_NOSLOPEID, SLOT_BCOMPAT },
{ "clipmidtex", BCOMPATF_CLIPMIDTEX, SLOT_BCOMPAT }, { "clipmidtex", BCOMPATF_CLIPMIDTEX, SLOT_BCOMPAT },
{ "nosectionmerge", BCOMPATF_NOSECTIONMERGE, SLOT_BCOMPAT },
// list copied from g_mapinfo.cpp // list copied from g_mapinfo.cpp
{ "shorttex", COMPATF_SHORTTEX, SLOT_COMPAT }, { "shorttex", COMPATF_SHORTTEX, SLOT_COMPAT },
@ -288,12 +290,13 @@ FName MapLoader::CheckCompatibility(MapData *map)
Level->ii_compatflags2 = 0; Level->ii_compatflags2 = 0;
Level->ib_compatflags = 0; Level->ib_compatflags = 0;
// When playing Doom IWAD levels force COMPAT_SHORTTEX and COMPATF_LIGHT. // When playing Doom IWAD levels force BCOMPATF_NOSECTIONMERGE, COMPAT_SHORTTEX and COMPATF_LIGHT.
// I'm not sure if the IWAD maps actually need COMPATF_LIGHT but it certainly does not hurt. // I'm not sure if the IWAD maps actually need COMPATF_LIGHT but it certainly does not hurt. BCOMPATF_NOSECTIONMERGE is mainly for MAP18's sector 0
// TNT's MAP31 also needs COMPATF_STAIRINDEX but that only gets activated for TNT.WAD. // TNT's MAP31 also needs COMPATF_STAIRINDEX but that only gets activated for TNT.WAD.
if (fileSystem.GetFileContainer(map->lumpnum) == fileSystem.GetIwadNum() && (gameinfo.flags & GI_COMPATSHORTTEX) && Level->maptype == MAPTYPE_DOOM) if (fileSystem.GetFileContainer(map->lumpnum) == fileSystem.GetIwadNum() && (gameinfo.flags & GI_COMPATSHORTTEX) && Level->maptype == MAPTYPE_DOOM)
{ {
Level->ii_compatflags = COMPATF_SHORTTEX|COMPATF_LIGHT; Level->ii_compatflags = COMPATF_SHORTTEX|COMPATF_LIGHT;
Level->ib_compatflags = BCOMPATF_NOSECTIONMERGE;
if (gameinfo.flags & GI_COMPATSTAIRS) Level->ii_compatflags |= COMPATF_STAIRINDEX; if (gameinfo.flags & GI_COMPATSTAIRS) Level->ii_compatflags |= COMPATF_STAIRINDEX;
} }

View file

@ -243,7 +243,8 @@ public:
{ {
if (sub->firstline[i].PartnerSeg && sub->firstline[i].Subsector->render_sector == sub->firstline[i].PartnerSeg->Subsector->render_sector) if (sub->firstline[i].PartnerSeg && sub->firstline[i].Subsector->render_sector == sub->firstline[i].PartnerSeg->Subsector->render_sector)
{ {
seglist.Push(sub->firstline[i].PartnerSeg); if (sub->firstline[i].sidedef == nullptr || !(Level->ib_compatflags & BCOMPATF_NOSECTIONMERGE))
seglist.Push(sub->firstline[i].PartnerSeg);
} }
} }
}; };