Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

rsx: Fix support for gamma pack/unpack instructions #10406

Merged
merged 2 commits into from Jun 5, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 2 additions & 0 deletions rpcs3/Emu/RSX/GL/GLFragmentProgram.cpp
Expand Up @@ -207,6 +207,8 @@ void GLFragmentDecompilerThread::insertGlobalFunctions(std::stringstream &OS)
m_shader_props.require_texture_ops = properties.has_tex_op;
m_shader_props.require_shadow_ops = properties.shadow_sampler_mask != 0;
m_shader_props.require_texture_expand = properties.has_exp_tex_op;
m_shader_props.require_srgb_to_linear = properties.has_upg;
m_shader_props.require_linear_to_srgb = properties.has_pkg;
m_shader_props.emulate_coverage_tests = true; // g_cfg.video.antialiasing_level == msaa_level::none;
m_shader_props.emulate_shadow_compare = device_props.emulate_depth_compare;
m_shader_props.low_precision_tests = ::gl::get_driver_caps().vendor_NVIDIA;
Expand Down
2 changes: 2 additions & 0 deletions rpcs3/Emu/RSX/GL/GLGSRender.cpp
Expand Up @@ -359,6 +359,8 @@ void GLGSRender::on_exit()
gl::g_typeless_transfer_buffer.remove();
}

gl::debug::g_vis_texture.reset(); // TODO

gl::destroy_pipe_compiler();

m_prog_buffer.clear();
Expand Down
40 changes: 40 additions & 0 deletions rpcs3/Emu/RSX/GL/GLPresent.cpp
Expand Up @@ -4,6 +4,22 @@

LOG_CHANNEL(screenshot_log, "SCREENSHOT");

namespace gl
{
namespace debug
{
std::unique_ptr<texture> g_vis_texture;

void set_vis_texture(texture* visual)
{
const auto target = static_cast<GLenum>(visual->get_target());
const auto ifmt = static_cast<GLenum>(visual->get_internal_format());
g_vis_texture.reset(new texture(target, visual->width(), visual->height(), 1, 1, ifmt, visual->format_class()));
glCopyImageSubData(visual->id(), target, 0, 0, 0, 0, g_vis_texture->id(), target, 0, 0, 0, 0, visual->width(), visual->height(), 1);
}
}
}

gl::texture* GLGSRender::get_present_source(gl::present_surface_info* info, const rsx::avconf& avconfig)
{
gl::texture* image = nullptr;
Expand Down Expand Up @@ -334,6 +350,30 @@ void GLGSRender::flip(const rsx::display_flip_info_t& info)
m_text_printer.print_text(4, 180, width, height, fmt::format("Texture uploads: %15u (%u from CPU - %02u%%)", num_texture_upload, num_texture_upload_miss, texture_upload_miss_ratio));
}

if (gl::debug::g_vis_texture)
{
// Optionally renders a single debug texture to framebuffer.
// Only programmatic access provided at the moment.
// TODO: Migrate to use overlay system. (kd-11)
gl::fbo m_vis_buffer;
m_vis_buffer.create();
m_vis_buffer.bind();
m_vis_buffer.color = gl::debug::g_vis_texture->id();
m_vis_buffer.read_buffer(m_vis_buffer.color);
m_vis_buffer.draw_buffer(m_vis_buffer.color);

const u32 vis_width = 320;
const u32 vis_height = 240;
areai display_view = areai(aspect_ratio).flipped_vertical();
display_view.x1 = display_view.x2 - vis_width;
display_view.y1 = vis_height;

// Blit
const auto src_region = areau{ 0u, 0u, gl::debug::g_vis_texture->width(), gl::debug::g_vis_texture->height() };
m_vis_buffer.blit(gl::screen, static_cast<areai>(src_region), display_view, gl::buffers::color, gl::filter::linear);
m_vis_buffer.remove();
}

m_frame->flip(m_context);
rsx::thread::flip(info);

Expand Down
5 changes: 5 additions & 0 deletions rpcs3/Emu/RSX/GL/GLTexture.cpp
Expand Up @@ -10,6 +10,11 @@

namespace gl
{
namespace debug
{
extern void set_vis_texture(texture*);
}

buffer g_typeless_transfer_buffer;

GLenum get_target(rsx::texture_dimension_extended type)
Expand Down
5 changes: 5 additions & 0 deletions rpcs3/Emu/RSX/GL/GLTexture.h
Expand Up @@ -119,5 +119,10 @@ namespace gl
void apply_defaults(GLenum default_filter = GL_NEAREST);
};

namespace debug
{
extern std::unique_ptr<texture> g_vis_texture;
}

extern buffer g_typeless_transfer_buffer;
}
28 changes: 27 additions & 1 deletion rpcs3/Emu/RSX/Program/FragmentProgramDecompiler.cpp
Expand Up @@ -830,6 +830,26 @@ std::string FragmentProgramDecompiler::BuildCode()
"#define _builtin_rsq(x) (1. / _builtin_sqrt(x))\n"
"#define _builtin_div(x, y) (x / y)\n\n";

if (properties.has_pkg)
{
OS <<
"vec4 _builtin_pkg(const in vec4 value)\n"
"{\n"
" vec4 convert = linear_to_srgb(value);\n"
" return uintBitsToFloat(packUnorm4x8(convert)).xxxx;\n"
"}\n\n";
}

