- changed shader loader to load only one shader at a time

This is merely preparation - the actual loading is still in one uninterrupted piece.
This commit is contained in:
Christoph Oelckers 2022-05-13 00:45:27 +02:00
parent 1452dd06a7
commit 2be13e1b9f
15 changed files with 197 additions and 86 deletions

View file

@ -561,6 +561,11 @@ void OpenGLFrameBuffer::PostProcessScene(bool swscene, int fixedcm, float flash,
GLRenderer->PostProcessScene(fixedcm, flash, afterBloomDrawEndScene2D);
}
bool OpenGLFrameBuffer::CompileNextShader()
{
return GLRenderer->mShaderManager->CompileNextShader();
}
//==========================================================================
//
// OpenGLFrameBuffer :: WipeStartScreen

View file

@ -23,7 +23,7 @@ public:
explicit OpenGLFrameBuffer() {}
OpenGLFrameBuffer(void *hMonitor, bool fullscreen) ;
~OpenGLFrameBuffer();
bool CompileNextShader() override;
void InitializeState() override;
void Update() override;

View file

@ -672,7 +672,7 @@ bool FShader::Bind()
FShader *FShaderCollection::Compile (const char *ShaderName, const char *ShaderPath, const char *LightModePath, const char *shaderdefines, bool usediscard, EPassType passType)
{
FString defines;
defines += shaderdefines;
if (shaderdefines) defines += shaderdefines;
// this can't be in the shader code due to ATI strangeness.
if (!usediscard) defines += "#define NO_ALPHATEST\n";
if (passType == GBUFFER_PASS) defines += "#define GBUFFER_PASS\n";
@ -707,6 +707,20 @@ FShaderManager::FShaderManager()
mPassShaders.Push(new FShaderCollection((EPassType)passType));
}
bool FShaderManager::CompileNextShader()
{
if (mPassShaders[mCompilePass]->CompileNextShader())
{
mCompilePass++;
if (mCompilePass >= MAX_PASS_TYPES)
{
mCompilePass = -1;
return true;
}
}
return false;
}
FShaderManager::~FShaderManager()
{
glUseProgram(0);
@ -727,7 +741,7 @@ void FShaderManager::SetActiveShader(FShader *sh)
FShader *FShaderManager::BindEffect(int effect, EPassType passType)
{
if (passType < mPassShaders.Size())
if (passType < mPassShaders.Size() && mCompilePass > -1)
return mPassShaders[passType]->BindEffect(effect);
else
return nullptr;
@ -735,7 +749,11 @@ FShader *FShaderManager::BindEffect(int effect, EPassType passType)
FShader *FShaderManager::Get(unsigned int eff, bool alphateston, EPassType passType)
{
if (r_skipmats && eff >= 3 && eff <= 4)
if (mCompilePass > -1)
{
return mPassShaders[0]->Get(0, false);
}
if ((r_skipmats && eff >= 3 && eff <= 4))
eff = 0;
if (passType < mPassShaders.Size())
@ -752,7 +770,14 @@ FShader *FShaderManager::Get(unsigned int eff, bool alphateston, EPassType passT
FShaderCollection::FShaderCollection(EPassType passType)
{
CompileShaders(passType);
mPassType = passType;
mMaterialShaders.Clear();
mMaterialShadersNAT.Clear();
for (int i = 0; i < MAX_EFFECTS; i++)
{
mEffectShaders[i] = NULL;
}
CompileNextShader();
}
//==========================================================================
@ -772,35 +797,46 @@ FShaderCollection::~FShaderCollection()
//
//==========================================================================
void FShaderCollection::CompileShaders(EPassType passType)
bool FShaderCollection::CompileNextShader()
{
mMaterialShaders.Clear();
mMaterialShadersNAT.Clear();
for (int i = 0; i < MAX_EFFECTS; i++)
int i = mCompileIndex;
if (mCompileState == 0)
{
mEffectShaders[i] = NULL;
}
for(int i=0;defaultshaders[i].ShaderName != NULL;i++)
{
FShader *shc = Compile(defaultshaders[i].ShaderName, defaultshaders[i].gettexelfunc, defaultshaders[i].lightfunc, defaultshaders[i].Defines, true, passType);
FShader *shc = Compile(defaultshaders[i].ShaderName, defaultshaders[i].gettexelfunc, defaultshaders[i].lightfunc, defaultshaders[i].Defines, true, mPassType);
mMaterialShaders.Push(shc);
if (i < SHADER_NoTexture)
mCompileIndex++;
if (defaultshaders[mCompileIndex].ShaderName == nullptr)
{
FShader *shc1 = Compile(defaultshaders[i].ShaderName, defaultshaders[i].gettexelfunc, defaultshaders[i].lightfunc, defaultshaders[i].Defines, false, passType);
mMaterialShadersNAT.Push(shc1);
mCompileIndex = 0;
mCompileState++;
}
}
for(unsigned i = 0; i < usershaders.Size(); i++)
else if (mCompileState == 1)
{
FShader *shc1 = Compile(defaultshaders[i].ShaderName, defaultshaders[i].gettexelfunc, defaultshaders[i].lightfunc, defaultshaders[i].Defines, false, mPassType);
mMaterialShadersNAT.Push(shc1);
mCompileIndex++;
if (mCompileIndex >= SHADER_NoTexture)
{
mCompileIndex = 0;
mCompileState++;
if (usershaders.Size() == 0) mCompileState++;
}
}
else if (mCompileState == 2)
{
FString name = ExtractFileBase(usershaders[i].shader);
FString defines = defaultshaders[usershaders[i].shaderType].Defines + usershaders[i].defines;
FShader *shc = Compile(name, usershaders[i].shader, defaultshaders[usershaders[i].shaderType].lightfunc, defines, true, passType);
FShader *shc = Compile(name, usershaders[i].shader, defaultshaders[usershaders[i].shaderType].lightfunc, defines, true, mPassType);
mMaterialShaders.Push(shc);
if (mCompileIndex >= (int)usershaders.Size())
{
mCompileIndex = 0;
mCompileState++;
}
}
for(int i=0;i<MAX_EFFECTS;i++)
else if (mCompileState == 3)
{
FShader *eff = new FShader(effectshaders[i].ShaderName);
if (!eff->Load(effectshaders[i].ShaderName, effectshaders[i].vp, effectshaders[i].fp1,
@ -809,7 +845,13 @@ void FShaderCollection::CompileShaders(EPassType passType)
delete eff;
}
else mEffectShaders[i] = eff;
mCompileIndex++;
if (mCompileIndex >= MAX_EFFECTS)
{
return true;
}
}
return false;
}
//==========================================================================

View file

@ -309,10 +309,12 @@ public:
FShader *Get(unsigned int eff, bool alphateston, EPassType passType);
void SetActiveShader(FShader *sh);
bool CompileNextShader();
private:
FShader *mActiveShader = nullptr;
TArray<FShaderCollection*> mPassShaders;
int mCompilePass = 0;
friend class FShader;
};
@ -322,21 +324,23 @@ class FShaderCollection
TArray<FShader*> mMaterialShaders;
TArray<FShader*> mMaterialShadersNAT;
FShader *mEffectShaders[MAX_EFFECTS];
int mCompileState = 0, mCompileIndex = 0;
EPassType mPassType;
void Clean();
void CompileShaders(EPassType passType);
public:
FShaderCollection(EPassType passType);
~FShaderCollection();
FShader *Compile(const char *ShaderName, const char *ShaderPath, const char *LightModePath, const char *shaderdefines, bool usediscard, EPassType passType);
int Find(const char *mame);
bool CompileNextShader();
FShader *BindEffect(int effect);
FShader *Get(unsigned int eff, bool alphateston)
{
// indices 0-2 match the warping modes, 3 no texture, the following are custom
if (!alphateston && eff <= 2)
if (!alphateston && eff < SHADER_NoTexture)
{
return mMaterialShadersNAT[eff]; // Non-alphatest shaders are only created for default, warp1+2 and brightmap. The rest won't get used anyway
}

View file

@ -26,6 +26,7 @@ public:
void InitializeState() override;
void Update() override;
int GetShaderCount() override { return 0; }
void FirstEye() override;
void NextEye(int eyecount) override;

View file

@ -733,7 +733,7 @@ bool FShader::Bind(ShaderFlavourData& flavour)
//==========================================================================
//
// Since all shaders are REQUIRED, any error here needs to be fatal
//
//
//==========================================================================
@ -744,21 +744,8 @@ FShader *FShaderCollection::Compile (const char *ShaderName, const char *ShaderP
// this can't be in the shader code due to ATI strangeness.
if (!usediscard) defines += "#define NO_ALPHATEST\n";
FShader *shader = NULL;
try
{
shader = new FShader(ShaderName);
if (!shader->Configure(ShaderName, "shaders_gles/glsl/main.vp", "shaders_gles/glsl/main.fp", ShaderPath, LightModePath, defines.GetChars()))
{
I_FatalError("Unable to load shader %s\n", ShaderName);
}
}
catch(CRecoverableError &err)
{
if (shader != NULL) delete shader;
shader = NULL;
I_FatalError("Unable to load shader %s:\n%s\n", ShaderName, err.GetMessage());
}
FShader *shader = new FShader(ShaderName);
shader->Configure(ShaderName, "shaders_gles/glsl/main.vp", "shaders_gles/glsl/main.fp", ShaderPath, LightModePath, defines.GetChars());
return shader;
}

View file

@ -34,7 +34,11 @@
*/
#include "cmdlib.h"
#include "hw_shaderpatcher.h"
#include "textures.h"
#include "hw_renderstate.h"
#include "v_video.h"
static bool IsGlslWhitespace(char c)
@ -296,3 +300,12 @@ const FEffectShader effectshaders[] =
{ "burn", "shaders/glsl/main.vp", "shaders/glsl/burn.fp", nullptr, nullptr, "#define SIMPLE\n#define NO_ALPHATEST\n" },
{ "stencil", "shaders/glsl/main.vp", "shaders/glsl/stencil.fp", nullptr, nullptr, "#define SIMPLE\n#define NO_ALPHATEST\n" },
};
int DFrameBuffer::GetShaderCount()
{
int i;
for (i = 0; defaultshaders[i].ShaderName != nullptr; i++);
return MAX_PASS_TYPES * (countof(defaultshaders) - 1 + usershaders.Size() + MAX_EFFECTS + SHADER_NoTexture);
}

View file

@ -28,3 +28,4 @@ struct FEffectShader
extern const FDefaultShader defaultshaders[];
extern const FEffectShader effectshaders[];

View file

@ -26,6 +26,7 @@ public:
PolyFrameBuffer(void *hMonitor, bool fullscreen);
~PolyFrameBuffer();
int GetShaderCount() override { return 0; }
void Update() override;

View file

@ -158,6 +158,8 @@ public:
virtual void InitializeState() = 0; // For stuff that needs 'screen' set.
virtual bool IsVulkan() { return false; }
virtual bool IsPoly() { return false; }
virtual int GetShaderCount();
virtual bool CompileNextShader() { return true; }
void SetAABBTree(hwrenderer::LevelAABBTree * tree)
{
mShadowMap.SetAABBTree(tree);

View file

@ -28,51 +28,93 @@
#include "version.h"
#include <ShaderLang.h>
bool VkShaderManager::CompileNextShader()
{
const char *mainvp = "shaders/glsl/main.vp";
const char *mainfp = "shaders/glsl/main.fp";
int i = compileIndex;
if (compileState == 0)
{
// regular material shaders
VkShaderProgram prog;
prog.vert = LoadVertShader(defaultshaders[i].ShaderName, mainvp, defaultshaders[i].Defines);
prog.frag = LoadFragShader(defaultshaders[i].ShaderName, mainfp, defaultshaders[i].gettexelfunc, defaultshaders[i].lightfunc, defaultshaders[i].Defines, true, compilePass == GBUFFER_PASS);
mMaterialShaders[compilePass].push_back(std::move(prog));
compileIndex++;
if (defaultshaders[compileIndex].ShaderName == nullptr)
{
compileIndex = 0;
compileState++;
}
}
else if (compileState == 1)
{
// NAT material shaders
VkShaderProgram natprog;
natprog.vert = LoadVertShader(defaultshaders[i].ShaderName, mainvp, defaultshaders[i].Defines);
natprog.frag = LoadFragShader(defaultshaders[i].ShaderName, mainfp, defaultshaders[i].gettexelfunc, defaultshaders[i].lightfunc, defaultshaders[i].Defines, false, compilePass == GBUFFER_PASS);
mMaterialShadersNAT[compilePass].push_back(std::move(natprog));
compileIndex++;
if (compileIndex == SHADER_NoTexture)
{
compileIndex = 0;
compileState++;
if (usershaders.Size() == 0) compileState++;
}
}
else if (compileState == 2)
{
// user shaders
const FString& name = ExtractFileBase(usershaders[i].shader);
FString defines = defaultshaders[usershaders[i].shaderType].Defines + usershaders[i].defines;
VkShaderProgram prog;
prog.vert = LoadVertShader(name, mainvp, defines);
prog.frag = LoadFragShader(name, mainfp, usershaders[i].shader, defaultshaders[usershaders[i].shaderType].lightfunc, defines, true, compilePass == GBUFFER_PASS);
mMaterialShaders[compilePass].push_back(std::move(prog));
compileIndex++;
if (compileIndex >= (int)usershaders.Size())
{
compileIndex = 0;
compileState++;
}
}
else if (compileState == 3)
{
// Effect shaders
VkShaderProgram prog;
prog.vert = LoadVertShader(effectshaders[i].ShaderName, effectshaders[i].vp, effectshaders[i].defines);
prog.frag = LoadFragShader(effectshaders[i].ShaderName, effectshaders[i].fp1, effectshaders[i].fp2, effectshaders[i].fp3, effectshaders[i].defines, true, compilePass == GBUFFER_PASS);
mEffectShaders[compilePass].push_back(std::move(prog));
compileIndex++;
if (compileIndex >= MAX_EFFECTS)
{
compileIndex = 0;
if (compilePass == MAX_PASS_TYPES)
{
compileIndex = -1; // we're done.
return true;
}
compileState = 0;
compilePass++;
}
}
return false;
}
VkShaderManager::VkShaderManager(VulkanDevice *device) : device(device)
{
ShInitialize();
const char *mainvp = "shaders/glsl/main.vp";
const char *mainfp = "shaders/glsl/main.fp";
for (int j = 0; j < MAX_PASS_TYPES; j++)
{
bool gbufferpass = j;
for (int i = 0; defaultshaders[i].ShaderName != nullptr; i++)
{
VkShaderProgram prog;
prog.vert = LoadVertShader(defaultshaders[i].ShaderName, mainvp, defaultshaders[i].Defines);
prog.frag = LoadFragShader(defaultshaders[i].ShaderName, mainfp, defaultshaders[i].gettexelfunc, defaultshaders[i].lightfunc, defaultshaders[i].Defines, true, gbufferpass);
mMaterialShaders[j].push_back(std::move(prog));
if (i < SHADER_NoTexture)
{
VkShaderProgram natprog;
natprog.vert = LoadVertShader(defaultshaders[i].ShaderName, mainvp, defaultshaders[i].Defines);
natprog.frag = LoadFragShader(defaultshaders[i].ShaderName, mainfp, defaultshaders[i].gettexelfunc, defaultshaders[i].lightfunc, defaultshaders[i].Defines, false, gbufferpass);
mMaterialShadersNAT[j].push_back(std::move(natprog));
}
}
for (unsigned i = 0; i < usershaders.Size(); i++)
{
FString name = ExtractFileBase(usershaders[i].shader);
FString defines = defaultshaders[usershaders[i].shaderType].Defines + usershaders[i].defines;
VkShaderProgram prog;
prog.vert = LoadVertShader(name, mainvp, defines);
prog.frag = LoadFragShader(name, mainfp, usershaders[i].shader, defaultshaders[usershaders[i].shaderType].lightfunc, defines, true, gbufferpass);
mMaterialShaders[j].push_back(std::move(prog));
}
for (int i = 0; i < MAX_EFFECTS; i++)
{
VkShaderProgram prog;
prog.vert = LoadVertShader(effectshaders[i].ShaderName, effectshaders[i].vp, effectshaders[i].defines);
prog.frag = LoadFragShader(effectshaders[i].ShaderName, effectshaders[i].fp1, effectshaders[i].fp2, effectshaders[i].fp3, effectshaders[i].defines, true, gbufferpass);
mEffectShaders[j].push_back(std::move(prog));
}
}
CompileNextShader();
}
VkShaderManager::~VkShaderManager()
@ -82,7 +124,7 @@ VkShaderManager::~VkShaderManager()
VkShaderProgram *VkShaderManager::GetEffect(int effect, EPassType passType)
{
if (effect >= 0 && effect < MAX_EFFECTS && mEffectShaders[passType][effect].frag)
if (compileIndex > -1 && effect >= 0 && effect < MAX_EFFECTS && mEffectShaders[passType][effect].frag)
{
return &mEffectShaders[passType][effect];
}
@ -91,8 +133,9 @@ VkShaderProgram *VkShaderManager::GetEffect(int effect, EPassType passType)
VkShaderProgram *VkShaderManager::Get(unsigned int eff, bool alphateston, EPassType passType)
{
if (compileIndex != -1) return &mMaterialShaders[0][0];
// indices 0-2 match the warping modes, 3 no texture, the following are custom
if (!alphateston && eff <= 2)
if (!alphateston && eff <= SHADER_NoTexture)
{
return &mMaterialShadersNAT[passType][eff]; // Non-alphatest shaders are only created for default, warp1+2. The rest won't get used anyway
}

View file

@ -65,6 +65,7 @@ public:
VkShaderProgram *GetEffect(int effect, EPassType passType);
VkShaderProgram *Get(unsigned int eff, bool alphateston, EPassType passType);
bool CompileNextShader();
private:
std::unique_ptr<VulkanShader> LoadVertShader(FString shadername, const char *vert_lump, const char *defines);
@ -79,4 +80,6 @@ private:
std::vector<VkShaderProgram> mMaterialShaders[MAX_PASS_TYPES];
std::vector<VkShaderProgram> mMaterialShadersNAT[MAX_PASS_TYPES];
std::vector<VkShaderProgram> mEffectShaders[MAX_PASS_TYPES];
uint8_t compilePass = 0, compileState = 0;
int compileIndex = 0;
};

View file

@ -207,6 +207,11 @@ void VulkanFrameBuffer::Update()
Super::Update();
}
bool VulkanFrameBuffer::CompileNextShader()
{
return mShaderManager->CompileNextShader();
}
void VulkanFrameBuffer::DeleteFrameObjects(bool uploadOnly)
{
FrameTextureUpload.Buffers.clear();

View file

@ -77,7 +77,7 @@ public:
void Update() override;
void InitializeState() override;
bool CompileNextShader() override;
void PrecacheMaterial(FMaterial *mat, int translation) override;
void UpdatePalette() override;
const char* DeviceName() const override;

View file

@ -3356,6 +3356,10 @@ static int D_InitGame(const FIWADInfo* iwad_info, TArray<FString>& allwads, TArr
}
V_Init2();
while(!screen->CompileNextShader())
{
// here we can do some visual updates later
}
twod->fullscreenautoaspect = gameinfo.fullscreenautoaspect;
// Initialize the size of the 2D drawer so that an attempt to access it outside the draw code won't crash.
twod->Begin(screen->GetWidth(), screen->GetHeight());