From 328509e719468f7c574ab0047ed3b5ebcab4353a Mon Sep 17 00:00:00 2001 From: goeiecool9999 <7033575+goeiecool9999@users.noreply.github.com> Date: Thu, 24 Jul 2025 09:45:02 +0200 Subject: [PATCH] GL: delay shader error check and program linking to improve parallel shader compilation --- .../Renderer/OpenGL/RendererShaderGL.cpp | 83 +++++++++---------- 1 file changed, 39 insertions(+), 44 deletions(-) diff --git a/src/Cafe/HW/Latte/Renderer/OpenGL/RendererShaderGL.cpp b/src/Cafe/HW/Latte/Renderer/OpenGL/RendererShaderGL.cpp index 60a1830d..f872328a 100644 --- a/src/Cafe/HW/Latte/Renderer/OpenGL/RendererShaderGL.cpp +++ b/src/Cafe/HW/Latte/Renderer/OpenGL/RendererShaderGL.cpp @@ -109,37 +109,13 @@ 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(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()) + if (LaunchSettings::NSightModeEnabled()) { auto objNameStr = fmt::format("shader_{:016x}_{:016x}", m_baseHash, m_auxHash); glObjectLabel(GL_SHADER, m_shader_object, objNameStr.size(), objNameStr.c_str()); } - m_program = glCreateProgram(); - glProgramParameteri(m_program, GL_PROGRAM_SEPARABLE, GL_TRUE); - glProgramParameteri(m_program, GL_PROGRAM_BINARY_RETRIEVABLE_HINT, GL_TRUE); - glAttachShader(m_program, m_shader_object); - 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(); @@ -168,47 +144,61 @@ void RendererShaderGL::PreponeCompilation() bool RendererShaderGL::IsCompiled() { - cemu_assert_debug(false); - return true; + if(m_isCompiled) + return true; + GLint isShaderComplete; + glGetShaderiv(m_shader_object, GL_COMPLETION_STATUS_ARB, &isShaderComplete); + if(isShaderComplete) + 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); m_isCompiled = true; return false; } + + m_program = glCreateProgram(); + glProgramParameteri(m_program, GL_PROGRAM_SEPARABLE, GL_TRUE); + glProgramParameteri(m_program, GL_PROGRAM_BINARY_RETRIEVABLE_HINT, GL_TRUE); + glAttachShader(m_program, m_shader_object); + m_shader_attached = true; + glLinkProgram(m_program); + // 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 +206,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; }