if (properties.has_upg)
{
OS <<
"vec4 _builtin_upg(const in float value)\n"
"{\n"
" vec4 raw = unpackUnorm4x8(floatBitsToUint(value));\n"
" return srgb_to_linear(raw);\n"
"}\n\n";
}

if (properties.has_divsq)
{
// Define RSX-compliant DIVSQ
Expand Down Expand Up @@ -954,6 +974,9 @@ bool FragmentProgramDecompiler::handle_sct_scb(u32 opcode)
case RSX_FP_OPCODE_PK16: SetDst(getFloatTypeName(4) + "(uintBitsToFloat(packUnorm2x16($0.xy)))"); return true;
case RSX_FP_OPCODE_PKG:
// Should be similar to PKB but with gamma correction, see description of PK4UBG in khronos page
properties.has_pkg = true;
SetDst("_builtin_pkg($0)");
return true;
case RSX_FP_OPCODE_PKB: SetDst(getFloatTypeName(4) + "(uintBitsToFloat(packUnorm4x8($0)))"); return true;
case RSX_FP_OPCODE_SIN: SetDst("sin($0.xxxx)"); return true;
}
Expand Down Expand Up @@ -1120,7 +1143,10 @@ bool FragmentProgramDecompiler::handle_tex_srb(u32 opcode)
case RSX_FP_OPCODE_UP4: SetDst("unpackSnorm4x8(floatBitsToUint($0.x))"); return true;
case RSX_FP_OPCODE_UP16: SetDst("unpackUnorm2x16(floatBitsToUint($0.x)).xyxy"); return true;
case RSX_FP_OPCODE_UPG:
// Same as UPB with gamma correction
// Same as UPB with gamma correction
properties.has_upg = true;
SetDst("_builtin_upg($0.x)");
return true;
case RSX_FP_OPCODE_UPB: SetDst("(unpackUnorm4x8(floatBitsToUint($0.x)))"); return true;
}
return false;
Expand Down
2 changes: 2 additions & 0 deletions rpcs3/Emu/RSX/Program/FragmentProgramDecompiler.h
Expand Up @@ -285,6 +285,8 @@ class FragmentProgramDecompiler
bool has_clamp = false;
bool has_w_access = false;
bool has_exp_tex_op = false;
bool has_pkg = false;
bool has_upg = false;
}
properties;

Expand Down
19 changes: 12 additions & 7 deletions rpcs3/Emu/RSX/Program/GLSLCommon.cpp
Expand Up @@ -673,7 +673,7 @@ namespace glsl
"}\n\n";
}

if (!props.fp32_outputs)
if (!props.fp32_outputs || props.require_linear_to_srgb)
{
OS <<
"vec4 linear_to_srgb(const in vec4 cl)\n"
Expand All @@ -685,6 +685,17 @@ namespace glsl
"}\n\n";
}

if (props.require_texture_ops || props.require_srgb_to_linear)
{
OS <<
"vec4 srgb_to_linear(const in vec4 cs)\n"
"{\n"
" vec4 a = cs / 12.92;\n"
" vec4 b = pow((cs + 0.055) / 1.055, vec4(2.4));\n"
" return _select(a, b, greaterThan(cs, vec4(0.04045)));\n"
"}\n\n";
}

if (props.require_depth_conversion)
{
ensure(props.require_texture_ops);
Expand Down Expand Up @@ -763,12 +774,6 @@ namespace glsl
" return mix(direct, indexed, choice);\n"
"}\n\n"
#endif
"vec4 srgb_to_linear(const in vec4 cs)\n"
"{\n"
" vec4 a = cs / 12.92;\n"
" vec4 b = pow((cs + 0.055) / 1.055, vec4(2.4));\n"
" return _select(a, b, greaterThan(cs, vec4(0.04045)));\n"
"}\n\n"

//TODO: Move all the texture read control operations here
"vec4 process_texel(in vec4 rgba, const in uint control_bits)\n"
Expand Down
2 changes: 2 additions & 0 deletions rpcs3/Emu/RSX/Program/GLSLTypes.h
Expand Up @@ -28,6 +28,8 @@ namespace glsl
bool require_texture_ops;
bool require_shadow_ops;
bool require_texture_expand;
bool require_srgb_to_linear;
bool require_linear_to_srgb;
bool emulate_coverage_tests;
bool emulate_shadow_compare;
bool emulate_zclip_transform;
Expand Down
2 changes: 2 additions & 0 deletions rpcs3/Emu/RSX/VK/VKFragmentProgram.cpp
Expand Up @@ -244,6 +244,8 @@ void VKFragmentDecompilerThread::insertGlobalFunctions(std::stringstream &OS)
m_shader_props.require_texture_ops = properties.has_tex_op;
m_shader_props.require_shadow_ops = properties.shadow_sampler_mask != 0;
m_shader_props.require_texture_expand = properties.has_exp_tex_op;
m_shader_props.require_srgb_to_linear = properties.has_upg;
m_shader_props.require_linear_to_srgb = properties.has_pkg;
m_shader_props.emulate_coverage_tests = g_cfg.video.antialiasing_level == msaa_level::none;
m_shader_props.emulate_shadow_compare = device_props.emulate_depth_compare;
m_shader_props.low_precision_tests = vk::get_driver_vendor() == vk::driver_vendor::NVIDIA;
Expand Down