mirror of
https://github.com/libretro/parallel-ps2.git
synced 2026-11-09 03:19:41 -10:00
paraLLEl-GS: an in-place blur biased a few texels is one too
A sprite reading the buffer it draws into, linear, from beside where it draws, is a blur in place: its texture is held for the render pass and read as the buffer was before it, rather than the pass ending at every column whose page the last one wrote. The rule matched a UV box exactly two texels larger than the draw on both axes at a bias of one; a blur sampling an axis on texel centres, or at the texture's edge, has fewer extra texels there, and one reaching a few texels aside has a larger bias. The rule now takes zero to two extra texels an axis and a bias up to four. A game blooming through such a blur, a column of 32 at a time: 80 render passes a frame become 33, with 2130 of every 2400 passes before holding one to three primitives. tests/swdraw blur_in_place: a buffer blurred in place a column at a time every frame, brightened until white and read back on every renderer, in at most two render passes a frame on paraLLEl-GS.
This commit is contained in:
1 parent
43df8d12e6
commit
ffbe9b705a
4 files changed
+96
-10
No files matched your search
@@ -1538,16 +1538,14 @@ uint32_t GSInterface::drawing_kick_update_texture(FBFeedbackMode feedback_mode,
|
||||
// It tends to look very broken, especially when using SSAA textures.
|
||||
int u_offset = std::abs(uv_bb.x - bb.x);
|
||||
int v_offset = std::abs(uv_bb.y - bb.y);
|
||||
int u_size = uv_bb.z - uv_bb.x;
|
||||
int v_size = uv_bb.w - uv_bb.y;
|
||||
int x_size = bb.z - bb.x;
|
||||
int y_size = bb.w - bb.y;
|
||||
/* For linear filter, UV bb is generally 2 extra pixels;
|
||||
* fewer on an axis sampled on texel centres, or at the
|
||||
* texture's edge. The bias is a few taps. */
|
||||
int u_extra = (uv_bb.z - uv_bb.x) - (bb.z - bb.x);
|
||||
int v_extra = (uv_bb.w - uv_bb.y) - (bb.w - bb.y);
|
||||
|
||||
// For linear filter, UV bb is generally 2 extra pixels.
|
||||
u_size -= 2;
|
||||
v_size -= 2;
|
||||
|
||||
if (u_offset <= 1 && v_offset <= 1 && u_size == x_size && v_size == y_size)
|
||||
if (u_offset <= 4 && v_offset <= 4 &&
|
||||
u_extra >= 0 && u_extra <= 2 && v_extra >= 0 && v_extra <= 2)
|
||||
long_term_cache_texture = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ SCRATCH=$(mktemp -d)
|
||||
trap 'rm -rf "$SCRATCH"' EXIT
|
||||
failed=0
|
||||
for c in aa1_small aa1_triangle aa1_triangle_2x aa1_line aa1_line_2x mip_tw8 mip_tw11 mip_tw11_2x \
|
||||
display_large display_large_2x frame_ct32 frame_after_t4 frame_ct32_2x frame_after_t4_2x copy_then_upload readback_t4hh dest_alpha many_copies upload_short upload_whole upload_split upload_clut_between readback_parts column_passes alpha_under_depth alpha_under_depth_wide alpha_under_depth_strip alpha_under_depth_big mip_shaded alpha_dirtied_parked depth_narrowed width_overwritten palette_engulfed block_offset_read engulfed_alpha palette_bilinear palette_bilinear_drawn palette_shaded big_triangles present points nine_frames fb_wrap uv_huge offset_reload vram_wrap_read frame_on_depth dirty_whole_target wrap_gradient depth_texture_far move_width_change frame_on_depth32 depth_states shuffle_left_of_offset split_clear_no_display frame_low frame_low_odd frame_low_odd_2x \
|
||||
display_large display_large_2x frame_ct32 frame_after_t4 frame_ct32_2x frame_after_t4_2x copy_then_upload readback_t4hh dest_alpha many_copies upload_short upload_whole upload_split upload_clut_between readback_parts column_passes alpha_under_depth alpha_under_depth_wide alpha_under_depth_strip alpha_under_depth_big mip_shaded alpha_dirtied_parked depth_narrowed width_overwritten blur_in_place palette_engulfed block_offset_read engulfed_alpha palette_bilinear palette_bilinear_drawn palette_shaded big_triangles present points nine_frames fb_wrap uv_huge offset_reload vram_wrap_read frame_on_depth dirty_whole_target wrap_gradient depth_texture_far move_width_change frame_on_depth32 depth_states shuffle_left_of_offset split_clear_no_display frame_low frame_low_odd frame_low_odd_2x \
|
||||
gif_nloop_past_data dual_blend date_no_depth_full t4_from_target t4_from_target_page t4_from_target_shaded texture_rewind draw_once \
|
||||
feedback_chain feedback_own_pixel feedback_runs; do
|
||||
if ! timeout 300 "$DIR/swdraw" "$CORE" "$SCRATCH" "$c" > "$SCRATCH/$c.out" 2>&1; then
|
||||
|
||||
@@ -3260,6 +3260,67 @@ static void case_width_overwritten(void)
|
||||
s_expect_run[1] = 0x80405060ul;
|
||||
}
|
||||
|
||||
/* A buffer 320x224 at page 140, five pages wide, laid down once in a
|
||||
* colour; every frame after, ten sprites a column of 32 each read it
|
||||
* as a texture, linear, a texel to the side of where they draw, and
|
||||
* draw it back into itself brightened (highlight), until it is white;
|
||||
* its first rows are read back: white. On paraLLEl-GS the columns are
|
||||
* one render pass, the blur in place reading the buffer as it was
|
||||
* before the pass, not one a column, each waiting for the last. */
|
||||
static void case_blur_in_place(void)
|
||||
{
|
||||
unsigned i, draw, rb;
|
||||
s_smode1_hi = 0x7; /* NTSC, for a display every renderer shows */
|
||||
s_smode1_lo = 0x40834504u;
|
||||
qw(0x8000u, 0x10000000u, 0xEu, 0);
|
||||
qw(1, 0, GS_PRMODECONT, 0);
|
||||
qw(0, 0, GS_XYOFFSET, 0);
|
||||
qw(2047u << 16, 2047u << 16, GS_SCISSOR, 0);
|
||||
qw((1u << 16) | (1u << 17), 0, GS_TEST_1, 0); /* ZTE, ZTST always */
|
||||
qw(8u, 1, GS_ZBUF_1, 0); /* ZMSK */
|
||||
qw(140u | (5u << 16), 0, GS_FRAME_1, 0);
|
||||
qw(6, 0, GS_PRIM, 0);
|
||||
qw(0xFF202020u, 0x3f800000u, GS_RGBAQ, 0);
|
||||
qw(0, 0, GS_XYZ2, 0);
|
||||
qw((unsigned)XY(160, 224), 0, GS_XYZ2, 0);
|
||||
qw(0xFF303030u, 0x3f800000u, GS_RGBAQ, 0);
|
||||
qw((unsigned)XY(160, 0), 0, GS_XYZ2, 0);
|
||||
qw((unsigned)XY(320, 224), 0, GS_XYZ2, 0);
|
||||
s_qw[0][0] = (s_qw_count - 1) | 0x8000u;
|
||||
kick(0, s_qw_count, 0);
|
||||
draw = s_qw_count;
|
||||
qw(0x8000u, 0x10000000u, 0xEu, 0);
|
||||
qw(140u | (5u << 16), 0, GS_FRAME_1, 0);
|
||||
qw(0x1180u | (5u << 14) | (9u << 26), 2u | (1u << 2) | (2u << 3), GS_TEX0_1, 0); /* 512x256, TCC, highlight */
|
||||
qw(1u << 5, 0, GS_TEX1_1, 0); /* MMAG linear */
|
||||
qw(0, 0, GS_CLAMP_1, 0);
|
||||
qw(6 | 0x10 | 0x100, 0, GS_PRIM, 0); /* sprite, TME, FST */
|
||||
s_bump_qw = s_qw_count; /* a sprite's first colour: bumped, drawn with the second */
|
||||
qw(0x10808080u, 0x3f800000u, GS_RGBAQ, 0);
|
||||
for (i = 0; i < 10; i++)
|
||||
{
|
||||
qw(0x10808080u, 0x3f800000u, GS_RGBAQ, 0); /* unity, plus 0x10 a frame */
|
||||
qw((unsigned)XY(i * 32 + 1, 0) + 0x00080008u, 0, GS_UV, 0);
|
||||
qw((unsigned)XY(i * 32, 0), 0, GS_XYZ2, 0);
|
||||
qw((unsigned)XY(i * 32 + 33, 224) + 0x00080008u, 0, GS_UV, 0);
|
||||
qw((unsigned)XY(i * 32 + 32, 224), 0, GS_XYZ2, 0);
|
||||
}
|
||||
s_qw[draw][0] = (s_qw_count - draw - 1) | 0x8000u;
|
||||
rb = s_qw_count;
|
||||
qw(4 | 0x8000u, 0x10000000u, 0xEu, 0);
|
||||
qw(140u | (5u << 16), 0, GS_BITBLTBUF, 0); /* SBP page 140, SBW 5 */
|
||||
qw(0, 0, GS_TRXPOS, 0);
|
||||
qw(128, 16, GS_TRXREG, 0);
|
||||
qw(1, 0, GS_TRXDIR, 0); /* local to host */
|
||||
s_loop = 1;
|
||||
s_loop_kick = s_kick_count;
|
||||
kick(draw, rb - draw, 1);
|
||||
kick(rb, s_qw_count - rb, 0);
|
||||
readback(128 * 16 / 4);
|
||||
s_run_frames = 60;
|
||||
s_expect_run[0] = 0xFFFFFFFFul;
|
||||
}
|
||||
|
||||
static const struct { const char* name; void (*build)(void); const char* scale; } s_cases[] = {
|
||||
{ "aa1_small", case_aa1_small, "1" },
|
||||
{ "stream_ct32", case_stream_ct32, "1" },
|
||||
@@ -3306,6 +3367,7 @@ static const struct { const char* name; void (*build)(void); const char* scale;
|
||||
{ "alpha_dirtied_parked", case_alpha_dirtied_parked, "1" },
|
||||
{ "depth_narrowed", case_depth_narrowed, "1" },
|
||||
{ "width_overwritten", case_width_overwritten, "1" },
|
||||
{ "blur_in_place", case_blur_in_place, "1" },
|
||||
{ "palette_engulfed", case_palette_engulfed, "1" },
|
||||
{ "block_offset_read", case_block_offset_read, "1" },
|
||||
{ "engulfed_alpha", case_engulfed_alpha, "1" },
|
||||
|
||||
@@ -236,6 +236,32 @@ if [ -z "$vk" ] || [ "$vk" != "$pgs" ] || [ "$vk" != "$sw" ] || [ -n "$copies" ]
|
||||
fi
|
||||
echo " a buffer overwritten at two widths in turn: the same picture on every renderer, no image copy a frame"
|
||||
|
||||
# A buffer blurred in place every frame, a column of 32 at a time, each
|
||||
# column a sprite reading the buffer linear a texel to the side of where
|
||||
# it draws (blur_in_place): the readback on every renderer, and on
|
||||
# paraLLEl-GS the columns in one render pass. paraLLEl-GS reads such a
|
||||
# blur's source as it was before the pass rather than ending the pass
|
||||
# at every column whose page the last one wrote.
|
||||
c=blur_in_place
|
||||
"$SCRATCH/swdraw" --bios "$SCRATCH/$c.bin" $c
|
||||
for renderer in Vulkan "Software (HW)"; do
|
||||
if ! VN_EXPECT_RUN=ffffffff VN_IDLE_BIOS=1 LRPS2_BIOS="$SCRATCH/$c.bin" VN_RENDERER="$renderer" \
|
||||
timeout 300 "$DIR/vknegotiate" "$CORE" "$SCRATCH" v2 > "$SCRATCH/$c.log" 2>&1; then
|
||||
rm -rf "$SCRATCH"
|
||||
echo " FAIL: $c, $renderer"
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
VN_COUNT_CALLS=1 VN_FRAMES=40 VN_EXPECT_RUN=ffffffff VN_IDLE_BIOS=1 LRPS2_BIOS="$SCRATCH/$c.bin" VN_RENDERER=paraLLEl-GS \
|
||||
timeout 300 "$DIR/vknegotiate" "$CORE" "$SCRATCH" v2 > "$SCRATCH/$c.log" 2>&1 || true
|
||||
passes=$(sed -n 's/.*run 40: calls.* dispatch_ind=\([0-9]*\).*/\1/p' "$SCRATCH/$c.log")
|
||||
if ! grep -q "vknegotiate v2: ok" "$SCRATCH/$c.log" || [ -z "$passes" ] || [ "$passes" -gt 2 ]; then
|
||||
rm -rf "$SCRATCH"
|
||||
echo " FAIL: $c: a frame of ten blur columns on paraLLEl-GS is ${passes:-no} render passes"
|
||||
exit 1
|
||||
fi
|
||||
echo " a buffer blurred in place a column at a time: $passes render passes a frame on paraLLEl-GS"
|
||||
|
||||
# A palette drawn into a buffer one page wide, whose page a wider buffer
|
||||
# drawn every frame takes without drawing over the palette: an indexed
|
||||
# read through the palette gets it, on both renderers, and still after a
|
||||
|
||||
Reference in new issue
Block a user