Merge pull request #4042 from wwylele/i-love-drivers

gl_rasterizer: apply AMD hack only when the vendor is AMD
This commit is contained in:
James Rowe 2018-08-02 11:01:25 -06:00 committed by GitHub
commit 4b59c1b601
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 34 additions and 18 deletions

View file

@ -34,11 +34,17 @@ MICROPROFILE_DEFINE(OpenGL_Drawing, "OpenGL", "Drawing", MP_RGB(128, 128, 192));
MICROPROFILE_DEFINE(OpenGL_Blits, "OpenGL", "Blits", MP_RGB(100, 100, 255)); MICROPROFILE_DEFINE(OpenGL_Blits, "OpenGL", "Blits", MP_RGB(100, 100, 255));
MICROPROFILE_DEFINE(OpenGL_CacheManagement, "OpenGL", "Cache Mgmt", MP_RGB(100, 255, 100)); MICROPROFILE_DEFINE(OpenGL_CacheManagement, "OpenGL", "Cache Mgmt", MP_RGB(100, 255, 100));
static bool IsVendorAmd() {
std::string gpu_vendor{reinterpret_cast<char const*>(glGetString(GL_VENDOR))};
return gpu_vendor == "ATI Technologies Inc." || gpu_vendor == "Advanced Micro Devices, Inc.";
}
RasterizerOpenGL::RasterizerOpenGL() RasterizerOpenGL::RasterizerOpenGL()
: shader_dirty(true), vertex_buffer(GL_ARRAY_BUFFER, VERTEX_BUFFER_SIZE), : is_amd(IsVendorAmd()), shader_dirty(true),
uniform_buffer(GL_UNIFORM_BUFFER, UNIFORM_BUFFER_SIZE), vertex_buffer(GL_ARRAY_BUFFER, VERTEX_BUFFER_SIZE, is_amd),
index_buffer(GL_ELEMENT_ARRAY_BUFFER, INDEX_BUFFER_SIZE), uniform_buffer(GL_UNIFORM_BUFFER, UNIFORM_BUFFER_SIZE, false),
texture_buffer(GL_TEXTURE_BUFFER, TEXTURE_BUFFER_SIZE) { index_buffer(GL_ELEMENT_ARRAY_BUFFER, INDEX_BUFFER_SIZE, false),
texture_buffer(GL_TEXTURE_BUFFER, TEXTURE_BUFFER_SIZE, false) {
allow_shadow = GLAD_GL_ARB_shader_image_load_store && GLAD_GL_ARB_shader_image_size && allow_shadow = GLAD_GL_ARB_shader_image_load_store && GLAD_GL_ARB_shader_image_size &&
GLAD_GL_ARB_framebuffer_no_attachments; GLAD_GL_ARB_framebuffer_no_attachments;
@ -145,7 +151,7 @@ RasterizerOpenGL::RasterizerOpenGL()
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffer.GetHandle()); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffer.GetHandle());
shader_program_manager = shader_program_manager =
std::make_unique<ShaderProgramManager>(GLAD_GL_ARB_separate_shader_objects); std::make_unique<ShaderProgramManager>(GLAD_GL_ARB_separate_shader_objects, is_amd);
glEnable(GL_BLEND); glEnable(GL_BLEND);

View file

@ -243,6 +243,8 @@ private:
/// Setup geometry shader for AccelerateDrawBatch /// Setup geometry shader for AccelerateDrawBatch
bool SetupGeometryShader(); bool SetupGeometryShader();
bool is_amd;
OpenGLState state; OpenGLState state;
RasterizerCacheOpenGL res_cache; RasterizerCacheOpenGL res_cache;

View file

