cellGem: fix RAW8 to RGBA_320x240
Some checks are pending
Generate Translation Template / Generate Translation Template (push) Waiting to run
Build RPCS3 / RPCS3 Linux ${{ matrix.os }} ${{ matrix.compiler }} (/rpcs3/.ci/build-linux-aarch64.sh, gcc, rpcs3/rpcs3-ci-jammy-aarch64:1.9, ubuntu-24.04-arm) (push) Waiting to run
Build RPCS3 / RPCS3 Linux ${{ matrix.os }} ${{ matrix.compiler }} (/rpcs3/.ci/build-linux.sh, gcc, rpcs3/rpcs3-ci-jammy:1.9, ubuntu-24.04) (push) Waiting to run
Build RPCS3 / RPCS3 Linux ${{ matrix.os }} ${{ matrix.compiler }} (a1d35836e8d45bfc6f63c26f0a3e5d46ef622fe1, rpcs3/rpcs3-binaries-linux-arm64, /rpcs3/.ci/build-linux-aarch64.sh, clang, rpcs3/rpcs3-ci-jammy-aarch64:1.9, ubuntu-24.04-arm) (push) Waiting to run
Build RPCS3 / RPCS3 Linux ${{ matrix.os }} ${{ matrix.compiler }} (d812f1254a1157c80fd402f94446310560f54e5f, rpcs3/rpcs3-binaries-linux, /rpcs3/.ci/build-linux.sh, clang, rpcs3/rpcs3-ci-jammy:1.9, ubuntu-24.04) (push) Waiting to run
Build RPCS3 / RPCS3 Mac ${{ matrix.name }} (0, 51ae32f468089a8169aaf1567de355ff4a3e0842, rpcs3/rpcs3-binaries-mac, Intel) (push) Waiting to run
Build RPCS3 / RPCS3 Mac ${{ matrix.name }} (1, 8e21bdbc40711a3fccd18fbf17b742348b0f4281, rpcs3/rpcs3-binaries-mac-arm64, Apple Silicon) (push) Waiting to run
Build RPCS3 / RPCS3 Windows (push) Waiting to run
Build RPCS3 / RPCS3 Windows Clang ${{ matrix.arch }} (aarch64, clang, clangarm64, ARM64, windows-11-arm) (push) Waiting to run
Build RPCS3 / RPCS3 Windows Clang ${{ matrix.arch }} (x86_64, clang, clang64, X64, windows-2025) (push) Waiting to run
Build RPCS3 / RPCS3 FreeBSD (push) Waiting to run

We were basically writing two rows into dst for each other src line.
This means we were writing 480 lines in total instead of 240,
overwriting one of the lines written in the previous iteration.
This led to writing one line out of bounds last iteration.
Let's just use a simple debayer technique which perfectly matches here.
This also applies the previously missing gain factors.

I also tried to first demosaic and then drop every other pixel.
The result was comparatively blurred and the performance worse.
This commit is contained in:
Megamouse 2026-03-10 03:38:24 +01:00
parent 763001ee91
commit 71f0d5c602

View file

@ -845,6 +845,53 @@ namespace gem
debayer_raw8_impl<false>(src, dst, alpha, gain_r, gain_g, gain_b);
}
template <bool use_gain>
static inline void debayer_raw8_downscale_impl(const u8* src, u8* dst, u8 alpha, f32 gain_r, f32 gain_g, f32 gain_b)
{
constexpr u32 in_pitch = 640;
constexpr u32 out_pitch = 320 * 4;
// Simple debayer
for (s32 y = 0; y < 240; y++)
{
const u8* src0 = src + y * 2 * in_pitch;
const u8* src1 = src0 + in_pitch;
u8* dst0 = dst + y * out_pitch;
for (s32 x = 0; x < 320; x++, dst0 += 4, src0 += 2, src1 += 2)
{
const u8 b = src0[0];
const u8 g0 = src0[1];
const u8 g1 = src1[0];
const u8 r = src1[1];
const u8 g = (g0 + g1) >> 1;
if constexpr (use_gain)
{
dst0[0] = static_cast<u8>(std::clamp(r * gain_r, 0.0f, 255.0f));
dst0[1] = static_cast<u8>(std::clamp(g * gain_g, 0.0f, 255.0f));
dst0[2] = static_cast<u8>(std::clamp(b * gain_b, 0.0f, 255.0f));
}
else
{
dst0[0] = r;
dst0[1] = g;
dst0[2] = b;
}
dst0[3] = alpha;
}
}
}
static void debayer_raw8_downscale(const u8* src, u8* dst, u8 alpha, f32 gain_r, f32 gain_g, f32 gain_b)
{
if (gain_r != 1.0f || gain_g != 1.0f || gain_b != 1.0f)
debayer_raw8_downscale_impl<true>(src, dst, alpha, gain_r, gain_g, gain_b);
else
debayer_raw8_downscale_impl<false>(src, dst, alpha, gain_r, gain_g, gain_b);
}
bool convert_image_format(CellCameraFormat input_format, const CellGemVideoConvertAttribute& vc,
const std::vector<u8>& video_data_in, u32 width, u32 height,
u8* video_data_out, u32 video_data_out_size, u8* buffer_memory,
@ -1183,34 +1230,7 @@ namespace gem
{
case CELL_CAMERA_RAW8:
{
const u32 in_pitch = width;
const u32 out_pitch = width * 4 / 2;
for (u32 y = 0; y < height - 1; y += 2)
{
const u8* src0 = src_data + y * in_pitch;
const u8* src1 = src0 + in_pitch;
u8* dst0 = video_data_out + (y / 2) * out_pitch;
u8* dst1 = dst0 + out_pitch;
for (u32 x = 0; x < width - 1; x += 2, src0 += 2, src1 += 2, dst0 += 4, dst1 += 4)
{
const u8 b = src0[0];
const u8 g0 = src0[1];
const u8 g1 = src1[0];
const u8 r = src1[1];
const u8 top[4] = { r, g0, b, alpha };
const u8 bottom[4] = { r, g1, b, alpha };
// Top-Left
std::memcpy(dst0, top, 4);
// Bottom-Left Pixel
std::memcpy(dst1, bottom, 4);
}
}
debayer_raw8_downscale(src_data, video_data_out, alpha, gain_r, gain_g, gain_b);
break;
}
case CELL_CAMERA_RGBA: