From 9e7a42d057383a51e322e31371a6a6faf1fc0861 Mon Sep 17 00:00:00 2001 From: kd-11 Date: Wed, 5 Jul 2017 01:16:59 +0300 Subject: [PATCH] rsx: Minor bug fixes - vk: Do not select first available format when choosing a swapchain format - gl/vk: Ignore rendering zero sized framebuffers/scissors - fp: Re-enable range clamp on fp16 registers; fix fx12 clamping [-2, 2] --- .../RSX/Common/FragmentProgramDecompiler.cpp | 23 ++++++----------- rpcs3/Emu/RSX/GL/GLGSRender.cpp | 21 +++++++++++++--- rpcs3/Emu/RSX/GL/GLGSRender.h | 2 ++ rpcs3/Emu/RSX/GL/GLRenderTargets.cpp | 10 ++++++-- rpcs3/Emu/RSX/VK/VKGSRender.cpp | 25 ++++++++++++++++++- rpcs3/Emu/RSX/VK/VKGSRender.h | 2 ++ rpcs3/Emu/RSX/VK/VKHelpers.h | 10 ++++++++ 7 files changed, 70 insertions(+), 23 deletions(-) diff --git a/rpcs3/Emu/RSX/Common/FragmentProgramDecompiler.cpp b/rpcs3/Emu/RSX/Common/FragmentProgramDecompiler.cpp index 88ad941c5d..794af06c73 100644 --- a/rpcs3/Emu/RSX/Common/FragmentProgramDecompiler.cpp +++ b/rpcs3/Emu/RSX/Common/FragmentProgramDecompiler.cpp @@ -37,13 +37,12 @@ void FragmentProgramDecompiler::SetDst(std::string code, bool append_mask) break; } - if (dst.saturate) - { - code = saturate(code); - } - else if (!dst.no_dest) + if (!dst.no_dest) { code = NoOverflow(code); + + if (dst.saturate) + code = saturate(code); } code += (append_mask ? "$m" : ""); @@ -64,13 +63,6 @@ void FragmentProgramDecompiler::SetDst(std::string code, bool append_mask) std::string dest = AddReg(dst.dest_reg, dst.fp16) + "$m"; - if (dst.exp_tex) - { - //TODO - //If exp_tex really sets _bx2 flag, we may need to perform extra modifications to the src - AddCode("//TODO: exp tex flag is set"); - } - AddCodeCond(Format(dest), code); //AddCode("$ifcond " + dest + code + (append_mask ? "$m;" : ";")); @@ -206,6 +198,7 @@ std::string FragmentProgramDecompiler::NoOverflow(const std::string& code) if (dst.exp_tex) { //If dst.exp_tex really is _bx2 postfix, we need to unpack dynamic range + AddCode("//exp tex flag is set"); return "((" + code + "- 0.5) * 2.)"; } @@ -214,11 +207,9 @@ std::string FragmentProgramDecompiler::NoOverflow(const std::string& code) case 0: break; case 1: - //Disabled: Causes blue output in some games such as persona V and soul calibur IV - //return "clamp(" + code + ", -65504., 65504.)"; - break; + return "clamp(" + code + ", -65504., 65504.)"; case 2: - return "clamp(" + code + ", -1., 1.)"; + return "clamp(" + code + ", -2., 2.)"; } return code; diff --git a/rpcs3/Emu/RSX/GL/GLGSRender.cpp b/rpcs3/Emu/RSX/GL/GLGSRender.cpp index c79172f94c..74494d5226 100644 --- a/rpcs3/Emu/RSX/GL/GLGSRender.cpp +++ b/rpcs3/Emu/RSX/GL/GLGSRender.cpp @@ -191,7 +191,7 @@ void GLGSRender::begin() init_buffers(); - if (!draw_fbo.check()) + if (!framebuffer_status_valid) return; std::chrono::time_point then = steady_clock::now(); @@ -322,7 +322,7 @@ namespace void GLGSRender::end() { - if (skip_frame || !draw_fbo || !draw_fbo.check()) + if (skip_frame || !framebuffer_status_valid) { rsx::thread::end(); return; @@ -523,13 +523,26 @@ void GLGSRender::end() void GLGSRender::set_viewport() { //NOTE: scale offset matrix already contains the viewport transformation - glViewport(0, 0, rsx::method_registers.surface_clip_width(), rsx::method_registers.surface_clip_height()); + const auto clip_width = rsx::method_registers.surface_clip_width(); + const auto clip_height = rsx::method_registers.surface_clip_height(); + glViewport(0, 0, clip_width, clip_height); u16 scissor_x = rsx::method_registers.scissor_origin_x(); u16 scissor_w = rsx::method_registers.scissor_width(); u16 scissor_y = rsx::method_registers.scissor_origin_y(); u16 scissor_h = rsx::method_registers.scissor_height(); + //Do not bother drawing anything if output is zero sized + //TODO: Clip scissor region + if (scissor_x >= clip_width || scissor_y >= clip_height || scissor_w == 0 || scissor_h == 0) + { + if (!g_cfg.video.strict_rendering_mode) + { + framebuffer_status_valid = false; + return; + } + } + //NOTE: window origin does not affect scissor region (probably only affects viewport matrix; already applied) //See LIMBO [NPUB-30373] which uses shader window origin = top __glcheck glScissor(scissor_x, scissor_y, scissor_w, scissor_h); @@ -726,7 +739,7 @@ void GLGSRender::on_exit() void GLGSRender::clear_surface(u32 arg) { - if (skip_frame) return; + if (skip_frame || !framebuffer_status_valid) return; if (rsx::method_registers.surface_color_target() == rsx::surface_target::none) return; if ((arg & 0xf3) == 0) return; diff --git a/rpcs3/Emu/RSX/GL/GLGSRender.h b/rpcs3/Emu/RSX/GL/GLGSRender.h index d324824ddb..4e8e7f6472 100644 --- a/rpcs3/Emu/RSX/GL/GLGSRender.h +++ b/rpcs3/Emu/RSX/GL/GLGSRender.h @@ -70,6 +70,8 @@ private: std::mutex queue_guard; std::list work_queue; + bool framebuffer_status_valid = false; + rsx::gcm_framebuffer_info surface_info[rsx::limits::color_buffers_count]; rsx::gcm_framebuffer_info depth_surface_info; diff --git a/rpcs3/Emu/RSX/GL/GLRenderTargets.cpp b/rpcs3/Emu/RSX/GL/GLRenderTargets.cpp index e83e160761..466024826a 100644 --- a/rpcs3/Emu/RSX/GL/GLRenderTargets.cpp +++ b/rpcs3/Emu/RSX/GL/GLRenderTargets.cpp @@ -165,6 +165,12 @@ void GLGSRender::init_buffers(bool skip_reading) const u16 clip_horizontal = rsx::method_registers.surface_clip_width(); const u16 clip_vertical = rsx::method_registers.surface_clip_height(); + if (clip_horizontal == 0 || clip_vertical == 0) + { + LOG_ERROR(RSX, "Invalid framebuffer setup, w=%d, h=%d", clip_horizontal, clip_vertical); + framebuffer_status_valid = false; + } + const auto pitchs = get_pitchs(); const auto surface_format = rsx::method_registers.surface_color(); const auto depth_format = rsx::method_registers.surface_depth_fmt(); @@ -235,8 +241,8 @@ void GLGSRender::init_buffers(bool skip_reading) else depth_surface_info = {}; - if (!draw_fbo.check()) - return; + framebuffer_status_valid = draw_fbo.check(); + if (!framebuffer_status_valid) return; draw_fbo.bind(); set_viewport(); diff --git a/rpcs3/Emu/RSX/VK/VKGSRender.cpp b/rpcs3/Emu/RSX/VK/VKGSRender.cpp index 56d162f282..2a652a2954 100644 --- a/rpcs3/Emu/RSX/VK/VKGSRender.cpp +++ b/rpcs3/Emu/RSX/VK/VKGSRender.cpp @@ -838,6 +838,9 @@ void VKGSRender::begin() init_buffers(); + if (!framebuffer_status_valid) + return; + float actual_line_width = rsx::method_registers.line_width(); vkCmdSetLineWidth(*m_current_command_buffer, actual_line_width); @@ -898,7 +901,7 @@ void VKGSRender::close_render_pass() void VKGSRender::end() { - if (skip_frame) + if (skip_frame || !framebuffer_status_valid) { rsx::thread::end(); return; @@ -1200,6 +1203,15 @@ void VKGSRender::set_viewport() scissor.offset.y = scissor_y; vkCmdSetScissor(*m_current_command_buffer, 0, 1, &scissor); + + if (scissor_x >= viewport.width || scissor_y >= viewport.height || scissor_w == 0 || scissor_h == 0) + { + if (!g_cfg.video.strict_rendering_mode) + { + framebuffer_status_valid = false; + return; + } + } } void VKGSRender::on_init_thread() @@ -1229,6 +1241,9 @@ void VKGSRender::clear_surface(u32 mask) if (m_current_present_image == 0xFFFF) return; init_buffers(); + + if (!framebuffer_status_valid) return; + copy_render_targets_to_dma_location(); float depth_clear = 1.f; @@ -1834,6 +1849,14 @@ void VKGSRender::prepare_rtts() u32 clip_x = rsx::method_registers.surface_clip_origin_x(); u32 clip_y = rsx::method_registers.surface_clip_origin_y(); + if (clip_width == 0 || clip_height == 0) + { + LOG_ERROR(RSX, "Invalid framebuffer setup, w=%d, h=%d", clip_width, clip_height); + framebuffer_status_valid = false; + } + + framebuffer_status_valid = true; + auto surface_addresses = get_color_surface_addresses(); auto zeta_address = get_zeta_surface_address(); diff --git a/rpcs3/Emu/RSX/VK/VKGSRender.h b/rpcs3/Emu/RSX/VK/VKGSRender.h index 3f9d490110..2a068e517e 100644 --- a/rpcs3/Emu/RSX/VK/VKGSRender.h +++ b/rpcs3/Emu/RSX/VK/VKGSRender.h @@ -167,6 +167,8 @@ private: u32 m_used_descriptors = 0; u8 m_draw_buffers_count = 0; + bool framebuffer_status_valid = false; + rsx::gcm_framebuffer_info m_surface_info[rsx::limits::color_buffers_count]; rsx::gcm_framebuffer_info m_depth_surface_info; diff --git a/rpcs3/Emu/RSX/VK/VKHelpers.h b/rpcs3/Emu/RSX/VK/VKHelpers.h index 311c09aeec..d2c02b6fe3 100644 --- a/rpcs3/Emu/RSX/VK/VKHelpers.h +++ b/rpcs3/Emu/RSX/VK/VKHelpers.h @@ -1293,6 +1293,16 @@ namespace vk { if (!formatCount) fmt::throw_exception("Format count is zero!" HERE); format = surfFormats[0].format; + + //Prefer BGRA8_UNORM to avoid sRGB compression (RADV) + for (auto& surface_format: surfFormats) + { + if (surface_format.format == VK_FORMAT_B8G8R8A8_UNORM) + { + format = VK_FORMAT_B8G8R8A8_UNORM; + break; + } + } } color_space = surfFormats[0].colorSpace;