mirror of
https://git.suyu.dev/suyu/suyu.git
synced 2024-11-09 00:12:45 +01:00
gl_device: Disable precise in fragment shaders on bugged drivers
This commit is contained in:
parent
03276e7490
commit
9cf52d027d
3 changed files with 43 additions and 15 deletions
|
@ -14,12 +14,22 @@
|
||||||
namespace OpenGL {
|
namespace OpenGL {
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
T GetInteger(GLenum pname) {
|
T GetInteger(GLenum pname) {
|
||||||
GLint temporary;
|
GLint temporary;
|
||||||
glGetIntegerv(pname, &temporary);
|
glGetIntegerv(pname, &temporary);
|
||||||
return static_cast<T>(temporary);
|
return static_cast<T>(temporary);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool TestProgram(const GLchar* glsl) {
|
||||||
|
const GLuint shader{glCreateShaderProgramv(GL_VERTEX_SHADER, 1, &glsl)};
|
||||||
|
GLint link_status;
|
||||||
|
glGetProgramiv(shader, GL_LINK_STATUS, &link_status);
|
||||||
|
glDeleteProgram(shader);
|
||||||
|
return link_status == GL_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
} // Anonymous namespace
|
} // Anonymous namespace
|
||||||
|
|
||||||
Device::Device() {
|
Device::Device() {
|
||||||
|
@ -32,6 +42,11 @@ Device::Device() {
|
||||||
has_vertex_viewport_layer = GLAD_GL_ARB_shader_viewport_layer_array;
|
has_vertex_viewport_layer = GLAD_GL_ARB_shader_viewport_layer_array;
|
||||||
has_variable_aoffi = TestVariableAoffi();
|
has_variable_aoffi = TestVariableAoffi();
|
||||||
has_component_indexing_bug = TestComponentIndexingBug();
|
has_component_indexing_bug = TestComponentIndexingBug();
|
||||||
|
has_precise_bug = TestPreciseBug();
|
||||||
|
|
||||||
|
LOG_INFO(Render_OpenGL, "Renderer_VariableAOFFI: {}", has_variable_aoffi);
|
||||||
|
LOG_INFO(Render_OpenGL, "Renderer_ComponentIndexingBug: {}", has_component_indexing_bug);
|
||||||
|
LOG_INFO(Render_OpenGL, "Renderer_PreciseBug: {}", has_precise_bug);
|
||||||
}
|
}
|
||||||
|
|
||||||
Device::Device(std::nullptr_t) {
|
Device::Device(std::nullptr_t) {
|
||||||
|
@ -42,30 +57,21 @@ Device::Device(std::nullptr_t) {
|
||||||
has_vertex_viewport_layer = true;
|
has_vertex_viewport_layer = true;
|
||||||
has_variable_aoffi = true;
|
has_variable_aoffi = true;
|
||||||
has_component_indexing_bug = false;
|
has_component_indexing_bug = false;
|
||||||
|
has_precise_bug = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Device::TestVariableAoffi() {
|
bool Device::TestVariableAoffi() {
|
||||||
const GLchar* AOFFI_TEST = R"(#version 430 core
|
return TestProgram(R"(#version 430 core
|
||||||
// This is a unit test, please ignore me on apitrace bug reports.
|
// This is a unit test, please ignore me on apitrace bug reports.
|
||||||
uniform sampler2D tex;
|
uniform sampler2D tex;
|
||||||
uniform ivec2 variable_offset;
|
uniform ivec2 variable_offset;
|
||||||
out vec4 output_attribute;
|
out vec4 output_attribute;
|
||||||
void main() {
|
void main() {
|
||||||
output_attribute = textureOffset(tex, vec2(0), variable_offset);
|
output_attribute = textureOffset(tex, vec2(0), variable_offset);
|
||||||
}
|
})");
|
||||||
)";
|
|
||||||
const GLuint shader{glCreateShaderProgramv(GL_VERTEX_SHADER, 1, &AOFFI_TEST)};
|
|
||||||
GLint link_status{};
|
|
||||||
glGetProgramiv(shader, GL_LINK_STATUS, &link_status);
|
|
||||||
glDeleteProgram(shader);
|
|
||||||
|
|
||||||
const bool supported{link_status == GL_TRUE};
|
|
||||||
LOG_INFO(Render_OpenGL, "Renderer_VariableAOFFI: {}", supported);
|
|
||||||
return supported;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Device::TestComponentIndexingBug() {
|
bool Device::TestComponentIndexingBug() {
|
||||||
constexpr char log_message[] = "Renderer_ComponentIndexingBug: {}";
|
|
||||||
const GLchar* COMPONENT_TEST = R"(#version 430 core
|
const GLchar* COMPONENT_TEST = R"(#version 430 core
|
||||||
layout (std430, binding = 0) buffer OutputBuffer {
|
layout (std430, binding = 0) buffer OutputBuffer {
|
||||||
uint output_value;
|
uint output_value;
|
||||||
|
@ -105,12 +111,21 @@ void main() {
|
||||||
GLuint result;
|
GLuint result;
|
||||||
glGetNamedBufferSubData(ssbo.handle, 0, sizeof(result), &result);
|
glGetNamedBufferSubData(ssbo.handle, 0, sizeof(result), &result);
|
||||||
if (result != values.at(index)) {
|
if (result != values.at(index)) {
|
||||||
LOG_INFO(Render_OpenGL, log_message, true);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
LOG_INFO(Render_OpenGL, log_message, false);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Device::TestPreciseBug() {
|
||||||
|
return !TestProgram(R"(#version 430 core
|
||||||
|
in vec3 coords;
|
||||||
|
out float out_value;
|
||||||
|
uniform sampler2DShadow tex;
|
||||||
|
void main() {
|
||||||
|
precise float tmp_value = vec4(texture(tex, coords)).x;
|
||||||
|
out_value = tmp_value;
|
||||||
|
})");
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace OpenGL
|
} // namespace OpenGL
|
||||||
|
|
|
@ -46,9 +46,14 @@ public:
|
||||||
return has_component_indexing_bug;
|
return has_component_indexing_bug;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool HasPreciseBug() const {
|
||||||
|
return has_precise_bug;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static bool TestVariableAoffi();
|
static bool TestVariableAoffi();
|
||||||
static bool TestComponentIndexingBug();
|
static bool TestComponentIndexingBug();
|
||||||
|
static bool TestPreciseBug();
|
||||||
|
|
||||||
std::size_t uniform_buffer_alignment{};
|
std::size_t uniform_buffer_alignment{};
|
||||||
std::size_t shader_storage_alignment{};
|
std::size_t shader_storage_alignment{};
|
||||||
|
@ -58,6 +63,7 @@ private:
|
||||||
bool has_vertex_viewport_layer{};
|
bool has_vertex_viewport_layer{};
|
||||||
bool has_variable_aoffi{};
|
bool has_variable_aoffi{};
|
||||||
bool has_component_indexing_bug{};
|
bool has_component_indexing_bug{};
|
||||||
|
bool has_precise_bug{};
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace OpenGL
|
} // namespace OpenGL
|
||||||
|
|
|
@ -957,8 +957,15 @@ private:
|
||||||
if (!IsPrecise(operation)) {
|
if (!IsPrecise(operation)) {
|
||||||
return {std::move(value), type};
|
return {std::move(value), type};
|
||||||
}
|
}
|
||||||
|
// Old Nvidia drivers have a bug with precise and texture sampling. These are more likely to
|
||||||
|
// be found in fragment shaders, so we disable precise there. There are vertex shaders that
|
||||||
|
// also fail to build but nobody seems to care about those.
|
||||||
|
// Note: Only bugged drivers will skip precise.
|
||||||
|
const bool disable_precise = device.HasPreciseBug() && stage == ProgramType::Fragment;
|
||||||
|
|
||||||
std::string temporary = code.GenerateTemporary();
|
std::string temporary = code.GenerateTemporary();
|
||||||
code.AddLine("precise {} {} = {};", GetTypeString(type), temporary, value);
|
code.AddLine("{}{} {} = {};", disable_precise ? "" : "precise ", GetTypeString(type),
|
||||||
|
temporary, value);
|
||||||
return {std::move(temporary), type};
|
return {std::move(temporary), type};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue