render: true ultrawide through the native renderer

This commit is contained in:
mchughalex 2026-07-20 00:36:16 +01:00
parent 035d3e22a0
commit 32eb60337a
12 changed files with 299 additions and 746 deletions

View file

@ -62,9 +62,9 @@ Create a `dlc` folder either beside the executable, inside the installed game fo
or in the user data folder. Place the DLC package files in that
folder and start the game.
## True 21:9 Ultrawide
## True Ultrawide
The builds include an experimental true ultrawide aspect ratio mode at 21:9. You may notice occasional visual bugs or graphical glitches, especially around shadows. Performance is somewhat reduced.
The builds include an experimental true ultrawide mode: the native renderer draws the world at your display's full aspect ratio (21:9 and wider) with a matching wider field of view, while the HUD and menus stay centered and undistorted. Enable it via the Aspect Ratio setting or `skate3_ultrawide = true`. It requires the native renderer; with the emulated renderer the game presents in standard 16:9. Rendering more of the scene costs proportionally more GPU time.
## Controls
@ -210,8 +210,7 @@ SKATE3_MNK=1 ./scripts/run-linux.sh
Fullscreen is on by default. Pass `--no-fullscreen` to start windowed.
On Windows, ultrawide displays are detected automatically in fullscreen. For an
ultrawide window, pass matching `--window_width` and `--window_height` values;
the renderer keeps the guest frontbuffer at a stable 16:9 size while applying
ultrawide presentation and Hor+ correction without stretching.
the native renderer then draws true widescreen frames at that aspect.
To run the Linux development executable directly:

View file

@ -16,18 +16,13 @@ mnk_mode = false
mnk_capture_mouse = false
fullscreen = true
# Automatically derive an ultrawide host aspect from the fullscreen monitor on
# Windows, or from an explicit window_width/window_height pair. Leave
# video_mode_width and video_mode_height at defaults for this path.
# Ultrawide (native renderer): true widescreen rendering at the host display
# aspect, derived from the fullscreen monitor on Windows or from an explicit
# window_width/window_height pair. The emulated renderer presents 16:9
# pillarboxed. skate3_ultrawide_target_aspect (default 0 = derive at boot)
# pins the aspect explicitly.
skate3_ultrawide = false
skate3_field_of_view = 60.0
skate3_ultrawide_base_height = 720
skate3_ultrawide_hor_plus = true
skate3_ultrawide_hor_plus_scale = 0.0
# Risky diagnostics for narrowing texture/visibility pop-in. Enable one at a
# time when testing.
skate3_ultrawide_force_main_visibility_flags = true
skate3_ultrawide_ignore_streamer_texture_invalidations = false
# window_width = 3440
# window_height = 1440
vsync = false

View file

