citra-emu
/
citra
Archived
1
0
Fork 0

renderer_opengl: Remove amd hacks and legacy paths

* AMDs new driver fixed many issues in the OpenGL driver. No reason to
  keep these hacks. In addition the upgrade to 4.3 guarantees the
  existance of required extensions, so no need to check for them
This commit is contained in:
emufan4568 2022-08-21 01:52:49 +03:00
parent 025cd31420
commit 07a69b7c7b
8 changed files with 20 additions and 241 deletions

View File

@ -2,11 +2,9 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include "common/assert.h"
#include "common/scope_exit.h"
#include "video_core/renderer_opengl/gl_format_reinterpreter.h"
#include "video_core/renderer_opengl/gl_state.h"
#include "video_core/renderer_opengl/gl_vars.h"
namespace OpenGL {
@ -98,129 +96,6 @@ private:
OGLVertexArray vao;
};
class PixelBufferD24S8toABGR final : public FormatReinterpreterBase {
public:
PixelBufferD24S8toABGR() {
attributeless_vao.Create();
d24s8_abgr_buffer.Create();
d24s8_abgr_buffer_size = 0;
constexpr std::string_view vs_source = R"(
const vec2 vertices[4] = vec2[4](vec2(-1.0, -1.0), vec2(1.0, -1.0),
vec2(-1.0, 1.0), vec2(1.0, 1.0));
void main() {
gl_Position = vec4(vertices[gl_VertexID], 0.0, 1.0);
}
)";
std::string fs_source = GLES ? fragment_shader_precision_OES : "";
fs_source += R"(
uniform samplerBuffer tbo;
uniform vec2 tbo_size;
uniform vec4 viewport;
out vec4 color;
void main() {
vec2 tbo_coord = (gl_FragCoord.xy - viewport.xy) * tbo_size / viewport.zw;
int tbo_offset = int(tbo_coord.y) * int(tbo_size.x) + int(tbo_coord.x);
color = texelFetch(tbo, tbo_offset).rabg;
}
)";
d24s8_abgr_shader.Create(vs_source.data(), fs_source.c_str());
OpenGLState state = OpenGLState::GetCurState();
GLuint old_program = state.draw.shader_program;
state.draw.shader_program = d24s8_abgr_shader.handle;
state.Apply();
GLint tbo_u_id = glGetUniformLocation(d24s8_abgr_shader.handle, "tbo");
ASSERT(tbo_u_id != -1);
glUniform1i(tbo_u_id, 0);
state.draw.shader_program = old_program;
state.Apply();
d24s8_abgr_tbo_size_u_id = glGetUniformLocation(d24s8_abgr_shader.handle, "tbo_size");
ASSERT(d24s8_abgr_tbo_size_u_id != -1);
d24s8_abgr_viewport_u_id = glGetUniformLocation(d24s8_abgr_shader.handle, "viewport");
ASSERT(d24s8_abgr_viewport_u_id != -1);
}
~PixelBufferD24S8toABGR() {}
PixelFormat GetSourceFormat() const override {
return PixelFormat::D24S8;
}
void Reinterpret(const OGLTexture& src_tex, Common::Rectangle<u32> src_rect,
const OGLTexture& dst_tex, Common::Rectangle<u32> dst_rect) override {
OpenGLState prev_state = OpenGLState::GetCurState();
SCOPE_EXIT({ prev_state.Apply(); });
OpenGLState state;
state.draw.read_framebuffer = read_fbo.handle;
state.draw.draw_framebuffer = draw_fbo.handle;
state.Apply();
glBindBuffer(GL_PIXEL_PACK_BUFFER, d24s8_abgr_buffer.handle);
GLsizeiptr target_pbo_size =
static_cast<GLsizeiptr>(src_rect.GetWidth()) * src_rect.GetHeight() * 4;
if (target_pbo_size > d24s8_abgr_buffer_size) {
d24s8_abgr_buffer_size = target_pbo_size * 2;
glBufferData(GL_PIXEL_PACK_BUFFER, d24s8_abgr_buffer_size, nullptr, GL_STREAM_COPY);
}
glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0);
glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D,
src_tex.handle, 0);
glReadPixels(static_cast<GLint>(src_rect.left), static_cast<GLint>(src_rect.bottom),
static_cast<GLsizei>(src_rect.GetWidth()),
static_cast<GLsizei>(src_rect.GetHeight()), GL_DEPTH_STENCIL,
GL_UNSIGNED_INT_24_8, 0);
glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
// PBO now contains src_tex in RABG format
state.draw.shader_program = d24s8_abgr_shader.handle;
state.draw.vertex_array = attributeless_vao.handle;
state.viewport.x = static_cast<GLint>(dst_rect.left);
state.viewport.y = static_cast<GLint>(dst_rect.bottom);
state.viewport.width = static_cast<GLsizei>(dst_rect.GetWidth());
state.viewport.height = static_cast<GLsizei>(dst_rect.GetHeight());
state.Apply();
OGLTexture tbo;
tbo.Create();
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_BUFFER, tbo.handle);
glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA8, d24s8_abgr_buffer.handle);
glUniform2f(d24s8_abgr_tbo_size_u_id, static_cast<GLfloat>(src_rect.GetWidth()),
static_cast<GLfloat>(src_rect.GetHeight()));
glUniform4f(d24s8_abgr_viewport_u_id, static_cast<GLfloat>(state.viewport.x),
static_cast<GLfloat>(state.viewport.y),
static_cast<GLfloat>(state.viewport.width),
static_cast<GLfloat>(state.viewport.height));
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
dst_tex.handle, 0);
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D,
0, 0);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glBindTexture(GL_TEXTURE_BUFFER, 0);
}
private:
OGLVertexArray attributeless_vao;
OGLBuffer d24s8_abgr_buffer;
GLsizeiptr d24s8_abgr_buffer_size;
OGLProgram d24s8_abgr_shader;
GLint d24s8_abgr_tbo_size_u_id;
GLint d24s8_abgr_viewport_u_id;
};
class ShaderD24S8toRGBA8 final : public FormatReinterpreterBase {
public:
@ -371,24 +246,13 @@ FormatReinterpreterOpenGL::FormatReinterpreterOpenGL() {
const std::string_view vendor{reinterpret_cast<const char*>(glGetString(GL_VENDOR))};
const std::string_view version{reinterpret_cast<const char*>(glGetString(GL_VERSION))};
// Fallback to PBO path on obsolete intel drivers
// intel`s GL_VERSION string - `3.3.0 - Build 25.20.100.6373`
const bool intel_broken_drivers =
vendor.find("Intel") != vendor.npos && (std::atoi(version.substr(14, 2).data()) < 30);
auto Register = [this](PixelFormat dest, std::unique_ptr<FormatReinterpreterBase>&& obj) {
const u32 dst_index = static_cast<u32>(dest);
return reinterpreters[dst_index].push_back(std::move(obj));
};
if ((!intel_broken_drivers && GLAD_GL_ARB_stencil_texturing &&
GLAD_GL_ARB_texture_storage && GLAD_GL_ARB_copy_image) || GLES) {
Register(PixelFormat::RGBA8, std::make_unique<ShaderD24S8toRGBA8>());
LOG_INFO(Render_OpenGL, "Using shader for D24S8 to RGBA8 reinterpretation");
} else {
Register(PixelFormat::RGBA8, std::make_unique<PixelBufferD24S8toABGR>());
LOG_INFO(Render_OpenGL, "Using PBO for D24S8 to RGBA8 reinterpretation");
}
Register(PixelFormat::RGBA8, std::make_unique<ShaderD24S8toRGBA8>());
LOG_INFO(Render_OpenGL, "Using shader for D24S8 to RGBA8 reinterpretation");
Register(PixelFormat::RGB5A1, std::make_unique<RGBA4toRGB5A1>());
}

View File

@ -13,7 +13,6 @@
#include "common/logging/log.h"
#include "common/math_util.h"
#include "common/microprofile.h"
#include "common/scope_exit.h"
#include "common/vector_math.h"
#include "core/hw/gpu.h"
#include "video_core/pica_state.h"
@ -36,34 +35,13 @@ 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_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.";
}
static bool IsVendorIntel() {
std::string gpu_vendor{reinterpret_cast<char const*>(glGetString(GL_VENDOR))};
return gpu_vendor == "Intel Inc.";
}
RasterizerOpenGL::RasterizerOpenGL(Frontend::EmuWindow& emu_window)
: is_amd(IsVendorAmd()), vertex_buffer(GL_ARRAY_BUFFER, VERTEX_BUFFER_SIZE, is_amd),
: vertex_buffer(GL_ARRAY_BUFFER, VERTEX_BUFFER_SIZE),
uniform_buffer(GL_UNIFORM_BUFFER, UNIFORM_BUFFER_SIZE, false),
index_buffer(GL_ELEMENT_ARRAY_BUFFER, INDEX_BUFFER_SIZE, false),
texture_buffer(GL_TEXTURE_BUFFER, TEXTURE_BUFFER_SIZE, false),
texture_lf_buffer(GL_TEXTURE_BUFFER, TEXTURE_BUFFER_SIZE, false) {
allow_shadow = GLES || (GLAD_GL_ARB_shader_image_load_store && GLAD_GL_ARB_shader_image_size &&
GLAD_GL_ARB_framebuffer_no_attachments);
if (!allow_shadow) {
LOG_WARNING(Render_OpenGL,
"Shadow might not be able to render because of unsupported OpenGL extensions.");
}
if (!GLAD_GL_ARB_copy_image && !GLES) {
LOG_WARNING(Render_OpenGL,
"ARB_copy_image not supported. Some games might produce artifacts.");
}
// Clipping plane 0 is always enabled for PICA fixed clip plane z <= 0
state.clip_distance[0] = true;
@ -178,7 +156,7 @@ RasterizerOpenGL::RasterizerOpenGL(Frontend::EmuWindow& emu_window)
}
#else
shader_program_manager = std::make_unique<ShaderProgramManager>(
emu_window, GLAD_GL_ARB_separate_shader_objects, is_amd);
emu_window, GLAD_GL_ARB_separate_shader_objects);
#endif
glEnable(GL_BLEND);
@ -574,9 +552,10 @@ bool RasterizerOpenGL::Draw(bool accelerate, bool is_indexed) {
state.Apply();
if (shadow_rendering) {
if (!allow_shadow || color_surface == nullptr) {
if (color_surface == nullptr) {
return true;
}
glFramebufferParameteri(GL_DRAW_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_WIDTH,
color_surface->width * color_surface->res_scale);
glFramebufferParameteri(GL_DRAW_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_HEIGHT,
@ -663,9 +642,6 @@ bool RasterizerOpenGL::Draw(bool accelerate, bool is_indexed) {
using TextureType = Pica::TexturingRegs::TextureConfig::TextureType;
switch (texture.config.type.Value()) {
case TextureType::Shadow2D: {
if (!allow_shadow)
continue;
Surface surface = res_cache.GetTextureSurface(texture);
if (surface != nullptr) {
CheckBarrier(state.image_shadow_texture_px = surface->texture.handle);
@ -675,8 +651,6 @@ bool RasterizerOpenGL::Draw(bool accelerate, bool is_indexed) {
continue;
}
case TextureType::ShadowCube: {
if (!allow_shadow)
continue;
Pica::Texture::TextureInfo info = Pica::Texture::TextureInfo::FromPicaRegister(
texture.config, texture.format);
Surface surface;
@ -875,15 +849,13 @@ bool RasterizerOpenGL::Draw(bool accelerate, bool is_indexed) {
state.texture_units[texture_index].texture_2d = 0;
}
state.texture_cube_unit.texture_cube = 0;
if (allow_shadow) {
state.image_shadow_texture_px = 0;
state.image_shadow_texture_nx = 0;
state.image_shadow_texture_py = 0;
state.image_shadow_texture_ny = 0;
state.image_shadow_texture_pz = 0;
state.image_shadow_texture_nz = 0;
state.image_shadow_buffer = 0;
}
state.image_shadow_texture_px = 0;
state.image_shadow_texture_nx = 0;
state.image_shadow_texture_py = 0;
state.image_shadow_texture_ny = 0;
state.image_shadow_texture_pz = 0;
state.image_shadow_texture_nz = 0;
state.image_shadow_buffer = 0;
state.Apply();
if (shadow_rendering) {

View File

@ -263,8 +263,6 @@ private:
/// Setup geometry shader for AccelerateDrawBatch
bool SetupGeometryShader();
bool is_amd;
OpenGLState state;
GLuint default_texture;
@ -323,8 +321,6 @@ private:
std::array<GLvec2, 128> proctex_alpha_map_data{};
std::array<GLvec4, 256> proctex_lut_data{};
std::array<GLvec4, 256> proctex_diff_lut_data{};
bool allow_shadow;
};
} // namespace OpenGL

View File

@ -1233,18 +1233,6 @@ ShaderDecompiler::ProgramResult GenerateFragmentShader(const PicaFSConfig& confi
const auto& state = config.state;
std::string out;
if (GLES) {
out += R"(
#define ALLOW_SHADOW (defined(CITRA_GLES))
)";
} else {
out += R"(
#extension GL_ARB_shader_image_load_store : enable
#extension GL_ARB_shader_image_size : enable
#define ALLOW_SHADOW (defined(GL_ARB_shader_image_load_store) && defined(GL_ARB_shader_image_size))
)";
}
if (separable_shader && !GLES) {
out += "#extension GL_ARB_separate_shader_objects : enable\n";
}
@ -1270,7 +1258,6 @@ uniform samplerBuffer texture_buffer_lut_lf;
uniform samplerBuffer texture_buffer_lut_rg;
uniform samplerBuffer texture_buffer_lut_rgba;
#if ALLOW_SHADOW
layout(r32ui) uniform readonly uimage2D shadow_texture_px;
layout(r32ui) uniform readonly uimage2D shadow_texture_nx;
layout(r32ui) uniform readonly uimage2D shadow_texture_py;
@ -1278,7 +1265,6 @@ layout(r32ui) uniform readonly uimage2D shadow_texture_ny;
layout(r32ui) uniform readonly uimage2D shadow_texture_pz;
layout(r32ui) uniform readonly uimage2D shadow_texture_nz;
layout(r32ui) uniform uimage2D shadow_buffer;
#endif
)";
out += UniformBlockDef;
@ -1332,8 +1318,6 @@ float getLod(vec2 coord) {
return log2(max(d.x, d.y));
}
#if ALLOW_SHADOW
uvec2 DecodeShadow(uint pixel) {
return uvec2(pixel >> 8, pixel & 0xFFu);
}
@ -1459,18 +1443,6 @@ vec4 shadowTextureCube(vec2 uv, float w) {
CompareShadow(pixels.w, z));
return vec4(mix2(s, f));
}
#else
vec4 shadowTexture(vec2 uv, float w) {
return vec4(1.0);
}
vec4 shadowTextureCube(vec2 uv, float w) {
return vec4(1.0);
}
#endif
)";
if (config.state.proctex.enable)
@ -1559,7 +1531,6 @@ vec4 secondary_fragment_color = vec4(0.0);
if (state.shadow_rendering) {
out += R"(
#if ALLOW_SHADOW
uint d = uint(clamp(depth, 0.0, 1.0) * float(0xFFFFFF));
uint s = uint(last_tex_env_out.g * float(0xFF));
ivec2 image_coord = ivec2(gl_FragCoord.xy);
@ -1582,7 +1553,6 @@ do {
new = EncodeShadow(ref);
} while ((old = imageAtomicCompSwap(shadow_buffer, image_coord, old, new)) != old2);
#endif // ALLOW_SHADOW
)";
} else {
out += "gl_FragDepth = depth;\n";

View File

@ -7,7 +7,6 @@
#include <unordered_map>
#include <boost/functional/hash.hpp>
#include <boost/variant.hpp>
#include "core/core.h"
#include "core/frontend/scope_acquire_context.h"
#include "video_core/renderer_opengl/gl_shader_disk_cache.h"
#include "video_core/renderer_opengl/gl_shader_manager.h"
@ -325,8 +324,8 @@ using FragmentShaders = ShaderCache<PicaFSConfig, &GenerateFragmentShader, GL_FR
class ShaderProgramManager::Impl {
public:
explicit Impl(bool separable, bool is_amd)
: is_amd(is_amd), separable(separable), programmable_vertex_shaders(separable),
explicit Impl(bool separable)
: separable(separable), programmable_vertex_shaders(separable),
trivial_vertex_shader(separable), fixed_geometry_shaders(separable),
fragment_shaders(separable), disk_cache(separable) {
if (separable)
@ -359,7 +358,6 @@ public:
}
};
bool is_amd;
bool separable;
ShaderTuple current;
@ -375,9 +373,8 @@ public:
ShaderDiskCache disk_cache;
};
ShaderProgramManager::ShaderProgramManager(Frontend::EmuWindow& emu_window_, bool separable,
bool is_amd)
: impl(std::make_unique<Impl>(separable, is_amd)), emu_window{emu_window_} {}
ShaderProgramManager::ShaderProgramManager(Frontend::EmuWindow& emu_window_, bool separable)
: impl(std::make_unique<Impl>(separable)), emu_window{emu_window_} {}
ShaderProgramManager::~ShaderProgramManager() = default;
@ -439,15 +436,6 @@ void ShaderProgramManager::UseFragmentShader(const Pica::Regs& regs) {
void ShaderProgramManager::ApplyTo(OpenGLState& state) {
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_GEOMETRY_SHADER_BIT, impl->current.gs);
glUseProgramStages(impl->pipeline.handle, GL_FRAGMENT_SHADER_BIT, impl->current.fs);

View File

@ -99,7 +99,7 @@ static_assert(sizeof(VSUniformData) < 16384,
/// A class that manage different shader stages and configures them with given config data.
class ShaderProgramManager {
public:
ShaderProgramManager(Frontend::EmuWindow& emu_window_, bool separable, bool is_amd);
ShaderProgramManager(Frontend::EmuWindow& emu_window_, bool separable);
~ShaderProgramManager();
void LoadDiskCache(const std::atomic_bool& stop_loading,

View File

@ -7,7 +7,6 @@
#include "common/alignment.h"
#include "common/assert.h"
#include "common/microprofile.h"
#include "video_core/renderer_opengl/gl_state.h"
#include "video_core/renderer_opengl/gl_stream_buffer.h"
MICROPROFILE_DEFINE(OpenGL_StreamBuffer, "OpenGL", "Stream Buffer Orphaning",
@ -15,21 +14,12 @@ MICROPROFILE_DEFINE(OpenGL_StreamBuffer, "OpenGL", "Stream Buffer Orphaning",
namespace OpenGL {
OGLStreamBuffer::OGLStreamBuffer(GLenum target, GLsizeiptr size, bool array_buffer_for_amd,
bool prefer_coherent)
OGLStreamBuffer::OGLStreamBuffer(GLenum target, GLsizeiptr size, bool prefer_coherent)
: gl_target(target), buffer_size(size) {
gl_buffer.Create();
glBindBuffer(gl_target, gl_buffer.handle);
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) {
persistent = true;

View File

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