Skip to content

Commit

Permalink
rsx image_in: Implement backwards reading
Browse files Browse the repository at this point in the history
  • Loading branch information
elad335 committed Dec 2, 2018
1 parent a02c5d7 commit 914c4c8
Show file tree
Hide file tree
Showing 4 changed files with 106 additions and 25 deletions.
36 changes: 31 additions & 5 deletions rpcs3/Emu/RSX/rsx_decode.h
@@ -1,4 +1,4 @@
#pragma once
#pragma once
#include "Utilities/types.h"
#include "Utilities/BitField.h"
#include "Utilities/StrFmt.h"
Expand Down Expand Up @@ -2243,9 +2243,22 @@ struct registers_decoder<NV3089_DS_DX>
public:
decoded_type(u32 raw_value) { m_data.raw_value = raw_value; }

u32 ds_dx() const
// Convert signed fixed point 32-bit format
f32 ds_dx() const
{
return m_data.raw_value;
const u32 val = m_data.raw_value;

if ((val & ~(1<<31)) == 0)
{
return 0;
}

if ((s32)val < 0)
{
return 1. / (((val & ~(1<<31)) / 1048576.f) - 2048.f);
}

return 1048576.f / val;
}
};

Expand All @@ -2268,9 +2281,22 @@ struct registers_decoder<NV3089_DT_DY>
public:
decoded_type(u32 raw_value) { m_data.raw_value = raw_value; }

u32 dt_dy() const
// Convert signed fixed point 32-bit format
f32 dt_dy() const
{
return m_data.raw_value;
const u32 val = m_data.raw_value;

if ((val & ~(1<<31)) == 0)
{
return 0;
}

if ((s32)val < 0)
{
return 1. / (((val & ~(1<<31)) / 1048576.f) - 2048.f);
}

return 1048576.f / val;
}
};

Expand Down
66 changes: 48 additions & 18 deletions rpcs3/Emu/RSX/rsx_methods.cpp
Expand Up @@ -803,15 +803,14 @@ 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 = std::ceil(method_registers.blit_engine_in_x());
const f32 in_y = std::ceil(method_registers.blit_engine_in_y());
f32 in_x = std::ceil(method_registers.blit_engine_in_x());
f32 in_y = std::ceil(method_registers.blit_engine_in_y());

//Clipping
//Validate that clipping rect will fit onto both src and dst regions
const u16 clip_w = std::min(method_registers.blit_engine_clip_width(), out_w);
const u16 clip_h = std::min(method_registers.blit_engine_clip_height(), out_h);

// Check both clip dimensions and dst dimensions
if (clip_w == 0 || clip_h == 0)
{
LOG_WARNING(RSX, "NV3089_IMAGE_IN: Operation NOPed out due to empty regions");
Expand Down Expand Up @@ -908,15 +907,15 @@ namespace rsx
fmt::throw_exception("NV3089_IMAGE_IN_SIZE: unknown src_color_format (%d)" HERE, (u8)src_color_format);
}

f32 scale_x = 1048576.f / method_registers.blit_engine_ds_dx();
f32 scale_y = 1048576.f / method_registers.blit_engine_dt_dy();
f32 scale_x = method_registers.blit_engine_ds_dx();
f32 scale_y = method_registers.blit_engine_dt_dy();

u32 convert_w = (u32)(scale_x * in_w);
u32 convert_h = (u32)(scale_y * in_h);
u32 convert_w = (u32)(std::abs(scale_x) * in_w);
u32 convert_h = (u32)(std::abs(scale_y) * in_h);

if (convert_w == 0 || convert_h == 0)
{
LOG_ERROR(RSX, "NV3089_IMAGE_IN: Invalid dimensions or scaling factor. Request ignored (ds_dx=%d, dt_dy=%d)",
LOG_ERROR(RSX, "NV3089_IMAGE_IN: Invalid dimensions or scaling factor. Request ignored (ds_dx=%f, dt_dy=%f)",
method_registers.blit_engine_ds_dx(), method_registers.blit_engine_dt_dy());
return;
}
Expand Down Expand Up @@ -960,7 +959,7 @@ namespace rsx
dst_info.max_tile_h = static_cast<u16>((dst_region.tile->size - dst_region.base) / out_pitch);
}

if (!g_cfg.video.force_cpu_blit_processing && (dst_dma == CELL_GCM_CONTEXT_DMA_MEMORY_FRAME_BUFFER || src_dma == CELL_GCM_CONTEXT_DMA_MEMORY_FRAME_BUFFER))
if (!g_cfg.video.force_cpu_blit_processing && (dst_dma == CELL_GCM_CONTEXT_DMA_MEMORY_FRAME_BUFFER || src_dma == CELL_GCM_CONTEXT_DMA_MEMORY_FRAME_BUFFER) && scale_x > 0 && scale_y > 0)
{
//For now, only use this for actual scaled images, there are use cases that should not go through 3d engine, e.g program ucode transfer
//TODO: Figure out more instances where we can use this without problems
Expand Down Expand Up @@ -996,7 +995,38 @@ namespace rsx
return;
}

std::unique_ptr<u8[]> temp1, temp2, sw_temp;
std::unique_ptr<u8[]> temp1, temp2, temp3, sw_temp;

