citra-emu
/
citra-canary
Archived
1
0
Fork 0

Partially Revert "renderer_opengl: Remove amd hacks and legacy paths" (#6122)

This reverts commit 07a69b7c7b.
This commit is contained in:
SachinVin 2022-09-10 15:35:13 +05:30 committed by GitHub
parent 30831e6367
commit baecc18d8c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 43 additions and 15 deletions

View File

@ -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);

View File

@ -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;

View File

@ -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);

View File

@ -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,

View File

@ -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;

View File

@ -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;