video_core: Remove assert in OpenGL LoadProgram and better logging (#1200)

This commit is contained in:
PabloMK7 2025-06-30 13:34:16 +02:00 committed by GitHub
parent f00d498f11
commit de7b457ee4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 61 additions and 27 deletions

View File

@ -1,4 +1,4 @@
// Copyright Citra Emulator Project / Lime3DS Emulator Project // Copyright Citra Emulator Project / Azahar Emulator Project
// Licensed under GPLv2 or any later version // Licensed under GPLv2 or any later version
// Refer to the license.txt file included. // Refer to the license.txt file included.
@ -43,8 +43,9 @@ OGLSampler CreateSampler(GLenum filter) {
return sampler; return sampler;
} }
OGLProgram CreateProgram(std::string_view frag) { OGLProgram CreateProgram(std::string_view frag, std::string_view debug_name) {
OGLProgram program; OGLProgram program;
program.SetDebugName(debug_name);
program.Create(HostShaders::FULL_SCREEN_TRIANGLE_VERT, frag); program.Create(HostShaders::FULL_SCREEN_TRIANGLE_VERT, frag);
glProgramUniform2f(program.handle, 0, 1.f, 1.f); glProgramUniform2f(program.handle, 0, 1.f, 1.f);
glProgramUniform2f(program.handle, 1, 0.f, 0.f); glProgramUniform2f(program.handle, 1, 0.f, 0.f);
@ -56,15 +57,15 @@ OGLProgram CreateProgram(std::string_view frag) {
BlitHelper::BlitHelper(const Driver& driver_) BlitHelper::BlitHelper(const Driver& driver_)
: driver{driver_}, linear_sampler{CreateSampler(GL_LINEAR)}, : driver{driver_}, linear_sampler{CreateSampler(GL_LINEAR)},
nearest_sampler{CreateSampler(GL_NEAREST)}, nearest_sampler{CreateSampler(GL_NEAREST)},
bicubic_program{CreateProgram(HostShaders::BICUBIC_FRAG)}, bicubic_program{CreateProgram(HostShaders::BICUBIC_FRAG, "BICUBIC_FRAG")},
scale_force_program{CreateProgram(HostShaders::SCALE_FORCE_FRAG)}, scale_force_program{CreateProgram(HostShaders::SCALE_FORCE_FRAG, "SCALE_FORCE_FRAG")},
xbrz_program{CreateProgram(HostShaders::XBRZ_FREESCALE_FRAG)}, xbrz_program{CreateProgram(HostShaders::XBRZ_FREESCALE_FRAG, "XBRZ_FREESCALE_FRAG")},
mmpx_program{CreateProgram(HostShaders::MMPX_FRAG)}, mmpx_program{CreateProgram(HostShaders::MMPX_FRAG, "MMPX_FRAG")},
gradient_x_program{CreateProgram(HostShaders::X_GRADIENT_FRAG)}, gradient_x_program{CreateProgram(HostShaders::X_GRADIENT_FRAG, "X_GRADIENT_FRAG")},
gradient_y_program{CreateProgram(HostShaders::Y_GRADIENT_FRAG)}, gradient_y_program{CreateProgram(HostShaders::Y_GRADIENT_FRAG, "Y_GRADIENT_FRAG")},
refine_program{CreateProgram(HostShaders::REFINE_FRAG)}, refine_program{CreateProgram(HostShaders::REFINE_FRAG, "REFINE_FRAG")},
d24s8_to_rgba8{CreateProgram(HostShaders::D24S8_TO_RGBA8_FRAG)}, d24s8_to_rgba8{CreateProgram(HostShaders::D24S8_TO_RGBA8_FRAG, "D24S8_TO_RGBA8_FRAG")},
rgba4_to_rgb5a1{CreateProgram(HostShaders::RGBA4_TO_RGB5A1_FRAG)} { rgba4_to_rgb5a1{CreateProgram(HostShaders::RGBA4_TO_RGB5A1_FRAG, "RGBA4_TO_RGB5A1_FRAG")} {
vao.Create(); vao.Create();
draw_fbo.Create(); draw_fbo.Create();
state.draw.vertex_array = vao.handle; state.draw.vertex_array = vao.handle;

View File

@ -1,4 +1,4 @@
// Copyright 2022 Citra Emulator Project // Copyright Citra Emulator Project / Azahar Emulator Project
// Licensed under GPLv2 or any later version // Licensed under GPLv2 or any later version
// Refer to the license.txt file included. // Refer to the license.txt file included.
@ -110,7 +110,7 @@ void OGLShader::Create(std::string_view source, GLenum type) {
return; return;
MICROPROFILE_SCOPE(OpenGL_ResourceCreation); MICROPROFILE_SCOPE(OpenGL_ResourceCreation);
handle = LoadShader(source, type); handle = LoadShader(source, type, debug_name);
} }
void OGLShader::Release() { void OGLShader::Release() {
@ -127,11 +127,13 @@ void OGLProgram::Create(bool separable_program, std::span<const GLuint> shaders)
return; return;
MICROPROFILE_SCOPE(OpenGL_ResourceCreation); MICROPROFILE_SCOPE(OpenGL_ResourceCreation);
handle = LoadProgram(separable_program, shaders); handle = LoadProgram(separable_program, shaders, debug_name);
} }
void OGLProgram::Create(std::string_view vert_shader, std::string_view frag_shader) { void OGLProgram::Create(std::string_view vert_shader, std::string_view frag_shader) {
OGLShader vert, frag; OGLShader vert, frag;
vert.SetDebugName(debug_name + "_vert");
frag.SetDebugName(debug_name + "_frag");
vert.Create(vert_shader, GL_VERTEX_SHADER); vert.Create(vert_shader, GL_VERTEX_SHADER);
frag.Create(frag_shader, GL_FRAGMENT_SHADER); frag.Create(frag_shader, GL_FRAGMENT_SHADER);

View File

@ -5,6 +5,7 @@
#pragma once #pragma once
#include <span> #include <span>
#include <string>
#include <string_view> #include <string_view>
#include <utility> #include <utility>
#include <vector> #include <vector>
@ -111,7 +112,14 @@ public:
void Release(); void Release();
void SetDebugName(std::string_view debug_name) {
this->debug_name = debug_name;
}
GLuint handle = 0; GLuint handle = 0;
private:
std::string debug_name = "Unk";
}; };
class OGLProgram : private NonCopyable { class OGLProgram : private NonCopyable {
@ -139,7 +147,14 @@ public:
/// Deletes the internal OpenGL resource /// Deletes the internal OpenGL resource
void Release(); void Release();
void SetDebugName(std::string_view debug_name) {
this->debug_name = debug_name;
}
GLuint handle = 0; GLuint handle = 0;
private:
std::string debug_name = "Unk";
}; };
class OGLPipeline : private NonCopyable { class OGLPipeline : private NonCopyable {

View File

@ -1,4 +1,4 @@
// Copyright 2014 Citra Emulator Project // Copyright Citra Emulator Project / Azahar Emulator Project
// Licensed under GPLv2 or any later version // Licensed under GPLv2 or any later version
// Refer to the license.txt file included. // Refer to the license.txt file included.
@ -13,7 +13,7 @@
namespace OpenGL { namespace OpenGL {
GLuint LoadShader(std::string_view source, GLenum type) { GLuint LoadShader(std::string_view source, GLenum type, const std::string& debug_name) {
std::string preamble; std::string preamble;
if (GLES) { if (GLES) {
preamble = R"(#version 320 es preamble = R"(#version 320 es
@ -49,8 +49,15 @@ GLuint LoadShader(std::string_view source, GLenum type) {
std::array<GLint, 2> lengths{static_cast<GLint>(preamble.size()), std::array<GLint, 2> lengths{static_cast<GLint>(preamble.size()),
static_cast<GLint>(source.size())}; static_cast<GLint>(source.size())};
GLuint shader_id = glCreateShader(type); GLuint shader_id = glCreateShader(type);
if (shader_id == 0) {
GLenum err = glGetError();
LOG_ERROR(Render_OpenGL, "glCreateShader failed for {} shader {} (err {})", debug_type,
debug_name, err);
return shader_id;
}
glShaderSource(shader_id, static_cast<GLsizei>(src_arr.size()), src_arr.data(), lengths.data()); glShaderSource(shader_id, static_cast<GLsizei>(src_arr.size()), src_arr.data(), lengths.data());
LOG_DEBUG(Render_OpenGL, "Compiling {} shader...", debug_type); LOG_DEBUG(Render_OpenGL, "Compiling {} shader {}...", debug_type, debug_name);
glCompileShader(shader_id); glCompileShader(shader_id);
GLint result = GL_FALSE; GLint result = GL_FALSE;
@ -62,17 +69,22 @@ GLuint LoadShader(std::string_view source, GLenum type) {
std::vector<char> shader_error(info_log_length); std::vector<char> shader_error(info_log_length);
glGetShaderInfoLog(shader_id, info_log_length, nullptr, &shader_error[0]); glGetShaderInfoLog(shader_id, info_log_length, nullptr, &shader_error[0]);
if (result == GL_TRUE) { if (result == GL_TRUE) {
LOG_DEBUG(Render_OpenGL, "{}", &shader_error[0]); LOG_DEBUG(Render_OpenGL, "Compile message for {} shader {}:\n{}", debug_type,
debug_name, &shader_error[0]);
} else { } else {
LOG_ERROR(Render_OpenGL, "Error compiling {} shader:\n{}", debug_type, LOG_ERROR(Render_OpenGL, "Error compiling {} shader {}:\n{}", debug_type, debug_name,
&shader_error[0]); &shader_error[0]);
LOG_ERROR(Render_OpenGL, "Shader source code:\n{}{}", src_arr[0], src_arr[1]); LOG_ERROR(Render_OpenGL, "Shader source code:\n{}{}", src_arr[0], src_arr[1]);
} }
} else if (result == GL_FALSE) {
LOG_ERROR(Render_OpenGL, "Error compiling {} shader {}:\nNo log produced.", debug_type,
debug_name);
} }
return shader_id; return shader_id;
} }
GLuint LoadProgram(bool separable_program, std::span<const GLuint> shaders) { GLuint LoadProgram(bool separable_program, std::span<const GLuint> shaders,
const std::string& debug_name) {
// Link the program // Link the program
LOG_DEBUG(Render_OpenGL, "Linking program..."); LOG_DEBUG(Render_OpenGL, "Linking program...");
@ -101,14 +113,15 @@ GLuint LoadProgram(bool separable_program, std::span<const GLuint> shaders) {
std::vector<char> program_error(info_log_length); std::vector<char> program_error(info_log_length);
glGetProgramInfoLog(program_id, info_log_length, nullptr, &program_error[0]); glGetProgramInfoLog(program_id, info_log_length, nullptr, &program_error[0]);
if (result == GL_TRUE) { if (result == GL_TRUE) {
LOG_DEBUG(Render_OpenGL, "{}", &program_error[0]); LOG_DEBUG(Render_OpenGL, "Link message for shader {}:\n{}", debug_name,
&program_error[0]);
} else { } else {
LOG_ERROR(Render_OpenGL, "Error linking shader:\n{}", &program_error[0]); LOG_ERROR(Render_OpenGL, "Error linking shader {}:\n{}", debug_name, &program_error[0]);
} }
} else if (result == GL_FALSE) {
LOG_ERROR(Render_OpenGL, "Error linking shader {}: No log produced.", debug_name);
} }
ASSERT_MSG(result == GL_TRUE, "Shader not linked");
for (GLuint shader : shaders) { for (GLuint shader : shaders) {
if (shader != 0) { if (shader != 0) {
glDetachShader(program_id, shader); glDetachShader(program_id, shader);

View File

@ -1,4 +1,4 @@
// Copyright 2014 Citra Emulator Project // Copyright Citra Emulator Project / Azahar Emulator Project
// Licensed under GPLv2 or any later version // Licensed under GPLv2 or any later version
// Refer to the license.txt file included. // Refer to the license.txt file included.
@ -13,15 +13,18 @@ namespace OpenGL {
* Utility function to create and compile an OpenGL GLSL shader * Utility function to create and compile an OpenGL GLSL shader
* @param source String of the GLSL shader program * @param source String of the GLSL shader program
* @param type Type of the shader (GL_VERTEX_SHADER, GL_GEOMETRY_SHADER or GL_FRAGMENT_SHADER) * @param type Type of the shader (GL_VERTEX_SHADER, GL_GEOMETRY_SHADER or GL_FRAGMENT_SHADER)
* @param debug_name debug name to show in logs
*/ */
GLuint LoadShader(std::string_view source, GLenum type); GLuint LoadShader(std::string_view source, GLenum type, const std::string& debug_name);
/** /**
* Utility function to create and link an OpenGL GLSL shader program * Utility function to create and link an OpenGL GLSL shader program
* @param separable_program whether to create a separable program * @param separable_program whether to create a separable program
* @param shaders ID of shaders to attach to the program * @param shaders ID of shaders to attach to the program
* @param debug_name debug name to show in logs
* @returns Handle of the newly created OpenGL program object * @returns Handle of the newly created OpenGL program object
*/ */
GLuint LoadProgram(bool separable_program, std::span<const GLuint> shaders); GLuint LoadProgram(bool separable_program, std::span<const GLuint> shaders,
const std::string& debug_name);
} // namespace OpenGL } // namespace OpenGL