|
@@ -2,11 +2,14 @@
|
|
|
// Licensed under GPLv2 or any later version
|
|
// Licensed under GPLv2 or any later version
|
|
|
// Refer to the license.txt file included.
|
|
// Refer to the license.txt file included.
|
|
|
|
|
|
|
|
|
|
+#include <array>
|
|
|
#include <cstddef>
|
|
#include <cstddef>
|
|
|
#include <glad/glad.h>
|
|
#include <glad/glad.h>
|
|
|
|
|
|
|
|
#include "common/logging/log.h"
|
|
#include "common/logging/log.h"
|
|
|
|
|
+#include "common/scope_exit.h"
|
|
|
#include "video_core/renderer_opengl/gl_device.h"
|
|
#include "video_core/renderer_opengl/gl_device.h"
|
|
|
|
|
+#include "video_core/renderer_opengl/gl_resource_manager.h"
|
|
|
|
|
|
|
|
namespace OpenGL {
|
|
namespace OpenGL {
|
|
|
|
|
|
|
@@ -24,6 +27,7 @@ Device::Device() {
|
|
|
max_vertex_attributes = GetInteger<u32>(GL_MAX_VERTEX_ATTRIBS);
|
|
max_vertex_attributes = GetInteger<u32>(GL_MAX_VERTEX_ATTRIBS);
|
|
|
max_varyings = GetInteger<u32>(GL_MAX_VARYING_VECTORS);
|
|
max_varyings = GetInteger<u32>(GL_MAX_VARYING_VECTORS);
|
|
|
has_variable_aoffi = TestVariableAoffi();
|
|
has_variable_aoffi = TestVariableAoffi();
|
|
|
|
|
+ has_component_indexing_bug = TestComponentIndexingBug();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
Device::Device(std::nullptr_t) {
|
|
Device::Device(std::nullptr_t) {
|
|
@@ -31,6 +35,7 @@ Device::Device(std::nullptr_t) {
|
|
|
max_vertex_attributes = 16;
|
|
max_vertex_attributes = 16;
|
|
|
max_varyings = 15;
|
|
max_varyings = 15;
|
|
|
has_variable_aoffi = true;
|
|
has_variable_aoffi = true;
|
|
|
|
|
+ has_component_indexing_bug = false;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
bool Device::TestVariableAoffi() {
|
|
bool Device::TestVariableAoffi() {
|
|
@@ -51,4 +56,53 @@ void main() {
|
|
|
return supported;
|
|
return supported;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+bool Device::TestComponentIndexingBug() {
|
|
|
|
|
+ constexpr char log_message[] = "Renderer_ComponentIndexingBug: {}";
|
|
|
|
|
+ const GLchar* COMPONENT_TEST = R"(#version 430 core
|
|
|
|
|
+layout (std430, binding = 0) buffer OutputBuffer {
|
|
|
|
|
+ uint output_value;
|
|
|
|
|
+};
|
|
|
|
|
+layout (std140, binding = 0) uniform InputBuffer {
|
|
|
|
|
+ uvec4 input_value[4096];
|
|
|
|
|
+};
|
|
|
|
|
+layout (location = 0) uniform uint idx;
|
|
|
|
|
+void main() {
|
|
|
|
|
+ output_value = input_value[idx >> 2][idx & 3];
|
|
|
|
|
+})";
|
|
|
|
|
+ const GLuint shader{glCreateShaderProgramv(GL_VERTEX_SHADER, 1, &COMPONENT_TEST)};
|
|
|
|
|
+ SCOPE_EXIT({ glDeleteProgram(shader); });
|
|
|
|
|
+ glUseProgram(shader);
|
|
|
|
|
+
|
|
|
|
|
+ OGLVertexArray vao;
|
|
|
|
|
+ vao.Create();
|
|
|
|
|
+ glBindVertexArray(vao.handle);
|
|
|
|
|
+
|
|
|
|
|
+ constexpr std::array<GLuint, 8> values{0, 0, 0, 0, 0x1236327, 0x985482, 0x872753, 0x2378432};
|
|
|
|
|
+ OGLBuffer ubo;
|
|
|
|
|
+ ubo.Create();
|
|
|
|
|
+ glNamedBufferData(ubo.handle, sizeof(values), values.data(), GL_STATIC_DRAW);
|
|
|
|
|
+ glBindBufferBase(GL_UNIFORM_BUFFER, 0, ubo.handle);
|
|
|
|
|
+
|
|
|
|
|
+ OGLBuffer ssbo;
|
|
|
|
|
+ ssbo.Create();
|
|
|
|
|
+ glNamedBufferStorage(ssbo.handle, sizeof(GLuint), nullptr, GL_CLIENT_STORAGE_BIT);
|
|
|
|
|
+
|
|
|
|
|
+ for (GLuint index = 4; index < 8; ++index) {
|
|
|
|
|
+ glInvalidateBufferData(ssbo.handle);
|
|
|
|
|
+ glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, ssbo.handle);
|
|
|
|
|
+
|
|
|
|
|
+ glProgramUniform1ui(shader, 0, index);
|
|
|
|
|
+ glDrawArrays(GL_POINTS, 0, 1);
|
|
|
|
|
+
|
|
|
|
|
+ GLuint result;
|
|
|
|
|
+ glGetNamedBufferSubData(ssbo.handle, 0, sizeof(result), &result);
|
|
|
|
|
+ if (result != values.at(index)) {
|
|
|
|
|
+ LOG_INFO(Render_OpenGL, log_message, true);
|
|
|
|
|
+ return true;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ LOG_INFO(Render_OpenGL, log_message, false);
|
|
|
|
|
+ return false;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
} // namespace OpenGL
|
|
} // namespace OpenGL
|