From 7072489a6e95a62bcb6131f641ffd51e9bb85a41 Mon Sep 17 00:00:00 2001 From: kd-11 Date: Fri, 8 Nov 2019 20:19:54 +0300 Subject: [PATCH] rsx: Implement point sprite coordinate generation - When the point sprite flag is set, overrides the input similar to the 2D mask. The returned X and Y values are always the gl_PointCoord values for the fragment. - Stacks with the 2D mask to override the z and w coordinates. --- .../RSX/Common/FragmentProgramDecompiler.cpp | 20 +++++++++++-- rpcs3/Emu/RSX/RSXFragmentProgram.h | 8 ++++- rpcs3/Emu/RSX/RSXThread.cpp | 7 +++++ rpcs3/Emu/RSX/rsx_decode.h | 29 +++++++++++++++++++ rpcs3/Emu/RSX/rsx_methods.h | 14 +++++++-- 5 files changed, 72 insertions(+), 6 deletions(-) diff --git a/rpcs3/Emu/RSX/Common/FragmentProgramDecompiler.cpp b/rpcs3/Emu/RSX/Common/FragmentProgramDecompiler.cpp index 4fa77e098c..a63270a6b3 100644 --- a/rpcs3/Emu/RSX/Common/FragmentProgramDecompiler.cpp +++ b/rpcs3/Emu/RSX/Common/FragmentProgramDecompiler.cpp @@ -579,10 +579,24 @@ template std::string FragmentProgramDecompiler::GetSRC(T src) case 0xD: { // TEX0 - TEX9 - // Texcoord mask seems to reset the last 2 arguments to 0 and 1 if set - if (m_prog.texcoord_is_2d(dst.src_attr_reg_num - 4)) + // Texcoord 2d mask seems to reset the last 2 arguments to 0 and w if set + const u8 texcoord = u8(dst.src_attr_reg_num) - 4; + if (m_prog.texcoord_is_point_coord(texcoord)) { - ret += getFloatTypeName(4) + "(" + reg_var + ".x, " + reg_var + ".y, 0., in_w)"; + // Point sprite coord generation. Stacks with the 2D override mask. + if (m_prog.texcoord_is_2d(texcoord)) + { + ret += getFloatTypeName(4) + "(gl_PointCoord, 0., in_w)"; + properties.has_w_access = true; + } + else + { + ret += getFloatTypeName(4) + "(gl_PointCoord, 1., 0.)"; + } + } + else if (m_prog.texcoord_is_2d(texcoord)) + { + ret += getFloatTypeName(4) + "(" + reg_var + ".xy, 0., in_w)"; properties.has_w_access = true; } else diff --git a/rpcs3/Emu/RSX/RSXFragmentProgram.h b/rpcs3/Emu/RSX/RSXFragmentProgram.h index ff1ac3260f..9911c1a4ce 100644 --- a/rpcs3/Emu/RSX/RSXFragmentProgram.h +++ b/rpcs3/Emu/RSX/RSXFragmentProgram.h @@ -251,7 +251,13 @@ struct RSXFragmentProgram bool texcoord_is_2d(u8 index) const { - return !!(texcoord_control_mask & (1u << index)); + return bool(texcoord_control_mask & (1u << index)); + } + + bool texcoord_is_point_coord(u8 index) const + { + index += 16; + return bool(texcoord_control_mask & (1u << index)); } RSXFragmentProgram() diff --git a/rpcs3/Emu/RSX/RSXThread.cpp b/rpcs3/Emu/RSX/RSXThread.cpp index 1fae028c0f..87cc313bfe 100644 --- a/rpcs3/Emu/RSX/RSXThread.cpp +++ b/rpcs3/Emu/RSX/RSXThread.cpp @@ -1698,6 +1698,13 @@ namespace rsx result.redirected_textures = 0; result.shadow_textures = 0; + if (method_registers.current_draw_clause.primitive == primitive_type::points && + method_registers.point_sprite_enabled()) + { + // Set high word of the control mask to store point sprite control + result.texcoord_control_mask |= u32(method_registers.point_sprite_control_mask()) << 16; + } + const auto resolution_scale = rsx::get_resolution_scale(); for (u32 i = 0; i < rsx::limits::fragment_textures_count; ++i) diff --git a/rpcs3/Emu/RSX/rsx_decode.h b/rpcs3/Emu/RSX/rsx_decode.h index c733529e97..d3e740befe 100644 --- a/rpcs3/Emu/RSX/rsx_decode.h +++ b/rpcs3/Emu/RSX/rsx_decode.h @@ -3256,6 +3256,35 @@ struct registers_decoder } }; +template<> +struct registers_decoder +{ + struct decoded_type + { + private: + u32 value; + + public: + decoded_type(u32 value) : value(value) {} + + bool enabled() const + { + return bf_decoder<0, 1, bool>(value); + } + + u16 texcoord_mask() const + { + return bf_decoder<8, 10>(value); + } + }; + + static std::string dump(decoded_type &&decoded_values) + { + return "Point sprite: enabled = " + print_boolean(decoded_values.enabled()) + + "override mask = " + fmt::format("0x%x", decoded_values.texcoord_mask()); + } +}; + template<> struct registers_decoder { diff --git a/rpcs3/Emu/RSX/rsx_methods.h b/rpcs3/Emu/RSX/rsx_methods.h index b1ad10ea0e..6d7e51c124 100644 --- a/rpcs3/Emu/RSX/rsx_methods.h +++ b/rpcs3/Emu/RSX/rsx_methods.h @@ -1102,6 +1102,11 @@ namespace rsx return decode().point_size(); } + bool point_sprite_enabled() const + { + return decode().enabled(); + } + u8 alpha_ref() const { return decode().alpha_ref(); @@ -1677,10 +1682,10 @@ namespace rsx return decode().depth_float(); } - u32 texcoord_control_mask() + u16 texcoord_control_mask() const { // Only 10 texture coords exist [0-9] - u32 control_mask = 0; + u16 control_mask = 0; for (u8 index = 0; index < 10; ++index) { control_mask |= ((registers[NV4097_SET_TEX_COORD_CONTROL + index] & 1) << index); @@ -1688,6 +1693,11 @@ namespace rsx return control_mask; } + + u16 point_sprite_control_mask() const + { + return decode().texcoord_mask(); + } }; extern rsx_state method_registers;