diff options
| author | 2019-08-31 03:03:35 -0300 | |
|---|---|---|
| committer | 2019-09-04 01:54:00 -0300 | |
| commit | 9cf52d027d5c1bc1bde71cd6c18b3646b102e7a1 (patch) | |
| tree | c8bd026b5ab2596e9f758144f7bee3d0786fa5b2 /src | |
| parent | gl_shader_decompiler: Fixup AMD's slow path type (diff) | |
| download | yuzu-9cf52d027d5c1bc1bde71cd6c18b3646b102e7a1.tar.gz yuzu-9cf52d027d5c1bc1bde71cd6c18b3646b102e7a1.tar.xz yuzu-9cf52d027d5c1bc1bde71cd6c18b3646b102e7a1.zip | |
gl_device: Disable precise in fragment shaders on bugged drivers
Diffstat (limited to 'src')
| -rw-r--r-- | src/video_core/renderer_opengl/gl_device.cpp | 43 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_device.h | 6 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_shader_decompiler.cpp | 9 |
3 files changed, 43 insertions, 15 deletions
diff --git a/src/video_core/renderer_opengl/gl_device.cpp b/src/video_core/renderer_opengl/gl_device.cpp index 03d434b28..4f59a87b4 100644 --- a/src/video_core/renderer_opengl/gl_device.cpp +++ b/src/video_core/renderer_opengl/gl_device.cpp | |||
| @@ -14,12 +14,22 @@ | |||
| 14 | namespace OpenGL { | 14 | namespace OpenGL { |
| 15 | 15 | ||
| 16 | namespace { | 16 | namespace { |
| 17 | |||
| 17 | template <typename T> | 18 | template <typename T> |
| 18 | T GetInteger(GLenum pname) { | 19 | T GetInteger(GLenum pname) { |
| 19 | GLint temporary; | 20 | GLint temporary; |
| 20 | glGetIntegerv(pname, &temporary); | 21 | glGetIntegerv(pname, &temporary); |
| 21 | return static_cast<T>(temporary); | 22 | return static_cast<T>(temporary); |
| 22 | } | 23 | } |
| 24 | |||
| 25 | bool TestProgram(const GLchar* glsl) { | ||
| 26 | const GLuint shader{glCreateShaderProgramv(GL_VERTEX_SHADER, 1, &glsl)}; | ||
| 27 | GLint link_status; | ||
| 28 | glGetProgramiv(shader, GL_LINK_STATUS, &link_status); | ||
| 29 | glDeleteProgram(shader); | ||
| 30 | return link_status == GL_TRUE; | ||
| 31 | } | ||
| 32 | |||
| 23 | } // Anonymous namespace | 33 | } // Anonymous namespace |
| 24 | 34 | ||
| 25 | Device::Device() { | 35 | Device::Device() { |
| @@ -32,6 +42,11 @@ Device::Device() { | |||
| 32 | has_vertex_viewport_layer = GLAD_GL_ARB_shader_viewport_layer_array; | 42 | has_vertex_viewport_layer = GLAD_GL_ARB_shader_viewport_layer_array; |
| 33 | has_variable_aoffi = TestVariableAoffi(); | 43 | has_variable_aoffi = TestVariableAoffi(); |
| 34 | has_component_indexing_bug = TestComponentIndexingBug(); | 44 | has_component_indexing_bug = TestComponentIndexingBug(); |
| 45 | has_precise_bug = TestPreciseBug(); | ||
| 46 | |||
| 47 | LOG_INFO(Render_OpenGL, "Renderer_VariableAOFFI: {}", has_variable_aoffi); | ||
| 48 | LOG_INFO(Render_OpenGL, "Renderer_ComponentIndexingBug: {}", has_component_indexing_bug); | ||
| 49 | LOG_INFO(Render_OpenGL, "Renderer_PreciseBug: {}", has_precise_bug); | ||
| 35 | } | 50 | } |
| 36 | 51 | ||
| 37 | Device::Device(std::nullptr_t) { | 52 | Device::Device(std::nullptr_t) { |
| @@ -42,30 +57,21 @@ Device::Device(std::nullptr_t) { | |||
| 42 | has_vertex_viewport_layer = true; | 57 | has_vertex_viewport_layer = true; |
| 43 | has_variable_aoffi = true; | 58 | has_variable_aoffi = true; |
| 44 | has_component_indexing_bug = false; | 59 | has_component_indexing_bug = false; |
| 60 | has_precise_bug = false; | ||
| 45 | } | 61 | } |
| 46 | 62 | ||
| 47 | bool Device::TestVariableAoffi() { | 63 | bool Device::TestVariableAoffi() { |
| 48 | const GLchar* AOFFI_TEST = R"(#version 430 core | 64 | return TestProgram(R"(#version 430 core |
| 49 | // This is a unit test, please ignore me on apitrace bug reports. | 65 | // This is a unit test, please ignore me on apitrace bug reports. |
| 50 | uniform sampler2D tex; | 66 | uniform sampler2D tex; |
| 51 | uniform ivec2 variable_offset; | 67 | uniform ivec2 variable_offset; |
| 52 | out vec4 output_attribute; | 68 | out vec4 output_attribute; |
| 53 | void main() { | 69 | void main() { |
| 54 | output_attribute = textureOffset(tex, vec2(0), variable_offset); | 70 | output_attribute = textureOffset(tex, vec2(0), variable_offset); |
| 55 | } | 71 | })"); |
| 56 | )"; | ||
| 57 | const GLuint shader{glCreateShaderProgramv(GL_VERTEX_SHADER, 1, &AOFFI_TEST)}; | ||
| 58 | GLint link_status{}; | ||
| 59 | glGetProgramiv(shader, GL_LINK_STATUS, &link_status); | ||
| 60 | glDeleteProgram(shader); | ||
| 61 | |||
| 62 | const bool supported{link_status == GL_TRUE}; | ||
| 63 | LOG_INFO(Render_OpenGL, "Renderer_VariableAOFFI: {}", supported); | ||
| 64 | return supported; | ||
| 65 | } | 72 | } |
| 66 | 73 | ||
| 67 | bool Device::TestComponentIndexingBug() { | 74 | bool Device::TestComponentIndexingBug() { |
| 68 | constexpr char log_message[] = "Renderer_ComponentIndexingBug: {}"; | ||
| 69 | const GLchar* COMPONENT_TEST = R"(#version 430 core | 75 | const GLchar* COMPONENT_TEST = R"(#version 430 core |
| 70 | layout (std430, binding = 0) buffer OutputBuffer { | 76 | layout (std430, binding = 0) buffer OutputBuffer { |
| 71 | uint output_value; | 77 | uint output_value; |
| @@ -105,12 +111,21 @@ void main() { | |||
| 105 | GLuint result; | 111 | GLuint result; |
| 106 | glGetNamedBufferSubData(ssbo.handle, 0, sizeof(result), &result); | 112 | glGetNamedBufferSubData(ssbo.handle, 0, sizeof(result), &result); |
| 107 | if (result != values.at(index)) { | 113 | if (result != values.at(index)) { |
| 108 | LOG_INFO(Render_OpenGL, log_message, true); | ||
| 109 | return true; | 114 | return true; |
| 110 | } | 115 | } |
| 111 | } | 116 | } |
| 112 | LOG_INFO(Render_OpenGL, log_message, false); | ||
| 113 | return false; | 117 | return false; |
| 114 | } | 118 | } |
| 115 | 119 | ||
| 120 | bool Device::TestPreciseBug() { | ||
| 121 | return !TestProgram(R"(#version 430 core | ||
| 122 | in vec3 coords; | ||
| 123 | out float out_value; | ||
| 124 | uniform sampler2DShadow tex; | ||
| 125 | void main() { | ||
| 126 | precise float tmp_value = vec4(texture(tex, coords)).x; | ||
| 127 | out_value = tmp_value; | ||
| 128 | })"); | ||
| 129 | } | ||
| 130 | |||
| 116 | } // namespace OpenGL | 131 | } // namespace OpenGL |
diff --git a/src/video_core/renderer_opengl/gl_device.h b/src/video_core/renderer_opengl/gl_device.h index 3ef7c6dd8..ba6dcd3be 100644 --- a/src/video_core/renderer_opengl/gl_device.h +++ b/src/video_core/renderer_opengl/gl_device.h | |||
| @@ -46,9 +46,14 @@ public: | |||
| 46 | return has_component_indexing_bug; | 46 | return has_component_indexing_bug; |
| 47 | } | 47 | } |
| 48 | 48 | ||
| 49 | bool HasPreciseBug() const { | ||
| 50 | return has_precise_bug; | ||
| 51 | } | ||
| 52 | |||
| 49 | private: | 53 | private: |
| 50 | static bool TestVariableAoffi(); | 54 | static bool TestVariableAoffi(); |
| 51 | static bool TestComponentIndexingBug(); | 55 | static bool TestComponentIndexingBug(); |
| 56 | static bool TestPreciseBug(); | ||
| 52 | 57 | ||
| 53 | std::size_t uniform_buffer_alignment{}; | 58 | std::size_t uniform_buffer_alignment{}; |
| 54 | std::size_t shader_storage_alignment{}; | 59 | std::size_t shader_storage_alignment{}; |
| @@ -58,6 +63,7 @@ private: | |||
| 58 | bool has_vertex_viewport_layer{}; | 63 | bool has_vertex_viewport_layer{}; |
| 59 | bool has_variable_aoffi{}; | 64 | bool has_variable_aoffi{}; |
| 60 | bool has_component_indexing_bug{}; | 65 | bool has_component_indexing_bug{}; |
| 66 | bool has_precise_bug{}; | ||
| 61 | }; | 67 | }; |
| 62 | 68 | ||
| 63 | } // namespace OpenGL | 69 | } // namespace OpenGL |
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp index 9e050347a..50aa73d0e 100644 --- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp +++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp | |||
| @@ -957,8 +957,15 @@ private: | |||
| 957 | if (!IsPrecise(operation)) { | 957 | if (!IsPrecise(operation)) { |
| 958 | return {std::move(value), type}; | 958 | return {std::move(value), type}; |
| 959 | } | 959 | } |
| 960 | // Old Nvidia drivers have a bug with precise and texture sampling. These are more likely to | ||
| 961 | // be found in fragment shaders, so we disable precise there. There are vertex shaders that | ||
| 962 | // also fail to build but nobody seems to care about those. | ||
| 963 | // Note: Only bugged drivers will skip precise. | ||
| 964 | const bool disable_precise = device.HasPreciseBug() && stage == ProgramType::Fragment; | ||
| 965 | |||
| 960 | std::string temporary = code.GenerateTemporary(); | 966 | std::string temporary = code.GenerateTemporary(); |
| 961 | code.AddLine("precise {} {} = {};", GetTypeString(type), temporary, value); | 967 | code.AddLine("{}{} {} = {};", disable_precise ? "" : "precise ", GetTypeString(type), |
| 968 | temporary, value); | ||
| 962 | return {std::move(temporary), type}; | 969 | return {std::move(temporary), type}; |
| 963 | } | 970 | } |
| 964 | 971 | ||