GL: delay shader error check and program linking to improve parallel shader compilation

This commit is contained in:
goeiecool9999 2025-07-24 09:45:02 +02:00
parent a96435a5dd
commit 328509e719

View file

@ -109,17 +109,6 @@ 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())
{ {
@ -127,19 +116,6 @@ RendererShaderGL::RendererShaderGL(ShaderType type, uint64 baseHash, uint64 auxH
glObjectLabel(GL_SHADER, m_shader_object, objNameStr.size(), objNameStr.c_str()); 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 // 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();
@ -168,47 +144,61 @@ void RendererShaderGL::PreponeCompilation()
bool RendererShaderGL::IsCompiled() bool RendererShaderGL::IsCompiled()
{ {
cemu_assert_debug(false); if(m_isCompiled)
return true; 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() 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);
m_isCompiled = true; m_isCompiled = true;
return false; 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 // 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 +206,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;
} }