@ -216,8 +216,8 @@ using FragmentShaders =
class ShaderProgramManager::Impl { class ShaderProgramManager::Impl {
public: public:
explicit Impl(bool separable) explicit Impl(bool separable, bool is_amd)
: separable(separable), programmable_vertex_shaders(separable), : is_amd(is_amd), separable(separable), programmable_vertex_shaders(separable),
trivial_vertex_shader(separable), programmable_geometry_shaders(separable), trivial_vertex_shader(separable), programmable_geometry_shaders(separable),
fixed_geometry_shaders(separable), fragment_shaders(separable) { fixed_geometry_shaders(separable), fragment_shaders(separable) {
if (separable) if (separable)
@ -248,6 +248,8 @@ public:
}; };
}; };
bool is_amd;
ShaderTuple current; ShaderTuple current;
ProgrammableVertexShaders programmable_vertex_shaders; ProgrammableVertexShaders programmable_vertex_shaders;
@ -263,8 +265,8 @@ public:
OGLPipeline pipeline; OGLPipeline pipeline;
}; };
ShaderProgramManager::ShaderProgramManager(bool separable) ShaderProgramManager::ShaderProgramManager(bool separable, bool is_amd)
: impl(std::make_unique<Impl>(separable)) {} : impl(std::make_unique<Impl>(separable, is_amd)) {}
ShaderProgramManager::~ShaderProgramManager() = default; ShaderProgramManager::~ShaderProgramManager() = default;
@ -304,11 +306,15 @@ void ShaderProgramManager::UseFragmentShader(const GLShader::PicaFSConfig& confi
void ShaderProgramManager::ApplyTo(OpenGLState& state) { void ShaderProgramManager::ApplyTo(OpenGLState& state) {
if (impl->separable) { if (impl->separable) {
// Without this reseting, AMD sometimes freezes when one stage is changed but not for the if (impl->is_amd) {
// others // Without this reseting, AMD sometimes freezes when one stage is changed but not for
glUseProgramStages(impl->pipeline.handle, // the others.
GL_VERTEX_SHADER_BIT | GL_GEOMETRY_SHADER_BIT | GL_FRAGMENT_SHADER_BIT, // On the other hand, including this reset seems to introduce memory leak in Intel
0); // Graphics.
glUseProgramStages(
impl->pipeline.handle,
GL_VERTEX_SHADER_BIT | GL_GEOMETRY_SHADER_BIT | GL_FRAGMENT_SHADER_BIT, 0);
}
glUseProgramStages(impl->pipeline.handle, GL_VERTEX_SHADER_BIT, impl->current.vs); glUseProgramStages(impl->pipeline.handle, GL_VERTEX_SHADER_BIT, impl->current.vs);
glUseProgramStages(impl->pipeline.handle, GL_GEOMETRY_SHADER_BIT, impl->current.gs); glUseProgramStages(impl->pipeline.handle, GL_GEOMETRY_SHADER_BIT, impl->current.gs);

View file

@ -99,7 +99,7 @@ static_assert(sizeof(GSUniformData) < 16384,
/// A class that manage different shader stages and configures them with given config data. /// A class that manage different shader stages and configures them with given config data.
class ShaderProgramManager { class ShaderProgramManager {
public: public:
explicit ShaderProgramManager(bool separable); ShaderProgramManager(bool separable, bool is_amd);
~ShaderProgramManager(); ~ShaderProgramManager();
bool UseProgrammableVertexShader(const GLShader::PicaVSConfig& config, bool UseProgrammableVertexShader(const GLShader::PicaVSConfig& config,

View file

@ -9,13 +9,14 @@
#include "video_core/renderer_opengl/gl_state.h" #include "video_core/renderer_opengl/gl_state.h"
#include "video_core/renderer_opengl/gl_stream_buffer.h" #include "video_core/renderer_opengl/gl_stream_buffer.h"
OGLStreamBuffer::OGLStreamBuffer(GLenum target, GLsizeiptr size, bool prefer_coherent) OGLStreamBuffer::OGLStreamBuffer(GLenum target, GLsizeiptr size, bool array_buffer_for_amd,
bool prefer_coherent)
: gl_target(target), buffer_size(size) { : gl_target(target), buffer_size(size) {
gl_buffer.Create(); gl_buffer.Create();
glBindBuffer(gl_target, gl_buffer.handle); glBindBuffer(gl_target, gl_buffer.handle);
GLsizeiptr allocate_size = size; GLsizeiptr allocate_size = size;
if (target == GL_ARRAY_BUFFER) { if (array_buffer_for_amd) {
// On AMD GPU there is a strange crash in indexed drawing. The crash happens when the buffer // On AMD GPU there is a strange crash in indexed drawing. The crash happens when the buffer
// read position is near the end and is an out-of-bound access to the vertex buffer. This is // read position is near the end and is an out-of-bound access to the vertex buffer. This is
// probably a bug in the driver and is related to the usage of vec3<byte> attributes in the // probably a bug in the driver and is related to the usage of vec3<byte> attributes in the

View file

@ -9,7 +9,8 @@
class OGLStreamBuffer : private NonCopyable { class OGLStreamBuffer : private NonCopyable {
public: public:
explicit OGLStreamBuffer(GLenum target, GLsizeiptr size, bool prefer_coherent = false); explicit OGLStreamBuffer(GLenum target, GLsizeiptr size, bool array_buffer_for_amd,
bool prefer_coherent = false);
~OGLStreamBuffer(); ~OGLStreamBuffer();
GLuint GetHandle() const; GLuint GetHandle() const;