@ -48,13 +48,17 @@ float4 ps_main(VSOut i) : SV_Target {
// taps covers reduction ratios up to ~4x (4K -> 1152 is 3.33x); narrower
// footprints undersampled the scale and the aliased detail crawled as the
// scene animated: the whole blurred backdrop shimmered, worst around
// high-contrast edges.
// high-contrast edges. This pass reads the second constant register as the
// source UV rect (xy = scale, zw = offset): the photo grab center-crops the
// 16:9 band out of a wide output; (1,1,0,0) = full frame.
float4 ps_down(VSOut i) : SV_Target {
float4 rect = tint;
float2 uv = i.uv * rect.xy + rect.zw;
float3 c = 0.0;
[unroll] for (int y = 0; y < 4; ++y) {
[unroll] for (int x = 0; x < 4; ++x) {
float2 off = float2(float(x) - 1.5, float(y) - 1.5) * dir.xy;
c += src.SampleLevel(smp_clamp, i.uv + off, 0).rgb;
c += src.SampleLevel(smp_clamp, uv + off, 0).rgb;
}
}
return float4(c / 16.0, 1.0);

View file

@ -7,7 +7,10 @@ cbuffer C : register(b0) {
float4 m[10]; // m[0..3] proj rows, m[4..7] world rows, m[8] color,
// m[9].x = apply D3D9 half-pixel (2D ortho draws only),
// m[9].y = sharp-magnification amount (0 = plain bilinear),
// m[9].zw = unused (the D3D9 half-pixel shift is derived
// m[9].z = clip-space X extent of the 2D band (0 = full
// target; < 1 when a wide output centers the 16:9 stream
// in a pillarboxed band, see the emit_draw column-0 scale),
// m[9].w = unused (the D3D9 half-pixel shift is derived
// in the VS from the draw's own ortho scale)
};
Texture2D<float4> tex : register(t0);
@ -55,8 +58,11 @@ VSOut vs_main(float4 p : POSITION, float2 uv : TEXCOORD0, float4 color : COLOR0)
float2 gpx = float2(abs(m[0].x), abs(m[1].y)); // one guest px in NDC
float2 ndc = o.pos.xy / o.pos.w;
float2 eps = 0.75 * gpx;
if (ndc.x <= 1.0 && ndc.x > 1.0 - eps.x) ndc.x = 1.0;
if (ndc.x >= -1.0 && ndc.x < -1.0 + eps.x) ndc.x = -1.0;
// The horizontal boundary is the 2D band edge: +-1 normally, +-m[9].z
// when a wide output pillarboxes the 16:9 stream.
float edge_x = m[9].z > 0.0 ? m[9].z : 1.0;
if (ndc.x <= edge_x && ndc.x > edge_x - eps.x) ndc.x = edge_x;
if (ndc.x >= -edge_x && ndc.x < -edge_x + eps.x) ndc.x = -edge_x;
if (ndc.y <= 1.0 && ndc.y > 1.0 - eps.y) ndc.y = 1.0;
if (ndc.y >= -1.0 && ndc.y < -1.0 + eps.y) ndc.y = -1.0;
o.pos.xy = ndc * o.pos.w;

View file

@ -16309,9 +16309,9 @@ static const uint32_t k_blur_ps_blit[] = {
0x00000003, 0x0000001d, 0x000100fd, 0x00010038,
};
// blur.hlsl : ps_down (4300 bytes)
// blur.hlsl : ps_down (4448 bytes)
static const uint32_t k_blur_ps_down[] = {
0x07230203, 0x00010300, 0x000e0000, 0x000000ba, 0x00000000, 0x00020011, 0x00000001, 0x0003000e,
0x07230203, 0x00010300, 0x000e0000, 0x000000c1, 0x00000000, 0x00020011, 0x00000001, 0x0003000e,
0x00000000, 0x00000001, 0x0007000f, 0x00000004, 0x00000001, 0x645f7370, 0x006e776f, 0x00000002,
0x00000003, 0x00030010, 0x00000001, 0x00000007, 0x00030003, 0x00000005, 0x00000258, 0x00040005,
0x00000004, 0x65707974, 0x0000432e, 0x00040006, 0x00000004, 0x00000000, 0x00726964, 0x00050006,
@ -16327,125 +16327,129 @@ static const uint32_t k_blur_ps_down[] = {
0x00040047, 0x00000007, 0x00000021, 0x00000000, 0x00040047, 0x00000009, 0x00000022, 0x00000000,
0x00040047, 0x00000009, 0x00000021, 0x00000005, 0x00050048, 0x00000004, 0x00000000, 0x00000023,
0x00000000, 0x00050048, 0x00000004, 0x00000001, 0x00000023, 0x00000010, 0x00030047, 0x00000004,
0x00000002, 0x00030016, 0x0000000b, 0x00000020, 0x0004002b, 0x0000000b, 0x0000000c, 0x00000000,
0x00040017, 0x0000000d, 0x0000000b, 0x00000003, 0x00040015, 0x0000000e, 0x00000020, 0x00000001,
0x0004002b, 0x0000000e, 0x0000000f, 0x00000000, 0x0004002b, 0x0000000b, 0x00000010, 0x3fc00000,
0x0004002b, 0x0000000b, 0x00000011, 0x3f800000, 0x00040017, 0x00000012, 0x0000000b, 0x00000004,
0x0004001e, 0x00000004, 0x00000012, 0x00000012, 0x00040020, 0x00000013, 0x00000002, 0x00000004,
0x00090019, 0x00000006, 0x0000000b, 0x00000001, 0x00000002, 0x00000000, 0x00000000, 0x00000001,
0x00000000, 0x00040020, 0x00000014, 0x00000000, 0x00000006, 0x0002001a, 0x00000008, 0x00040020,
0x00000015, 0x00000000, 0x00000008, 0x00040017, 0x00000016, 0x0000000b, 0x00000002, 0x00040020,
0x00000017, 0x00000001, 0x00000016, 0x00040020, 0x00000018, 0x00000003, 0x00000012, 0x00020013,
0x00000019, 0x00030021, 0x0000001a, 0x00000019, 0x00040020, 0x0000001b, 0x00000002, 0x00000012,
0x0003001b, 0x0000000a, 0x00000006, 0x0004003b, 0x00000013, 0x00000005, 0x00000002, 0x0004003b,
0x00000014, 0x00000007, 0x00000000, 0x0004003b, 0x00000015, 0x00000009, 0x00000000, 0x0004003b,
0x00000017, 0x00000002, 0x00000001, 0x0004003b, 0x00000018, 0x00000003, 0x00000003, 0x0004002b,
0x0000000b, 0x0000001c, 0xbfc00000, 0x0005002c, 0x00000016, 0x0000001d, 0x0000001c, 0x0000001c,
0x0004002b, 0x0000000b, 0x0000001e, 0xbf000000, 0x0005002c, 0x00000016, 0x0000001f, 0x0000001e,
0x0000001c, 0x0004002b, 0x0000000b, 0x00000020, 0x3f000000, 0x0005002c, 0x00000016, 0x00000021,
0x00000020, 0x0000001c, 0x0005002c, 0x00000016, 0x00000022, 0x00000010, 0x0000001c, 0x0005002c,
0x00000016, 0x00000023, 0x0000001c, 0x0000001e, 0x0005002c, 0x00000016, 0x00000024, 0x0000001e,
0x0000001e, 0x0005002c, 0x00000016, 0x00000025, 0x00000020, 0x0000001e, 0x0005002c, 0x00000016,
0x00000026, 0x00000010, 0x0000001e, 0x0005002c, 0x00000016, 0x00000027, 0x0000001c, 0x00000020,
0x0005002c, 0x00000016, 0x00000028, 0x0000001e, 0x00000020, 0x0005002c, 0x00000016, 0x00000029,
0x00000020, 0x00000020, 0x0005002c, 0x00000016, 0x0000002a, 0x00000010, 0x00000020, 0x0005002c,
0x00000016, 0x0000002b, 0x0000001c, 0x00000010, 0x0005002c, 0x00000016, 0x0000002c, 0x0000001e,
0x00000010, 0x0005002c, 0x00000016, 0x0000002d, 0x00000020, 0x00000010, 0x0005002c, 0x00000016,
0x0000002e, 0x00000010, 0x00000010, 0x0004002b, 0x0000000b, 0x0000002f, 0x3d800000, 0x0006002c,
0x0000000d, 0x00000030, 0x0000002f, 0x0000002f, 0x0000002f, 0x00050036, 0x00000019, 0x00000001,
0x00000000, 0x0000001a, 0x000200f8, 0x00000031, 0x0004003d, 0x00000016, 0x00000032, 0x00000002,
0x00050041, 0x0000001b, 0x00000033, 0x00000005, 0x0000000f, 0x0004003d, 0x00000012, 0x00000034,
0x00000033, 0x0007004f, 0x00000016, 0x00000035, 0x00000034, 0x00000034, 0x00000000, 0x00000001,
0x00050085, 0x00000016, 0x00000036, 0x0000001d, 0x00000035, 0x0004003d, 0x00000006, 0x00000037,
0x00000007, 0x0004003d, 0x00000008, 0x00000038, 0x00000009, 0x00050081, 0x00000016, 0x00000039,
0x00000032, 0x00000036, 0x00050056, 0x0000000a, 0x0000003a, 0x00000037, 0x00000038, 0x00070058,
0x00000012, 0x0000003b, 0x0000003a, 0x00000039, 0x00000002, 0x0000000c, 0x0008004f, 0x0000000d,
0x0000003c, 0x0000003b, 0x0000003b, 0x00000000, 0x00000001, 0x00000002, 0x00050085, 0x00000016,
0x0000003d, 0x0000001f, 0x00000035, 0x0004003d, 0x00000006, 0x0000003e, 0x00000007, 0x0004003d,
0x00000008, 0x0000003f, 0x00000009, 0x00050081, 0x00000016, 0x00000040, 0x00000032, 0x0000003d,
0x00050056, 0x0000000a, 0x00000041, 0x0000003e, 0x0000003f, 0x00070058, 0x00000012, 0x00000042,
0x00000041, 0x00000040, 0x00000002, 0x0000000c, 0x0008004f, 0x0000000d, 0x00000043, 0x00000042,
0x00000042, 0x00000000, 0x00000001, 0x00000002, 0x00050081, 0x0000000d, 0x00000044, 0x0000003c,
0x00000043, 0x00050085, 0x00000016, 0x00000045, 0x00000021, 0x00000035, 0x0004003d, 0x00000006,
0x00000046, 0x00000007, 0x0004003d, 0x00000008, 0x00000047, 0x00000009, 0x00050081, 0x00000016,
0x00000048, 0x00000032, 0x00000045, 0x00050056, 0x0000000a, 0x00000049, 0x00000046, 0x00000047,
0x00070058, 0x00000012, 0x0000004a, 0x00000049, 0x00000048, 0x00000002, 0x0000000c, 0x0008004f,
0x0000000d, 0x0000004b, 0x0000004a, 0x0000004a, 0x00000000, 0x00000001, 0x00000002, 0x00050081,
0x0000000d, 0x0000004c, 0x00000044, 0x0000004b, 0x00050085, 0x00000016, 0x0000004d, 0x00000022,
0x00000035, 0x0004003d, 0x00000006, 0x0000004e, 0x00000007, 0x0004003d, 0x00000008, 0x0000004f,
0x00000009, 0x00050081, 0x00000016, 0x00000050, 0x00000032, 0x0000004d, 0x00050056, 0x0000000a,
0x00000051, 0x0000004e, 0x0000004f, 0x00070058, 0x00000012, 0x00000052, 0x00000051, 0x00000050,
0x00000002, 0x0000000c, 0x0008004f, 0x0000000d, 0x00000053, 0x00000052, 0x00000052, 0x00000000,
0x00000001, 0x00000002, 0x00050081, 0x0000000d, 0x00000054, 0x0000004c, 0x00000053, 0x00050085,
0x00000016, 0x00000055, 0x00000023, 0x00000035, 0x0004003d, 0x00000006, 0x00000056, 0x00000007,
0x0004003d, 0x00000008, 0x00000057, 0x00000009, 0x00050081, 0x00000016, 0x00000058, 0x00000032,
0x00000055, 0x00050056, 0x0000000a, 0x00000059, 0x00000056, 0x00000057, 0x00070058, 0x00000012,
0x0000005a, 0x00000059, 0x00000058, 0x00000002, 0x0000000c, 0x0008004f, 0x0000000d, 0x0000005b,
0x0000005a, 0x0000005a, 0x00000000, 0x00000001, 0x00000002, 0x00050081, 0x0000000d, 0x0000005c,
0x00000054, 0x0000005b, 0x00050085, 0x00000016, 0x0000005d, 0x00000024, 0x00000035, 0x0004003d,
0x00000006, 0x0000005e, 0x00000007, 0x0004003d, 0x00000008, 0x0000005f, 0x00000009, 0x00050081,
0x00000016, 0x00000060, 0x00000032, 0x0000005d, 0x00050056, 0x0000000a, 0x00000061, 0x0000005e,
0x0000005f, 0x00070058, 0x00000012, 0x00000062, 0x00000061, 0x00000060, 0x00000002, 0x0000000c,
0x0008004f, 0x0000000d, 0x00000063, 0x00000062, 0x00000062, 0x00000000, 0x00000001, 0x00000002,
0x00050081, 0x0000000d, 0x00000064, 0x0000005c, 0x00000063, 0x00050085, 0x00000016, 0x00000065,
0x00000025, 0x00000035, 0x0004003d, 0x00000006, 0x00000066, 0x00000007, 0x0004003d, 0x00000008,
0x00000067, 0x00000009, 0x00050081, 0x00000016, 0x00000068, 0x00000032, 0x00000065, 0x00050056,
0x0000000a, 0x00000069, 0x00000066, 0x00000067, 0x00070058, 0x00000012, 0x0000006a, 0x00000069,
0x00000068, 0x00000002, 0x0000000c, 0x0008004f, 0x0000000d, 0x0000006b, 0x0000006a, 0x0000006a,
0x00000000, 0x00000001, 0x00000002, 0x00050081, 0x0000000d, 0x0000006c, 0x00000064, 0x0000006b,
0x00050085, 0x00000016, 0x0000006d, 0x00000026, 0x00000035, 0x0004003d, 0x00000006, 0x0000006e,
0x00000007, 0x0004003d, 0x00000008, 0x0000006f, 0x00000009, 0x00050081, 0x00000016, 0x00000070,
0x00000032, 0x0000006d, 0x00050056, 0x0000000a, 0x00000071, 0x0000006e, 0x0000006f, 0x00070058,
0x00000012, 0x00000072, 0x00000071, 0x00000070, 0x00000002, 0x0000000c, 0x0008004f, 0x0000000d,
0x00000073, 0x00000072, 0x00000072, 0x00000000, 0x00000001, 0x00000002, 0x00050081, 0x0000000d,
0x00000074, 0x0000006c, 0x00000073, 0x00050085, 0x00000016, 0x00000075, 0x00000027, 0x00000035,
0x0004003d, 0x00000006, 0x00000076, 0x00000007, 0x0004003d, 0x00000008, 0x00000077, 0x00000009,
0x00050081, 0x00000016, 0x00000078, 0x00000032, 0x00000075, 0x00050056, 0x0000000a, 0x00000079,
0x00000076, 0x00000077, 0x00070058, 0x00000012, 0x0000007a, 0x00000079, 0x00000078, 0x00000002,
0x0000000c, 0x0008004f, 0x0000000d, 0x0000007b, 0x0000007a, 0x0000007a, 0x00000000, 0x00000001,
0x00000002, 0x00050081, 0x0000000d, 0x0000007c, 0x00000074, 0x0000007b, 0x00050085, 0x00000016,
0x0000007d, 0x00000028, 0x00000035, 0x0004003d, 0x00000006, 0x0000007e, 0x00000007, 0x0004003d,
0x00000008, 0x0000007f, 0x00000009, 0x00050081, 0x00000016, 0x00000080, 0x00000032, 0x0000007d,
0x00050056, 0x0000000a, 0x00000081, 0x0000007e, 0x0000007f, 0x00070058, 0x00000012, 0x00000082,
0x00000081, 0x00000080, 0x00000002, 0x0000000c, 0x0008004f, 0x0000000d, 0x00000083, 0x00000082,
0x00000082, 0x00000000, 0x00000001, 0x00000002, 0x00050081, 0x0000000d, 0x00000084, 0x0000007c,
0x00000083, 0x00050085, 0x00000016, 0x00000085, 0x00000029, 0x00000035, 0x0004003d, 0x00000006,
0x00000086, 0x00000007, 0x0004003d, 0x00000008, 0x00000087, 0x00000009, 0x00050081, 0x00000016,
0x00000088, 0x00000032, 0x00000085, 0x00050056, 0x0000000a, 0x00000089, 0x00000086, 0x00000087,
0x00070058, 0x00000012, 0x0000008a, 0x00000089, 0x00000088, 0x00000002, 0x0000000c, 0x0008004f,
0x0000000d, 0x0000008b, 0x0000008a, 0x0000008a, 0x00000000, 0x00000001, 0x00000002, 0x00050081,
0x0000000d, 0x0000008c, 0x00000084, 0x0000008b, 0x00050085, 0x00000016, 0x0000008d, 0x0000002a,
0x00000035, 0x0004003d, 0x00000006, 0x0000008e, 0x00000007, 0x0004003d, 0x00000008, 0x0000008f,
0x00000009, 0x00050081, 0x00000016, 0x00000090, 0x00000032, 0x0000008d, 0x00050056, 0x0000000a,
0x00000091, 0x0000008e, 0x0000008f, 0x00070058, 0x00000012, 0x00000092, 0x00000091, 0x00000090,
0x00000002, 0x0000000c, 0x0008004f, 0x0000000d, 0x00000093, 0x00000092, 0x00000092, 0x00000000,
0x00000001, 0x00000002, 0x00050081, 0x0000000d, 0x00000094, 0x0000008c, 0x00000093, 0x00050085,
0x00000016, 0x00000095, 0x0000002b, 0x00000035, 0x0004003d, 0x00000006, 0x00000096, 0x00000007,
0x0004003d, 0x00000008, 0x00000097, 0x00000009, 0x00050081, 0x00000016, 0x00000098, 0x00000032,
0x00000095, 0x00050056, 0x0000000a, 0x00000099, 0x00000096, 0x00000097, 0x00070058, 0x00000012,
0x0000009a, 0x00000099, 0x00000098, 0x00000002, 0x0000000c, 0x0008004f, 0x0000000d, 0x0000009b,
0x0000009a, 0x0000009a, 0x00000000, 0x00000001, 0x00000002, 0x00050081, 0x0000000d, 0x0000009c,
0x00000094, 0x0000009b, 0x00050085, 0x00000016, 0x0000009d, 0x0000002c, 0x00000035, 0x0004003d,
0x00000006, 0x0000009e, 0x00000007, 0x0004003d, 0x00000008, 0x0000009f, 0x00000009, 0x00050081,
0x00000016, 0x000000a0, 0x00000032, 0x0000009d, 0x00050056, 0x0000000a, 0x000000a1, 0x0000009e,
0x0000009f, 0x00070058, 0x00000012, 0x000000a2, 0x000000a1, 0x000000a0, 0x00000002, 0x0000000c,
0x0008004f, 0x0000000d, 0x000000a3, 0x000000a2, 0x000000a2, 0x00000000, 0x00000001, 0x00000002,
0x00050081, 0x0000000d, 0x000000a4, 0x0000009c, 0x000000a3, 0x00050085, 0x00000016, 0x000000a5,
0x0000002d, 0x00000035, 0x0004003d, 0x00000006, 0x000000a6, 0x00000007, 0x0004003d, 0x00000008,
0x000000a7, 0x00000009, 0x00050081, 0x00000016, 0x000000a8, 0x00000032, 0x000000a5, 0x00050056,
0x0000000a, 0x000000a9, 0x000000a6, 0x000000a7, 0x00070058, 0x00000012, 0x000000aa, 0x000000a9,
0x000000a8, 0x00000002, 0x0000000c, 0x0008004f, 0x0000000d, 0x000000ab, 0x000000aa, 0x000000aa,
0x00000000, 0x00000001, 0x00000002, 0x00050081, 0x0000000d, 0x000000ac, 0x000000a4, 0x000000ab,
0x00050085, 0x00000016, 0x000000ad, 0x0000002e, 0x00000035, 0x0004003d, 0x00000006, 0x000000ae,
0x00000007, 0x0004003d, 0x00000008, 0x000000af, 0x00000009, 0x00050081, 0x00000016, 0x000000b0,
0x00000032, 0x000000ad, 0x00050056, 0x0000000a, 0x000000b1, 0x000000ae, 0x000000af, 0x00070058,
0x00000012, 0x000000b2, 0x000000b1, 0x000000b0, 0x00000002, 0x0000000c, 0x0008004f, 0x0000000d,
0x000000b3, 0x000000b2, 0x000000b2, 0x00000000, 0x00000001, 0x00000002, 0x00050081, 0x0000000d,
0x000000b4, 0x000000ac, 0x000000b3, 0x00050085, 0x0000000d, 0x000000b5, 0x000000b4, 0x00000030,
0x00050051, 0x0000000b, 0x000000b6, 0x000000b5, 0x00000000, 0x00050051, 0x0000000b, 0x000000b7,
0x000000b5, 0x00000001, 0x00050051, 0x0000000b, 0x000000b8, 0x000000b5, 0x00000002, 0x00070050,
0x00000012, 0x000000b9, 0x000000b6, 0x000000b7, 0x000000b8, 0x00000011, 0x0003003e, 0x00000003,
0x000000b9, 0x000100fd, 0x00010038,
0x00000002, 0x00040015, 0x0000000b, 0x00000020, 0x00000001, 0x0004002b, 0x0000000b, 0x0000000c,
0x00000001, 0x00030016, 0x0000000d, 0x00000020, 0x0004002b, 0x0000000d, 0x0000000e, 0x00000000,
0x00040017, 0x0000000f, 0x0000000d, 0x00000003, 0x0004002b, 0x0000000b, 0x00000010, 0x00000000,
0x0004002b, 0x0000000d, 0x00000011, 0x3fc00000, 0x0004002b, 0x0000000d, 0x00000012, 0x3f800000,
0x00040017, 0x00000013, 0x0000000d, 0x00000004, 0x0004001e, 0x00000004, 0x00000013, 0x00000013,
0x00040020, 0x00000014, 0x00000002, 0x00000004, 0x00090019, 0x00000006, 0x0000000d, 0x00000001,
0x00000002, 0x00000000, 0x00000000, 0x00000001, 0x00000000, 0x00040020, 0x00000015, 0x00000000,
0x00000006, 0x0002001a, 0x00000008, 0x00040020, 0x00000016, 0x00000000, 0x00000008, 0x00040017,
0x00000017, 0x0000000d, 0x00000002, 0x00040020, 0x00000018, 0x00000001, 0x00000017, 0x00040020,
0x00000019, 0x00000003, 0x00000013, 0x00020013, 0x0000001a, 0x00030021, 0x0000001b, 0x0000001a,
0x00040020, 0x0000001c, 0x00000002, 0x00000013, 0x0003001b, 0x0000000a, 0x00000006, 0x0004003b,
0x00000014, 0x00000005, 0x00000002, 0x0004003b, 0x00000015, 0x00000007, 0x00000000, 0x0004003b,
0x00000016, 0x00000009, 0x00000000, 0x0004003b, 0x00000018, 0x00000002, 0x00000001, 0x0004003b,
0x00000019, 0x00000003, 0x00000003, 0x0004002b, 0x0000000d, 0x0000001d, 0xbfc00000, 0x0005002c,
0x00000017, 0x0000001e, 0x0000001d, 0x0000001d, 0x0004002b, 0x0000000d, 0x0000001f, 0xbf000000,
0x0005002c, 0x00000017, 0x00000020, 0x0000001f, 0x0000001d, 0x0004002b, 0x0000000d, 0x00000021,
0x3f000000, 0x0005002c, 0x00000017, 0x00000022, 0x00000021, 0x0000001d, 0x0005002c, 0x00000017,
0x00000023, 0x00000011, 0x0000001d, 0x0005002c, 0x00000017, 0x00000024, 0x0000001d, 0x0000001f,
0x0005002c, 0x00000017, 0x00000025, 0x0000001f, 0x0000001f, 0x0005002c, 0x00000017, 0x00000026,
0x00000021, 0x0000001f, 0x0005002c, 0x00000017, 0x00000027, 0x00000011, 0x0000001f, 0x0005002c,
0x00000017, 0x00000028, 0x0000001d, 0x00000021, 0x0005002c, 0x00000017, 0x00000029, 0x0000001f,
0x00000021, 0x0005002c, 0x00000017, 0x0000002a, 0x00000021, 0x00000021, 0x0005002c, 0x00000017,
0x0000002b, 0x00000011, 0x00000021, 0x0005002c, 0x00000017, 0x0000002c, 0x0000001d, 0x00000011,
0x0005002c, 0x00000017, 0x0000002d, 0x0000001f, 0x00000011, 0x0005002c, 0x00000017, 0x0000002e,
0x00000021, 0x00000011, 0x0005002c, 0x00000017, 0x0000002f, 0x00000011, 0x00000011, 0x0004002b,
0x0000000d, 0x00000030, 0x3d800000, 0x0006002c, 0x0000000f, 0x00000031, 0x00000030, 0x00000030,
0x00000030, 0x00050036, 0x0000001a, 0x00000001, 0x00000000, 0x0000001b, 0x000200f8, 0x00000032,
0x0004003d, 0x00000017, 0x00000033, 0x00000002, 0x00050041, 0x0000001c, 0x00000034, 0x00000005,
0x0000000c, 0x0004003d, 0x00000013, 0x00000035, 0x00000034, 0x0007004f, 0x00000017, 0x00000036,
0x00000035, 0x00000035, 0x00000000, 0x00000001, 0x00050085, 0x00000017, 0x00000037, 0x00000033,
0x00000036, 0x0007004f, 0x00000017, 0x00000038, 0x00000035, 0x00000035, 0x00000002, 0x00000003,
0x00050081, 0x00000017, 0x00000039, 0x00000037, 0x00000038, 0x00050041, 0x0000001c, 0x0000003a,
0x00000005, 0x00000010, 0x0004003d, 0x00000013, 0x0000003b, 0x0000003a, 0x0007004f, 0x00000017,
0x0000003c, 0x0000003b, 0x0000003b, 0x00000000, 0x00000001, 0x00050085, 0x00000017, 0x0000003d,
0x0000001e, 0x0000003c, 0x0004003d, 0x00000006, 0x0000003e, 0x00000007, 0x0004003d, 0x00000008,
0x0000003f, 0x00000009, 0x00050081, 0x00000017, 0x00000040, 0x00000039, 0x0000003d, 0x00050056,
0x0000000a, 0x00000041, 0x0000003e, 0x0000003f, 0x00070058, 0x00000013, 0x00000042, 0x00000041,
0x00000040, 0x00000002, 0x0000000e, 0x0008004f, 0x0000000f, 0x00000043, 0x00000042, 0x00000042,
0x00000000, 0x00000001, 0x00000002, 0x00050085, 0x00000017, 0x00000044, 0x00000020, 0x0000003c,
0x0004003d, 0x00000006, 0x00000045, 0x00000007, 0x0004003d, 0x00000008, 0x00000046, 0x00000009,
0x00050081, 0x00000017, 0x00000047, 0x00000039, 0x00000044, 0x00050056, 0x0000000a, 0x00000048,
0x00000045, 0x00000046, 0x00070058, 0x00000013, 0x00000049, 0x00000048, 0x00000047, 0x00000002,
0x0000000e, 0x0008004f, 0x0000000f, 0x0000004a, 0x00000049, 0x00000049, 0x00000000, 0x00000001,
0x00000002, 0x00050081, 0x0000000f, 0x0000004b, 0x00000043, 0x0000004a, 0x00050085, 0x00000017,
0x0000004c, 0x00000022, 0x0000003c, 0x0004003d, 0x00000006, 0x0000004d, 0x00000007, 0x0004003d,
0x00000008, 0x0000004e, 0x00000009, 0x00050081, 0x00000017, 0x0000004f, 0x00000039, 0x0000004c,
0x00050056, 0x0000000a, 0x00000050, 0x0000004d, 0x0000004e, 0x00070058, 0x00000013, 0x00000051,
0x00000050, 0x0000004f, 0x00000002, 0x0000000e, 0x0008004f, 0x0000000f, 0x00000052, 0x00000051,
0x00000051, 0x00000000, 0x00000001, 0x00000002, 0x00050081, 0x0000000f, 0x00000053, 0x0000004b,
0x00000052, 0x00050085, 0x00000017, 0x00000054, 0x00000023, 0x0000003c, 0x0004003d, 0x00000006,
0x00000055, 0x00000007, 0x0004003d, 0x00000008, 0x00000056, 0x00000009, 0x00050081, 0x00000017,
0x00000057, 0x00000039, 0x00000054, 0x00050056, 0x0000000a, 0x00000058, 0x00000055, 0x00000056,
0x00070058, 0x00000013, 0x00000059, 0x00000058, 0x00000057, 0x00000002, 0x0000000e, 0x0008004f,
0x0000000f, 0x0000005a, 0x00000059, 0x00000059, 0x00000000, 0x00000001, 0x00000002, 0x00050081,
0x0000000f, 0x0000005b, 0x00000053, 0x0000005a, 0x00050085, 0x00000017, 0x0000005c, 0x00000024,
0x0000003c, 0x0004003d, 0x00000006, 0x0000005d, 0x00000007, 0x0004003d, 0x00000008, 0x0000005e,
0x00000009, 0x00050081, 0x00000017, 0x0000005f, 0x00000039, 0x0000005c, 0x00050056, 0x0000000a,
0x00000060, 0x0000005d, 0x0000005e, 0x00070058, 0x00000013, 0x00000061, 0x00000060, 0x0000005f,
0x00000002, 0x0000000e, 0x0008004f, 0x0000000f, 0x00000062, 0x00000061, 0x00000061, 0x00000000,
0x00000001, 0x00000002, 0x00050081, 0x0000000f, 0x00000063, 0x0000005b, 0x00000062, 0x00050085,
0x00000017, 0x00000064, 0x00000025, 0x0000003c, 0x0004003d, 0x00000006, 0x00000065, 0x00000007,
0x0004003d, 0x00000008, 0x00000066, 0x00000009, 0x00050081, 0x00000017, 0x00000067, 0x00000039,
0x00000064, 0x00050056, 0x0000000a, 0x00000068, 0x00000065, 0x00000066, 0x00070058, 0x00000013,
0x00000069, 0x00000068, 0x00000067, 0x00000002, 0x0000000e, 0x0008004f, 0x0000000f, 0x0000006a,
0x00000069, 0x00000069, 0x00000000, 0x00000001, 0x00000002, 0x00050081, 0x0000000f, 0x0000006b,
0x00000063, 0x0000006a, 0x00050085, 0x00000017, 0x0000006c, 0x00000026, 0x0000003c, 0x0004003d,
0x00000006, 0x0000006d, 0x00000007, 0x0004003d, 0x00000008, 0x0000006e, 0x00000009, 0x00050081,
0x00000017, 0x0000006f, 0x00000039, 0x0000006c, 0x00050056, 0x0000000a, 0x00000070, 0x0000006d,
0x0000006e, 0x00070058, 0x00000013, 0x00000071, 0x00000070, 0x0000006f, 0x00000002, 0x0000000e,
0x0008004f, 0x0000000f, 0x00000072, 0x00000071, 0x00000071, 0x00000000, 0x00000001, 0x00000002,
0x00050081, 0x0000000f, 0x00000073, 0x0000006b, 0x00000072, 0x00050085, 0x00000017, 0x00000074,
0x00000027, 0x0000003c, 0x0004003d, 0x00000006, 0x00000075, 0x00000007, 0x0004003d, 0x00000008,
0x00000076, 0x00000009, 0x00050081, 0x00000017, 0x00000077, 0x00000039, 0x00000074, 0x00050056,
0x0000000a, 0x00000078, 0x00000075, 0x00000076, 0x00070058, 0x00000013, 0x00000079, 0x00000078,
0x00000077, 0x00000002, 0x0000000e, 0x0008004f, 0x0000000f, 0x0000007a, 0x00000079, 0x00000079,
0x00000000, 0x00000001, 0x00000002, 0x00050081, 0x0000000f, 0x0000007b, 0x00000073, 0x0000007a,
0x00050085, 0x00000017, 0x0000007c, 0x00000028, 0x0000003c, 0x0004003d, 0x00000006, 0x0000007d,
0x00000007, 0x0004003d, 0x00000008, 0x0000007e, 0x00000009, 0x00050081, 0x00000017, 0x0000007f,
0x00000039, 0x0000007c, 0x00050056, 0x0000000a, 0x00000080, 0x0000007d, 0x0000007e, 0x00070058,
0x00000013, 0x00000081, 0x00000080, 0x0000007f, 0x00000002, 0x0000000e, 0x0008004f, 0x0000000f,
0x00000082, 0x00000081, 0x00000081, 0x00000000, 0x00000001, 0x00000002, 0x00050081, 0x0000000f,
0x00000083, 0x0000007b, 0x00000082, 0x00050085, 0x00000017, 0x00000084, 0x00000029, 0x0000003c,
0x0004003d, 0x00000006, 0x00000085, 0x00000007, 0x0004003d, 0x00000008, 0x00000086, 0x00000009,
0x00050081, 0x00000017, 0x00000087, 0x00000039, 0x00000084, 0x00050056, 0x0000000a, 0x00000088,
0x00000085, 0x00000086, 0x00070058, 0x00000013, 0x00000089, 0x00000088, 0x00000087, 0x00000002,
0x0000000e, 0x0008004f, 0x0000000f, 0x0000008a, 0x00000089, 0x00000089, 0x00000000, 0x00000001,
0x00000002, 0x00050081, 0x0000000f, 0x0000008b, 0x00000083, 0x0000008a, 0x00050085, 0x00000017,
0x0000008c, 0x0000002a, 0x0000003c, 0x0004003d, 0x00000006, 0x0000008d, 0x00000007, 0x0004003d,
0x00000008, 0x0000008e, 0x00000009, 0x00050081, 0x00000017, 0x0000008f, 0x00000039, 0x0000008c,
0x00050056, 0x0000000a, 0x00000090, 0x0000008d, 0x0000008e, 0x00070058, 0x00000013, 0x00000091,
0x00000090, 0x0000008f, 0x00000002, 0x0000000e, 0x0008004f, 0x0000000f, 0x00000092, 0x00000091,
0x00000091, 0x00000000, 0x00000001, 0x00000002, 0x00050081, 0x0000000f, 0x00000093, 0x0000008b,
0x00000092, 0x00050085, 0x00000017, 0x00000094, 0x0000002b, 0x0000003c, 0x0004003d, 0x00000006,
0x00000095, 0x00000007, 0x0004003d, 0x00000008, 0x00000096, 0x00000009, 0x00050081, 0x00000017,
0x00000097, 0x00000039, 0x00000094, 0x00050056, 0x0000000a, 0x00000098, 0x00000095, 0x00000096,
0x00070058, 0x00000013, 0x00000099, 0x00000098, 0x00000097, 0x00000002, 0x0000000e, 0x0008004f,
0x0000000f, 0x0000009a, 0x00000099, 0x00000099, 0x00000000, 0x00000001, 0x00000002, 0x00050081,
0x0000000f, 0x0000009b, 0x00000093, 0x0000009a, 0x00050085, 0x00000017, 0x0000009c, 0x0000002c,
0x0000003c, 0x0004003d, 0x00000006, 0x0000009d, 0x00000007, 0x0004003d, 0x00000008, 0x0000009e,
0x00000009, 0x00050081, 0x00000017, 0x0000009f, 0x00000039, 0x0000009c, 0x00050056, 0x0000000a,
0x000000a0, 0x0000009d, 0x0000009e, 0x00070058, 0x00000013, 0x000000a1, 0x000000a0, 0x0000009f,
0x00000002, 0x0000000e, 0x0008004f, 0x0000000f, 0x000000a2, 0x000000a1, 0x000000a1, 0x00000000,
0x00000001, 0x00000002, 0x00050081, 0x0000000f, 0x000000a3, 0x0000009b, 0x000000a2, 0x00050085,
0x00000017, 0x000000a4, 0x0000002d, 0x0000003c, 0x0004003d, 0x00000006, 0x000000a5, 0x00000007,
0x0004003d, 0x00000008, 0x000000a6, 0x00000009, 0x00050081, 0x00000017, 0x000000a7, 0x00000039,
0x000000a4, 0x00050056, 0x0000000a, 0x000000a8, 0x000000a5, 0x000000a6, 0x00070058, 0x00000013,
0x000000a9, 0x000000a8, 0x000000a7, 0x00000002, 0x0000000e, 0x0008004f, 0x0000000f, 0x000000aa,
0x000000a9, 0x000000a9, 0x00000000, 0x00000001, 0x00000002, 0x00050081, 0x0000000f, 0x000000ab,
0x000000a3, 0x000000aa, 0x00050085, 0x00000017, 0x000000ac, 0x0000002e, 0x0000003c, 0x0004003d,
0x00000006, 0x000000ad, 0x00000007, 0x0004003d, 0x00000008, 0x000000ae, 0x00000009, 0x00050081,
0x00000017, 0x000000af, 0x00000039, 0x000000ac, 0x00050056, 0x0000000a, 0x000000b0, 0x000000ad,
0x000000ae, 0x00070058, 0x00000013, 0x000000b1, 0x000000b0, 0x000000af, 0x00000002, 0x0000000e,
0x0008004f, 0x0000000f, 0x000000b2, 0x000000b1, 0x000000b1, 0x00000000, 0x00000001, 0x00000002,
0x00050081, 0x0000000f, 0x000000b3, 0x000000ab, 0x000000b2, 0x00050085, 0x00000017, 0x000000b4,
0x0000002f, 0x0000003c, 0x0004003d, 0x00000006, 0x000000b5, 0x00000007, 0x0004003d, 0x00000008,
0x000000b6, 0x00000009, 0x00050081, 0x00000017, 0x000000b7, 0x00000039, 0x000000b4, 0x00050056,
0x0000000a, 0x000000b8, 0x000000b5, 0x000000b6, 0x00070058, 0x00000013, 0x000000b9, 0x000000b8,
0x000000b7, 0x00000002, 0x0000000e, 0x0008004f, 0x0000000f, 0x000000ba, 0x000000b9, 0x000000b9,
0x00000000, 0x00000001, 0x00000002, 0x00050081, 0x0000000f, 0x000000bb, 0x000000b3, 0x000000ba,
0x00050085, 0x0000000f, 0x000000bc, 0x000000bb, 0x00000031, 0x00050051, 0x0000000d, 0x000000bd,
0x000000bc, 0x00000000, 0x00050051, 0x0000000d, 0x000000be, 0x000000bc, 0x00000001, 0x00050051,
0x0000000d, 0x000000bf, 0x000000bc, 0x00000002, 0x00070050, 0x00000013, 0x000000c0, 0x000000bd,
0x000000be, 0x000000bf, 0x00000012, 0x0003003e, 0x00000003, 0x000000c0, 0x000100fd, 0x00010038,
};
// blur.hlsl : ps_menu_gauss (2284 bytes)
@ -16728,9 +16732,9 @@ static const uint32_t k_outline_ps_main[] = {
0x00000011, 0x0003003e, 0x00000004, 0x000000ff, 0x000100fd, 0x00010038,
};
// overlay2d.hlsl : vs_main (3496 bytes)
// overlay2d.hlsl : vs_main (3600 bytes)
static const uint32_t k_overlay2d_vs_main[] = {
0x07230203, 0x00010300, 0x000e0000, 0x00000094, 0x00000000, 0x00020011, 0x00000001, 0x0006000b,
0x07230203, 0x00010300, 0x000e0000, 0x00000099, 0x00000000, 0x00020011, 0x00000001, 0x0006000b,
0x00000001, 0x4c534c47, 0x6474732e, 0x3035342e, 0x00000000, 0x0003000e, 0x00000000, 0x00000001,
0x000b000f, 0x00000000, 0x00000002, 0x6d5f7376, 0x006e6961, 0x00000003, 0x00000004, 0x00000005,
0x00000006, 0x00000007, 0x00000008, 0x00030003, 0x00000005, 0x00000258, 0x00040005, 0x00000009,
@ -16799,47 +16803,50 @@ static const uint32_t k_overlay2d_vs_main[] = {
0x00000023, 0x0000005c, 0x00000050, 0x00000057, 0x0007004f, 0x00000023, 0x0000005d, 0x0000005b,
0x0000005b, 0x00000000, 0x00000001, 0x00050050, 0x00000023, 0x0000005e, 0x00000047, 0x00000047,
0x00050088, 0x00000023, 0x0000005f, 0x0000005d, 0x0000005e, 0x0005008e, 0x00000023, 0x00000060,
0x0000005c, 0x0000001a, 0x00050051, 0x00000016, 0x00000061, 0x0000005f, 0x00000000, 0x000500bc,
0x0000001c, 0x00000062, 0x00000061, 0x0000001b, 0x000300f7, 0x00000063, 0x00000000, 0x000400fa,
0x00000062, 0x00000064, 0x00000063, 0x000200f8, 0x00000064, 0x00050051, 0x00000016, 0x00000065,
0x00000060, 0x00000000, 0x00050083, 0x00000016, 0x00000066, 0x0000001b, 0x00000065, 0x000500ba,
0x0000001c, 0x00000067, 0x00000061, 0x00000066, 0x000200f9, 0x00000063, 0x000200f8, 0x00000063,
0x000700f5, 0x0000001c, 0x00000068, 0x0000001d, 0x0000004d, 0x00000067, 0x00000064, 0x000300f7,
0x00000069, 0x00000000, 0x000400fa, 0x00000068, 0x0000006a, 0x00000069, 0x000200f8, 0x0000006a,
0x00060052, 0x00000023, 0x0000006b, 0x0000001b, 0x0000005f, 0x00000000, 0x000200f9, 0x00000069,
0x000200f8, 0x00000069, 0x000700f5, 0x00000023, 0x0000006c, 0x0000005f, 0x00000063, 0x0000006b,
0x0000006a, 0x00050051, 0x00000016, 0x0000006d, 0x0000006c, 0x00000000, 0x000500be, 0x0000001c,
0x0000006e, 0x0000006d, 0x0000001e, 0x000300f7, 0x0000006f, 0x00000000, 0x000400fa, 0x0000006e,
0x00000070, 0x0000006f, 0x000200f8, 0x00000070, 0x00050051, 0x00000016, 0x00000071, 0x00000060,
0x00000000, 0x00050081, 0x00000016, 0x00000072, 0x0000001e, 0x00000071, 0x000500b8, 0x0000001c,
0x00000073, 0x0000006d, 0x00000072, 0x000200f9, 0x0000006f, 0x000200f8, 0x0000006f, 0x000700f5,
0x0000001c, 0x00000074, 0x0000001d, 0x00000069, 0x00000073, 0x00000070, 0x000300f7, 0x00000075,
0x00000000, 0x000400fa, 0x00000074, 0x00000076, 0x00000075, 0x000200f8, 0x00000076, 0x00060052,
0x00000023, 0x00000077, 0x0000001e, 0x0000006c, 0x00000000, 0x000200f9, 0x00000075, 0x000200f8,
0x00000075, 0x000700f5, 0x00000023, 0x00000078, 0x0000006c, 0x0000006f, 0x00000077, 0x00000076,
0x00050051, 0x00000016, 0x00000079, 0x00000078, 0x00000001, 0x000500bc, 0x0000001c, 0x0000007a,
0x00000079, 0x0000001b, 0x000300f7, 0x0000007b, 0x00000000, 0x000400fa, 0x0000007a, 0x0000007c,
0x0000007b, 0x000200f8, 0x0000007c, 0x00050051, 0x00000016, 0x0000007d, 0x00000060, 0x00000001,
0x00050083, 0x00000016, 0x0000007e, 0x0000001b, 0x0000007d, 0x000500ba, 0x0000001c, 0x0000007f,
0x00000079, 0x0000007e, 0x000200f9, 0x0000007b, 0x000200f8, 0x0000007b, 0x000700f5, 0x0000001c,
0x00000080, 0x0000001d, 0x00000075, 0x0000007f, 0x0000007c, 0x000300f7, 0x00000081, 0x00000000,
0x000400fa, 0x00000080, 0x00000082, 0x00000081, 0x000200f8, 0x00000082, 0x00060052, 0x00000023,
0x00000083, 0x0000001b, 0x00000078, 0x00000001, 0x000200f9, 0x00000081, 0x000200f8, 0x00000081,
0x000700f5, 0x00000023, 0x00000084, 0x00000078, 0x0000007b, 0x00000083, 0x00000082, 0x00050051,
0x00000016, 0x00000085, 0x00000084, 0x00000001, 0x000500be, 0x0000001c, 0x00000086, 0x00000085,
0x0000001e, 0x000300f7, 0x00000087, 0x00000000, 0x000400fa, 0x00000086, 0x00000088, 0x00000087,
0x000200f8, 0x00000088, 0x00050051, 0x00000016, 0x00000089, 0x00000060, 0x00000001, 0x00050081,
0x00000016, 0x0000008a, 0x0000001e, 0x00000089, 0x000500b8, 0x0000001c, 0x0000008b, 0x00000085,
0x0000008a, 0x000200f9, 0x00000087, 0x000200f8, 0x00000087, 0x000700f5, 0x0000001c, 0x0000008c,
0x0000001d, 0x00000081, 0x0000008b, 0x00000088, 0x000300f7, 0x0000008d, 0x00000000, 0x000400fa,
0x0000008c, 0x0000008e, 0x0000008d, 0x000200f8, 0x0000008e, 0x00060052, 0x00000023, 0x0000008f,
0x0000001e, 0x00000084, 0x00000001, 0x000200f9, 0x0000008d, 0x000200f8, 0x0000008d, 0x000700f5,
0x00000023, 0x00000090, 0x00000084, 0x00000087, 0x0000008f, 0x0000008e, 0x0005008e, 0x00000023,
0x00000091, 0x00000090, 0x00000047, 0x0009004f, 0x00000020, 0x00000092, 0x0000005b, 0x00000091,
0x00000004, 0x00000005, 0x00000002, 0x00000003, 0x000200f9, 0x0000004c, 0x000200f8, 0x0000004c,
0x000700f5, 0x00000020, 0x00000093, 0x00000048, 0x0000002b, 0x00000092, 0x0000008d, 0x0003003e,
0x00000006, 0x00000093, 0x0003003e, 0x00000007, 0x0000002d, 0x0003003e, 0x00000008, 0x0000002e,
0x000100fd, 0x00010038,
0x0000005c, 0x0000001a, 0x00070041, 0x0000002a, 0x00000061, 0x0000000a, 0x0000000d, 0x00000015,
0x00000013, 0x0004003d, 0x00000016, 0x00000062, 0x00000061, 0x000500ba, 0x0000001c, 0x00000063,
0x00000062, 0x00000017, 0x000600a9, 0x00000016, 0x00000064, 0x00000063, 0x00000062, 0x0000001b,
0x00050051, 0x00000016, 0x00000065, 0x0000005f, 0x00000000, 0x000500bc, 0x0000001c, 0x00000066,
0x00000065, 0x00000064, 0x000300f7, 0x00000067, 0x00000000, 0x000400fa, 0x00000066, 0x00000068,
0x00000067, 0x000200f8, 0x00000068, 0x00050051, 0x00000016, 0x00000069, 0x00000060, 0x00000000,
0x00050083, 0x00000016, 0x0000006a, 0x00000064, 0x00000069, 0x000500ba, 0x0000001c, 0x0000006b,
0x00000065, 0x0000006a, 0x000200f9, 0x00000067, 0x000200f8, 0x00000067, 0x000700f5, 0x0000001c,
0x0000006c, 0x0000001d, 0x0000004d, 0x0000006b, 0x00000068, 0x000300f7, 0x0000006d, 0x00000000,
0x000400fa, 0x0000006c, 0x0000006e, 0x0000006d, 0x000200f8, 0x0000006e, 0x00060052, 0x00000023,
0x0000006f, 0x00000064, 0x0000005f, 0x00000000, 0x000200f9, 0x0000006d, 0x000200f8, 0x0000006d,
0x000700f5, 0x00000023, 0x00000070, 0x0000005f, 0x00000067, 0x0000006f, 0x0000006e, 0x00050051,
0x00000016, 0x00000071, 0x00000070, 0x00000000, 0x0004007f, 0x00000016, 0x00000072, 0x00000064,
0x000500be, 0x0000001c, 0x00000073, 0x00000071, 0x00000072, 0x000300f7, 0x00000074, 0x00000000,
0x000400fa, 0x00000073, 0x00000075, 0x00000074, 0x000200f8, 0x00000075, 0x00050051, 0x00000016,
0x00000076, 0x00000060, 0x00000000, 0x00050083, 0x00000016, 0x00000077, 0x00000076, 0x00000064,
0x000500b8, 0x0000001c, 0x00000078, 0x00000071, 0x00000077, 0x000200f9, 0x00000074, 0x000200f8,
0x00000074, 0x000700f5, 0x0000001c, 0x00000079, 0x0000001d, 0x0000006d, 0x00000078, 0x00000075,
0x000300f7, 0x0000007a, 0x00000000, 0x000400fa, 0x00000079, 0x0000007b, 0x0000007a, 0x000200f8,
0x0000007b, 0x00060052, 0x00000023, 0x0000007c, 0x00000072, 0x00000070, 0x00000000, 0x000200f9,
0x0000007a, 0x000200f8, 0x0000007a, 0x000700f5, 0x00000023, 0x0000007d, 0x00000070, 0x00000074,
0x0000007c, 0x0000007b, 0x00050051, 0x00000016, 0x0000007e, 0x0000007d, 0x00000001, 0x000500bc,
0x0000001c, 0x0000007f, 0x0000007e, 0x0000001b, 0x000300f7, 0x00000080, 0x00000000, 0x000400fa,
0x0000007f, 0x00000081, 0x00000080, 0x000200f8, 0x00000081, 0x00050051, 0x00000016, 0x00000082,
0x00000060, 0x00000001, 0x00050083, 0x00000016, 0x00000083, 0x0000001b, 0x00000082, 0x000500ba,
0x0000001c, 0x00000084, 0x0000007e, 0x00000083, 0x000200f9, 0x00000080, 0x000200f8, 0x00000080,
0x000700f5, 0x0000001c, 0x00000085, 0x0000001d, 0x0000007a, 0x00000084, 0x00000081, 0x000300f7,
0x00000086, 0x00000000, 0x000400fa, 0x00000085, 0x00000087, 0x00000086, 0x000200f8, 0x00000087,
0x00060052, 0x00000023, 0x00000088, 0x0000001b, 0x0000007d, 0x00000001, 0x000200f9, 0x00000086,
0x000200f8, 0x00000086, 0x000700f5, 0x00000023, 0x00000089, 0x0000007d, 0x00000080, 0x00000088,
0x00000087, 0x00050051, 0x00000016, 0x0000008a, 0x00000089, 0x00000001, 0x000500be, 0x0000001c,
0x0000008b, 0x0000008a, 0x0000001e, 0x000300f7, 0x0000008c, 0x00000000, 0x000400fa, 0x0000008b,
0x0000008d, 0x0000008c, 0x000200f8, 0x0000008d, 0x00050051, 0x00000016, 0x0000008e, 0x00000060,
0x00000001, 0x00050081, 0x00000016, 0x0000008f, 0x0000001e, 0x0000008e, 0x000500b8, 0x0000001c,
0x00000090, 0x0000008a, 0x0000008f, 0x000200f9, 0x0000008c, 0x000200f8, 0x0000008c, 0x000700f5,
0x0000001c, 0x00000091, 0x0000001d, 0x00000086, 0x00000090, 0x0000008d, 0x000300f7, 0x00000092,
0x00000000, 0x000400fa, 0x00000091, 0x00000093, 0x00000092, 0x000200f8, 0x00000093, 0x00060052,
0x00000023, 0x00000094, 0x0000001e, 0x00000089, 0x00000001, 0x000200f9, 0x00000092, 0x000200f8,
0x00000092, 0x000700f5, 0x00000023, 0x00000095, 0x00000089, 0x0000008c, 0x00000094, 0x00000093,
0x0005008e, 0x00000023, 0x00000096, 0x00000095, 0x00000047, 0x0009004f, 0x00000020, 0x00000097,
0x0000005b, 0x00000096, 0x00000004, 0x00000005, 0x00000002, 0x00000003, 0x000200f9, 0x0000004c,
0x000200f8, 0x0000004c, 0x000700f5, 0x00000020, 0x00000098, 0x00000048, 0x0000002b, 0x00000097,
0x00000092, 0x0003003e, 0x00000006, 0x00000098, 0x0003003e, 0x00000007, 0x0000002d, 0x0003003e,
0x00000008, 0x0000002e, 0x000100fd, 0x00010038,
};
// overlay2d.hlsl : ps_main (5168 bytes)

View file

@ -49,7 +49,7 @@
#include <rex/filesystem/devices/host_path_device.h>
#include <rex/filesystem/vfs.h>
#include <rex/graphics/flags.h>
#include <rex/graphics/ultrawide_debug.h>
#include <rex/graphics/native_guest_renderer.h>
#include <rex/input/input_system.h>
#include <rex/kernel/xam/module.h>
#include <rex/logging.h>
@ -66,7 +66,6 @@
#include <rex/ui/keybinds.h>
#include <rex/ui/window.h>
#include <rex/ui/overlay/simple_settings_overlay.h>
#include <rex/ui/overlay/ultrawide_targets_overlay.h>
#include <imgui.h>
#include <toml++/toml.hpp>
@ -93,44 +92,17 @@ REXCVAR_DEFINE_STRING(skate3_dlc_root, "", "Skate 3",
REXCVAR_DEFINE_BOOL(skate3_auto_install_dlc, true, "Skate 3",
"Install DLC package files found in configured DLC folders");
REXCVAR_DEFINE_BOOL(skate3_ultrawide, false, "Skate 3",
"Automatically derive an ultrawide guest video mode from the host display");
"Ultrawide display support: the native renderer draws true widescreen "
"frames at the host display aspect (requires the native renderer; the "
"emulated fallback presents 16:9 pillarboxed)")
.lifecycle(rex::cvar::Lifecycle::kRequiresRestart);
REXCVAR_DEFINE_DOUBLE(skate3_field_of_view, 60.0, "Skate 3",
"Gameplay camera field of view in degrees")
.range(40.0, 120.0);
REXCVAR_DEFINE_INT32(skate3_ultrawide_base_height, 720, "Skate 3",
"Guest video mode height used when deriving ultrawide modes")
.range(480, 2160)
.lifecycle(rex::cvar::Lifecycle::kRequiresRestart);
REXCVAR_DEFINE_BOOL(skate3_ultrawide_hor_plus, true, "Skate 3",
"Apply Hor+ clip-space correction for ultrawide video modes");
REXCVAR_DEFINE_DOUBLE(skate3_ultrawide_hor_plus_scale, 0.0, "Skate 3",
"Manual Hor+ X scale override (0 = derive from host aspect)")
.range(0.0, 4.0)
.lifecycle(rex::cvar::Lifecycle::kRequiresRestart);
REXCVAR_DEFINE_BOOL(skate3_ultrawide_disable_ndc_correction, false, "Skate 3",
"Diagnostic: disable the GPU NDC Hor+ correction while preserving guest-side "
"ultrawide diagnostics");
REXCVAR_DEFINE_BOOL(skate3_ultrawide_trace_draws, false, "Skate 3",
"Diagnostic: collect live draw fingerprints for the F7 ultrawide overlay");
REXCVAR_DEFINE_BOOL(skate3_ultrawide_object_stage_trace_to_disk, false, "Skate 3",
"Diagnostic: write object render-stage transition summaries to disk");
REXCVAR_DEFINE_BOOL(skate3_ultrawide_object_stage_trace_continuous, false, "Skate 3",
"Diagnostic: continuously trace object render-stage summaries");
REXCVAR_DEFINE_INT32(skate3_ultrawide_object_stage_trace_frames_remaining, 0, "Skate 3",
"Diagnostic: trace this many object render-stage frames")
.range(0, 1000000);
REXCVAR_DEFINE_INT32(skate3_ultrawide_object_stage_marker, 0, "Skate 3",
"Diagnostic: mark the next object-stage frame (1 visible, 2 invisible)")
.range(0, 2);
REXCVAR_DEFINE_INT32(skate3_ultrawide_object_stage_missing_limit, 256, "Skate 3",
"Diagnostic: maximum missing-main objects to log per object-stage frame")
.range(0, 4096);
REXCVAR_DEFINE_BOOL(skate3_ultrawide_force_main_visibility_flags, false, "Skate 3",
"Force main render object visibility flags while Hor+ ultrawide is active");
REXCVAR_DEFINE_BOOL(skate3_ultrawide_widen_game_frustum, true, "Skate 3",
"Widen the game-side main-world cull frustum to match the ultrawide view");
REXCVAR_DEFINE_DOUBLE(skate3_ultrawide_target_aspect, 0.0, "Skate 3",
"Derived host display aspect for ultrawide presentation (0 = disabled)")
"Ultrawide display aspect (0 = derive from the host display at boot)")
.range(0.0, 8.0);
namespace {
@ -290,40 +262,42 @@ std::optional<DisplaySize> ResolveUltrawideTargetDisplaySize() {
}
void ApplyUltrawideVideoDefaults() {
if (!REXCVAR_GET(skate3_ultrawide) ||
rex::cvar::HasNonDefaultValue("skate3_ultrawide_target_aspect")) {
if (!REXCVAR_GET(skate3_ultrawide)) {
return;
}
// Explicitly configured aspect wins; otherwise derive it from the
// fullscreen monitor (or a configured window size) once at boot.
double target_aspect = rex::cvar::HasNonDefaultValue("skate3_ultrawide_target_aspect")
? REXCVAR_GET(skate3_ultrawide_target_aspect)
: 0.0;
if (target_aspect <= kSixteenNineAspect + kUltrawideAspectEpsilon) {
const std::optional<DisplaySize> target_size = ResolveUltrawideTargetDisplaySize();
if (!target_size || target_size->width <= 0 || target_size->height <= 0) {
return;
}
const double target_aspect =
target_aspect =
static_cast<double>(target_size->width) / static_cast<double>(target_size->height);
if (target_aspect <= kSixteenNineAspect + kUltrawideAspectEpsilon) {
return;
}
rex::cvar::SetFlagByName("skate3_ultrawide_target_aspect", std::to_string(target_aspect));
}
// The native renderer draws true wide frames at this aspect (wide guest
// output + Hor+ projection + centered 2D band). Emulated fallback frames
// keep the 16:9 guest output and present pillarboxed via the letterbox
// default below.
rex::graphics::SetNativeGuestOutputWideAspect(
std::clamp(target_aspect, kSixteenNineAspect, 8.0));
if (!rex::cvar::HasNonDefaultValue("present_letterbox")) {
rex::cvar::SetFlagByName("present_letterbox", "true");
}
}
void DisableActiveUltrawideDiagnostics() {
void DisableActiveDebugDiagnostics() {
constexpr std::string_view kFalseFlags[] = {
"skate3_ultrawide_trace_draws",
"skate3_ultrawide_object_stage_trace_to_disk",
"skate3_ultrawide_object_stage_trace_continuous",
"skate3_ultrawide_force_main_visibility_flags",
"skate3_ultrawide_texture_trace_bind_keys",
"skate3_ultrawide_texture_trace_scaled_resolve",
"skate3_ultrawide_ignore_streamer_texture_invalidations",
"skate3_ultrawide_screen_callback_tracking",
"skate3_ultrawide_fake_occlusion_queries",
"perf_draw_fingerprints",
"perf_keep_heavyweight_draw_diagnostics",
"trace_gpu_stream",
@ -333,9 +307,6 @@ void DisableActiveUltrawideDiagnostics() {
}
constexpr std::string_view kZeroFlags[] = {
"skate3_ultrawide_texture_trace_remaining",
"skate3_ultrawide_object_stage_trace_frames_remaining",
"skate3_ultrawide_object_stage_marker",
"vulkan_debug_log_frame_summaries_remaining",
"vulkan_debug_log_resolve_decisions_remaining",
"vulkan_debug_log_team_profile_background_candidates_remaining",
@ -346,8 +317,6 @@ void DisableActiveUltrawideDiagnostics() {
for (std::string_view flag : kZeroFlags) {
rex::cvar::SetFlagByName(std::string(flag), "0");
}
rex::cvar::SetFlagByName("skate3_ultrawide_fake_occlusion_sample_count", "1000");
}
std::filesystem::path DefaultDocumentsUserRoot() {
@ -558,11 +527,7 @@ void Skate3BaseApp::OnConfigurePaths(rex::PathConfig& paths) {
LoadAndNormalizeSimpleSettings(user_settings_path_, config_path_);
Skate3InitializeFieldOfViewOverride();
ApplyUltrawideVideoDefaults();
if (!rex::graphics::ultrawide_debug::LoadTargets(paths.cache_root /
"skate3_ultrawide_targets.toml")) {
rex::graphics::ultrawide_debug::LoadBuiltInSkate3Classifier();
}
DisableActiveUltrawideDiagnostics();
DisableActiveDebugDiagnostics();
}
void Skate3BaseApp::OnConfigureFonts(ImFontAtlas* atlas) {
@ -745,15 +710,6 @@ void Skate3BaseApp::OnCreateDialogs(rex::ui::ImGuiDrawer* drawer) {
"Toggle native/emulated renderer", [] {
skate3::native_scene::ToggleSceneEnabled();
});
rex::ui::RegisterBind("bind_skate3_ultrawide_targets", "F7",
"Skate 3 ultrawide targets", [this] {
// Developer tuning dialog; rides the same opt-in as
// the F4 cvar browser.
if (rex::cvar::Query<bool>(
"advanced_settings_overlay_enabled")) {
ToggleUltrawideTargets();
}
});
rex::ui::RegisterBind("bind_skate3_save_draw_fingerprints", "F8",
"Save draw fingerprint log", [this] {
SaveDrawFingerprintLog();
@ -856,7 +812,6 @@ void Skate3BaseApp::OnPostSetup() {
void Skate3BaseApp::OnShutdown() {
rex::ui::UnregisterBind("bind_skate3_menu");
rex::ui::UnregisterBind("bind_skate3_menu_alt");
rex::ui::UnregisterBind("bind_skate3_ultrawide_targets");
rex::ui::UnregisterBind("bind_skate3_save_draw_fingerprints");
rex::ui::UnregisterBind("bind_skate3_log_debug_marker");
rex::ui::UnregisterBind("bind_skate3_log_user_marker");
@ -864,7 +819,6 @@ void Skate3BaseApp::OnShutdown() {
ApplyGameplayCursorMode();
skate3::native_scene::SetSettingsMenuBlur(false);
simple_settings_dialog_.reset();
ultrawide_targets_dialog_.reset();
native_debug_dialog_.reset();
render_mode_indicator_.reset();
}
@ -969,24 +923,6 @@ void Skate3BaseApp::ToggleSimpleSettings() {
simple_settings_dialog_->Show();
}
void Skate3BaseApp::ToggleUltrawideTargets() {
if (ultrawide_targets_dialog_) {
if (ultrawide_targets_dialog_->visible()) {
ultrawide_targets_dialog_->Hide();
} else {
ApplySettingsCursorMode();
ultrawide_targets_dialog_->Show();
}
return;
}
const auto export_path = cache_root() / "skate3_ultrawide_targets.toml";
ultrawide_targets_dialog_ = std::make_unique<rex::ui::UltrawideTargetsDialog>(
imgui_drawer(), export_path, [this]() { ApplyGameplayCursorMode(); });
ApplySettingsCursorMode();
ultrawide_targets_dialog_->Show();
}
void Skate3BaseApp::ToggleNativeDebug() {
if (!native_debug_dialog_) {
native_debug_dialog_ = std::make_unique<skate3::NativeDebugDialog>(imgui_drawer());
@ -1126,7 +1062,7 @@ void Skate3BaseApp::LogUserMarker() {
void Skate3BaseApp::LogDebugMarker() {
const uint32_t marker = debug_marker_count_.fetch_add(1, std::memory_order_relaxed) + 1;
DisableActiveUltrawideDiagnostics();
DisableActiveDebugDiagnostics();
REXLOG_WARN("USER DEBUG MARKER #{}: F9 pressed; active diagnostics disabled", marker);
}

View file

@ -12,7 +12,6 @@
#include <rex/rex_app.h>
#include <rex/ui/overlay/simple_settings_overlay.h>
#include <rex/ui/overlay/ultrawide_targets_overlay.h>
#include "skate3_native_debug_dialog.h"
@ -40,7 +39,6 @@ class Skate3BaseApp : public rex::ReXApp {
void InstallBigDeviceAliases();
void InstallDlcPackages();
void ToggleSimpleSettings();
void ToggleUltrawideTargets();
void ToggleNativeDebug();
void ApplySettingsCursorMode();
void ApplyGameplayCursorMode();
@ -60,7 +58,6 @@ class Skate3BaseApp : public rex::ReXApp {
std::filesystem::path user_settings_path_;
std::filesystem::path profiles_path_;
std::unique_ptr<rex::ui::SimpleSettingsDialog> simple_settings_dialog_;
std::unique_ptr<rex::ui::UltrawideTargetsDialog> ultrawide_targets_dialog_;
std::unique_ptr<skate3::NativeDebugDialog> native_debug_dialog_;
std::unique_ptr<skate3::RenderModeIndicator> render_mode_indicator_;
bool recipe_overlay_installed_ = false;

View file

@ -13,7 +13,7 @@
#include <vector>
#include <rex/cvar.h>
#include <rex/graphics/ultrawide_debug.h>
#include <rex/kernel/guest_presence.h>
#include <rex/input/input.h>
#include <rex/input/input_system.h>
#include <rex/kernel/xam/input_injection.h>
@ -356,7 +356,7 @@ void StartGameplayInputWorkerIfNeeded() {
}
g_input_worker = std::thread([tokens, settle_ms] {
// Wait for the gameplay presence context (0x8001 == 1).
while (rex::graphics::ultrawide_debug::Skate3GameplayContextValue() != 1) {
while (rex::kernel::guest_presence::GameplayContextValue() != 1) {
if (!InterruptibleSleepMs(100)) {
return;
}

View file

@ -33,7 +33,7 @@
#include <rex/cvar.h>
#include <rex/graphics/native_guest_renderer.h>
#include <rex/graphics/ultrawide_debug.h>
#include <rex/kernel/guest_presence.h>
#include <rex/logging.h>
#include "native/skate3_native_diag.h"
@ -9853,7 +9853,7 @@ void BuildFrameScene(uint8_t* base, const SubmitRecord* records, size_t count) {
// behind a live menu). The editor's _nis shader heartbeat separates the
// two: editor draws stamp it every frame, portrait passes use the
// _default compiles and never do.
if (rex::graphics::ultrawide_debug::Skate3GameplayContextValue() == 0 &&
if (rex::kernel::guest_presence::GameplayContextValue() == 0 &&
!scene.items.empty() && scene.items.size() <= 48 &&
!CasEditorActive(base)) {
bool all_char = true;

View file

@ -33,7 +33,7 @@
#include <rex/cvar.h>
#include <rex/graphics/native_guest_renderer.h>
#include <rex/graphics/ultrawide_debug.h>
#include <rex/kernel/guest_presence.h>
#include <rex/logging.h>
#include "native/skate3_native_diag.h"
@ -4609,7 +4609,7 @@ bool YieldForMenus(const NativeGuestOutputRenderContext& context) {
static bool s_in_loading = false;
static bool s_seen_gameplay = false;
static bool s_pause_native = false;
const bool in_menus = rex::graphics::ultrawide_debug::Skate3GameplayContextValue() == 0;
const bool in_menus = rex::kernel::guest_presence::GameplayContextValue() == 0;
// Render-thread mirror for the 2D texture resolver: menu screens shorten
// the content-liveness recheck cadence (see resolve_2d_texture) so
// in-place rewrites of UI textures (the one-shot skater-portrait resolves)
@ -9945,6 +9945,17 @@ bool RenderScene(const NativeGuestOutputRenderContext& context, void* /*user_dat
}
}
// Hor+ ultrawide: the 2D stream and the guest screenshot raster are
// authored for the 16:9 frontbuffer. On a wide output the 2D replay
// scales clip-space X by this factor (centering ortho HUD/menu/FMV draws
// in a pillarboxed 16:9 band and narrowing perspective SimpleDraw markers
// to match the widened scene projection - one operation covers both), and
// the photo grab center-crops the same band.
const float out_aspect2d =
float(context.guest_output_width) / float(context.guest_output_height);
const float wide_2d_scale =
out_aspect2d > (16.0f / 9.0f) * 1.01f ? (16.0f / 9.0f) / out_aspect2d : 1.0f;
// ---- Native photo grab (photo_grab_native) ----
// Consume: CPU-tile the newest fence-completed readback into the guest
// screenshot target. Produce: downsample this frame's finished output
@ -10055,10 +10066,17 @@ bool RenderScene(const NativeGuestOutputRenderContext& context, void* /*user_dat
cmd->SetScissor(grab_sc);
cmd->SetPrimitiveTopology(nrhi::PrimitiveTopology::kTriangleList);
cmd->SetPipeline(g_r.pso_blur_down);
const float grab_consts[4] = {1.0f / float(context.guest_output_width),
// Source UV rect (second register): the centered 16:9 band on a
// wide output; the guest screenshot raster is 16:9.
const float grab_consts[8] = {1.0f / float(context.guest_output_width),
1.0f / float(context.guest_output_height),
0.0f, 0.0f};
cmd->SetRootConstants(0, 4, grab_consts, 0);
0.0f,
0.0f,
wide_2d_scale,
1.0f,
(1.0f - wide_2d_scale) * 0.5f,
0.0f};
cmd->SetRootConstants(0, 8, grab_consts, 0);
cmd->SetTexture(1, g_r.output_srv_slot);
cmd->Draw(3, 0);
// blur_tex[0] -> the readback buffer; restore steady states.
@ -10144,9 +10162,17 @@ bool RenderScene(const NativeGuestOutputRenderContext& context, void* /*user_dat
cmd->SetViewport(blur_vp);
cmd->SetScissor(blur_sc);
cmd->SetPipeline(g_r.pso_blur_down);
const float d_consts[4] = {1.0f / float(context.guest_output_width),
1.0f / float(context.guest_output_height), 0.0f, 0.0f};
cmd->SetRootConstants(0, 4, d_consts, 0);
// Full-frame source rect: the blur squeezes the whole wide frame into
// the 1152x640 blur space and the final stretch-back undoes it.
const float d_consts[8] = {1.0f / float(context.guest_output_width),
1.0f / float(context.guest_output_height),
0.0f,
0.0f,
1.0f,
1.0f,
0.0f,
0.0f};
cmd->SetRootConstants(0, 8, d_consts, 0);
cmd->SetTexture(1, g_r.output_srv_slot);
cmd->Draw(3, 0);
// H: blur_tex[0] -> blur_tex[1].
@ -10242,6 +10268,15 @@ bool RenderScene(const NativeGuestOutputRenderContext& context, void* /*user_dat
}
float constants[40];
std::memcpy(constants, d.consts, sizeof(d.consts));
// Wide output: scale the staged projection's clip.x row (the VS
// computes clip.x = dot(wp, c0)) so the 16:9-authored stream lands
// centered (see wide_2d_scale).
if (wide_2d_scale != 1.0f) {
constants[0] *= wide_2d_scale;
constants[1] *= wide_2d_scale;
constants[2] *= wide_2d_scale;
constants[3] *= wide_2d_scale;
}
// 2D ortho draws have no translation row in the projection (c3 ==
// (0,0,0,1)); perspective view-proj rows do. Half-pixel applies to
// the former only.
@ -10252,12 +10287,14 @@ bool RenderScene(const NativeGuestOutputRenderContext& context, void* /*user_dat
// (see the cvar; the shader gates on actual fetch magnification).
constants[37] = float(std::clamp(
REXCVAR_GET(skate3_native_render_scene_2d_sharp), 0.0, 2.0));
// m[9].zw: unused. The D3D9 half-pixel shift is derived in the VS
// from the draw's own ortho scale (+0.5 GUEST pixel down-right,
// matching the emulated path's half_pixel_offset reversal); the
// old up-left OUTPUT-pixel nudge staged here left a see-through
// sliver along the bottom/right of edge-to-edge loading quads.
constants[38] = 0.0f;
// m[9].z: clip-space X extent of the 2D band, the edge-snap
// boundary in the VS (0 = full target). m[9].w: unused. The D3D9
// half-pixel shift is derived in the VS from the draw's own ortho
// scale (+0.5 GUEST pixel down-right, matching the emulated path's
// half_pixel_offset reversal); the old up-left OUTPUT-pixel nudge
// staged here left a see-through sliver along the bottom/right of
// edge-to-edge loading quads.
constants[38] = wide_2d_scale != 1.0f ? wide_2d_scale : 0.0f;
constants[39] = 0.0f;
cmd->SetRootConstants(0, 40, constants, 0);
cmd->SetTexture(1, srv_view);

View file

@ -32,7 +32,6 @@
#include <rex/cvar.h>
#include <rex/graphics/native_guest_renderer.h>
#include <rex/graphics/ultrawide_debug.h>
#include <rex/logging.h>
#include "native/skate3_native_diag.h"

View file

@ -2,25 +2,23 @@
#include <algorithm>
#include <array>
#include <atomic>
#include <cmath>
#include <cstdlib>
#include <cstdint>
#include <filesystem>
#include <fstream>
#include <unordered_map>
#include <string>
#include <string_view>
#include <mutex>
#include <rex/cvar.h>
#include <rex/graphics/ultrawide_debug.h>
#include <rex/logging.h>
#include <rex/graphics/native_guest_renderer.h>
// Guest-side ultrawide support: the native renderer draws true widescreen
// frames (wide guest output + Hor+ projection), but the game's own CPU
// culling still tests against its 16:9 view frustum and would drop side
// content before it ever reaches the renderer. The frustum patch scope below
// is injected into the recompiled cull routine (see
// cmake/ApplySkate3CodegenPatches.cmake) and widens the cull planes in guest
// memory to match the wide view.
inline bool Skate3UltrawideHasExpandedTargetAspect() {
if (!rex::cvar::Query<bool>("skate3_ultrawide") ||
!rex::cvar::Query<bool>("skate3_ultrawide_hor_plus") ||
!rex::graphics::ultrawide_debug::IsSkate3GameplayUltrawideActive()) {
!rex::graphics::IsNativeGuestOutputActive()) {
return false;
}
@ -28,165 +26,16 @@ inline bool Skate3UltrawideHasExpandedTargetAspect() {
(16.0 / 9.0) + 0.01;
}
inline float Skate3UltrawideFloatFromU32(uint32_t value) {
union {
uint32_t u;
float f;
} bits{value};
return bits.f;
}
inline uint32_t Skate3UltrawideU32FromFloat(float value) {
union {
float f;
uint32_t u;
} bits{value};
return bits.u;
}
inline double Skate3UltrawideMaybeOverrideGameplayFrustumAspect(uint32_t site_id,
double native_aspect) {
if (!Skate3UltrawideHasExpandedTargetAspect() ||
!rex::cvar::Query<bool>("skate3_ultrawide_force_main_visibility_flags") ||
!std::isfinite(native_aspect) || native_aspect <= 0.0) {
return native_aspect;
}
const double forced_aspect = std::clamp(
rex::cvar::Query<double>("skate3_ultrawide_target_aspect"), 16.0 / 9.0, 8.0);
if (forced_aspect <= native_aspect + 0.001) {
return native_aspect;
}
const uint32_t native_milli = uint32_t(std::clamp(native_aspect * 1000.0, 0.0, 100000.0));
const uint32_t forced_milli = uint32_t(std::clamp(forced_aspect * 1000.0, 0.0, 100000.0));
rex::graphics::ultrawide_debug::RecordScreenCallback(
rex::graphics::ultrawide_debug::ScreenCallbackKind::kWidth, site_id, native_milli);
rex::graphics::ultrawide_debug::RecordScreenCallbackResult(
rex::graphics::ultrawide_debug::ScreenCallbackKind::kWidth, site_id, native_milli,
forced_milli);
return forced_aspect;
}
inline void Skate3UltrawideMaybeExpandMainCullRange(PPCContext& ctx, u8* base,
uint32_t min_addr,
uint32_t max_addr) {
if (!Skate3UltrawideHasExpandedTargetAspect()) {
return;
}
const double target_aspect = std::clamp(
rex::cvar::Query<double>("skate3_ultrawide_target_aspect"), 16.0 / 9.0, 8.0);
const float scale = float(target_aspect / (16.0 / 9.0));
if (scale <= 1.0f) {
return;
}
const float native_min = Skate3UltrawideFloatFromU32(REX_LOAD_U32(min_addr));
const float native_max = Skate3UltrawideFloatFromU32(REX_LOAD_U32(max_addr));
if (!std::isfinite(native_min) || !std::isfinite(native_max) ||
native_max <= native_min) {
return;
}
const float center = (native_min + native_max) * 0.5f;
const float half_width = (native_max - native_min) * 0.5f * scale;
const float widened_min = center - half_width;
const float widened_max = center + half_width;
if (!std::isfinite(widened_min) || !std::isfinite(widened_max)) {
return;
}
REX_STORE_U32(min_addr, Skate3UltrawideU32FromFloat(widened_min));
REX_STORE_U32(max_addr, Skate3UltrawideU32FromFloat(widened_max));
}
inline uint32_t Skate3UltrawideRecordScreenHeight(uint32_t site_id, uint32_t native_height) {
rex::graphics::ultrawide_debug::RecordScreenCallback(
rex::graphics::ultrawide_debug::ScreenCallbackKind::kHeight, site_id, native_height);
return native_height;
}
inline uint32_t Skate3UltrawideMaybeOverrideScreenFlag(
rex::graphics::ultrawide_debug::ScreenCallbackKind kind, uint32_t site_id,
uint32_t native_value) {
const bool selected =
rex::graphics::ultrawide_debug::RecordScreenCallback(kind, site_id, native_value);
return selected ? 1 : native_value;
}
inline uint32_t Skate3UltrawideMaybeForceMainVisibilityFlag(uint32_t site_id,
uint32_t native_value) {
rex::graphics::ultrawide_debug::RecordScreenCallback(
rex::graphics::ultrawide_debug::ScreenCallbackKind::kScreenFlag, site_id, native_value);
if (!Skate3UltrawideHasExpandedTargetAspect() ||
!rex::cvar::Query<bool>("skate3_ultrawide_force_main_visibility_flags")) {
return native_value;
}
rex::graphics::ultrawide_debug::RecordScreenCallbackResult(
rex::graphics::ultrawide_debug::ScreenCallbackKind::kScreenFlag, site_id, native_value, 1);
return 1;
}
inline uint32_t Skate3UltrawideMaybeForceHighestLodState(uint32_t site_id, uint32_t object,
uint32_t native_state) {
if (!Skate3UltrawideHasExpandedTargetAspect() ||
!rex::cvar::Query<bool>("skate3_ultrawide_force_main_visibility_flags") ||
native_state == 0) {
return native_state;
}
return 0;
}
inline thread_local bool g_skate3_ultrawide_force_main_cull_classifier = false;
struct Skate3UltrawideMainCullClassifierScope {
explicit Skate3UltrawideMainCullClassifierScope(bool enabled)
: previous(g_skate3_ultrawide_force_main_cull_classifier) {
g_skate3_ultrawide_force_main_cull_classifier =
previous || (enabled && Skate3UltrawideHasExpandedTargetAspect());
}
~Skate3UltrawideMainCullClassifierScope() {
g_skate3_ultrawide_force_main_cull_classifier = previous;
}
bool previous;
};
inline uint32_t Skate3UltrawideMaybeForceMainCullClassifierHalfword(uint32_t native_value) {
if (!g_skate3_ultrawide_force_main_cull_classifier ||
!rex::cvar::Query<bool>("skate3_ultrawide_force_main_visibility_flags")) {
return native_value;
}
return 1;
}
inline bool Skate3UltrawideShouldForceWorldMainCullDescriptor(u8* base, uint32_t descriptor) {
if (!Skate3UltrawideHasExpandedTargetAspect() ||
!rex::cvar::Query<bool>("skate3_ultrawide_force_main_visibility_flags") ||
descriptor < 512) {
return false;
}
constexpr uint32_t kWorldVtable = 0x8230B278;
const uint32_t object = descriptor - 512;
if (REX_LOAD_U32(object) != kWorldVtable) {
return false;
}
const uint32_t output_flags = REX_LOAD_U32(descriptor + 12);
return output_flags != 0 && output_flags == REX_LOAD_U32(object + 496);
}
inline bool Skate3UltrawideShouldWidenGameCullFrustum(u8* base, uint32_t cull_block) {
if (!Skate3UltrawideHasExpandedTargetAspect() ||
!rex::cvar::Query<bool>("skate3_ultrawide_widen_game_frustum") || !cull_block) {
return false;
}
return REX_LOAD_U32(cull_block + 5260) != 0;
// Every cull block reaching the vectorized cull job gets its left/right
// planes widened: DoFrustumCulling reads them unconditionally, including
// blocks with no extra cull volumes (the word at +5260); gating on that
// count left 16:9 culling holes at the frame edges in the areas whose
// blocks carry none. Over-inclusion is safe (a few extra submitted
// meshes); the plane sanity checks below still veto implausible data.
(void)base;
return cull_block != 0 && Skate3UltrawideHasExpandedTargetAspect() &&
rex::cvar::Query<bool>("skate3_ultrawide_widen_game_frustum");
}
struct Skate3UltrawideGameFrustumPatchScope {
@ -336,279 +185,3 @@ struct Skate3UltrawideGameFrustumPatchScope {
float side_scale = 1.0f;
bool active = false;
};
inline std::filesystem::path Skate3UltrawideCacheLogPath(const char* filename);
enum Skate3UltrawideObjectStageBits : uint32_t {
kSkate3ObjectStageActive = 1u << 0,
kSkate3ObjectStagePrep = 1u << 1,
kSkate3ObjectStageList = 1u << 2,
kSkate3ObjectStageMain = 1u << 3,
};
struct Skate3UltrawideObjectStageRecord {
uint32_t bits = 0;
uint32_t vtable = 0;
uint32_t target = 0;
uint32_t first_site = 0;
uint32_t last_site = 0;
uint32_t aux0 = 0;
uint32_t aux1 = 0;
};
inline uint64_t& Skate3UltrawideObjectStageFrameId() {
static uint64_t frame = 0;
return frame;
}
inline uint32_t& Skate3UltrawideObjectStageRenderer() {
static uint32_t renderer = 0;
return renderer;
}
inline std::unordered_map<uint32_t, Skate3UltrawideObjectStageRecord>&
Skate3UltrawideObjectStageRecords() {
static std::unordered_map<uint32_t, Skate3UltrawideObjectStageRecord> records;
return records;
}
inline std::mutex& Skate3UltrawideObjectStageMutex() {
static std::mutex mutex;
return mutex;
}
inline std::ofstream& Skate3UltrawideObjectStageLogFile() {
static std::ofstream log_file;
if (!log_file.is_open()) {
std::filesystem::path log_path =
Skate3UltrawideCacheLogPath("skate3_ultrawide_object_stage_trace.log");
std::error_code ec;
if (log_path.has_parent_path()) {
std::filesystem::create_directories(log_path.parent_path(), ec);
}
log_file.open(log_path, std::ios::out | std::ios::trunc);
if (log_file.is_open()) {
log_file << "seq,frame,kind,marker,renderer,object,bits,site,vtable,target,aux0,aux1,"
"active,prep,list,main,missing_main,total\n";
}
}
return log_file;
}
inline bool Skate3UltrawideObjectStageTraceEnabled() {
return rex::cvar::Query<bool>("skate3_ultrawide_object_stage_trace_continuous") ||
rex::cvar::Query<int32_t>("skate3_ultrawide_object_stage_trace_frames_remaining") > 0 ||
rex::cvar::Query<int32_t>("skate3_ultrawide_object_stage_marker") != 0;
}
inline void Skate3UltrawideWriteObjectStageLog(
uint64_t frame, const char* kind, uint32_t marker, uint32_t renderer, uint32_t object,
uint32_t bits, uint32_t site, uint32_t vtable, uint32_t target, uint32_t aux0,
uint32_t aux1, uint32_t active_count, uint32_t prep_count, uint32_t list_count,
uint32_t main_count, uint32_t missing_main_count, uint32_t total_count) {
if (!rex::cvar::Query<bool>("skate3_ultrawide_object_stage_trace_to_disk")) {
return;
}
static std::atomic<uint64_t> sequence{0};
std::ofstream& log_file = Skate3UltrawideObjectStageLogFile();
if (!log_file.is_open()) {
return;
}
log_file << std::dec << sequence.fetch_add(1, std::memory_order_relaxed) << ',' << frame
<< ',' << kind << ',' << marker << ",0x" << std::hex << renderer << ",0x"
<< object << ",0x" << bits << ",0x" << site << ",0x" << vtable << ",0x"
<< target << ",0x" << aux0 << ",0x" << aux1 << ',' << std::dec << active_count
<< ',' << prep_count << ',' << list_count << ',' << main_count << ','
<< missing_main_count << ',' << total_count << '\n';
log_file.flush();
}
inline void Skate3UltrawideFinalizeObjectStageFrameLocked(const char* reason) {
auto& records = Skate3UltrawideObjectStageRecords();
if (records.empty()) {
return;
}
const uint32_t marker =
static_cast<uint32_t>(rex::cvar::Query<int32_t>("skate3_ultrawide_object_stage_marker"));
const bool enabled = Skate3UltrawideObjectStageTraceEnabled();
uint32_t remaining =
static_cast<uint32_t>(std::max(0, rex::cvar::Query<int32_t>(
"skate3_ultrawide_object_stage_trace_frames_remaining")));
if (!enabled) {
records.clear();
return;
}
uint32_t active_count = 0;
uint32_t prep_count = 0;
uint32_t list_count = 0;
uint32_t main_count = 0;
uint32_t missing_main_count = 0;
for (const auto& [object, record] : records) {
active_count += (record.bits & kSkate3ObjectStageActive) ? 1 : 0;
prep_count += (record.bits & kSkate3ObjectStagePrep) ? 1 : 0;
list_count += (record.bits & kSkate3ObjectStageList) ? 1 : 0;
main_count += (record.bits & kSkate3ObjectStageMain) ? 1 : 0;
if ((record.bits & (kSkate3ObjectStagePrep | kSkate3ObjectStageList)) &&
!(record.bits & kSkate3ObjectStageMain)) {
++missing_main_count;
}
}
const uint64_t frame = Skate3UltrawideObjectStageFrameId();
const uint32_t renderer = Skate3UltrawideObjectStageRenderer();
Skate3UltrawideWriteObjectStageLog(frame, reason, marker, renderer, 0, 0, 0, 0, 0, 0, 0,
active_count, prep_count, list_count, main_count,
missing_main_count, static_cast<uint32_t>(records.size()));
uint32_t emitted_missing = 0;
const uint32_t missing_limit = static_cast<uint32_t>(std::clamp(
rex::cvar::Query<int32_t>("skate3_ultrawide_object_stage_missing_limit"), 0, 4096));
for (const auto& [object, record] : records) {
if (!((record.bits & (kSkate3ObjectStagePrep | kSkate3ObjectStageList)) &&
!(record.bits & kSkate3ObjectStageMain))) {
continue;
}
if (emitted_missing++ >= missing_limit) {
break;
}
Skate3UltrawideWriteObjectStageLog(frame, "missing-main", marker, renderer, object,
record.bits, record.last_site, record.vtable,
record.target, record.aux0, record.aux1, active_count,
prep_count, list_count, main_count, missing_main_count,
static_cast<uint32_t>(records.size()));
}
if (remaining > 0) {
rex::cvar::SetFlagByName("skate3_ultrawide_object_stage_trace_frames_remaining",
std::to_string(remaining - 1));
}
if (marker != 0) {
rex::cvar::SetFlagByName("skate3_ultrawide_object_stage_marker", "0");
}
records.clear();
}
inline void Skate3UltrawideBeginObjectStageFrame(uint32_t site_id, uint32_t renderer) {
if (!Skate3UltrawideHasExpandedTargetAspect()) {
return;
}
if (renderer < 0x10000) {
return;
}
std::lock_guard lock(Skate3UltrawideObjectStageMutex());
Skate3UltrawideFinalizeObjectStageFrameLocked("frame");
++Skate3UltrawideObjectStageFrameId();
Skate3UltrawideObjectStageRenderer() = renderer;
if (Skate3UltrawideObjectStageTraceEnabled()) {
Skate3UltrawideWriteObjectStageLog(Skate3UltrawideObjectStageFrameId(), "begin", 0,
renderer, 0, 0, site_id, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
}
}
inline uint32_t Skate3UltrawideObjectStageBitForAction(std::string_view action) {
if (action == "render-active-v68") {
return kSkate3ObjectStageActive;
}
if (action == "render-prep-v48") {
return kSkate3ObjectStagePrep;
}
if (action == "render-list-v24") {
return kSkate3ObjectStageList;
}
if (action == "render-main-v52") {
return kSkate3ObjectStageMain;
}
return 0;
}
inline void Skate3UltrawideRecordObjectStage(const char* action, uint32_t site_id,
uint32_t object, uint32_t vtable,
uint32_t target, uint32_t aux0,
uint32_t aux1, uint32_t renderer) {
const uint32_t bit = Skate3UltrawideObjectStageBitForAction(action ? action : "");
if (!bit || !object || !Skate3UltrawideHasExpandedTargetAspect()) {
return;
}
std::lock_guard lock(Skate3UltrawideObjectStageMutex());
auto& record = Skate3UltrawideObjectStageRecords()[object];
if (!record.bits) {
record.first_site = site_id;
record.vtable = vtable;
record.target = target;
}
record.bits |= bit;
record.last_site = site_id;
record.aux0 = aux0;
record.aux1 = aux1;
if (vtable) {
record.vtable = vtable;
}
if (target) {
record.target = target;
}
if (renderer >= 0x10000) {
Skate3UltrawideObjectStageRenderer() = renderer;
}
}
inline uint32_t Skate3UltrawideMaybeForceMainObjectActive(uint32_t site_id,
uint32_t native_value) {
rex::graphics::ultrawide_debug::RecordScreenCallback(
rex::graphics::ultrawide_debug::ScreenCallbackKind::kScreenFlag, site_id, native_value);
if (!Skate3UltrawideHasExpandedTargetAspect() ||
!rex::cvar::Query<bool>("skate3_ultrawide_force_main_visibility_flags")) {
return native_value;
}
rex::graphics::ultrawide_debug::RecordScreenCallbackResult(
rex::graphics::ultrawide_debug::ScreenCallbackKind::kScreenFlag, site_id, native_value, 1);
return 1;
}
inline uint32_t Skate3UltrawideMaybeForceWorldPartVisible(uint32_t site_id,
uint32_t native_value,
uint32_t sibling_value) {
rex::graphics::ultrawide_debug::RecordScreenCallback(
rex::graphics::ultrawide_debug::ScreenCallbackKind::kScreenFlag, site_id, native_value);
if (native_value != 0 || sibling_value == 0 || !Skate3UltrawideHasExpandedTargetAspect() ||
!rex::cvar::Query<bool>("skate3_ultrawide_force_main_visibility_flags")) {
return native_value;
}
rex::graphics::ultrawide_debug::RecordScreenCallbackResult(
rex::graphics::ultrawide_debug::ScreenCallbackKind::kScreenFlag, site_id, native_value, 1);
return 1;
}
inline std::filesystem::path Skate3UltrawideCacheLogPath(const char* filename) {
#if defined(_WIN32)
char* appdata_raw = nullptr;
size_t appdata_length = 0;
if (_dupenv_s(&appdata_raw, &appdata_length, "APPDATA") == 0 && appdata_raw &&
appdata_length > 0) {
std::filesystem::path appdata_path(appdata_raw);
std::free(appdata_raw);
return appdata_path / "skate3" / "cache" / filename;
}
std::free(appdata_raw);
#else
if (const char* appdata = std::getenv("APPDATA")) {
return std::filesystem::path(appdata) / "skate3" / "cache" / filename;
}
#endif
return filename;
}
inline void Skate3UltrawideTraceRenderVirtual(const char* action, uint32_t site_id,
uint32_t object_ptr, uint32_t vtable_ptr,
uint32_t target_ptr, uint32_t aux0 = 0,
uint32_t aux1 = 0, uint32_t renderer = 0) {
Skate3UltrawideRecordObjectStage(action, site_id, object_ptr, vtable_ptr, target_ptr, aux0,
aux1, renderer);
}