diff options
| author | 2018-04-06 23:54:44 -0400 | |
|---|---|---|
| committer | 2018-04-13 23:48:21 -0400 | |
| commit | 4f2b2d0bc5e56a5f1e05a2d1cae52d8890fa3ce9 (patch) | |
| tree | b74c3770fcd689a378db1093c60ae82543841093 | |
| parent | gl_resource_manager: Grab latest upstream. (diff) | |
| download | yuzu-4f2b2d0bc5e56a5f1e05a2d1cae52d8890fa3ce9.tar.gz yuzu-4f2b2d0bc5e56a5f1e05a2d1cae52d8890fa3ce9.tar.xz yuzu-4f2b2d0bc5e56a5f1e05a2d1cae52d8890fa3ce9.zip | |
gl_shader_util: Grab latest upstream.
| -rw-r--r-- | src/video_core/renderer_opengl/gl_shader_util.cpp | 169 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_shader_util.h | 54 |
2 files changed, 74 insertions, 149 deletions
diff --git a/src/video_core/renderer_opengl/gl_shader_util.cpp b/src/video_core/renderer_opengl/gl_shader_util.cpp index a6c6204d5..8568fface 100644 --- a/src/video_core/renderer_opengl/gl_shader_util.cpp +++ b/src/video_core/renderer_opengl/gl_shader_util.cpp | |||
| @@ -10,156 +10,41 @@ | |||
| 10 | 10 | ||
| 11 | namespace GLShader { | 11 | namespace GLShader { |
| 12 | 12 | ||
| 13 | GLuint LoadProgram(const char* vertex_shader, const char* geometry_shader, | 13 | GLuint LoadShader(const char* source, GLenum type) { |
| 14 | const char* fragment_shader, const std::vector<const char*>& feedback_vars, | 14 | const char* debug_type; |
| 15 | bool separable_program) { | 15 | switch (type) { |
| 16 | // Create the shaders | 16 | case GL_VERTEX_SHADER: |
| 17 | GLuint vertex_shader_id = vertex_shader ? glCreateShader(GL_VERTEX_SHADER) : 0; | 17 | debug_type = "vertex"; |
| 18 | GLuint geometry_shader_id = geometry_shader ? glCreateShader(GL_GEOMETRY_SHADER) : 0; | 18 | break; |
| 19 | GLuint fragment_shader_id = fragment_shader ? glCreateShader(GL_FRAGMENT_SHADER) : 0; | 19 | case GL_GEOMETRY_SHADER: |
| 20 | debug_type = "geometry"; | ||
| 21 | break; | ||
| 22 | case GL_FRAGMENT_SHADER: | ||
| 23 | debug_type = "fragment"; | ||
| 24 | break; | ||
| 25 | default: | ||
| 26 | UNREACHABLE(); | ||
| 27 | } | ||
| 28 | GLuint shader_id = glCreateShader(type); | ||
| 29 | glShaderSource(shader_id, 1, &source, nullptr); | ||
| 30 | NGLOG_DEBUG(Render_OpenGL, "Compiling {} shader...", debug_type); | ||
| 31 | glCompileShader(shader_id); | ||
| 20 | 32 | ||
| 21 | GLint result = GL_FALSE; | 33 | GLint result = GL_FALSE; |
| 22 | int info_log_length; | 34 | GLint info_log_length; |
| 23 | 35 | glGetShaderiv(shader_id, GL_COMPILE_STATUS, &result); | |
| 24 | if (vertex_shader) { | 36 | glGetShaderiv(shader_id, GL_INFO_LOG_LENGTH, &info_log_length); |
| 25 | // Compile Vertex Shader | ||
| 26 | LOG_DEBUG(Render_OpenGL, "Compiling vertex shader..."); | ||
| 27 | |||
| 28 | glShaderSource(vertex_shader_id, 1, &vertex_shader, nullptr); | ||
| 29 | glCompileShader(vertex_shader_id); | ||
| 30 | |||
| 31 | // Check Vertex Shader | ||
| 32 | glGetShaderiv(vertex_shader_id, GL_COMPILE_STATUS, &result); | ||
| 33 | glGetShaderiv(vertex_shader_id, GL_INFO_LOG_LENGTH, &info_log_length); | ||
| 34 | |||
| 35 | if (info_log_length > 1) { | ||
| 36 | std::vector<char> vertex_shader_error(info_log_length); | ||
| 37 | glGetShaderInfoLog(vertex_shader_id, info_log_length, nullptr, &vertex_shader_error[0]); | ||
| 38 | if (result == GL_TRUE) { | ||
| 39 | LOG_DEBUG(Render_OpenGL, "%s", &vertex_shader_error[0]); | ||
| 40 | } else { | ||
| 41 | LOG_CRITICAL(Render_OpenGL, "Error compiling vertex shader:\n%s", | ||
| 42 | &vertex_shader_error[0]); | ||
| 43 | } | ||
| 44 | } | ||
| 45 | } | ||
| 46 | |||
| 47 | if (geometry_shader) { | ||
| 48 | // Compile Geometry Shader | ||
| 49 | LOG_DEBUG(Render_OpenGL, "Compiling geometry shader..."); | ||
| 50 | |||
| 51 | glShaderSource(geometry_shader_id, 1, &geometry_shader, nullptr); | ||
| 52 | glCompileShader(geometry_shader_id); | ||
| 53 | |||
| 54 | // Check Geometry Shader | ||
| 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_CRITICAL(Render_OpenGL, "Error compiling geometry shader:\n%s", | ||
| 66 | &geometry_shader_error[0]); | ||
| 67 | } | ||
| 68 | } | ||
| 69 | } | ||
| 70 | |||
| 71 | if (fragment_shader) { | ||
| 72 | // Compile Fragment Shader | ||
| 73 | LOG_DEBUG(Render_OpenGL, "Compiling fragment shader..."); | ||
| 74 | |||
| 75 | glShaderSource(fragment_shader_id, 1, &fragment_shader, nullptr); | ||
| 76 | glCompileShader(fragment_shader_id); | ||
| 77 | |||
| 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_CRITICAL(Render_OpenGL, "Error compiling fragment shader:\n%s", | ||
| 90 | &fragment_shader_error[0]); | ||
| 91 | } | ||
| 92 | } | ||
| 93 | } | ||
| 94 | |||
| 95 | // Link the program | ||
| 96 | LOG_DEBUG(Render_OpenGL, "Linking program..."); | ||
| 97 | |||
| 98 | GLuint program_id = glCreateProgram(); | ||
| 99 | if (vertex_shader) { | ||
| 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 | } | ||
| 118 | |||
| 119 | glLinkProgram(program_id); | ||
| 120 | |||
| 121 | // Check the program | ||
| 122 | glGetProgramiv(program_id, GL_LINK_STATUS, &result); | ||
| 123 | glGetProgramiv(program_id, GL_INFO_LOG_LENGTH, &info_log_length); | ||
| 124 | 37 | ||
| 125 | if (info_log_length > 1) { | 38 | if (info_log_length > 1) { |
| 126 | std::vector<char> program_error(info_log_length); | 39 | std::string shader_error(info_log_length, ' '); |
| 127 | glGetProgramInfoLog(program_id, info_log_length, nullptr, &program_error[0]); | 40 | glGetShaderInfoLog(shader_id, info_log_length, nullptr, &shader_error[0]); |
| 128 | if (result == GL_TRUE) { | 41 | if (result == GL_TRUE) { |
| 129 | LOG_DEBUG(Render_OpenGL, "%s", &program_error[0]); | 42 | NGLOG_DEBUG(Render_OpenGL, "{}", shader_error); |
| 130 | } else { | 43 | } else { |
| 131 | LOG_CRITICAL(Render_OpenGL, "Error linking shader:\n%s", &program_error[0]); | 44 | NGLOG_ERROR(Render_OpenGL, "Error compiling {} shader:\n{}", debug_type, shader_error); |
| 132 | } | 45 | } |
| 133 | } | 46 | } |
| 134 | 47 | return shader_id; | |
| 135 | // If the program linking failed at least one of the shaders was probably bad | ||
| 136 | if (result == GL_FALSE) { | ||
| 137 | if (vertex_shader) { | ||
| 138 | LOG_CRITICAL(Render_OpenGL, "Vertex shader:\n%s", vertex_shader); | ||
| 139 | } | ||
| 140 | if (geometry_shader) { | ||
| 141 | LOG_CRITICAL(Render_OpenGL, "Geometry shader:\n%s", geometry_shader); | ||
| 142 | } | ||
| 143 | if (fragment_shader) { | ||
| 144 | LOG_CRITICAL(Render_OpenGL, "Fragment shader:\n%s", fragment_shader); | ||
| 145 | } | ||
| 146 | } | ||
| 147 | ASSERT_MSG(result == GL_TRUE, "Shader not linked"); | ||
| 148 | |||
| 149 | if (vertex_shader) { | ||
| 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 | } | ||
| 161 | |||
| 162 | return program_id; | ||
| 163 | } | 48 | } |
| 164 | 49 | ||
| 165 | } // namespace GLShader | 50 | } // namespace GLShader |
diff --git a/src/video_core/renderer_opengl/gl_shader_util.h b/src/video_core/renderer_opengl/gl_shader_util.h index fc7b5e080..5a0008703 100644 --- a/src/video_core/renderer_opengl/gl_shader_util.h +++ b/src/video_core/renderer_opengl/gl_shader_util.h | |||
| @@ -10,14 +10,54 @@ | |||
| 10 | namespace GLShader { | 10 | namespace GLShader { |
| 11 | 11 | ||
| 12 | /** | 12 | /** |
| 13 | * Utility function to create and compile an OpenGL GLSL shader | ||
| 14 | * @param source String of the GLSL shader program | ||
| 15 | * @param type Type of the shader (GL_VERTEX_SHADER, GL_GEOMETRY_SHADER or GL_FRAGMENT_SHADER) | ||
| 16 | */ | ||
| 17 | GLuint LoadShader(const char* source, GLenum type); | ||
| 18 | |||
| 19 | /** | ||
| 13 | * Utility function to create and compile an OpenGL GLSL shader program (vertex + fragment shader) | 20 | * Utility function to create and compile an OpenGL GLSL shader program (vertex + fragment shader) |
| 14 | * @param vertex_shader String of the GLSL vertex shader program | 21 | * @param separable_program whether to create a separable program |
| 15 | * @param geometry_shader String of the GLSL geometry shader program | 22 | * @param shaders ID of shaders to attach to the program |
| 16 | * @param fragment_shader String of the GLSL fragment shader program | 23 | * @returns Handle of the newly created OpenGL program object |
| 17 | * @returns Handle of the newly created OpenGL shader object | ||
| 18 | */ | 24 | */ |
| 19 | GLuint LoadProgram(const char* vertex_shader, const char* geometry_shader, | 25 | template <typename... T> |
| 20 | const char* fragment_shader, const std::vector<const char*>& feedback_vars = {}, | 26 | GLuint LoadProgram(bool separable_program, T... shaders) { |
| 21 | bool separable_program = false); | 27 | // Link the program |
| 28 | NGLOG_DEBUG(Render_OpenGL, "Linking program..."); | ||
| 29 | |||
| 30 | GLuint program_id = glCreateProgram(); | ||
| 31 | |||
| 32 | ((shaders == 0 ? (void)0 : glAttachShader(program_id, shaders)), ...); | ||
| 33 | |||
| 34 | if (separable_program) { | ||
| 35 | glProgramParameteri(program_id, GL_PROGRAM_SEPARABLE, GL_TRUE); | ||
| 36 | } | ||
| 37 | |||
| 38 | glLinkProgram(program_id); | ||
| 39 | |||
| 40 | // Check the program | ||
| 41 | GLint result = GL_FALSE; | ||
| 42 | GLint info_log_length; | ||
| 43 | glGetProgramiv(program_id, GL_LINK_STATUS, &result); | ||
| 44 | glGetProgramiv(program_id, GL_INFO_LOG_LENGTH, &info_log_length); | ||
| 45 | |||
| 46 | if (info_log_length > 1) { | ||
| 47 | std::string program_error(info_log_length, ' '); | ||
| 48 | glGetProgramInfoLog(program_id, info_log_length, nullptr, &program_error[0]); | ||
| 49 | if (result == GL_TRUE) { | ||
| 50 | NGLOG_DEBUG(Render_OpenGL, "{}", program_error); | ||
| 51 | } else { | ||
| 52 | NGLOG_ERROR(Render_OpenGL, "Error linking shader:\n{}", program_error); | ||
| 53 | } | ||
| 54 | } | ||
| 55 | |||
| 56 | ASSERT_MSG(result == GL_TRUE, "Shader not linked"); | ||
| 57 | |||
| 58 | ((shaders == 0 ? (void)0 : glDetachShader(program_id, shaders)), ...); | ||
| 59 | |||
| 60 | return program_id; | ||
| 61 | } | ||
| 22 | 62 | ||
| 23 | } // namespace GLShader | 63 | } // namespace GLShader |