diff --git a/README.md b/README.md index 0d20117..d4e5193 100644 --- a/README.md +++ b/README.md @@ -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: diff --git a/config/skate3.example.toml b/config/skate3.example.toml index 6620542..2b32142 100644 --- a/config/skate3.example.toml +++ b/config/skate3.example.toml @@ -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 diff --git a/src/native/shaders/blur.hlsl b/src/native/shaders/blur.hlsl index bbed35a..e194186 100644 --- a/src/native/shaders/blur.hlsl +++ b/src/native/shaders/blur.hlsl @@ -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); diff --git a/src/native/shaders/overlay2d.hlsl b/src/native/shaders/overlay2d.hlsl index 9096d2e..8225b7e 100644 --- a/src/native/shaders/overlay2d.hlsl +++ b/src/native/shaders/overlay2d.hlsl @@ -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 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; diff --git a/src/native/shaders/spirv/skate3_native_shaders_spirv.h b/src/native/shaders/spirv/skate3_native_shaders_spirv.h index 2d2fc3c..d1f79c4 100644 --- a/src/native/shaders/spirv/skate3_native_shaders_spirv.h +++ b/src/native/shaders/spirv/skate3_native_shaders_spirv.h @@ -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) diff --git a/src/skate3_app_common.cpp b/src/skate3_app_common.cpp index 32986f6..b7e6390 100644 --- a/src/skate3_app_common.cpp +++ b/src/skate3_app_common.cpp @@ -49,7 +49,7 @@ #include #include #include -#include +#include #include #include #include @@ -66,7 +66,6 @@ #include #include #include -#include #include #include @@ -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 ResolveUltrawideTargetDisplaySize() { } void ApplyUltrawideVideoDefaults() { - if (!REXCVAR_GET(skate3_ultrawide) || - rex::cvar::HasNonDefaultValue("skate3_ultrawide_target_aspect")) { + if (!REXCVAR_GET(skate3_ultrawide)) { return; } - const std::optional target_size = ResolveUltrawideTargetDisplaySize(); - if (!target_size || target_size->width <= 0 || target_size->height <= 0) { - return; - } - - const double target_aspect = - static_cast(target_size->width) / static_cast(target_size->height); + // 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) { - return; + const std::optional target_size = ResolveUltrawideTargetDisplaySize(); + if (!target_size || target_size->width <= 0 || target_size->height <= 0) { + return; + } + target_aspect = + static_cast(target_size->width) / static_cast(target_size->height); + if (target_aspect <= kSixteenNineAspect + kUltrawideAspectEpsilon) { + return; + } + rex::cvar::SetFlagByName("skate3_ultrawide_target_aspect", std::to_string(target_aspect)); } - 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( - "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( - imgui_drawer(), export_path, [this]() { ApplyGameplayCursorMode(); }); - ApplySettingsCursorMode(); - ultrawide_targets_dialog_->Show(); -} - void Skate3BaseApp::ToggleNativeDebug() { if (!native_debug_dialog_) { native_debug_dialog_ = std::make_unique(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); } diff --git a/src/skate3_app_common.h b/src/skate3_app_common.h index c9acdf3..f93a082 100644 --- a/src/skate3_app_common.h +++ b/src/skate3_app_common.h @@ -12,7 +12,6 @@ #include #include -#include #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 simple_settings_dialog_; - std::unique_ptr ultrawide_targets_dialog_; std::unique_ptr native_debug_dialog_; std::unique_ptr render_mode_indicator_; bool recipe_overlay_installed_ = false; diff --git a/src/skate3_demo_path.cpp b/src/skate3_demo_path.cpp index fee2aa0..c332418 100644 --- a/src/skate3_demo_path.cpp +++ b/src/skate3_demo_path.cpp @@ -13,7 +13,7 @@ #include #include -#include +#include #include #include #include @@ -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; } diff --git a/src/skate3_native_scene.cpp b/src/skate3_native_scene.cpp index e020fc6..92e9f71 100644 --- a/src/skate3_native_scene.cpp +++ b/src/skate3_native_scene.cpp @@ -33,7 +33,7 @@ #include #include -#include +#include #include #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; diff --git a/src/skate3_native_scene_gpu.cpp b/src/skate3_native_scene_gpu.cpp index 3561e46..6682d7b 100644 --- a/src/skate3_native_scene_gpu.cpp +++ b/src/skate3_native_scene_gpu.cpp @@ -33,7 +33,7 @@ #include #include -#include +#include #include #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); diff --git a/src/skate3_native_scene_post.cpp b/src/skate3_native_scene_post.cpp index 4319e45..9df0882 100644 --- a/src/skate3_native_scene_post.cpp +++ b/src/skate3_native_scene_post.cpp @@ -32,7 +32,6 @@ #include #include -#include #include #include "native/skate3_native_diag.h" diff --git a/src/skate3_ultrawide_guest.h b/src/skate3_ultrawide_guest.h index d28d9a1..d25dce4 100644 --- a/src/skate3_ultrawide_guest.h +++ b/src/skate3_ultrawide_guest.h @@ -2,25 +2,23 @@ #include #include -#include #include -#include #include -#include -#include -#include -#include -#include -#include #include -#include -#include +#include + +// 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("skate3_ultrawide") || - !rex::cvar::Query("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("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("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("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("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("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("skate3_ultrawide_force_main_visibility_flags")) { - return native_value; - } - return 1; -} - -inline bool Skate3UltrawideShouldForceWorldMainCullDescriptor(u8* base, uint32_t descriptor) { - if (!Skate3UltrawideHasExpandedTargetAspect() || - !rex::cvar::Query("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("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("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& -Skate3UltrawideObjectStageRecords() { - static std::unordered_map 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("skate3_ultrawide_object_stage_trace_continuous") || - rex::cvar::Query("skate3_ultrawide_object_stage_trace_frames_remaining") > 0 || - rex::cvar::Query("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("skate3_ultrawide_object_stage_trace_to_disk")) { - return; - } - - static std::atomic 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(rex::cvar::Query("skate3_ultrawide_object_stage_marker")); - const bool enabled = Skate3UltrawideObjectStageTraceEnabled(); - uint32_t remaining = - static_cast(std::max(0, rex::cvar::Query( - "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(records.size())); - - uint32_t emitted_missing = 0; - const uint32_t missing_limit = static_cast(std::clamp( - rex::cvar::Query("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(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("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("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); -}