diff options
Diffstat (limited to '')
| -rw-r--r-- | src/video_core/renderer_opengl/gl_resource_manager.cpp | 27 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_resource_manager.h | 14 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_shader_cache.cpp | 81 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_shader_util.cpp | 117 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_shader_util.h | 89 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/renderer_opengl.cpp | 12 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/util_shaders.cpp | 11 |
7 files changed, 106 insertions, 245 deletions
diff --git a/src/video_core/renderer_opengl/gl_resource_manager.cpp b/src/video_core/renderer_opengl/gl_resource_manager.cpp index 3428e5e21..8695c29e3 100644 --- a/src/video_core/renderer_opengl/gl_resource_manager.cpp +++ b/src/video_core/renderer_opengl/gl_resource_manager.cpp | |||
| @@ -83,18 +83,6 @@ void OGLSampler::Release() { | |||
| 83 | handle = 0; | 83 | handle = 0; |
| 84 | } | 84 | } |
| 85 | 85 | ||
| 86 | void OGLShader::Create(std::string_view source, GLenum type) { | ||
| 87 | if (handle != 0) { | ||
| 88 | return; | ||
| 89 | } | ||
| 90 | if (source.empty()) { | ||
| 91 | return; | ||
| 92 | } | ||
| 93 | |||
| 94 | MICROPROFILE_SCOPE(OpenGL_ResourceCreation); | ||
| 95 | handle = GLShader::LoadShader(source, type); | ||
| 96 | } | ||
| 97 | |||
| 98 | void OGLShader::Release() { | 86 | void OGLShader::Release() { |
| 99 | if (handle == 0) | 87 | if (handle == 0) |
| 100 | return; | 88 | return; |
| @@ -104,21 +92,6 @@ void OGLShader::Release() { | |||
| 104 | handle = 0; | 92 | handle = 0; |
| 105 | } | 93 | } |
| 106 | 94 | ||
| 107 | void OGLProgram::CreateFromSource(const char* vert_shader, const char* geo_shader, | ||
| 108 | const char* frag_shader, bool separable_program, | ||
| 109 | bool hint_retrievable) { | ||
| 110 | OGLShader vert, geo, frag; | ||
| 111 | if (vert_shader) | ||
| 112 | vert.Create(vert_shader, GL_VERTEX_SHADER); | ||
| 113 | if (geo_shader) | ||
| 114 | geo.Create(geo_shader, GL_GEOMETRY_SHADER); | ||
| 115 | if (frag_shader) | ||
| 116 | frag.Create(frag_shader, GL_FRAGMENT_SHADER); | ||
| 117 | |||
| 118 | MICROPROFILE_SCOPE(OpenGL_ResourceCreation); | ||
| 119 | Create(separable_program, hint_retrievable, vert.handle, geo.handle, frag.handle); | ||
| 120 | } | ||
| 121 | |||
| 122 | void OGLProgram::Release() { | 95 | void OGLProgram::Release() { |
| 123 | if (handle == 0) | 96 | if (handle == 0) |
| 124 | return; | 97 | return; |
diff --git a/src/video_core/renderer_opengl/gl_resource_manager.h b/src/video_core/renderer_opengl/gl_resource_manager.h index 552d79db4..b2d5bfd3b 100644 --- a/src/video_core/renderer_opengl/gl_resource_manager.h +++ b/src/video_core/renderer_opengl/gl_resource_manager.h | |||
| @@ -8,7 +8,6 @@ | |||
| 8 | #include <utility> | 8 | #include <utility> |
| 9 | #include <glad/glad.h> | 9 | #include <glad/glad.h> |
| 10 | #include "common/common_types.h" | 10 | #include "common/common_types.h" |
| 11 | #include "video_core/renderer_opengl/gl_shader_util.h" | ||
| 12 | 11 | ||
| 13 | namespace OpenGL { | 12 | namespace OpenGL { |
| 14 | 13 | ||
| @@ -128,8 +127,6 @@ public: | |||
| 128 | return *this; | 127 | return *this; |
| 129 | } | 128 | } |
| 130 | 129 | ||
| 131 | void Create(std::string_view source, GLenum type); | ||
| 132 | |||
| 133 | void Release(); | 130 | void Release(); |
| 134 | 131 | ||
| 135 | GLuint handle = 0; | 132 | GLuint handle = 0; |
| @@ -151,17 +148,6 @@ public: | |||
| 151 | return *this; | 148 | return *this; |
| 152 | } | 149 | } |
| 153 | 150 | ||
| 154 | template <typename... T> | ||
| 155 | void Create(bool separable_program, bool hint_retrievable, T... shaders) { | ||
| 156 | if (handle != 0) | ||
| 157 | return; | ||
| 158 | handle = GLShader::LoadProgram(separable_program, hint_retrievable, shaders...); | ||
| 159 | } | ||
| 160 | |||
| 161 | /// Creates a new internal OpenGL resource and stores the handle | ||
| 162 | void CreateFromSource(const char* vert_shader, const char* geo_shader, const char* frag_shader, | ||
| 163 | bool separable_program = false, bool hint_retrievable = false); | ||
| 164 | |||
| 165 | /// Deletes the internal OpenGL resource | 151 | /// Deletes the internal OpenGL resource |
| 166 | void Release(); | 152 | void Release(); |
| 167 | 153 | ||
diff --git a/src/video_core/renderer_opengl/gl_shader_cache.cpp b/src/video_core/renderer_opengl/gl_shader_cache.cpp index 9d6cef6e8..da0b36368 100644 --- a/src/video_core/renderer_opengl/gl_shader_cache.cpp +++ b/src/video_core/renderer_opengl/gl_shader_cache.cpp | |||
| @@ -31,6 +31,7 @@ | |||
| 31 | #include "video_core/renderer_opengl/gl_rasterizer.h" | 31 | #include "video_core/renderer_opengl/gl_rasterizer.h" |
| 32 | #include "video_core/renderer_opengl/gl_resource_manager.h" | 32 | #include "video_core/renderer_opengl/gl_resource_manager.h" |
| 33 | #include "video_core/renderer_opengl/gl_shader_cache.h" | 33 | #include "video_core/renderer_opengl/gl_shader_cache.h" |
| 34 | #include "video_core/renderer_opengl/gl_shader_util.h" | ||
| 34 | #include "video_core/renderer_opengl/gl_state_tracker.h" | 35 | #include "video_core/renderer_opengl/gl_state_tracker.h" |
| 35 | #include "video_core/shader_cache.h" | 36 | #include "video_core/shader_cache.h" |
| 36 | #include "video_core/shader_environment.h" | 37 | #include "video_core/shader_environment.h" |
| @@ -53,77 +54,6 @@ auto MakeSpan(Container& container) { | |||
| 53 | return std::span(container.data(), container.size()); | 54 | return std::span(container.data(), container.size()); |
| 54 | } | 55 | } |
| 55 | 56 | ||
| 56 | void AddShader(GLenum stage, GLuint program, std::span<const u32> code) { | ||
| 57 | OGLShader shader; | ||
| 58 | shader.handle = glCreateShader(stage); | ||
| 59 | |||
| 60 | glShaderBinary(1, &shader.handle, GL_SHADER_BINARY_FORMAT_SPIR_V_ARB, code.data(), | ||
| 61 | static_cast<GLsizei>(code.size_bytes())); | ||
| 62 | glSpecializeShader(shader.handle, "main", 0, nullptr, nullptr); | ||
| 63 | glAttachShader(program, shader.handle); | ||
| 64 | if (!Settings::values.renderer_debug) { | ||
| 65 | return; | ||
| 66 | } | ||
| 67 | GLint shader_status{}; | ||
| 68 | glGetShaderiv(shader.handle, GL_COMPILE_STATUS, &shader_status); | ||
| 69 | if (shader_status == GL_FALSE) { | ||
| 70 | LOG_ERROR(Render_OpenGL, "Failed to build shader"); | ||
| 71 | } | ||
| 72 | GLint log_length{}; | ||
| 73 | glGetShaderiv(shader.handle, GL_INFO_LOG_LENGTH, &log_length); | ||
| 74 | if (log_length == 0) { | ||
| 75 | return; | ||
| 76 | } | ||
| 77 | std::string log(log_length, 0); | ||
| 78 | glGetShaderInfoLog(shader.handle, log_length, nullptr, log.data()); | ||
| 79 | if (shader_status == GL_FALSE) { | ||
| 80 | LOG_ERROR(Render_OpenGL, "{}", log); | ||
| 81 | } else { | ||
| 82 | LOG_WARNING(Render_OpenGL, "{}", log); | ||
| 83 | } | ||
| 84 | } | ||
| 85 | |||
| 86 | void LinkProgram(GLuint program) { | ||
| 87 | glLinkProgram(program); | ||
| 88 | if (!Settings::values.renderer_debug) { | ||
| 89 | return; | ||
| 90 | } | ||
| 91 | GLint link_status{}; | ||
| 92 | glGetProgramiv(program, GL_LINK_STATUS, &link_status); | ||
| 93 | |||
| 94 | GLint log_length{}; | ||
| 95 | glGetProgramiv(program, GL_INFO_LOG_LENGTH, &log_length); | ||
| 96 | if (log_length == 0) { | ||
| 97 | return; | ||
| 98 | } | ||
| 99 | std::string log(log_length, 0); | ||
| 100 | glGetProgramInfoLog(program, log_length, nullptr, log.data()); | ||
| 101 | if (link_status == GL_FALSE) { | ||
| 102 | LOG_ERROR(Render_OpenGL, "{}", log); | ||
| 103 | } else { | ||
| 104 | LOG_WARNING(Render_OpenGL, "{}", log); | ||
| 105 | } | ||
| 106 | } | ||
| 107 | |||
| 108 | OGLAssemblyProgram CompileProgram(std::string_view code, GLenum target) { | ||
| 109 | OGLAssemblyProgram program; | ||
| 110 | glGenProgramsARB(1, &program.handle); | ||
| 111 | glNamedProgramStringEXT(program.handle, target, GL_PROGRAM_FORMAT_ASCII_ARB, | ||
| 112 | static_cast<GLsizei>(code.size()), code.data()); | ||
| 113 | if (Settings::values.renderer_debug) { | ||
| 114 | const auto err = reinterpret_cast<const char*>(glGetString(GL_PROGRAM_ERROR_STRING_NV)); | ||
| 115 | if (err && *err) { | ||
| 116 | if (std::strstr(err, "error")) { | ||
| 117 | LOG_CRITICAL(Render_OpenGL, "\n{}", err); | ||
| 118 | LOG_INFO(Render_OpenGL, "\n{}", code); | ||
| 119 | } else { | ||
| 120 | LOG_WARNING(Render_OpenGL, "\n{}", err); | ||
| 121 | } | ||
| 122 | } | ||
| 123 | } | ||
| 124 | return program; | ||
| 125 | } | ||
| 126 | |||
| 127 | GLenum Stage(size_t stage_index) { | 57 | GLenum Stage(size_t stage_index) { |
| 128 | switch (stage_index) { | 58 | switch (stage_index) { |
| 129 | case 0: | 59 | case 0: |
| @@ -492,9 +422,8 @@ std::unique_ptr<GraphicsPipeline> ShaderCache::CreateGraphicsPipeline( | |||
| 492 | if (!device.UseAssemblyShaders()) { | 422 | if (!device.UseAssemblyShaders()) { |
| 493 | source_program.handle = glCreateProgram(); | 423 | source_program.handle = glCreateProgram(); |
| 494 | } | 424 | } |
| 495 | 425 | const size_t first_index = uses_vertex_a && uses_vertex_b ? 1 : 0; | |
| 496 | for (size_t index = uses_vertex_a && uses_vertex_b ? 1 : 0; index < Maxwell::MaxShaderProgram; | 426 | for (size_t index = first_index; index < Maxwell::MaxShaderProgram; ++index) { |
| 497 | ++index) { | ||
| 498 | if (key.unique_hashes[index] == 0) { | 427 | if (key.unique_hashes[index] == 0) { |
| 499 | continue; | 428 | continue; |
| 500 | } | 429 | } |
| @@ -510,7 +439,7 @@ std::unique_ptr<GraphicsPipeline> ShaderCache::CreateGraphicsPipeline( | |||
| 510 | assembly_programs[stage_index] = CompileProgram(code, AssemblyStage(stage_index)); | 439 | assembly_programs[stage_index] = CompileProgram(code, AssemblyStage(stage_index)); |
| 511 | } else { | 440 | } else { |
| 512 | const std::vector<u32> code{EmitSPIRV(profile, runtime_info, program, binding)}; | 441 | const std::vector<u32> code{EmitSPIRV(profile, runtime_info, program, binding)}; |
| 513 | AddShader(Stage(stage_index), source_program.handle, code); | 442 | AttachShader(Stage(stage_index), source_program.handle, code); |
| 514 | } | 443 | } |
| 515 | } | 444 | } |
| 516 | if (!device.UseAssemblyShaders()) { | 445 | if (!device.UseAssemblyShaders()) { |
| @@ -565,7 +494,7 @@ std::unique_ptr<ComputePipeline> ShaderCache::CreateComputePipeline(ShaderPools& | |||
| 565 | } else { | 494 | } else { |
| 566 | const std::vector<u32> code{EmitSPIRV(profile, program)}; | 495 | const std::vector<u32> code{EmitSPIRV(profile, program)}; |
| 567 | source_program.handle = glCreateProgram(); | 496 | source_program.handle = glCreateProgram(); |
| 568 | AddShader(GL_COMPUTE_SHADER, source_program.handle, code); | 497 | AttachShader(GL_COMPUTE_SHADER, source_program.handle, code); |
| 569 | LinkProgram(source_program.handle); | 498 | LinkProgram(source_program.handle); |
| 570 | } | 499 | } |
| 571 | return std::make_unique<ComputePipeline>(device, texture_cache, buffer_cache, gpu_memory, | 500 | return std::make_unique<ComputePipeline>(device, texture_cache, buffer_cache, gpu_memory, |
diff --git a/src/video_core/renderer_opengl/gl_shader_util.cpp b/src/video_core/renderer_opengl/gl_shader_util.cpp index 4bf0d6090..99cb81819 100644 --- a/src/video_core/renderer_opengl/gl_shader_util.cpp +++ b/src/video_core/renderer_opengl/gl_shader_util.cpp | |||
| @@ -5,57 +5,100 @@ | |||
| 5 | #include <string_view> | 5 | #include <string_view> |
| 6 | #include <vector> | 6 | #include <vector> |
| 7 | #include <glad/glad.h> | 7 | #include <glad/glad.h> |
| 8 | |||
| 8 | #include "common/assert.h" | 9 | #include "common/assert.h" |
| 9 | #include "common/logging/log.h" | 10 | #include "common/logging/log.h" |
| 11 | #include "common/settings.h" | ||
| 10 | #include "video_core/renderer_opengl/gl_shader_util.h" | 12 | #include "video_core/renderer_opengl/gl_shader_util.h" |
| 11 | 13 | ||
| 12 | namespace OpenGL::GLShader { | 14 | namespace OpenGL { |
| 13 | |||
| 14 | namespace { | ||
| 15 | 15 | ||
| 16 | std::string_view StageDebugName(GLenum type) { | 16 | static void LogShader(GLuint shader) { |
| 17 | switch (type) { | 17 | GLint shader_status{}; |
| 18 | case GL_VERTEX_SHADER: | 18 | glGetShaderiv(shader, GL_COMPILE_STATUS, &shader_status); |
| 19 | return "vertex"; | 19 | if (shader_status == GL_FALSE) { |
| 20 | case GL_GEOMETRY_SHADER: | 20 | LOG_ERROR(Render_OpenGL, "Failed to build shader"); |
| 21 | return "geometry"; | 21 | } |
| 22 | case GL_FRAGMENT_SHADER: | 22 | GLint log_length{}; |
| 23 | return "fragment"; | 23 | glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &log_length); |
| 24 | case GL_COMPUTE_SHADER: | 24 | if (log_length == 0) { |
| 25 | return "compute"; | 25 | return; |
| 26 | } | ||
| 27 | std::string log(log_length, 0); | ||
| 28 | glGetShaderInfoLog(shader, log_length, nullptr, log.data()); | ||
| 29 | if (shader_status == GL_FALSE) { | ||
| 30 | LOG_ERROR(Render_OpenGL, "{}", log); | ||
| 31 | } else { | ||
| 32 | LOG_WARNING(Render_OpenGL, "{}", log); | ||
| 26 | } | 33 | } |
| 27 | UNIMPLEMENTED(); | ||
| 28 | return "unknown"; | ||
| 29 | } | 34 | } |
| 30 | 35 | ||
| 31 | } // Anonymous namespace | 36 | void AttachShader(GLenum stage, GLuint program, std::string_view code) { |
| 37 | OGLShader shader; | ||
| 38 | shader.handle = glCreateShader(stage); | ||
| 32 | 39 | ||
| 33 | GLuint LoadShader(std::string_view source, GLenum type) { | 40 | const GLint length = static_cast<GLint>(code.size()); |
| 34 | const std::string_view debug_type = StageDebugName(type); | 41 | const GLchar* const code_ptr = code.data(); |
| 35 | const GLuint shader_id = glCreateShader(type); | 42 | glShaderSource(shader.handle, 1, &code_ptr, &length); |
| 43 | glCompileShader(shader.handle); | ||
| 44 | glAttachShader(program, shader.handle); | ||
| 45 | if (Settings::values.renderer_debug) { | ||
| 46 | LogShader(shader.handle); | ||
| 47 | } | ||
| 48 | } | ||
| 36 | 49 | ||
| 37 | const GLchar* source_string = source.data(); | 50 | void AttachShader(GLenum stage, GLuint program, std::span<const u32> code) { |
| 38 | const GLint source_length = static_cast<GLint>(source.size()); | 51 | OGLShader shader; |
| 52 | shader.handle = glCreateShader(stage); | ||
| 39 | 53 | ||
| 40 | glShaderSource(shader_id, 1, &source_string, &source_length); | 54 | glShaderBinary(1, &shader.handle, GL_SHADER_BINARY_FORMAT_SPIR_V_ARB, code.data(), |
| 41 | LOG_DEBUG(Render_OpenGL, "Compiling {} shader...", debug_type); | 55 | static_cast<GLsizei>(code.size_bytes())); |
| 42 | glCompileShader(shader_id); | 56 | glSpecializeShader(shader.handle, "main", 0, nullptr, nullptr); |
| 57 | glAttachShader(program, shader.handle); | ||
| 58 | if (Settings::values.renderer_debug) { | ||
| 59 | LogShader(shader.handle); | ||
| 60 | } | ||
| 61 | } | ||
| 62 | |||
| 63 | void LinkProgram(GLuint program) { | ||
| 64 | glLinkProgram(program); | ||
| 65 | if (!Settings::values.renderer_debug) { | ||
| 66 | return; | ||
| 67 | } | ||
| 68 | GLint link_status{}; | ||
| 69 | glGetProgramiv(program, GL_LINK_STATUS, &link_status); | ||
| 43 | 70 | ||
| 44 | GLint result = GL_FALSE; | 71 | GLint log_length{}; |
| 45 | GLint info_log_length; | 72 | glGetProgramiv(program, GL_INFO_LOG_LENGTH, &log_length); |
| 46 | glGetShaderiv(shader_id, GL_COMPILE_STATUS, &result); | 73 | if (log_length == 0) { |
| 47 | glGetShaderiv(shader_id, GL_INFO_LOG_LENGTH, &info_log_length); | 74 | return; |
| 75 | } | ||
| 76 | std::string log(log_length, 0); | ||
| 77 | glGetProgramInfoLog(program, log_length, nullptr, log.data()); | ||
| 78 | if (link_status == GL_FALSE) { | ||
| 79 | LOG_ERROR(Render_OpenGL, "{}", log); | ||
| 80 | } else { | ||
| 81 | LOG_WARNING(Render_OpenGL, "{}", log); | ||
| 82 | } | ||
| 83 | } | ||
| 48 | 84 | ||
| 49 | if (info_log_length > 1) { | 85 | OGLAssemblyProgram CompileProgram(std::string_view code, GLenum target) { |
| 50 | std::string shader_error(info_log_length, ' '); | 86 | OGLAssemblyProgram program; |
| 51 | glGetShaderInfoLog(shader_id, info_log_length, nullptr, &shader_error[0]); | 87 | glGenProgramsARB(1, &program.handle); |
| 52 | if (result == GL_TRUE) { | 88 | glNamedProgramStringEXT(program.handle, target, GL_PROGRAM_FORMAT_ASCII_ARB, |
| 53 | LOG_DEBUG(Render_OpenGL, "{}", shader_error); | 89 | static_cast<GLsizei>(code.size()), code.data()); |
| 54 | } else { | 90 | if (Settings::values.renderer_debug) { |
| 55 | LOG_ERROR(Render_OpenGL, "Error compiling {} shader:\n{}", debug_type, shader_error); | 91 | const auto err = reinterpret_cast<const char*>(glGetString(GL_PROGRAM_ERROR_STRING_NV)); |
| 92 | if (err && *err) { | ||
| 93 | if (std::strstr(err, "error")) { | ||
| 94 | LOG_CRITICAL(Render_OpenGL, "\n{}", err); | ||
| 95 | LOG_INFO(Render_OpenGL, "\n{}", code); | ||
| 96 | } else { | ||
| 97 | LOG_WARNING(Render_OpenGL, "\n{}", err); | ||
| 98 | } | ||
| 56 | } | 99 | } |
| 57 | } | 100 | } |
| 58 | return shader_id; | 101 | return program; |
| 59 | } | 102 | } |
| 60 | 103 | ||
| 61 | } // namespace OpenGL::GLShader | 104 | } // namespace OpenGL |
diff --git a/src/video_core/renderer_opengl/gl_shader_util.h b/src/video_core/renderer_opengl/gl_shader_util.h index 1b770532e..ff5aa024f 100644 --- a/src/video_core/renderer_opengl/gl_shader_util.h +++ b/src/video_core/renderer_opengl/gl_shader_util.h | |||
| @@ -4,92 +4,25 @@ | |||
| 4 | 4 | ||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include <span> | ||
| 7 | #include <string> | 8 | #include <string> |
| 9 | #include <string_view> | ||
| 8 | #include <vector> | 10 | #include <vector> |
| 11 | |||
| 9 | #include <glad/glad.h> | 12 | #include <glad/glad.h> |
| 13 | |||
| 10 | #include "common/assert.h" | 14 | #include "common/assert.h" |
| 11 | #include "common/logging/log.h" | 15 | #include "common/logging/log.h" |
| 16 | #include "video_core/renderer_opengl/gl_resource_manager.h" | ||
| 12 | 17 | ||
| 13 | namespace OpenGL::GLShader { | 18 | namespace OpenGL { |
| 14 | |||
| 15 | /** | ||
| 16 | * Utility function to log the source code of a list of shaders. | ||
| 17 | * @param shaders The OpenGL shaders whose source we will print. | ||
| 18 | */ | ||
| 19 | template <typename... T> | ||
| 20 | void LogShaderSource(T... shaders) { | ||
| 21 | auto shader_list = {shaders...}; | ||
| 22 | |||
| 23 | for (const auto& shader : shader_list) { | ||
| 24 | if (shader == 0) | ||
| 25 | continue; | ||
| 26 | |||
| 27 | GLint source_length; | ||
| 28 | glGetShaderiv(shader, GL_SHADER_SOURCE_LENGTH, &source_length); | ||
| 29 | |||
| 30 | std::string source(source_length, ' '); | ||
| 31 | glGetShaderSource(shader, source_length, nullptr, &source[0]); | ||
| 32 | LOG_INFO(Render_OpenGL, "Shader source {}", source); | ||
| 33 | } | ||
| 34 | } | ||
| 35 | |||
| 36 | /** | ||
| 37 | * Utility function to create and compile an OpenGL GLSL shader | ||
| 38 | * @param source String of the GLSL shader program | ||
| 39 | * @param type Type of the shader (GL_VERTEX_SHADER, GL_GEOMETRY_SHADER or GL_FRAGMENT_SHADER) | ||
| 40 | */ | ||
| 41 | GLuint LoadShader(std::string_view source, GLenum type); | ||
| 42 | |||
| 43 | /** | ||
| 44 | * Utility function to create and compile an OpenGL GLSL shader program (vertex + fragment shader) | ||
| 45 | * @param separable_program whether to create a separable program | ||
| 46 | * @param shaders ID of shaders to attach to the program | ||
| 47 | * @returns Handle of the newly created OpenGL program object | ||
| 48 | */ | ||
| 49 | template <typename... T> | ||
| 50 | GLuint LoadProgram(bool separable_program, bool hint_retrievable, T... shaders) { | ||
| 51 | // Link the program | ||
| 52 | LOG_DEBUG(Render_OpenGL, "Linking program..."); | ||
| 53 | |||
| 54 | GLuint program_id = glCreateProgram(); | ||
| 55 | |||
| 56 | ((shaders == 0 ? (void)0 : glAttachShader(program_id, shaders)), ...); | ||
| 57 | |||
| 58 | if (separable_program) { | ||
| 59 | glProgramParameteri(program_id, GL_PROGRAM_SEPARABLE, GL_TRUE); | ||
| 60 | } | ||
| 61 | if (hint_retrievable) { | ||
| 62 | glProgramParameteri(program_id, GL_PROGRAM_BINARY_RETRIEVABLE_HINT, GL_TRUE); | ||
| 63 | } | ||
| 64 | |||
| 65 | glLinkProgram(program_id); | ||
| 66 | |||
| 67 | // Check the program | ||
| 68 | GLint result = GL_FALSE; | ||
| 69 | GLint info_log_length; | ||
| 70 | glGetProgramiv(program_id, GL_LINK_STATUS, &result); | ||
| 71 | glGetProgramiv(program_id, GL_INFO_LOG_LENGTH, &info_log_length); | ||
| 72 | |||
| 73 | if (info_log_length > 1) { | ||
| 74 | std::string program_error(info_log_length, ' '); | ||
| 75 | glGetProgramInfoLog(program_id, info_log_length, nullptr, &program_error[0]); | ||
| 76 | if (result == GL_TRUE) { | ||
| 77 | LOG_DEBUG(Render_OpenGL, "{}", program_error); | ||
| 78 | } else { | ||
| 79 | LOG_ERROR(Render_OpenGL, "Error linking shader:\n{}", program_error); | ||
| 80 | } | ||
| 81 | } | ||
| 82 | 19 | ||
| 83 | if (result == GL_FALSE) { | 20 | void AttachShader(GLenum stage, GLuint program, std::string_view code); |
| 84 | // There was a problem linking the shader, print the source for debugging purposes. | ||
| 85 | LogShaderSource(shaders...); | ||
| 86 | } | ||
| 87 | 21 | ||
| 88 | ASSERT_MSG(result == GL_TRUE, "Shader not linked"); | 22 | void AttachShader(GLenum stage, GLuint program, std::span<const u32> code); |
| 89 | 23 | ||
| 90 | ((shaders == 0 ? (void)0 : glDetachShader(program_id, shaders)), ...); | 24 | void LinkProgram(GLuint program); |
| 91 | 25 | ||
| 92 | return program_id; | 26 | OGLAssemblyProgram CompileProgram(std::string_view code, GLenum target); |
| 93 | } | ||
| 94 | 27 | ||
| 95 | } // namespace OpenGL::GLShader | 28 | } // namespace OpenGL |
diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp index a4805f3da..b8777643b 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.cpp +++ b/src/video_core/renderer_opengl/renderer_opengl.cpp | |||
| @@ -24,6 +24,7 @@ | |||
| 24 | #include "video_core/host_shaders/opengl_present_frag.h" | 24 | #include "video_core/host_shaders/opengl_present_frag.h" |
| 25 | #include "video_core/host_shaders/opengl_present_vert.h" | 25 | #include "video_core/host_shaders/opengl_present_vert.h" |
| 26 | #include "video_core/renderer_opengl/gl_rasterizer.h" | 26 | #include "video_core/renderer_opengl/gl_rasterizer.h" |
| 27 | #include "video_core/renderer_opengl/gl_shader_util.h" | ||
| 27 | #include "video_core/renderer_opengl/gl_shader_manager.h" | 28 | #include "video_core/renderer_opengl/gl_shader_manager.h" |
| 28 | #include "video_core/renderer_opengl/renderer_opengl.h" | 29 | #include "video_core/renderer_opengl/renderer_opengl.h" |
| 29 | #include "video_core/textures/decoders.h" | 30 | #include "video_core/textures/decoders.h" |
| @@ -230,13 +231,10 @@ void RendererOpenGL::LoadColorToActiveGLTexture(u8 color_r, u8 color_g, u8 color | |||
| 230 | 231 | ||
| 231 | void RendererOpenGL::InitOpenGLObjects() { | 232 | void RendererOpenGL::InitOpenGLObjects() { |
| 232 | // Create shader programs | 233 | // Create shader programs |
| 233 | OGLShader vertex_shader; | 234 | present_program.handle = glCreateProgram(); |
| 234 | vertex_shader.Create(HostShaders::OPENGL_PRESENT_VERT, GL_VERTEX_SHADER); | 235 | AttachShader(GL_VERTEX_SHADER, present_program.handle, HostShaders::OPENGL_PRESENT_VERT); |
| 235 | 236 | AttachShader(GL_FRAGMENT_SHADER, present_program.handle, HostShaders::OPENGL_PRESENT_FRAG); | |
| 236 | OGLShader fragment_shader; | 237 | LinkProgram(present_program.handle); |
| 237 | fragment_shader.Create(HostShaders::OPENGL_PRESENT_FRAG, GL_FRAGMENT_SHADER); | ||
| 238 | |||
| 239 | present_program.Create(false, false, vertex_shader.handle, fragment_shader.handle); | ||
| 240 | 238 | ||
| 241 | // Generate presentation sampler | 239 | // Generate presentation sampler |
| 242 | present_sampler.Create(); | 240 | present_sampler.Create(); |
diff --git a/src/video_core/renderer_opengl/util_shaders.cpp b/src/video_core/renderer_opengl/util_shaders.cpp index 51e72b705..8aa0683c8 100644 --- a/src/video_core/renderer_opengl/util_shaders.cpp +++ b/src/video_core/renderer_opengl/util_shaders.cpp | |||
| @@ -17,6 +17,7 @@ | |||
| 17 | #include "video_core/host_shaders/opengl_copy_bgra_comp.h" | 17 | #include "video_core/host_shaders/opengl_copy_bgra_comp.h" |
| 18 | #include "video_core/host_shaders/pitch_unswizzle_comp.h" | 18 | #include "video_core/host_shaders/pitch_unswizzle_comp.h" |
| 19 | #include "video_core/renderer_opengl/gl_shader_manager.h" | 19 | #include "video_core/renderer_opengl/gl_shader_manager.h" |
| 20 | #include "video_core/renderer_opengl/gl_shader_util.h" | ||
| 20 | #include "video_core/renderer_opengl/gl_texture_cache.h" | 21 | #include "video_core/renderer_opengl/gl_texture_cache.h" |
| 21 | #include "video_core/renderer_opengl/util_shaders.h" | 22 | #include "video_core/renderer_opengl/util_shaders.h" |
| 22 | #include "video_core/texture_cache/accelerated_swizzle.h" | 23 | #include "video_core/texture_cache/accelerated_swizzle.h" |
| @@ -40,13 +41,12 @@ using VideoCommon::Accelerated::MakeBlockLinearSwizzle3DParams; | |||
| 40 | using VideoCore::Surface::BytesPerBlock; | 41 | using VideoCore::Surface::BytesPerBlock; |
| 41 | 42 | ||
| 42 | namespace { | 43 | namespace { |
| 43 | |||
| 44 | OGLProgram MakeProgram(std::string_view source) { | 44 | OGLProgram MakeProgram(std::string_view source) { |
| 45 | OGLShader shader; | ||
| 46 | shader.Create(source, GL_COMPUTE_SHADER); | ||
| 47 | |||
| 48 | OGLProgram program; | 45 | OGLProgram program; |
| 49 | program.Create(true, false, shader.handle); | 46 | OGLShader shader; |
| 47 | program.handle = glCreateProgram(); | ||
| 48 | AttachShader(GL_COMPUTE_SHADER, program.handle, source); | ||
| 49 | LinkProgram(program.handle); | ||
| 50 | return program; | 50 | return program; |
| 51 | } | 51 | } |
| 52 | 52 | ||
| @@ -54,7 +54,6 @@ size_t NumPixelsInCopy(const VideoCommon::ImageCopy& copy) { | |||
| 54 | return static_cast<size_t>(copy.extent.width * copy.extent.height * | 54 | return static_cast<size_t>(copy.extent.width * copy.extent.height * |
| 55 | copy.src_subresource.num_layers); | 55 | copy.src_subresource.num_layers); |
| 56 | } | 56 | } |
| 57 | |||
| 58 | } // Anonymous namespace | 57 | } // Anonymous namespace |
| 59 | 58 | ||
| 60 | UtilShaders::UtilShaders(ProgramManager& program_manager_) | 59 | UtilShaders::UtilShaders(ProgramManager& program_manager_) |