Partially Revert "renderer_opengl: Remove amd hacks and legacy paths" (#6122)
This reverts commit 07a69b7c7b
.
This commit is contained in:
parent
30831e6367
commit
baecc18d8c
|
@ -26,6 +26,10 @@ 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() {
|
||||||
|
const std::string_view gpu_vendor{reinterpret_cast<char const*>(glGetString(GL_VENDOR))};
|
||||||
|
return gpu_vendor == "ATI Technologies Inc." || gpu_vendor == "Advanced Micro Devices, Inc.";
|
||||||
|
}
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
static bool IsVendorIntel() {
|
static bool IsVendorIntel() {
|
||||||
std::string gpu_vendor{reinterpret_cast<char const*>(glGetString(GL_VENDOR))};
|
std::string gpu_vendor{reinterpret_cast<char const*>(glGetString(GL_VENDOR))};
|
||||||
|
@ -34,11 +38,11 @@ static bool IsVendorIntel() {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
RasterizerOpenGL::RasterizerOpenGL(Frontend::EmuWindow& emu_window)
|
RasterizerOpenGL::RasterizerOpenGL(Frontend::EmuWindow& emu_window)
|
||||||
: vertex_buffer(GL_ARRAY_BUFFER, VERTEX_BUFFER_SIZE),
|
: is_amd(IsVendorAmd()), vertex_buffer(GL_ARRAY_BUFFER, VERTEX_BUFFER_SIZE, is_amd),
|
||||||
uniform_buffer(GL_UNIFORM_BUFFER, UNIFORM_BUFFER_SIZE),
|
uniform_buffer(GL_UNIFORM_BUFFER, UNIFORM_BUFFER_SIZE, false),
|
||||||
index_buffer(GL_ELEMENT_ARRAY_BUFFER, INDEX_BUFFER_SIZE),
|
index_buffer(GL_ELEMENT_ARRAY_BUFFER, INDEX_BUFFER_SIZE, false),
|
||||||
texture_buffer(GL_TEXTURE_BUFFER, TEXTURE_BUFFER_SIZE),
|
texture_buffer(GL_TEXTURE_BUFFER, TEXTURE_BUFFER_SIZE, false),
|
||||||
texture_lf_buffer(GL_TEXTURE_BUFFER, TEXTURE_BUFFER_SIZE) {
|
texture_lf_buffer(GL_TEXTURE_BUFFER, TEXTURE_BUFFER_SIZE, false) {
|
||||||
|
|
||||||
// Clipping plane 0 is always enabled for PICA fixed clip plane z <= 0
|
// Clipping plane 0 is always enabled for PICA fixed clip plane z <= 0
|
||||||
state.clip_distance[0] = true;
|
state.clip_distance[0] = true;
|
||||||
|
@ -144,12 +148,13 @@ RasterizerOpenGL::RasterizerOpenGL(Frontend::EmuWindow& emu_window)
|
||||||
|
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
if (IsVendorIntel()) {
|
if (IsVendorIntel()) {
|
||||||
shader_program_manager = std::make_unique<ShaderProgramManager>(emu_window, false);
|
shader_program_manager = std::make_unique<ShaderProgramManager>(
|
||||||
|
emu_window, VideoCore::g_separable_shader_enabled, is_amd);
|
||||||
} else {
|
} else {
|
||||||
shader_program_manager = std::make_unique<ShaderProgramManager>(emu_window, false);
|
shader_program_manager = std::make_unique<ShaderProgramManager>(emu_window, true, is_amd);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
shader_program_manager = std::make_unique<ShaderProgramManager>(emu_window, !GLES);
|
shader_program_manager = std::make_unique<ShaderProgramManager>(emu_window, !GLES, is_amd);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
glEnable(GL_BLEND);
|
glEnable(GL_BLEND);
|
||||||
|
|
|
@ -247,6 +247,8 @@ private:
|
||||||
/// Setup geometry shader for AccelerateDrawBatch
|
/// Setup geometry shader for AccelerateDrawBatch
|
||||||
bool SetupGeometryShader();
|
bool SetupGeometryShader();
|
||||||
|
|
||||||
|
bool is_amd;
|
||||||
|
|
||||||
OpenGLState state;
|
OpenGLState state;
|
||||||
GLuint default_texture;
|
GLuint default_texture;
|
||||||
|
|
||||||
|
|
|
@ -327,8 +327,8 @@ using FragmentShaders = ShaderCache<PicaFSConfig, &GenerateFragmentShader, GL_FR
|
||||||
|
|
||||||
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), fixed_geometry_shaders(separable),
|
trivial_vertex_shader(separable), fixed_geometry_shaders(separable),
|
||||||
fragment_shaders(separable), disk_cache(separable) {
|
fragment_shaders(separable), disk_cache(separable) {
|
||||||
if (separable)
|
if (separable)
|
||||||
|
@ -361,6 +361,7 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
bool is_amd;
|
||||||
bool separable;
|
bool separable;
|
||||||
|
|
||||||
ShaderTuple current;
|
ShaderTuple current;
|
||||||
|
@ -376,8 +377,9 @@ public:
|
||||||
ShaderDiskCache disk_cache;
|
ShaderDiskCache disk_cache;
|
||||||
};
|
};
|
||||||
|
|
||||||
ShaderProgramManager::ShaderProgramManager(Frontend::EmuWindow& emu_window_, bool separable)
|
ShaderProgramManager::ShaderProgramManager(Frontend::EmuWindow& emu_window_, bool separable,
|
||||||
: impl(std::make_unique<Impl>(separable)), emu_window{emu_window_} {}
|
bool is_amd)
|
||||||
|
: impl(std::make_unique<Impl>(separable, is_amd)), emu_window{emu_window_} {}
|
||||||
|
|
||||||
ShaderProgramManager::~ShaderProgramManager() = default;
|
ShaderProgramManager::~ShaderProgramManager() = default;
|
||||||
|
|
||||||
|
@ -439,6 +441,15 @@ void ShaderProgramManager::UseFragmentShader(const Pica::Regs& regs) {
|
||||||
|
|
||||||
void ShaderProgramManager::ApplyTo(OpenGLState& state) {
|
void ShaderProgramManager::ApplyTo(OpenGLState& state) {
|
||||||
if (impl->separable) {
|
if (impl->separable) {
|
||||||
|
if (impl->is_amd) {
|
||||||
|
// Without this reseting, AMD sometimes freezes when one stage is changed but not
|
||||||
|
// for the others. On the other hand, including this reset seems to introduce memory
|
||||||
|
// leak in Intel 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);
|
||||||
glUseProgramStages(impl->pipeline.handle, GL_FRAGMENT_SHADER_BIT, impl->current.fs);
|
glUseProgramStages(impl->pipeline.handle, GL_FRAGMENT_SHADER_BIT, impl->current.fs);
|
||||||
|
|
|
@ -108,7 +108,7 @@ class OpenGLState;
|
||||||
/// 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:
|
||||||
ShaderProgramManager(Frontend::EmuWindow& emu_window_, bool separable);
|
ShaderProgramManager(Frontend::EmuWindow& emu_window_, bool separable, bool is_amd);
|
||||||
~ShaderProgramManager();
|
~ShaderProgramManager();
|
||||||
|
|
||||||
void LoadDiskCache(const std::atomic_bool& stop_loading,
|
void LoadDiskCache(const std::atomic_bool& stop_loading,
|
||||||
|
|
|
@ -12,12 +12,21 @@ MICROPROFILE_DEFINE(OpenGL_StreamBuffer, "OpenGL", "Stream Buffer Orphaning",
|
||||||
|
|
||||||
namespace OpenGL {
|
namespace OpenGL {
|
||||||
|
|
||||||
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 (array_buffer_for_amd) {
|
||||||
|
// 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
|
||||||
|
// probably a bug in the driver and is related to the usage of vec3<byte> attributes in the
|
||||||
|
// vertex array. Doubling the allocation size for the vertex buffer seems to avoid the
|
||||||
|
// crash.
|
||||||
|
allocate_size *= 2;
|
||||||
|
}
|
||||||
|
|
||||||
if (GLAD_GL_ARB_buffer_storage) {
|
if (GLAD_GL_ARB_buffer_storage) {
|
||||||
persistent = true;
|
persistent = true;
|
||||||
|
|
|
@ -10,7 +10,8 @@ namespace OpenGL {
|
||||||
|
|
||||||
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;
|
||||||
|
|
Reference in New Issue