1
0
mirror of https://github.com/RPCS3/rpcs3.git synced 2025-01-26 18:35:18 +00:00

rsx: Implement proper Z-order curve in 3 dimensions

- Should fix garbage palette textures getting uploaded (LSD graphics)
This commit is contained in:
kd-11 2018-04-01 02:47:43 +03:00
parent e291494282
commit 53f2533a08
2 changed files with 71 additions and 7 deletions
rpcs3/Emu/RSX

@ -42,13 +42,25 @@ struct copy_unmodified_block_swizzled
template<typename T, typename U>
static void copy_mipmap_level(gsl::span<T> dst, gsl::span<const U> src, u16 width_in_block, u16 row_count, u16 depth, u32 dst_pitch_in_block)
{
std::unique_ptr<U[]> temp_swizzled(new U[width_in_block * row_count]);
for (int d = 0; d < depth; ++d)
if (std::is_same<T, U>::value && dst_pitch_in_block == width_in_block)
{
rsx::convert_linear_swizzle<U>((void*)src.subspan(d * width_in_block * row_count).data(), temp_swizzled.get(), width_in_block, row_count, true);
gsl::span<const U> swizzled_src{ temp_swizzled.get(), ::narrow<int>(width_in_block * row_count) };
for (int row = 0; row < row_count; ++row)
copy(dst.subspan((row + d * row_count) * dst_pitch_in_block, width_in_block), swizzled_src.subspan(row * width_in_block, width_in_block));
rsx::convert_linear_swizzle_3d<T>((void*)src.data(), (void*)dst.data(), width_in_block, row_count, depth);
}
else
{
std::vector<U> tmp(width_in_block * row_count * depth);
rsx::convert_linear_swizzle_3d<U>((void*)src.data(), tmp.data(), width_in_block, row_count, depth);
gsl::span<U> src_span = tmp;
u32 src_offset = 0;
u32 dst_offset = 0;
for (int n = 0; n < row_count * depth; ++n)
{
copy(dst.subspan(dst_offset, width_in_block), src_span.subspan(src_offset, width_in_block));
dst_offset += dst_pitch_in_block;
src_offset += width_in_block;
}
}
}
};

@ -96,10 +96,32 @@ namespace rsx
return static_cast<u32>((1ULL << 32) >> ::cntlz32(x - 1, true));
}
// 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)
{
//Result = X' | Y' | Z' which are x,y,z bits interleaved
u32 shift_size = 0;
u32 result = 0;
while (x | y | z)
{
result |= (x & 0x1) << shift_size++;
result |= (y & 0x1) << shift_size++;
result |= (z & 0x1) << shift_size++;
x >>= 1;
y >>= 1;
z >>= 1;
}
return result;
}
/* 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
* Restriction: It has mixed results if the height or width is not a power of 2
* Restriction: It has mixed results if the height or width is not a power of 2
* Restriction: Only works with 2D surfaces
*/
template<typename T>
void convert_linear_swizzle(void* input_pixels, void* output_pixels, u16 width, u16 height, bool input_is_swizzled)
@ -172,6 +194,36 @@ namespace rsx
}
}
/**
* Write swizzled data to linear memory with support for 3 dimensions
* Z ordering is done in all 3 planes independently with a unit being a 2x2 block per-plane
* A unit in 3d textures is a group of 2x2x2 texels advancing towards depth in units of 2x2x1 blocks
* i.e 32 texels per "unit"
*/
template <typename T>
void convert_linear_swizzle_3d(void *input_pixels, void *output_pixels, u16 width, u16 height, u16 depth)
{
if (depth == 1)
{
convert_linear_swizzle<T>(input_pixels, output_pixels, width, height, true);
return;
}
T *src = static_cast<T*>(input_pixels);
T *dst = static_cast<T*>(output_pixels);
for (u32 z = 0; z < depth; ++z)
{
for (u32 y = 0; y < height; ++y)
{
for (u32 x = 0; x < width; ++x)
{
*dst++ = src[calculate_z_index(x, y, z)];
}
}
}
}
void scale_image_nearest(void* dst, const void* src, u16 src_width, u16 src_height, u16 dst_pitch, u16 src_pitch, u8 pixel_size, u8 samples_u, u8 samples_v, bool swap_bytes = false);
void convert_scale_image(u8 *dst, AVPixelFormat dst_format, int dst_width, int dst_height, int dst_pitch,