if (scale_y < 0 || scale_x < 0)
{
temp1.reset(new u8[in_pitch * (in_h - 1) + (in_bpp * in_w)]);

const s32 stride_y = (scale_y < 0 ? -1 : 1) * in_pitch;

for (u32 y = 0; y < in_h; ++y)
{
u8 *dst = temp1.get() + (in_pitch * y);
u8 *src = pixels_src + (y * stride_y);

if (scale_x < 0)
{
if (in_bpp == 2)
{
rsx::memcpy_r<2>(dst, src, in_w);
}
else
{
rsx::memcpy_r<4>(dst, src, in_w);
}
}
else
{
std::memcpy(dst, src, in_bpp * in_w);
}
}

pixels_src = temp1.get();
}

const AVPixelFormat in_format = (src_color_format == rsx::blit_engine::transfer_source_format::r5g6b5) ? AV_PIX_FMT_RGB565BE : AV_PIX_FMT_ARGB;
const AVPixelFormat out_format = (dst_color_format == rsx::blit_engine::transfer_destination_format::r5g6b5) ? AV_PIX_FMT_RGB565BE : AV_PIX_FMT_ARGB;
Expand All @@ -1007,7 +1037,7 @@ namespace rsx
clip_x > 0 || clip_y > 0 ||
convert_w != out_w || convert_h != out_h;

const bool need_convert = out_format != in_format || scale_x != 1.0 || scale_y != 1.0;
const bool need_convert = out_format != in_format || std::abs(scale_x) != 1.0 || std::abs(scale_y) != 1.0;

if (method_registers.blit_engine_context_surface() != blit_engine::context_surface::swizzle2d)
{
Expand All @@ -1017,10 +1047,10 @@ namespace rsx
{
if (need_convert)
{
convert_scale_image(temp1, out_format, convert_w, convert_h, out_pitch,
convert_scale_image(temp2, out_format, convert_w, convert_h, out_pitch,
pixels_src, in_format, in_w, in_h, in_pitch, slice_h, in_inter == blit_engine::transfer_interpolator::foh);

clip_image(pixels_dst, temp1.get(), clip_x, clip_y, clip_w, clip_h, out_bpp, out_pitch, out_pitch);
clip_image(pixels_dst, temp2.get(), clip_x, clip_y, clip_w, clip_h, out_bpp, out_pitch, out_pitch);
}
else
{
Expand Down Expand Up @@ -1059,23 +1089,23 @@ namespace rsx
{
if (need_convert)
{
convert_scale_image(temp1, out_format, convert_w, convert_h, out_pitch,
convert_scale_image(temp2, out_format, convert_w, convert_h, out_pitch,
pixels_src, in_format, in_w, in_h, in_pitch, slice_h, in_inter == blit_engine::transfer_interpolator::foh);

clip_image(temp2, temp1.get(), clip_x, clip_y, clip_w, clip_h, out_bpp, out_pitch, out_pitch);
clip_image(temp3, temp2.get(), clip_x, clip_y, clip_w, clip_h, out_bpp, out_pitch, out_pitch);
}
else
{
clip_image(temp2, pixels_src, clip_x, clip_y, clip_w, clip_h, out_bpp, in_pitch, out_pitch);
clip_image(temp3, pixels_src, clip_x, clip_y, clip_w, clip_h, out_bpp, in_pitch, out_pitch);
}
}
else
{
convert_scale_image(temp2, out_format, out_w, out_h, out_pitch,
convert_scale_image(temp3, out_format, out_w, out_h, out_pitch,
pixels_src, in_format, in_w, in_h, in_pitch, clip_h, in_inter == blit_engine::transfer_interpolator::foh);
}

pixels_src = temp2.get();
pixels_src = temp3.get();
}

// It looks like rsx may ignore the requested swizzle size and just always
Expand Down
4 changes: 2 additions & 2 deletions rpcs3/Emu/RSX/rsx_methods.h
Expand Up @@ -1469,12 +1469,12 @@ namespace rsx
return decode<NV309E_SET_FORMAT>().format();
}

u32 blit_engine_ds_dx() const
f32 blit_engine_ds_dx() const
{
return decode<NV3089_DS_DX>().ds_dx();
}

u32 blit_engine_dt_dy() const
f32 blit_engine_dt_dy() const
{
return decode<NV3089_DT_DY>().dt_dy();
}
Expand Down
25 changes: 25 additions & 0 deletions rpcs3/Emu/RSX/rsx_utils.h
Expand Up @@ -161,6 +161,31 @@ namespace rsx
return static_cast<u32>((1ULL << 32) >> utils::cntlz32(x - 1, true));
}

// Copy memory in inverse direction from source
// Used to rscale negatively x axis while transfering image data
template <size_t pixel_sz = 1>
static void memcpy_r(void* dst, void* src, std::size_t size)
{
for (u32 i = 0; i < size; i++)
{
if constexpr (pixel_sz == 1)
{
// Reverse memcpy
*((u8*)dst + i) = *((u8*)src - i);
}
if constexpr (pixel_sz == 2)
{
// R5B6G5
*((u16*)dst + i) = *((u16*)src - i);
}
if constexpr (pixel_sz == 4)
{
// A8R8G8B8
*((u32*)dst + i) = *((u32*)src - i);
}
}
}

// Returns interleaved bits of X|Y|Z used as Z-order curve indices
static inline u32 calculate_z_index(u32 x, u32 y, u32 z)
{
Expand Down

0 comments on commit 914c4c8

Please sign in to comment.