summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar ReinUsesLisp2019-05-23 20:19:56 -0300
committerGravatar ReinUsesLisp2019-05-24 02:47:56 -0300
commit46177901b8d76f16223ac2716abcd6393faae25a (patch)
tree4d98018a7f9ad90b23b991003bd0316b88c7772e /src
parentshader/shader_ir: Make Comment() take a std::string by value (diff)
downloadyuzu-46177901b8d76f16223ac2716abcd6393faae25a.tar.gz
yuzu-46177901b8d76f16223ac2716abcd6393faae25a.tar.xz
yuzu-46177901b8d76f16223ac2716abcd6393faae25a.zip
gl_device: Add test to detect broken component indexing
Component indexing on AMD's proprietary driver is broken. This commit adds a test to detect when we are on a driver that can't successfully manage component indexing. It dispatches a dummy draw with just one vertex shader that writes to an indexed SSBO from the GPU with data sent through uniforms, it then reads that data from the CPU and compares the expected output.
Diffstat (limited to 'src')
-rw-r--r--src/video_core/renderer_opengl/gl_device.cpp54
-rw-r--r--src/video_core/renderer_opengl/gl_device.h6
2 files changed, 60 insertions, 0 deletions
diff --git a/src/video_core/renderer_opengl/gl_device.cpp b/src/video_core/renderer_opengl/gl_device.cpp
index 38497678a..5f86574cd 100644
--- a/src/video_core/renderer_opengl/gl_device.cpp
+++ b/src/video_core/renderer_opengl/gl_device.cpp
@@ -2,11 +2,14 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <array>
5#include <cstddef> 6#include <cstddef>
6#include <glad/glad.h> 7#include <glad/glad.h>
7 8
8#include "common/logging/log.h" 9#include "common/logging/log.h"
10#include "common/scope_exit.h"
9#include "video_core/renderer_opengl/gl_device.h" 11#include "video_core/renderer_opengl/gl_device.h"
12#include "video_core/renderer_opengl/gl_resource_manager.h"
10 13
11namespace OpenGL { 14namespace OpenGL {
12 15
@@ -24,6 +27,7 @@ Device::Device() {
24 max_vertex_attributes = GetInteger<u32>(GL_MAX_VERTEX_ATTRIBS); 27 max_vertex_attributes = GetInteger<u32>(GL_MAX_VERTEX_ATTRIBS);
25 max_varyings = GetInteger<u32>(GL_MAX_VARYING_VECTORS); 28 max_varyings = GetInteger<u32>(GL_MAX_VARYING_VECTORS);
26 has_variable_aoffi = TestVariableAoffi(); 29 has_variable_aoffi = TestVariableAoffi();
30 has_component_indexing_bug = TestComponentIndexingBug();
27} 31}
28 32
29Device::Device(std::nullptr_t) { 33Device::Device(std::nullptr_t) {
@@ -31,6 +35,7 @@ Device::Device(std::nullptr_t) {
31 max_vertex_attributes = 16; 35 max_vertex_attributes = 16;
32 max_varyings = 15; 36 max_varyings = 15;
33 has_variable_aoffi = true; 37 has_variable_aoffi = true;
38 has_component_indexing_bug = false;
34} 39}
35 40
36bool Device::TestVariableAoffi() { 41bool Device::TestVariableAoffi() {
@@ -51,4 +56,53 @@ void main() {
51 return supported; 56 return supported;
52} 57}
53 58
59bool Device::TestComponentIndexingBug() {
60 constexpr char log_message[] = "Renderer_ComponentIndexingBug: {}";
61 const GLchar* COMPONENT_TEST = R"(#version 430 core
62layout (std430, binding = 0) buffer OutputBuffer {
63 uint output_value;
64};
65layout (std140, binding = 0) uniform InputBuffer {
66 uvec4 input_value[4096];
67};
68layout (location = 0) uniform uint idx;
69void main() {
70 output_value = input_value[idx >> 2][idx & 3];
71})";
72 const GLuint shader{glCreateShaderProgramv(GL_VERTEX_SHADER, 1, &COMPONENT_TEST)};
73 SCOPE_EXIT({ glDeleteProgram(shader); });
74 glUseProgram(shader);
75
76 OGLVertexArray vao;
77 vao.Create();
78 glBindVertexArray(vao.handle);
79
80 constexpr std::array<GLuint, 8> values{0, 0, 0, 0, 0x1236327, 0x985482, 0x872753, 0x2378432};
81 OGLBuffer ubo;
82 ubo.Create();
83 glNamedBufferData(ubo.handle, sizeof(values), values.data(), GL_STATIC_DRAW);
84 glBindBufferBase(GL_UNIFORM_BUFFER, 0, ubo.handle);
85
86 OGLBuffer ssbo;
87 ssbo.Create();
88 glNamedBufferStorage(ssbo.handle, sizeof(GLuint), nullptr, GL_CLIENT_STORAGE_BIT);
89
90 for (GLuint index = 4; index < 8; ++index) {
91 glInvalidateBufferData(ssbo.handle);
92 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, ssbo.handle);
93
94 glProgramUniform1ui(shader, 0, index);
95 glDrawArrays(GL_POINTS, 0, 1);
96
97 GLuint result;
98 glGetNamedBufferSubData(ssbo.handle, 0, sizeof(result), &result);
99 if (result != values.at(index)) {
100 LOG_INFO(Render_OpenGL, log_message, true);
101 return true;
102 }
103 }
104 LOG_INFO(Render_OpenGL, log_message, false);
105 return false;
106}
107
54} // namespace OpenGL 108} // namespace OpenGL
diff --git a/src/video_core/renderer_opengl/gl_device.h b/src/video_core/renderer_opengl/gl_device.h
index de8490682..8c8c93760 100644
--- a/src/video_core/renderer_opengl/gl_device.h
+++ b/src/video_core/renderer_opengl/gl_device.h
@@ -30,13 +30,19 @@ public:
30 return has_variable_aoffi; 30 return has_variable_aoffi;
31 } 31 }
32 32
33 bool HasComponentIndexingBug() const {
34 return has_component_indexing_bug;
35 }
36
33private: 37private:
34 static bool TestVariableAoffi(); 38 static bool TestVariableAoffi();
39 static bool TestComponentIndexingBug();
35 40
36 std::size_t uniform_buffer_alignment{}; 41 std::size_t uniform_buffer_alignment{};
37 u32 max_vertex_attributes{}; 42 u32 max_vertex_attributes{};
38 u32 max_varyings{}; 43 u32 max_varyings{};
39 bool has_variable_aoffi{}; 44 bool has_variable_aoffi{};
45 bool has_component_indexing_bug{};
40}; 46};
41 47
42} // namespace OpenGL 48} // namespace OpenGL