This commit is contained in:
goeiecool9999 2025-12-06 14:01:03 -03:00 committed by GitHub
commit 88a05e5c7c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
13 changed files with 94 additions and 86 deletions

View file

@ -367,19 +367,6 @@ void LatteShader_CreateRendererShader(LatteDecompilerShader* shader, bool compil
LatteShader_CleanupAfterCompile(shader); LatteShader_CleanupAfterCompile(shader);
} }
void LatteShader_FinishCompilation(LatteDecompilerShader* shader)
{
if (shader->hasError)
{
cemuLog_logDebug(LogType::Force, "LatteShader_finishCompilation(): Skipped because of error in shader {:x}", shader->baseHash);
return;
}
shader->shader->WaitForCompiled();
LatteShader_prepareSeparableUniforms(shader);
LatteShader_CleanupAfterCompile(shader);
}
void LatteSHRC_RegisterShader(LatteDecompilerShader* shader, uint64 baseHash, uint64 auxHash) void LatteSHRC_RegisterShader(LatteDecompilerShader* shader, uint64 baseHash, uint64 auxHash)
{ {
auto& cache = LatteSHRC_GetCacheByType(shader->shaderType); auto& cache = LatteSHRC_GetCacheByType(shader->shaderType);
@ -846,8 +833,8 @@ LatteDecompilerShader* LatteShader_CompileSeparableVertexShader(uint64 baseHash,
if (g_renderer->GetType() == RendererAPI::OpenGL) if (g_renderer->GetType() == RendererAPI::OpenGL)
{ {
if (vertexShader->shader) if (vertexShader->shader)
vertexShader->shader->PreponeCompilation(true); vertexShader->shader->PreponeCompilation();
LatteShader_FinishCompilation(vertexShader); LatteShader_prepareSeparableUniforms(vertexShader);
} }
LatteSHRC_RegisterShader(vertexShader, vertexShader->baseHash, vertexShader->auxHash); LatteSHRC_RegisterShader(vertexShader, vertexShader->baseHash, vertexShader->auxHash);
@ -875,8 +862,8 @@ LatteDecompilerShader* LatteShader_CompileSeparableGeometryShader(uint64 baseHas
if (g_renderer->GetType() == RendererAPI::OpenGL) if (g_renderer->GetType() == RendererAPI::OpenGL)
{ {
if (geometryShader->shader) if (geometryShader->shader)
geometryShader->shader->PreponeCompilation(true); geometryShader->shader->PreponeCompilation();
LatteShader_FinishCompilation(geometryShader); LatteShader_prepareSeparableUniforms(geometryShader);
} }
LatteSHRC_RegisterShader(geometryShader, geometryShader->baseHash, geometryShader->auxHash); LatteSHRC_RegisterShader(geometryShader, geometryShader->baseHash, geometryShader->auxHash);
@ -904,8 +891,8 @@ LatteDecompilerShader* LatteShader_CompileSeparablePixelShader(uint64 baseHash,
if (g_renderer->GetType() == RendererAPI::OpenGL) if (g_renderer->GetType() == RendererAPI::OpenGL)
{ {
if (pixelShader->shader) if (pixelShader->shader)
pixelShader->shader->PreponeCompilation(true); pixelShader->shader->PreponeCompilation();
LatteShader_FinishCompilation(pixelShader); LatteShader_prepareSeparableUniforms(pixelShader);
} }
LatteSHRC_RegisterShader(pixelShader, _shaderBaseHash_ps, psAuxHash); LatteSHRC_RegisterShader(pixelShader, _shaderBaseHash_ps, psAuxHash);

View file

@ -100,7 +100,6 @@ void LatteShader_GetDecompilerOptions(struct LatteDecompilerOptions& options, La
LatteDecompilerShader* LatteShader_CreateShaderFromDecompilerOutput(LatteDecompilerOutput_t& decompilerOutput, uint64 baseHash, bool calculateAuxHash, uint64 optionalAuxHash, uint32* contextRegister); LatteDecompilerShader* LatteShader_CreateShaderFromDecompilerOutput(LatteDecompilerOutput_t& decompilerOutput, uint64 baseHash, bool calculateAuxHash, uint64 optionalAuxHash, uint32* contextRegister);
void LatteShader_CreateRendererShader(LatteDecompilerShader* shader, bool compileAsync); void LatteShader_CreateRendererShader(LatteDecompilerShader* shader, bool compileAsync);
void LatteShader_FinishCompilation(LatteDecompilerShader* shader);
void LatteShader_prepareSeparableUniforms(LatteDecompilerShader* shader); void LatteShader_prepareSeparableUniforms(LatteDecompilerShader* shader);

View file

@ -106,13 +106,28 @@ void LatteShaderCache_removeFromCompileQueue(sint32 index)
*/ */
void LatteShaderCache_updateCompileQueue(sint32 maxRemainingEntries) void LatteShaderCache_updateCompileQueue(sint32 maxRemainingEntries)
{ {
// remove any shaders that are already done
for (size_t i = 0; i < shaderCompileQueue.count; i++)
{
auto shaderEntry = shaderCompileQueue.entry[i].shader;
if (!shaderEntry)
continue;
if (shaderEntry->shader->IsCompiled())
{
LatteShader_prepareSeparableUniforms(shaderEntry);
LatteShaderCache_removeFromCompileQueue(i);
}
}
while (true) while (true)
{ {
if (shaderCompileQueue.count <= maxRemainingEntries) if (shaderCompileQueue.count <= maxRemainingEntries)
break; break;
auto shader = shaderCompileQueue.entry[0].shader; auto shader = shaderCompileQueue.entry[0].shader;
if (shader) if (shader)
LatteShader_FinishCompilation(shader); {
shader->shader->PreponeCompilation();
LatteShader_prepareSeparableUniforms(shader);
}
LatteShaderCache_removeFromCompileQueue(0); LatteShaderCache_removeFromCompileQueue(0);
} }
} }

View file

@ -28,6 +28,8 @@ void LatteShader_prepareSeparableUniforms(LatteDecompilerShader* shader)
{ {
if (g_renderer->GetType() != RendererAPI::OpenGL) if (g_renderer->GetType() != RendererAPI::OpenGL)
return; return;
if(shader->hasError)
return;
auto shaderGL = (RendererShaderGL*)shader->shader; auto shaderGL = (RendererShaderGL*)shader->shader;
// setup uniform info // setup uniform info

View file

@ -868,7 +868,7 @@ RendererShaderGL* rectsEmulationGS_generateShaderGL(LatteDecompilerShader* verte
gsSrc.append("}\r\n"); gsSrc.append("}\r\n");
auto glShader = new RendererShaderGL(RendererShader::ShaderType::kGeometry, 0, 0, false, false, gsSrc); auto glShader = new RendererShaderGL(RendererShader::ShaderType::kGeometry, 0, 0, false, false, gsSrc);
glShader->PreponeCompilation(true); glShader->PreponeCompilation();
return glShader; return glShader;
} }

View file

@ -109,19 +109,8 @@ RendererShaderGL::RendererShaderGL(ShaderType type, uint64 baseHash, uint64 auxH
glShaderSource(m_shader_object, 1, &c_str, &size); glShaderSource(m_shader_object, 1, &c_str, &size);
glCompileShader(m_shader_object); glCompileShader(m_shader_object);
GLint log_length;
glGetShaderiv(m_shader_object, GL_INFO_LOG_LENGTH, &log_length);
if (log_length > 0)
{
char log[2048]{};
GLsizei log_size;
glGetShaderInfoLog(m_shader_object, std::min<uint32>(log_length, sizeof(log) - 1), &log_size, log);
cemuLog_log(LogType::Force, "Error/Warning in shader:");
cemuLog_log(LogType::Force, log);
}
// set debug name // set debug name
if (LaunchSettings::NSightModeEnabled()) if (LaunchSettings::NSightModeEnabled())
{ {
auto objNameStr = fmt::format("shader_{:016x}_{:016x}", m_baseHash, m_auxHash); auto objNameStr = fmt::format("shader_{:016x}_{:016x}", m_baseHash, m_auxHash);
glObjectLabel(GL_SHADER, m_shader_object, objNameStr.size(), objNameStr.c_str()); glObjectLabel(GL_SHADER, m_shader_object, objNameStr.size(), objNameStr.c_str());
@ -134,12 +123,6 @@ RendererShaderGL::RendererShaderGL(ShaderType type, uint64 baseHash, uint64 auxH
m_shader_attached = true; m_shader_attached = true;
glLinkProgram(m_program); glLinkProgram(m_program);
storeBinary();
// count shader compilation
if (!s_isLoadingShaders)
++g_compiled_shaders_total;
// we can throw away the GLSL code to conserve RAM // we can throw away the GLSL code to conserve RAM
m_glslSource.clear(); m_glslSource.clear();
m_glslSource.shrink_to_fit(); m_glslSource.shrink_to_fit();
@ -157,7 +140,7 @@ RendererShaderGL::~RendererShaderGL()
glDeleteProgram(m_program); glDeleteProgram(m_program);
} }
void RendererShaderGL::PreponeCompilation(bool isRenderThread) void RendererShaderGL::PreponeCompilation()
{ {
// the logic for initiating compilation is currently in the constructor // the logic for initiating compilation is currently in the constructor
// here we only guarantee that it is finished before we return // here we only guarantee that it is finished before we return
@ -168,47 +151,67 @@ void RendererShaderGL::PreponeCompilation(bool isRenderThread)
bool RendererShaderGL::IsCompiled() bool RendererShaderGL::IsCompiled()
{ {
cemu_assert_debug(false); if(m_isCompiled)
return true; return true;
if(!glMaxShaderCompilerThreadsARB)
{
WaitForCompiled();
return true;
}
GLint isShaderComplete = 0, isProgramComplete = 0;
glGetShaderiv(m_shader_object, GL_COMPLETION_STATUS_ARB, &isShaderComplete);
if(!isShaderComplete)
return false;
glGetProgramiv(m_program, GL_COMPLETION_STATUS_ARB, &isProgramComplete);
if (isProgramComplete)
WaitForCompiled(); // since COMPLETION_STATUS == true, this should be very fast
return m_isCompiled;
} }
bool RendererShaderGL::WaitForCompiled() bool RendererShaderGL::WaitForCompiled()
{ {
char infoLog[8 * 1024]; char infoLog[8 * 1024];
GLint log_length;
if (m_isCompiled) if (m_isCompiled)
return true; return true;
// count shader compilation
if (!s_isLoadingShaders)
++g_compiled_shaders_total;
// check if compilation was successful // check if compilation was successful
GLint compileStatus = GL_FALSE; GLint compileStatus = GL_FALSE;
glGetShaderiv(m_shader_object, GL_COMPILE_STATUS, &compileStatus); glGetShaderiv(m_shader_object, GL_COMPILE_STATUS, &compileStatus);
if (compileStatus == 0) if (compileStatus == GL_FALSE)
{ {
uint32 infoLogLength, tempLength; glGetShaderiv(m_shader_object, GL_INFO_LOG_LENGTH, &log_length);
glGetShaderiv(m_shader_object, GL_INFO_LOG_LENGTH, (GLint *)&infoLogLength); if (log_length > 0)
if (infoLogLength != 0)
{ {
tempLength = sizeof(infoLog) - 1; glGetShaderInfoLog(m_shader_object, sizeof(infoLog), &log_length, infoLog);
glGetShaderInfoLog(m_shader_object, std::min(infoLogLength, tempLength), (GLsizei*)&tempLength, (GLcharARB*)infoLog); cemuLog_log(LogType::Force, "Error/Warning in shader:");
infoLog[tempLength] = '\0';
cemuLog_log(LogType::Force, "Compile error in shader. Log:");
cemuLog_log(LogType::Force, infoLog); cemuLog_log(LogType::Force, infoLog);
} }
if (m_shader_object != 0) if (m_shader_object != 0)
glDeleteShader(m_shader_object); glDeleteShader(m_shader_object);
if (m_program != 0)
glDeleteProgram(m_program);
m_program = m_shader_object = 0;
m_isCompiled = true; m_isCompiled = true;
return false; return false;
} }
// get shader binary // get shader binary
GLint linkStatus = GL_FALSE; GLint linkStatus = GL_FALSE;
glGetProgramiv(m_program, GL_LINK_STATUS, &linkStatus); glGetProgramiv(m_program, GL_LINK_STATUS, &linkStatus);
if (linkStatus == 0) if (linkStatus == GL_FALSE)
{ {
uint32 infoLogLength, tempLength; glGetProgramiv(m_program, GL_INFO_LOG_LENGTH, (GLint *)&log_length);
glGetProgramiv(m_program, GL_INFO_LOG_LENGTH, (GLint *)&infoLogLength); if (log_length != 0)
if (infoLogLength != 0)
{ {
tempLength = sizeof(infoLog) - 1; glGetProgramInfoLog(m_program, sizeof(infoLog), &log_length, (GLcharARB*)infoLog);
glGetProgramInfoLog(m_program, std::min(infoLogLength, tempLength), (GLsizei*)&tempLength, (GLcharARB*)infoLog);
infoLog[tempLength] = '\0';
cemuLog_log(LogType::Force, "Link error in shader. Log:"); cemuLog_log(LogType::Force, "Link error in shader. Log:");
cemuLog_log(LogType::Force, infoLog); cemuLog_log(LogType::Force, infoLog);
} }
@ -216,8 +219,13 @@ bool RendererShaderGL::WaitForCompiled()
return false; return false;
} }
/*glDetachShader(m_program, m_shader_object); storeBinary();
m_shader_attached = false;*/
glDetachShader(m_program, m_shader_object);
m_shader_attached = false;
glDeleteShader(m_shader_object);
m_shader_object = 0;
m_isCompiled = true; m_isCompiled = true;
return true; return true;
} }
@ -276,8 +284,8 @@ void RendererShaderGL::ShaderCacheLoading_begin(uint64 cacheTitleId)
{ {
const uint32 cacheMagic = GeneratePrecompiledCacheId(); const uint32 cacheMagic = GeneratePrecompiledCacheId();
const std::string cacheFilename = fmt::format("{:016x}_gl.bin", cacheTitleId); const std::string cacheFilename = fmt::format("{:016x}_gl.bin", cacheTitleId);
s_programBinaryCache = FileCache::Open(ActiveSettings::GetCachePath("shaderCache/precompiled/{}", cacheFilename), true, cacheMagic); s_programBinaryCache.reset(FileCache::Open(ActiveSettings::GetCachePath("shaderCache/precompiled/{}", cacheFilename), true, cacheMagic));
if (s_programBinaryCache == nullptr) if (!s_programBinaryCache)
cemuLog_log(LogType::Force, "Unable to open OpenGL precompiled cache {}", cacheFilename); cemuLog_log(LogType::Force, "Unable to open OpenGL precompiled cache {}", cacheFilename);
} }
s_isLoadingShaders = true; s_isLoadingShaders = true;
@ -290,13 +298,10 @@ void RendererShaderGL::ShaderCacheLoading_end()
void RendererShaderGL::ShaderCacheLoading_Close() void RendererShaderGL::ShaderCacheLoading_Close()
{ {
if(s_programBinaryCache) s_programBinaryCache.reset();
{
delete s_programBinaryCache;
s_programBinaryCache = nullptr;
}
g_compiled_shaders_total = 0; g_compiled_shaders_total = 0;
g_compiled_shaders_async = 0; g_compiled_shaders_async = 0;
} }
FileCache* RendererShaderGL::s_programBinaryCache{};
std::unique_ptr<class FileCache> RendererShaderGL::s_programBinaryCache{};

View file

@ -10,7 +10,7 @@ public:
virtual ~RendererShaderGL(); virtual ~RendererShaderGL();
void PreponeCompilation(bool isRenderThread) override; void PreponeCompilation() override;
bool IsCompiled() override; bool IsCompiled() override;
bool WaitForCompiled() override; bool WaitForCompiled() override;
@ -40,6 +40,6 @@ private:
bool m_shader_attached{ false }; bool m_shader_attached{ false };
bool m_isCompiled{ false }; bool m_isCompiled{ false };
static class FileCache* s_programBinaryCache; static std::unique_ptr<class FileCache> s_programBinaryCache;
}; };

View file

@ -254,8 +254,8 @@ RendererOutputShader::RendererOutputShader(const std::string& vertex_source, con
m_vertex_shader.reset(g_renderer->shader_create(RendererShader::ShaderType::kVertex, 0, 0, vertex_source, false, false)); m_vertex_shader.reset(g_renderer->shader_create(RendererShader::ShaderType::kVertex, 0, 0, vertex_source, false, false));
m_fragment_shader.reset(g_renderer->shader_create(RendererShader::ShaderType::kFragment, 0, 0, finalFragmentSrc, false, false)); m_fragment_shader.reset(g_renderer->shader_create(RendererShader::ShaderType::kFragment, 0, 0, finalFragmentSrc, false, false));
m_vertex_shader->PreponeCompilation(true); m_vertex_shader->PreponeCompilation();
m_fragment_shader->PreponeCompilation(true); m_fragment_shader->PreponeCompilation();
if (!m_vertex_shader->WaitForCompiled()) if (!m_vertex_shader->WaitForCompiled())
throw std::exception(); throw std::exception();

View file

@ -14,7 +14,7 @@ public:
ShaderType GetType() const { return m_type; } ShaderType GetType() const { return m_type; }
virtual void PreponeCompilation(bool isRenderThread) = 0; // if shader not yet compiled, compile it synchronously (if possible) or alternatively wait for compilation. After this function IsCompiled() is guaranteed to be true virtual void PreponeCompilation() = 0; // if shader not yet compiled, compile it synchronously (if possible) or alternatively wait for compilation. After this function IsCompiled() is guaranteed to be true
virtual bool IsCompiled() = 0; virtual bool IsCompiled() = 0;
virtual bool WaitForCompiled() = 0; virtual bool WaitForCompiled() = 0;

View file

@ -174,7 +174,7 @@ public:
job->m_compilationState.setValue(RendererShaderVk::COMPILATION_STATE::COMPILING); job->m_compilationState.setValue(RendererShaderVk::COMPILATION_STATE::COMPILING);
s_compilationQueueMutex.unlock(); s_compilationQueueMutex.unlock();
// compile // compile
job->CompileInternal(false); job->CompileInternal();
++g_compiled_shaders_async; ++g_compiled_shaders_async;
// mark as compiled // mark as compiled
cemu_assert_debug(job->m_compilationState.getValue() == RendererShaderVk::COMPILATION_STATE::COMPILING); cemu_assert_debug(job->m_compilationState.getValue() == RendererShaderVk::COMPILATION_STATE::COMPILING);
@ -290,7 +290,7 @@ void RendererShaderVk::FinishCompilation()
m_glslCode.shrink_to_fit(); m_glslCode.shrink_to_fit();
} }
void RendererShaderVk::CompileInternal(bool isRenderThread) void RendererShaderVk::CompileInternal()
{ {
const bool compileWithDebugInfo = ((VulkanRenderer*)g_renderer.get())->IsTracingToolEnabled(); const bool compileWithDebugInfo = ((VulkanRenderer*)g_renderer.get())->IsTracingToolEnabled();
@ -419,7 +419,7 @@ void RendererShaderVk::CompileInternal(bool isRenderThread)
FinishCompilation(); FinishCompilation();
} }
void RendererShaderVk::PreponeCompilation(bool isRenderThread) void RendererShaderVk::PreponeCompilation()
{ {
ShaderVkThreadPool.s_compilationQueueMutex.lock(); ShaderVkThreadPool.s_compilationQueueMutex.lock();
bool isStillQueued = m_compilationState.hasState(COMPILATION_STATE::QUEUED); bool isStillQueued = m_compilationState.hasState(COMPILATION_STATE::QUEUED);
@ -439,7 +439,7 @@ void RendererShaderVk::PreponeCompilation(bool isRenderThread)
else else
{ {
// compile synchronously // compile synchronously
CompileInternal(isRenderThread); CompileInternal();
m_compilationState.setValue(COMPILATION_STATE::DONE); m_compilationState.setValue(COMPILATION_STATE::DONE);
} }
} }

View file

@ -54,12 +54,12 @@ public:
s_dependencyLock.unlock(); s_dependencyLock.unlock();
} }
void PreponeCompilation(bool isRenderThread) override; void PreponeCompilation() override;
bool IsCompiled() override; bool IsCompiled() override;
bool WaitForCompiled() override; bool WaitForCompiled() override;
private: private:
void CompileInternal(bool isRenderThread); void CompileInternal();
void FinishCompilation(); void FinishCompilation();

View file

@ -159,7 +159,7 @@ RendererShaderVk* rectsEmulationGS_generate(LatteDecompilerShader* vertexShader,
gsSrc.append("}\r\n"); gsSrc.append("}\r\n");
auto vkShader = new RendererShaderVk(RendererShader::ShaderType::kGeometry, 0, 0, false, false, gsSrc); auto vkShader = new RendererShaderVk(RendererShader::ShaderType::kGeometry, 0, 0, false, false, gsSrc);
vkShader->PreponeCompilation(true); vkShader->PreponeCompilation();
return vkShader; return vkShader;
} }
@ -966,11 +966,11 @@ bool PipelineCompiler::Compile(bool forceCompile, bool isRenderThread, bool show
{ {
// if some shader stages are not compiled yet, compile them now // if some shader stages are not compiled yet, compile them now
if (m_vkVertexShader && m_vkVertexShader->IsCompiled() == false) if (m_vkVertexShader && m_vkVertexShader->IsCompiled() == false)
m_vkVertexShader->PreponeCompilation(isRenderThread); m_vkVertexShader->PreponeCompilation();
if (m_vkPixelShader && m_vkPixelShader->IsCompiled() == false) if (m_vkPixelShader && m_vkPixelShader->IsCompiled() == false)
m_vkPixelShader->PreponeCompilation(isRenderThread); m_vkPixelShader->PreponeCompilation();
if (m_vkGeometryShader && m_vkGeometryShader->IsCompiled() == false) if (m_vkGeometryShader && m_vkGeometryShader->IsCompiled() == false)
m_vkGeometryShader->PreponeCompilation(isRenderThread); m_vkGeometryShader->PreponeCompilation();
} }
if (shaderStages.empty()) if (shaderStages.empty())

View file

@ -181,7 +181,7 @@ RendererShaderVk* _vkGenSurfaceCopyShader_vs()
std::string shaderStr(vsShaderSrc); std::string shaderStr(vsShaderSrc);
auto vkShader = new RendererShaderVk(RendererShader::ShaderType::kVertex, 0, 0, false, false, shaderStr); auto vkShader = new RendererShaderVk(RendererShader::ShaderType::kVertex, 0, 0, false, false, shaderStr);
vkShader->PreponeCompilation(true); vkShader->PreponeCompilation();
return vkShader; return vkShader;
} }
@ -199,7 +199,7 @@ RendererShaderVk* _vkGenSurfaceCopyShader_ps_colorToDepth()
std::string shaderStr(psShaderSrc); std::string shaderStr(psShaderSrc);
auto vkShader = new RendererShaderVk(RendererShader::ShaderType::kFragment, 0, 0, false, false, shaderStr); auto vkShader = new RendererShaderVk(RendererShader::ShaderType::kFragment, 0, 0, false, false, shaderStr);
vkShader->PreponeCompilation(true); vkShader->PreponeCompilation();
return vkShader; return vkShader;
} }
@ -218,7 +218,7 @@ RendererShaderVk* _vkGenSurfaceCopyShader_ps_depthToColor()
std::string shaderStr(psShaderSrc); std::string shaderStr(psShaderSrc);
auto vkShader = new RendererShaderVk(RendererShader::ShaderType::kFragment, 0, 0, false, false, shaderStr); auto vkShader = new RendererShaderVk(RendererShader::ShaderType::kFragment, 0, 0, false, false, shaderStr);
vkShader->PreponeCompilation(true); vkShader->PreponeCompilation();
return vkShader; return vkShader;
} }