diff --git a/rpcs3/Emu/RSX/rsx_decode.h b/rpcs3/Emu/RSX/rsx_decode.h index 4b96fc2637..bc96cba982 100644 --- a/rpcs3/Emu/RSX/rsx_decode.h +++ b/rpcs3/Emu/RSX/rsx_decode.h @@ -4064,21 +4064,23 @@ struct registers_decoder public: decoded_type(u32 raw_value) { m_data.raw_value = raw_value; } - u16 x() const + // x and y given as 16 bit fixed point + + f32 x() const { - return m_data.x; + return m_data.x / 16.f; } - u16 y() const + f32 y() const { - return m_data.y; + return m_data.y / 16.f; } }; static std::string dump(decoded_type &&decoded_values) { - return "NV3089: in x = " + std::to_string(decoded_values.x() / 16.f) + - " y = " + std::to_string(decoded_values.y() / 16.f); + return "NV3089: in x = " + std::to_string(decoded_values.x()) + + " y = " + std::to_string(decoded_values.y()); } }; diff --git a/rpcs3/Emu/RSX/rsx_methods.cpp b/rpcs3/Emu/RSX/rsx_methods.cpp index 197e474d7b..a389fbb969 100644 --- a/rpcs3/Emu/RSX/rsx_methods.cpp +++ b/rpcs3/Emu/RSX/rsx_methods.cpp @@ -576,8 +576,8 @@ namespace rsx const blit_engine::transfer_interpolator in_inter = method_registers.blit_engine_input_inter(); const rsx::blit_engine::transfer_source_format src_color_format = method_registers.blit_engine_src_color_format(); - const f32 in_x = method_registers.blit_engine_in_x(); - const f32 in_y = method_registers.blit_engine_in_y(); + const f32 in_x = std::ceil(method_registers.blit_engine_in_x()); + const f32 in_y = std::ceil(method_registers.blit_engine_in_y()); //Clipping //Validate that clipping rect will fit onto both src and dst regions @@ -855,7 +855,9 @@ namespace rsx pixels_src = temp2.get(); } - u8 sw_width_log2 = method_registers.nv309e_sw_width_log2(); + // It looks like rsx may ignore the requested swizzle size and just always + // round up to nearest power of 2 + /*u8 sw_width_log2 = method_registers.nv309e_sw_width_log2(); u8 sw_height_log2 = method_registers.nv309e_sw_height_log2(); // 0 indicates height of 1 pixel @@ -864,31 +866,31 @@ namespace rsx // swizzle based on destination size u16 sw_width = 1 << sw_width_log2; u16 sw_height = 1 << sw_height_log2; + */ + + u32 sw_width = next_pow2(out_w); + u32 sw_height = next_pow2(out_h); temp2.reset(new u8[out_bpp * sw_width * sw_height]); u8* linear_pixels = pixels_src; u8* swizzled_pixels = temp2.get(); - // restrict output to size of swizzle - const u16 sw_in_w = std::min(out_w, sw_width); - const u16 sw_in_h = std::min(out_h, sw_height); - - // Check and pad texture out if we are given non square texture for swizzle to be correct - if (sw_width != sw_in_w || sw_height != sw_in_h) + // Check and pad texture out if we are given non power of 2 output + if (sw_width != out_w || sw_height != out_h) { sw_temp.reset(new u8[out_bpp * sw_width * sw_height]); switch (out_bpp) { case 1: - pad_texture(linear_pixels, sw_temp.get(), sw_in_w, sw_in_h, sw_width, sw_height); + pad_texture(linear_pixels, sw_temp.get(), out_w, out_h, sw_width, sw_height); break; case 2: - pad_texture(linear_pixels, sw_temp.get(), sw_in_w, sw_in_h, sw_width, sw_height); + pad_texture(linear_pixels, sw_temp.get(), out_w, out_h, sw_width, sw_height); break; case 4: - pad_texture(linear_pixels, sw_temp.get(), sw_in_w, sw_in_h, sw_width, sw_height); + pad_texture(linear_pixels, sw_temp.get(), out_w, out_h, sw_width, sw_height); break; } diff --git a/rpcs3/Emu/RSX/rsx_utils.h b/rpcs3/Emu/RSX/rsx_utils.h index 408a803801..1a09e211ba 100644 --- a/rpcs3/Emu/RSX/rsx_utils.h +++ b/rpcs3/Emu/RSX/rsx_utils.h @@ -67,6 +67,13 @@ namespace rsx return value <= 1 ? 0 : ::cntlz32((value - 1) << 1, true) ^ 31; } + static inline u32 next_pow2(u32 x) + { + if (x <= 2) return x; + + return (1ULL << 32) >> ::cntlz32(x - 1, true); + } + /* Note: What the ps3 calls swizzling in this case is actually z-ordering / morton ordering of pixels * - Input can be swizzled or linear, bool flag handles conversion to and from * - It will handle any width and height that are a power of 2, square or non square