diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/video_core/renderer_opengl/gl_shader_util.cpp | 154 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_shader_util.h | 6 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/renderer_opengl.cpp | 2 |
3 files changed, 116 insertions, 46 deletions
diff --git a/src/video_core/renderer_opengl/gl_shader_util.cpp b/src/video_core/renderer_opengl/gl_shader_util.cpp index 4da241d83..a3ba16761 100644 --- a/src/video_core/renderer_opengl/gl_shader_util.cpp +++ b/src/video_core/renderer_opengl/gl_shader_util.cpp | |||
| @@ -10,53 +10,85 @@ | |||
| 10 | 10 | ||
| 11 | namespace GLShader { | 11 | namespace GLShader { |
| 12 | 12 | ||
| 13 | GLuint LoadProgram(const char* vertex_shader, const char* fragment_shader) { | 13 | GLuint LoadProgram(const char* vertex_shader, const char* geometry_shader, |
| 14 | 14 | const char* fragment_shader, const std::vector<const char*>& feedback_vars, | |
| 15 | bool separable_program) { | ||
| 15 | // Create the shaders | 16 | // Create the shaders |
| 16 | GLuint vertex_shader_id = glCreateShader(GL_VERTEX_SHADER); | 17 | GLuint vertex_shader_id = vertex_shader ? glCreateShader(GL_VERTEX_SHADER) : 0; |
| 17 | GLuint fragment_shader_id = glCreateShader(GL_FRAGMENT_SHADER); | 18 | GLuint geometry_shader_id = geometry_shader ? glCreateShader(GL_GEOMETRY_SHADER) : 0; |
| 19 | GLuint fragment_shader_id = fragment_shader ? glCreateShader(GL_FRAGMENT_SHADER) : 0; | ||
| 18 | 20 | ||
| 19 | GLint result = GL_FALSE; | 21 | GLint result = GL_FALSE; |
| 20 | int info_log_length; | 22 | int info_log_length; |
| 21 | 23 | ||
| 22 | // Compile Vertex Shader | 24 | if (vertex_shader) { |
| 23 | LOG_DEBUG(Render_OpenGL, "Compiling vertex shader..."); | 25 | // Compile Vertex Shader |
| 24 | 26 | LOG_DEBUG(Render_OpenGL, "Compiling vertex shader..."); | |
| 25 | glShaderSource(vertex_shader_id, 1, &vertex_shader, nullptr); | 27 | |
| 26 | glCompileShader(vertex_shader_id); | 28 | glShaderSource(vertex_shader_id, 1, &vertex_shader, nullptr); |
| 27 | 29 | glCompileShader(vertex_shader_id); | |
| 28 | // Check Vertex Shader | 30 | |
| 29 | glGetShaderiv(vertex_shader_id, GL_COMPILE_STATUS, &result); | 31 | // Check Vertex Shader |
| 30 | glGetShaderiv(vertex_shader_id, GL_INFO_LOG_LENGTH, &info_log_length); | 32 | glGetShaderiv(vertex_shader_id, GL_COMPILE_STATUS, &result); |
| 31 | 33 | glGetShaderiv(vertex_shader_id, GL_INFO_LOG_LENGTH, &info_log_length); | |
| 32 | if (info_log_length > 1) { | 34 | |
| 33 | std::vector<char> vertex_shader_error(info_log_length); | 35 | if (info_log_length > 1) { |
| 34 | glGetShaderInfoLog(vertex_shader_id, info_log_length, nullptr, &vertex_shader_error[0]); | 36 | std::vector<char> vertex_shader_error(info_log_length); |
| 35 | if (result == GL_TRUE) { | 37 | glGetShaderInfoLog(vertex_shader_id, info_log_length, nullptr, &vertex_shader_error[0]); |
| 36 | LOG_DEBUG(Render_OpenGL, "%s", &vertex_shader_error[0]); | 38 | if (result == GL_TRUE) { |
| 37 | } else { | 39 | LOG_DEBUG(Render_OpenGL, "%s", &vertex_shader_error[0]); |
| 38 | LOG_ERROR(Render_OpenGL, "Error compiling vertex shader:\n%s", &vertex_shader_error[0]); | 40 | } else { |
| 41 | LOG_ERROR(Render_OpenGL, "Error compiling vertex shader:\n%s", | ||
| 42 | &vertex_shader_error[0]); | ||
| 43 | } | ||
| 39 | } | 44 | } |
| 40 | } | 45 | } |
| 41 | 46 | ||
| 42 | // Compile Fragment Shader | 47 | if (geometry_shader) { |
| 43 | LOG_DEBUG(Render_OpenGL, "Compiling fragment shader..."); | 48 | // Compile Geometry Shader |
| 44 | 49 | LOG_DEBUG(Render_OpenGL, "Compiling geometry shader..."); | |
| 45 | glShaderSource(fragment_shader_id, 1, &fragment_shader, nullptr); | 50 | |
| 46 | glCompileShader(fragment_shader_id); | 51 | glShaderSource(geometry_shader_id, 1, &geometry_shader, nullptr); |
| 47 | 52 | glCompileShader(geometry_shader_id); | |
| 48 | // Check Fragment Shader | 53 | |
| 49 | glGetShaderiv(fragment_shader_id, GL_COMPILE_STATUS, &result); | 54 | // Check Geometry Shader |
| 50 | glGetShaderiv(fragment_shader_id, GL_INFO_LOG_LENGTH, &info_log_length); | 55 | glGetShaderiv(geometry_shader_id, GL_COMPILE_STATUS, &result); |
| 56 | glGetShaderiv(geometry_shader_id, GL_INFO_LOG_LENGTH, &info_log_length); | ||
| 57 | |||
| 58 | if (info_log_length > 1) { | ||
| 59 | std::vector<char> geometry_shader_error(info_log_length); | ||
| 60 | glGetShaderInfoLog(geometry_shader_id, info_log_length, nullptr, | ||
| 61 | &geometry_shader_error[0]); | ||
| 62 | if (result == GL_TRUE) { | ||
| 63 | LOG_DEBUG(Render_OpenGL, "%s", &geometry_shader_error[0]); | ||
| 64 | } else { | ||
| 65 | LOG_ERROR(Render_OpenGL, "Error compiling geometry shader:\n%s", | ||
| 66 | &geometry_shader_error[0]); | ||
| 67 | } | ||
| 68 | } | ||
| 69 | } | ||
| 51 | 70 | ||
| 52 | if (info_log_length > 1) { | 71 | if (fragment_shader) { |
| 53 | std::vector<char> fragment_shader_error(info_log_length); | 72 | // Compile Fragment Shader |
| 54 | glGetShaderInfoLog(fragment_shader_id, info_log_length, nullptr, &fragment_shader_error[0]); | 73 | LOG_DEBUG(Render_OpenGL, "Compiling fragment shader..."); |
| 55 | if (result == GL_TRUE) { | 74 | |
| 56 | LOG_DEBUG(Render_OpenGL, "%s", &fragment_shader_error[0]); | 75 | glShaderSource(fragment_shader_id, 1, &fragment_shader, nullptr); |
| 57 | } else { | 76 | glCompileShader(fragment_shader_id); |
| 58 | LOG_ERROR(Render_OpenGL, "Error compiling fragment shader:\n%s", | 77 | |
| 59 | &fragment_shader_error[0]); | 78 | // Check Fragment Shader |
| 79 | glGetShaderiv(fragment_shader_id, GL_COMPILE_STATUS, &result); | ||
| 80 | glGetShaderiv(fragment_shader_id, GL_INFO_LOG_LENGTH, &info_log_length); | ||
| 81 | |||
| 82 | if (info_log_length > 1) { | ||
| 83 | std::vector<char> fragment_shader_error(info_log_length); | ||
| 84 | glGetShaderInfoLog(fragment_shader_id, info_log_length, nullptr, | ||
| 85 | &fragment_shader_error[0]); | ||
| 86 | if (result == GL_TRUE) { | ||
| 87 | LOG_DEBUG(Render_OpenGL, "%s", &fragment_shader_error[0]); | ||
| 88 | } else { | ||
| 89 | LOG_ERROR(Render_OpenGL, "Error compiling fragment shader:\n%s", | ||
| 90 | &fragment_shader_error[0]); | ||
| 91 | } | ||
| 60 | } | 92 | } |
| 61 | } | 93 | } |
| 62 | 94 | ||
| @@ -64,8 +96,25 @@ GLuint LoadProgram(const char* vertex_shader, const char* fragment_shader) { | |||
| 64 | LOG_DEBUG(Render_OpenGL, "Linking program..."); | 96 | LOG_DEBUG(Render_OpenGL, "Linking program..."); |
| 65 | 97 | ||
| 66 | GLuint program_id = glCreateProgram(); | 98 | GLuint program_id = glCreateProgram(); |
| 67 | glAttachShader(program_id, vertex_shader_id); | 99 | if (vertex_shader) { |
| 68 | glAttachShader(program_id, fragment_shader_id); | 100 | glAttachShader(program_id, vertex_shader_id); |
| 101 | } | ||
| 102 | if (geometry_shader) { | ||
| 103 | glAttachShader(program_id, geometry_shader_id); | ||
| 104 | } | ||
| 105 | if (fragment_shader) { | ||
| 106 | glAttachShader(program_id, fragment_shader_id); | ||
| 107 | } | ||
| 108 | |||
| 109 | if (!feedback_vars.empty()) { | ||
| 110 | auto varyings = feedback_vars; | ||
| 111 | glTransformFeedbackVaryings(program_id, static_cast<GLsizei>(feedback_vars.size()), | ||
| 112 | &varyings[0], GL_INTERLEAVED_ATTRIBS); | ||
| 113 | } | ||
| 114 | |||
| 115 | if (separable_program) { | ||
| 116 | glProgramParameteri(program_id, GL_PROGRAM_SEPARABLE, GL_TRUE); | ||
| 117 | } | ||
| 69 | 118 | ||
| 70 | glLinkProgram(program_id); | 119 | glLinkProgram(program_id); |
| 71 | 120 | ||
| @@ -85,13 +134,30 @@ GLuint LoadProgram(const char* vertex_shader, const char* fragment_shader) { | |||
| 85 | 134 | ||
| 86 | // If the program linking failed at least one of the shaders was probably bad | 135 | // If the program linking failed at least one of the shaders was probably bad |
| 87 | if (result == GL_FALSE) { | 136 | if (result == GL_FALSE) { |
| 88 | LOG_ERROR(Render_OpenGL, "Vertex shader:\n%s", vertex_shader); | 137 | if (vertex_shader) { |
| 89 | LOG_ERROR(Render_OpenGL, "Fragment shader:\n%s", fragment_shader); | 138 | LOG_ERROR(Render_OpenGL, "Vertex shader:\n%s", vertex_shader); |
| 139 | } | ||
| 140 | if (geometry_shader) { | ||
| 141 | LOG_ERROR(Render_OpenGL, "Geometry shader:\n%s", geometry_shader); | ||
| 142 | } | ||
| 143 | if (fragment_shader) { | ||
| 144 | LOG_ERROR(Render_OpenGL, "Fragment shader:\n%s", fragment_shader); | ||
| 145 | } | ||
| 90 | } | 146 | } |
| 91 | ASSERT_MSG(result == GL_TRUE, "Shader not linked"); | 147 | ASSERT_MSG(result == GL_TRUE, "Shader not linked"); |
| 92 | 148 | ||
| 93 | glDeleteShader(vertex_shader_id); | 149 | if (vertex_shader) { |
| 94 | glDeleteShader(fragment_shader_id); | 150 | glDetachShader(program_id, vertex_shader_id); |
| 151 | glDeleteShader(vertex_shader_id); | ||
| 152 | } | ||
| 153 | if (geometry_shader) { | ||
| 154 | glDetachShader(program_id, geometry_shader_id); | ||
| 155 | glDeleteShader(geometry_shader_id); | ||
| 156 | } | ||
| 157 | if (fragment_shader) { | ||
| 158 | glDetachShader(program_id, fragment_shader_id); | ||
| 159 | glDeleteShader(fragment_shader_id); | ||
| 160 | } | ||
| 95 | 161 | ||
| 96 | return program_id; | 162 | return program_id; |
| 97 | } | 163 | } |
diff --git a/src/video_core/renderer_opengl/gl_shader_util.h b/src/video_core/renderer_opengl/gl_shader_util.h index a4bcffdfa..fc7b5e080 100644 --- a/src/video_core/renderer_opengl/gl_shader_util.h +++ b/src/video_core/renderer_opengl/gl_shader_util.h | |||
| @@ -4,6 +4,7 @@ | |||
| 4 | 4 | ||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include <vector> | ||
| 7 | #include <glad/glad.h> | 8 | #include <glad/glad.h> |
| 8 | 9 | ||
| 9 | namespace GLShader { | 10 | namespace GLShader { |
| @@ -11,9 +12,12 @@ namespace GLShader { | |||
| 11 | /** | 12 | /** |
| 12 | * Utility function to create and compile an OpenGL GLSL shader program (vertex + fragment shader) | 13 | * Utility function to create and compile an OpenGL GLSL shader program (vertex + fragment shader) |
| 13 | * @param vertex_shader String of the GLSL vertex shader program | 14 | * @param vertex_shader String of the GLSL vertex shader program |
| 15 | * @param geometry_shader String of the GLSL geometry shader program | ||
| 14 | * @param fragment_shader String of the GLSL fragment shader program | 16 | * @param fragment_shader String of the GLSL fragment shader program |
| 15 | * @returns Handle of the newly created OpenGL shader object | 17 | * @returns Handle of the newly created OpenGL shader object |
| 16 | */ | 18 | */ |
| 17 | GLuint LoadProgram(const char* vertex_shader, const char* fragment_shader); | 19 | GLuint LoadProgram(const char* vertex_shader, const char* geometry_shader, |
| 20 | const char* fragment_shader, const std::vector<const char*>& feedback_vars = {}, | ||
| 21 | bool separable_program = false); | ||
| 18 | 22 | ||
| 19 | } // namespace GLShader | 23 | } // namespace GLShader |
diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp index 7f921fa32..65d38ade5 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.cpp +++ b/src/video_core/renderer_opengl/renderer_opengl.cpp | |||
| @@ -318,7 +318,7 @@ void RendererOpenGL::InitOpenGLObjects() { | |||
| 318 | 0.0f); | 318 | 0.0f); |
| 319 | 319 | ||
| 320 | // Link shaders and get variable locations | 320 | // Link shaders and get variable locations |
| 321 | shader.Create(vertex_shader, fragment_shader); | 321 | shader.Create(vertex_shader, nullptr, fragment_shader); |
| 322 | state.draw.shader_program = shader.handle; | 322 | state.draw.shader_program = shader.handle; |
| 323 | state.Apply(); | 323 | state.Apply(); |
| 324 | uniform_modelview_matrix = glGetUniformLocation(shader.handle, "modelview_matrix"); | 324 | uniform_modelview_matrix = glGetUniformLocation(shader.handle, "modelview_matrix"); |