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);
}
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)
{
auto& cache = LatteSHRC_GetCacheByType(shader->shaderType);
@ -846,8 +833,8 @@ LatteDecompilerShader* LatteShader_CompileSeparableVertexShader(uint64 baseHash,
if (g_renderer->GetType() == RendererAPI::OpenGL)
{
if (vertexShader->shader)
vertexShader->shader->PreponeCompilation(true);
LatteShader_FinishCompilation(vertexShader);
vertexShader->shader->PreponeCompilation();
LatteShader_prepareSeparableUniforms(vertexShader);
}
LatteSHRC_RegisterShader(vertexShader, vertexShader->baseHash, vertexShader->auxHash);
@ -875,8 +862,8 @@ LatteDecompilerShader* LatteShader_CompileSeparableGeometryShader(uint64 baseHas
if (g_renderer->GetType() == RendererAPI::OpenGL)
{
if (geometryShader->shader)
geometryShader->shader->PreponeCompilation(true);
LatteShader_FinishCompilation(geometryShader);
geometryShader->shader->PreponeCompilation();
LatteShader_prepareSeparableUniforms(geometryShader);
}
LatteSHRC_RegisterShader(geometryShader, geometryShader->baseHash, geometryShader->auxHash);
@ -904,8 +891,8 @@ LatteDecompilerShader* LatteShader_CompileSeparablePixelShader(uint64 baseHash,
if (g_renderer->GetType() == RendererAPI::OpenGL)
{
if (pixelShader->shader)
pixelShader->shader->PreponeCompilation(true);
LatteShader_FinishCompilation(pixelShader);
pixelShader->shader->PreponeCompilation();
LatteShader_prepareSeparableUniforms(pixelShader);
}
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);
void LatteShader_CreateRendererShader(LatteDecompilerShader* shader, bool compileAsync);
void LatteShader_FinishCompilation(LatteDecompilerShader* shader);
void LatteShader_prepareSeparableUniforms(LatteDecompilerShader* shader);

View file

@ -106,13 +106,28 @@ void LatteShaderCache_removeFromCompileQueue(sint32 index)
*/
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)
{
if (shaderCompileQueue.count <= maxRemainingEntries)
break;
auto shader = shaderCompileQueue.entry[0].shader;
if (shader)
LatteShader_FinishCompilation(shader);
{
shader->shader->PreponeCompilation();
LatteShader_prepareSeparableUniforms(shader);
}
LatteShaderCache_removeFromCompileQueue(0);
}
}

View file

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

View file

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

View file

@ -109,17 +109,6 @@ RendererShaderGL::RendererShaderGL(ShaderType type, uint64 baseHash, uint64 auxH
glShaderSource(m_shader_object, 1, &c_str, &size);
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
if (LaunchSettings::NSightModeEnabled())
{
@ -134,12 +123,6 @@ RendererShaderGL::RendererShaderGL(ShaderType type, uint64 baseHash, uint64 auxH
m_shader_attached = true;
glLinkProgram(m_program);
storeBinary();
// count shader compilation
if (!s_isLoadingShaders)
++g_compiled_shaders_total;
// we can throw away the GLSL code to conserve RAM
m_glslSource.clear();
m_glslSource.shrink_to_fit();
@ -157,7 +140,7 @@ RendererShaderGL::~RendererShaderGL()
glDeleteProgram(m_program);
}
void RendererShaderGL::PreponeCompilation(bool isRenderThread)
void RendererShaderGL::PreponeCompilation()
{
// the logic for initiating compilation is currently in the constructor
// here we only guarantee that it is finished before we return
@ -168,47 +151,67 @@ void RendererShaderGL::PreponeCompilation(bool isRenderThread)
bool RendererShaderGL::IsCompiled()
{
cemu_assert_debug(false);
return true;
if(m_isCompiled)
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()
{
char infoLog[8 * 1024];
GLint log_length;
if (m_isCompiled)
return true;
// count shader compilation
if (!s_isLoadingShaders)
++g_compiled_shaders_total;
// check if compilation was successful
GLint compileStatus = GL_FALSE;
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, (GLint *)&infoLogLength);
if (infoLogLength != 0)
glGetShaderiv(m_shader_object, GL_INFO_LOG_LENGTH, &log_length);
if (log_length > 0)
{
tempLength = sizeof(infoLog) - 1;
glGetShaderInfoLog(m_shader_object, std::min(infoLogLength, tempLength), (GLsizei*)&tempLength, (GLcharARB*)infoLog);
infoLog[tempLength] = '\0';
cemuLog_log(LogType::Force, "Compile error in shader. Log:");
glGetShaderInfoLog(m_shader_object, sizeof(infoLog), &log_length, infoLog);
cemuLog_log(LogType::Force, "Error/Warning in shader:");
cemuLog_log(LogType::Force, infoLog);
}
if (m_shader_object != 0)
glDeleteShader(m_shader_object);
if (m_program != 0)
glDeleteProgram(m_program);
m_program = m_shader_object = 0;
m_isCompiled = true;
return false;
}
// get shader binary
GLint linkStatus = GL_FALSE;
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 *)&infoLogLength);
if (infoLogLength != 0)
glGetProgramiv(m_program, GL_INFO_LOG_LENGTH, (GLint *)&log_length);
if (log_length != 0)
{
tempLength = sizeof(infoLog) - 1;
glGetProgramInfoLog(m_program, std::min(infoLogLength, tempLength), (GLsizei*)&tempLength, (GLcharARB*)infoLog);
infoLog[tempLength] = '\0';
glGetProgramInfoLog(m_program, sizeof(infoLog), &log_length, (GLcharARB*)infoLog);
cemuLog_log(LogType::Force, "Link error in shader. Log:");
cemuLog_log(LogType::Force, infoLog);
}
@ -216,8 +219,13 @@ bool RendererShaderGL::WaitForCompiled()
return false;
}
/*glDetachShader(m_program, m_shader_object);
m_shader_attached = false;*/
storeBinary();
glDetachShader(m_program, m_shader_object);
m_shader_attached = false;
glDeleteShader(m_shader_object);
m_shader_object = 0;
m_isCompiled = true;
return true;
}
@ -276,8 +284,8 @@ void RendererShaderGL::ShaderCacheLoading_begin(uint64 cacheTitleId)
{
const uint32 cacheMagic = GeneratePrecompiledCacheId();
const std::string cacheFilename = fmt::format("{:016x}_gl.bin", cacheTitleId);
s_programBinaryCache = FileCache::Open(ActiveSettings::GetCachePath("shaderCache/precompiled/{}", cacheFilename), true, cacheMagic);
if (s_programBinaryCache == nullptr)
s_programBinaryCache.reset(FileCache::Open(ActiveSettings::GetCachePath("shaderCache/precompiled/{}", cacheFilename), true, cacheMagic));
if (!s_programBinaryCache)
cemuLog_log(LogType::Force, "Unable to open OpenGL precompiled cache {}", cacheFilename);
}
s_isLoadingShaders = true;
@ -290,13 +298,10 @@ void RendererShaderGL::ShaderCacheLoading_end()
void RendererShaderGL::ShaderCacheLoading_Close()
{
if(s_programBinaryCache)
{
delete s_programBinaryCache;
s_programBinaryCache = nullptr;
}
s_programBinaryCache.reset();
g_compiled_shaders_total = 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();
void PreponeCompilation(bool isRenderThread) override;
void PreponeCompilation() override;
bool IsCompiled() override;
bool WaitForCompiled() override;
@ -40,6 +40,6 @@ private:
bool m_shader_attached{ 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_fragment_shader.reset(g_renderer->shader_create(RendererShader::ShaderType::kFragment, 0, 0, finalFragmentSrc, false, false));
m_vertex_shader->PreponeCompilation(true);
m_fragment_shader->PreponeCompilation(true);
m_vertex_shader->PreponeCompilation();
m_fragment_shader->PreponeCompilation();
if (!m_vertex_shader->WaitForCompiled())
throw std::exception();

View file

@ -14,7 +14,7 @@ public:
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 WaitForCompiled() = 0;

View file

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

View file

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

View file

@ -159,7 +159,7 @@ RendererShaderVk* rectsEmulationGS_generate(LatteDecompilerShader* vertexShader,
gsSrc.append("}\r\n");
auto vkShader = new RendererShaderVk(RendererShader::ShaderType::kGeometry, 0, 0, false, false, gsSrc);
vkShader->PreponeCompilation(true);
vkShader->PreponeCompilation();
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 (m_vkVertexShader && m_vkVertexShader->IsCompiled() == false)
m_vkVertexShader->PreponeCompilation(isRenderThread);
m_vkVertexShader->PreponeCompilation();
if (m_vkPixelShader && m_vkPixelShader->IsCompiled() == false)
m_vkPixelShader->PreponeCompilation(isRenderThread);
m_vkPixelShader->PreponeCompilation();
if (m_vkGeometryShader && m_vkGeometryShader->IsCompiled() == false)
m_vkGeometryShader->PreponeCompilation(isRenderThread);
m_vkGeometryShader->PreponeCompilation();
}
if (shaderStages.empty())

View file

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