diff --git a/docs/upscaler.md b/docs/upscaler.md index 4b10d9ba5a..8e72680720 100644 --- a/docs/upscaler.md +++ b/docs/upscaler.md @@ -384,10 +384,50 @@ skipping screen-space passes (3 or 4 indices) so a shifted full-screen quad leav - `pad` bits: 0-7 diagnostic view (4 = history debug view: red depth-rejected, green history lost, blue weight used), 8-15 A/B switches, 16-23 moving-object history loss in percent, 24 view-projection depth, 25 8-bit scene, 26-31 spatial smoothing. -- Defaults (tuned in game on a GTX 1070 Ti): history 99% still / 55% moving, tolerance 115%, - moving objects 90%, edges 70%, texture detail 75%, sharpening 165%. They live in +- Defaults (tuned in game on a GTX 1070 Ti): history 99% still / 55% moving, tolerance 175%, + moving objects 55%, edges 55%, texture detail 80%, sharpening 130%. They live in `shim/spartanport_settings.h` and in the menu hints. +### XeSS in place of the accumulation (upscaler "XeSS", ini `upscaler=xess`, Windows only) + +Intel XeSS-SR at its native anti-aliasing setting (`XESS_QUALITY_SETTING_AA`, the game's own +resolution) can take the place of `taa.comp`. It gets the same inputs: the jittered scene colour (the +sRGB view, so linear values, with `XESS_INIT_FLAG_LDR_INPUT_COLOR` since the colour is already tonemapped), +the scene depth (not inverted: 0 at the near plane) and the motion vectors of `camera_motion_vp.comp` in render pixels +(previous minus current, without jitter), and it writes into the TAA's output image, so the alpha +pass, the write back and the HUD stay as they are. Code: `vk_xess.cpp` (loads `libxess.dll` at run time, +Windows only), the hook is `TemporalUpscaler::RecordXess`. + +- The library is Intel's binary (`packaging/fetch_xess.sh` takes it from github.com/intel/xess at a pinned + commit and checks its hash; the Intel Simplified Software License allows redistributing it unmodified + with its license, which the package keeps in `LICENSES/`). The headers in `gpu/third_party/xess` are MIT. +- XeSS needs `VK_EXT_mutable_descriptor_type` and the extensions its library lists + (`xessVKGetRequiredDeviceExtensions`); `Instance::CreateDevice` enables them only when `upscaler=xess` is in + the ini at start, which fits the upscaler choice being applied on restart. It is a choice of its own in the + launcher and the menu, next to the TAA (`IsTaa()` covers both: same live path, jitter and motion vectors). +- The device is created with XeSS's extensions and its required features (`xessVKGetRequiredDeviceFeatures`, + patched into the device's feature chain) only when XeSS is the upscaler at start. If the card cannot give + them, the device is created from a copy of the chain without them. The result goes to + `XessAa::SetDeviceReady`: `Record` refuses to create a context on a device that was not made for XeSS and + fails for good with a message in the menu, so the TAA runs. Choosing XeSS in the menu when the game did not + start with it therefore needs a restart (`NeedsXessRestart`, in the three restart predicates and the menu's + count of changes). +- `libxess.dll` is loaded only by full path, from the executable's folder or its `bin` folder, with the + search limited to that folder and the system folder (never the current directory or `PATH`). The waits + for an idle GPU (at the start and when the picture changes size) hold `Scheduler::submit_mutex`, the lock + the scheduler and the presenter take around `vkQueueSubmit` and `vkQueuePresent`. +- The TAA look sliders (history, tolerance, moving objects, edges) do not apply to XeSS, which has its own + history. Texture detail (`taa_lod`, the rasterizer's mip bias) and the sharpening (`xess_sharpen`, default 145%; the + `taa_sharpen.comp` pass run over the output image through `SharpenImage`) do, and are logged as + `XeSS look:`. If XeSS cannot run, the TAA does, and the menu shows why. +- Ghosting: the scene TAA's motion vectors are the camera's only (characters have none), so XeSS gets a + responsive pixel mask (`XESS_INIT_FLAG_RESPONSIVE_PIXEL_MASK`, R8): the scene stencil's characters and + objects, the mask `RecordStencilReactive` makes for FSR, clipped by `xessSetMaxResponsiveMaskValue` to + the menu's "Moving objects" (`xess_objects`, default 95%, 0 = off). Without a stencil XeSS runs without it. +- Jitter sign: the same as FSR's; `SPARTAN_XESS_INVERT_JITTER=1` flips it for a test. +- XeSS is meant to run before tonemapping; here it gets the tonemapped scene, because that is where the + game's TAA sits. Treat the quality as unproven. + ### Simulator The tuning used a software renderer of a procedural scene (static, slow and fast camera, moving box) diff --git a/gpu/CMakeLists.txt b/gpu/CMakeLists.txt index 01bc9b703f..d9ffd0fde6 100644 --- a/gpu/CMakeLists.txt +++ b/gpu/CMakeLists.txt @@ -177,7 +177,7 @@ target_compile_definitions(spartanportgpu PRIVATE IMGUI_IMPL_VULKAN_NO_PROTOTYPE SPARTAN_TITLE_FONT_PATH="${CMAKE_CURRENT_SOURCE_DIR}/../launcher/Cinzel-Black.ttf") set_source_files_properties(shim/spartanport_overlay.cpp PROPERTIES OBJECT_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/third_party/fonts/DejaVuSans.ttf;${CMAKE_CURRENT_SOURCE_DIR}/../launcher/Cinzel-Black.ttf") -target_include_directories(spartanportgpu PRIVATE shim shadps4 ${SHADER_INCLUDE} third_party/gcn/include third_party/half/include) +target_include_directories(spartanportgpu PRIVATE shim shadps4 ${SHADER_INCLUDE} third_party/gcn/include third_party/half/include third_party/xess) target_compile_definitions(spartanportgpu PRIVATE BOOST_ASIO_STANDALONE NDEBUG) target_compile_options(spartanportgpu PRIVATE -Wno-deprecated-declarations -Wno-missing-field-initializers) # Runtime symbols (runtime_memory_*, runtime_process_*) resolve against spartanport-probe. diff --git a/gpu/shadps4/video_core/renderer_vulkan/vk_camera_motion.cpp b/gpu/shadps4/video_core/renderer_vulkan/vk_camera_motion.cpp index 69a44f7fad..e91dc687e4 100644 --- a/gpu/shadps4/video_core/renderer_vulkan/vk_camera_motion.cpp +++ b/gpu/shadps4/video_core/renderer_vulkan/vk_camera_motion.cpp @@ -539,7 +539,7 @@ void CameraMotion::OnDisplayPass(VideoCore::ImageId frame) { if (debug_overlay && frame && DepthLive() && current.valid && previous.valid) { Overlay(frame); } - if (SpartanSettings::Get().upscaler != SpartanSettings::UpscalerTaa) { + if (!SpartanSettings::IsTaa(SpartanSettings::Get().upscaler)) { // Upscaler path (FSR): the unchanged upstream behaviour, nothing of the scene TAA applies. if (!frame_has_camera) InvalidateHistory(); frame_has_camera = false; diff --git a/gpu/shadps4/video_core/renderer_vulkan/vk_instance.cpp b/gpu/shadps4/video_core/renderer_vulkan/vk_instance.cpp index bbb8430cb7..3f436a4eea 100644 --- a/gpu/shadps4/video_core/renderer_vulkan/vk_instance.cpp +++ b/gpu/shadps4/video_core/renderer_vulkan/vk_instance.cpp @@ -1,6 +1,7 @@ // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later +#include #include #include #include @@ -20,6 +21,7 @@ #include "video_core/renderer_vulkan/vk_amd_paths.h" #include "video_core/renderer_vulkan/vk_instance.h" #include "video_core/renderer_vulkan/vk_platform.h" +#include "video_core/renderer_vulkan/vk_xess.h" #include @@ -276,7 +278,8 @@ bool Instance::CreateDevice() { vk::PhysicalDeviceShaderMixedFloatDotProductFeaturesVALVE, vk::PhysicalDevicePipelineBinaryFeaturesKHR, vk::PhysicalDeviceMaintenance5FeaturesKHR, - vk::PhysicalDevicePipelineExecutablePropertiesFeaturesKHR>(); + vk::PhysicalDevicePipelineExecutablePropertiesFeaturesKHR, + vk::PhysicalDeviceMutableDescriptorTypeFeaturesEXT>(); features = feature_chain.get().features; const vk::StructureChain properties_chain = physical_device.getProperties2< @@ -422,6 +425,26 @@ bool Instance::CreateDevice() { LOG_INFO(Render_Vulkan, "- sampler2DViewOf3D: {}", image_2d_view_of_3d_features.sampler2DViewOf3D); } + // spartanport: XeSS (vk_xess.cpp) asks for device extensions of its own (mutable descriptors + // among them); they are enabled only when it is selected, so the device is the same without it. + const bool xess_selected = SpartanSettings::Get().upscaler == SpartanSettings::UpscalerXess; + bool xess_extensions = false; ///< XeSS's own extensions are all enabled + if (xess_selected) { + const auto enable = [&](const char* name) { + const bool already = std::any_of( + enabled_extensions.begin(), enabled_extensions.end(), + [&](const char* have) { return std::strcmp(have, name) == 0; }); + return already || add_extension(name); + }; + const auto xess_names = XessAa::DeviceExtensions(*instance, physical_device); + xess_extensions = !xess_names.empty(); + for (const char* name : xess_names) { + xess_extensions = enable(name) && xess_extensions; + } + mutable_descriptor_type = enable(VK_EXT_MUTABLE_DESCRIPTOR_TYPE_EXTENSION_NAME) && + feature_chain.get() + .mutableDescriptorType; + } image_view_min_lod = add_extension(VK_EXT_IMAGE_VIEW_MIN_LOD_EXTENSION_NAME); supports_memory_budget = add_extension(VK_EXT_MEMORY_BUDGET_EXTENSION_NAME); // spartanport: FSR 4 v07 INT8 (vk_temporal_upscaler): quad derivatives in compute shaders. @@ -646,6 +669,9 @@ bool Instance::CreateDevice() { .image2DViewOf3D = image_2d_view_of_3d_features.image2DViewOf3D, .sampler2DViewOf3D = image_2d_view_of_3d_features.sampler2DViewOf3D, }, + vk::PhysicalDeviceMutableDescriptorTypeFeaturesEXT{ + .mutableDescriptorType = mutable_descriptor_type, + }, vk::PhysicalDeviceImageViewMinLodFeaturesEXT{ .minLod = true, }, @@ -715,6 +741,9 @@ bool Instance::CreateDevice() { if (!image_2d_view_of_3d) { device_chain.unlink(); } + if (!mutable_descriptor_type) { + device_chain.unlink(); + } if (!image_view_min_lod) { device_chain.unlink(); } @@ -728,7 +757,36 @@ bool Instance::CreateDevice() { device_chain.unlink(); } - auto [device_result, dev] = physical_device.createDeviceUnique(device_chain.get()); + // spartanport: XeSS's device features (xessVKGetRequiredDeviceFeatures) are patched into the + // chain only when its extensions are there too. A copy of the chain without them is the way + // back if the card cannot give them: the game starts, XeSS says why it does not run and the + // TAA runs. + auto plain_chain = device_chain; + bool xess_patched = false; + if (xess_selected) { + void* head = &device_chain.get(); + if (xess_extensions && XessAa::PatchDeviceFeatures(*instance, physical_device, head)) { + if (head != static_cast(&device_chain.get())) { + device_chain.get().pNext = head; + } + xess_patched = true; + } + XessAa::SetDeviceReady(xess_patched, + xess_extensions ? "the graphics card or driver does not offer the " + "features XeSS needs" + : "the graphics driver does not offer the " + "extensions XeSS needs"); + } + auto created = physical_device.createDeviceUnique(device_chain.get()); + if (xess_patched && created.result != vk::Result::eSuccess) { + LOG_WARNING(Render_Vulkan, "Device with XeSS's features failed ({}), creating it without", + vk::to_string(created.result)); + XessAa::SetDeviceReady(false, "the graphics card or driver does not offer the features " + "XeSS needs"); + created = physical_device.createDeviceUnique(plain_chain.get()); + } + const vk::Result device_result = created.result; + auto dev = std::move(created.value); if (device_result != vk::Result::eSuccess) { LOG_CRITICAL(Render_Vulkan, "Failed to create device: {}", vk::to_string(device_result)); return false; @@ -819,7 +877,7 @@ void Instance::CollectDeviceParameters() { // The port's TAA is also chosen by the launcher in spartanport.ini (upscaler=taa; settings are // loaded before the device), without any environment variable. const bool temporal_mode = - SpartanSettings::Get().upscaler == SpartanSettings::UpscalerTaa || + SpartanSettings::IsTaa(SpartanSettings::Get().upscaler) || (temporal_env && temporal_on && *temporal_on == '1' && (std::strcmp(temporal_env, "taa") == 0 || std::strcmp(temporal_env, "fsr3") == 0)); const bool no_msaa = no_msaa_env && *no_msaa_env diff --git a/gpu/shadps4/video_core/renderer_vulkan/vk_instance.h b/gpu/shadps4/video_core/renderer_vulkan/vk_instance.h index abf9936466..ab8d4e5708 100644 --- a/gpu/shadps4/video_core/renderer_vulkan/vk_instance.h +++ b/gpu/shadps4/video_core/renderer_vulkan/vk_instance.h @@ -593,6 +593,7 @@ class Instance { bool maintenance_8{}; bool attachment_feedback_loop{}; bool image_2d_view_of_3d{}; + bool mutable_descriptor_type{}; ///< enabled for XeSS only (vk_xess.cpp) bool image_view_min_lod{}; bool shader_clock{}; bool pipeline_executable_properties{}; // spartanport: SPARTAN_WAVE_STATS=1 (vk_wave_stats.h) diff --git a/gpu/shadps4/video_core/renderer_vulkan/vk_temporal_upscaler.cpp b/gpu/shadps4/video_core/renderer_vulkan/vk_temporal_upscaler.cpp index 04870db095..fd78e174b2 100644 --- a/gpu/shadps4/video_core/renderer_vulkan/vk_temporal_upscaler.cpp +++ b/gpu/shadps4/video_core/renderer_vulkan/vk_temporal_upscaler.cpp @@ -167,6 +167,7 @@ TemporalUpscaler::TemporalUpscaler(const Instance& instance_, Scheduler& schedul // Reject unsupported shaders before allocating resources or recording a frame. fsr4 = std::make_unique(instance, scheduler); frame_generation = std::make_unique(instance, scheduler); + xess = std::make_unique(instance); #ifdef _WIN32 SpartanSettings::ConfigureUpscalerSupport(instance.IsFsr4Int8Supported(), fsr4->DriverAvailable(), fsr4->DriverProblem()); @@ -240,14 +241,14 @@ bool TemporalUpscaler::Active() const { return enabled && !failed && (SpartanSettings::IsFsr3(SpartanSettings::Get().upscaler) || SpartanSettings::IsFsr4(SpartanSettings::Get().upscaler) || - SpartanSettings::Get().upscaler == SpartanSettings::UpscalerTaa) && + SpartanSettings::IsTaa(SpartanSettings::Get().upscaler)) && !SpartanToggle::Disabled(1u << 24); } bool TemporalUpscaler::ReactiveOn() const { // FSR 4 takes no reactive mask: the opaque snapshot and the mask pass would be wasted. return !SpartanToggle::Disabled(1u << 27) && !UseFsr4() && - SpartanSettings::Get().upscaler != SpartanSettings::UpscalerTaa; + !SpartanSettings::IsTaa(SpartanSettings::Get().upscaler); } void TemporalUpscaler::OnSceneColor(VideoCore::ImageId color) { @@ -508,7 +509,10 @@ bool TemporalUpscaler::RecordStencilReactive(vk::CommandBuffer cmdbuf, VideoCore return env && env[0] ? std::clamp(float(std::atof(env)), 0.0f, 1.0f) : 1.0f; }(); // FSR 3.1 with native HUD and text: the menu's "Moving objects" sets it live. - const float stencil_value = SpartanSettings::Get().upscaler == SpartanSettings::UpscalerFsr3Ui + // XeSS: a full mask, its "Moving objects" slider clips it (the responsive mask's maximum). + const float stencil_value = SpartanSettings::Get().upscaler == SpartanSettings::UpscalerXess + ? 1.0f + : SpartanSettings::Get().upscaler == SpartanSettings::UpscalerFsr3Ui ? std::clamp(float(SpartanSettings::Get().fsr_objects.load()) / 100.0f, 0.0f, 1.0f) : env_value; if (stencil_value <= 0.0f || SpartanToggle::Disabled(1u << 28) || @@ -560,7 +564,7 @@ bool TemporalUpscaler::RecordStencilReactive(vk::CommandBuffer cmdbuf, VideoCore void TemporalUpscaler::RunLdr() { if ((UseFsr4() && (SpartanSettings::Get().upscaler != SpartanSettings::UpscalerFsr411 || !fsr4->DriverAvailable())) || - SpartanSettings::Get().upscaler == SpartanSettings::UpscalerTaa) { + SpartanSettings::IsTaa(SpartanSettings::Get().upscaler)) { return; } if (!SceneImagesLive()) { @@ -776,7 +780,7 @@ bool TemporalUpscaler::SharpenOn() const { } bool TemporalUpscaler::SceneTaa() const { - return enabled && SpartanSettings::Get().upscaler == SpartanSettings::UpscalerTaa; + return enabled && SpartanSettings::IsTaa(SpartanSettings::Get().upscaler); } void TemporalUpscaler::OnPixelShader(u64 ps_hash, VideoCore::ImageId color) { @@ -843,7 +847,7 @@ bool TemporalUpscaler::JitterDepth(VideoCore::ImageId depth) const { bool TemporalUpscaler::EnsureResources(u32 w, u32 h, u32 ow, u32 oh, bool hdr) { // FSR 4 has its own context: no portable FSR 3 context is made. const bool use_fsr4 = UseFsr4(); - const bool use_taa = SpartanSettings::Get().upscaler == SpartanSettings::UpscalerTaa; + const bool use_taa = SpartanSettings::IsTaa(SpartanSettings::Get().upscaler); if (use_taa && (w != ow || h != oh)) { std::printf("TAA: remove SPARTAN_RENDER_RES to use native-resolution TAA\n"); return false; @@ -1142,8 +1146,86 @@ void TemporalUpscaler::CreatePipelines() { } } +bool TemporalUpscaler::RecordXess(vk::CommandBuffer cmdbuf, const XessInputs& inputs, + vk::ImageView color, vk::ImageView depth) { + const auto& settings = SpartanSettings::Get(); + if (settings.upscaler != SpartanSettings::UpscalerXess || !xess || inputs.width != out_width || inputs.height != out_height) { + return false; + } + const bool ok = xess->Record({ + .cmdbuf = cmdbuf, + .color = {inputs.color, color, inputs.color_format, vk::ImageAspectFlagBits::eColor, + inputs.width, inputs.height}, + .depth = {inputs.depth, depth, inputs.depth_format, vk::ImageAspectFlagBits::eDepth, + inputs.width, inputs.height}, + .motion = {vk::Image(motion_image), *motion_view, vk::Format::eR16G16Sfloat, + vk::ImageAspectFlagBits::eColor, inputs.width, inputs.height}, + .output = {vk::Image(output_image), *output_view, vk::Format::eR16G16B16A16Sfloat, + vk::ImageAspectFlagBits::eColor, out_width, out_height}, + .responsive = inputs.has_mask + ? XessAa::Image{vk::Image(reactive_image), *reactive_view, vk::Format::eR8Unorm, + vk::ImageAspectFlagBits::eColor, inputs.width, inputs.height} + : XessAa::Image{}, + .responsive_max = float(settings.xess_objects.load()) / 100.0f, + .jitter = jitter, + .reset = reset || !xess_active, // XeSS has not been drawing: its history is old + }); + // The menu shows why XeSS is not running; the text outlives this frame. + static std::string shown; + const char* problem = xess->Problem(); + if (!problem) { + SpartanSettings::Get().xess_problem = nullptr; + shown.clear(); // the same problem coming back is shown again + } else if (shown != problem) { + shown = problem; + static std::array kept; + static u32 next = 0; + kept[next] = shown; + SpartanSettings::Get().xess_problem = kept[next].c_str(); + next = (next + 1) % kept.size(); + } + if (!ok && xess->Fatal()) { + static bool said = false; + if (!said) { + said = true; + std::printf("XeSS: not available, the TAA accumulates instead\n"); + } + } + return ok; +} + void TemporalUpscaler::RecordTaa(vk::CommandBuffer cmdbuf, vk::ImageView color, - vk::ImageView depth) { + vk::ImageView depth, const XessInputs* xess_inputs) { + // XeSS in place of the accumulation: it writes the result into output_view and has its own + // history, so the TAA's pass and its sharpening (which reads the TAA's history) are skipped. + if (xess_inputs && RecordXess(cmdbuf, *xess_inputs, color, depth)) { + xess_active = true; + // The look sliders of the accumulation do not apply to XeSS; the texture detail (the + // rasterizer's mip bias) and the sharpening do, and are logged like the TAA's look. + const auto& xs = SpartanSettings::Get(); + const bool camera = camera_motion.ViewProjectionCamera(); + const float strength = camera ? std::clamp(xs.xess_sharpen.load() / 100.0f, 0.0f, 2.0f) : 0.0f; + static std::array logged{-1, -1, -1}, pending{-1, -1, -1}; + static u32 stable_frames = 0; + const std::array now{xs.taa_lod.load(), xs.xess_sharpen.load(), xs.xess_objects.load()}; + if (now != pending) { + pending = now; + stable_frames = 0; + } else if (stable_frames < 12 && ++stable_frames == 12 && pending != logged) { + logged = pending; + std::printf("XeSS look: texture detail %d sharpen %d moving objects %d\n", now[0], now[1], + now[2]); + } + if (strength > 0.0f) { + SharpenImage(cmdbuf, vk::Image(output_image), false, out_width, out_height, strength); + } + return; + } + if (xess_active) { + // Back to the TAA: its history is from before XeSS ran. + xess_active = false; + reset = true; + } // Make scene writes and the last storage-image history writes visible to sampled reads. const vk::MemoryBarrier2 inputs{ .srcStageMask = vk::PipelineStageFlagBits2::eAllCommands, @@ -1320,6 +1402,11 @@ void TemporalUpscaler::ExtraSharpen(vk::CommandBuffer cmdbuf, vk::Image target, if (!SharpenOn() || extra <= 0.0f) { return; } + SharpenImage(cmdbuf, target, ldr, w, h, extra); +} + +void TemporalUpscaler::SharpenImage(vk::CommandBuffer cmdbuf, vk::Image target, bool ldr, u32 w, + u32 h, float extra) { const auto device = instance.GetDevice(); if (extra_sharpen_width != w || extra_sharpen_height != h) { // Retired command buffers may still read the old copy. `cmdbuf` stays open. @@ -1580,7 +1667,7 @@ bool TemporalUpscaler::RecordReactive(vk::ImageView color_view) { void TemporalUpscaler::Run() { if (auto* profiler = GpuProfiler::Get()) { - const char* label = SpartanSettings::Get().upscaler == SpartanSettings::UpscalerTaa + const char* label = SpartanSettings::IsTaa(SpartanSettings::Get().upscaler) ? "upscaler Run (TAA)" : "upscaler Run (FSR)"; profiler->Mark(0xF5A0'0000ull ^ std::hash{}(label), [label] { return std::string{label}; }); @@ -1675,7 +1762,7 @@ void TemporalUpscaler::Run() { last_frame = now; bool dispatched = false; - if (SpartanSettings::Get().upscaler == SpartanSettings::UpscalerTaa) { + if (SpartanSettings::IsTaa(SpartanSettings::Get().upscaler)) { RecordTaa(cmdbuf, input_color_view, input_depth_view); dispatched = true; } else if (UseFsr4()) { @@ -1753,7 +1840,7 @@ void TemporalUpscaler::Run() { if (dispatched) { reset = false; dispatched_last_frame = true; frames_since_run = 0; - if (SpartanSettings::Get().upscaler != SpartanSettings::UpscalerTaa) { + if (!SpartanSettings::IsTaa(SpartanSettings::Get().upscaler)) { ExtraSharpen(cmdbuf, vk::Image(output_image), false, ow, oh); } // The result replaces the scene color's RGB (its alpha carries data for the post). @@ -1900,7 +1987,14 @@ void TemporalUpscaler::RunSceneTaa() { } last_frame = now; - RecordTaa(cmdbuf, color_view, depth_view); + // XeSS's responsive mask: the characters and objects of the scene stencil (they move without + // motion vectors, so their history would ghost). The mask pass needs the depth in General. + const bool has_mask = SpartanSettings::Get().upscaler == SpartanSettings::UpscalerXess && + RecordStencilReactive(cmdbuf, depth, depth_format, w, h); + const XessInputs xess_inputs{color.GetImage(), depth.GetImage(), + srgb_color ? vk::Format::eR8G8B8A8Srgb : vk::Format::eR8G8B8A8Unorm, + depth_format, w, h, has_mask}; + RecordTaa(cmdbuf, color_view, depth_view, &xess_inputs); const bool dispatched = true; if (!dispatched) { return; // the scene colour stays as the game made it @@ -2001,7 +2095,7 @@ std::array TemporalUpscaler::SceneSize(u32 w, u32 h) const { } float TemporalUpscaler::SceneMipBias() const { - if (!Active() || SpartanSettings::Get().upscaler == SpartanSettings::UpscalerTaa) return 0.0f; + if (!Active() || SpartanSettings::IsTaa(SpartanSettings::Get().upscaler)) return 0.0f; const float render = float(SpartanSettings::Get().active_render_width.load()); const float output = float(Scaled() ? target_width : 1920u); float bias = render > 0.0f && render < output ? std::log2(render / output) : 0.0f; @@ -2259,7 +2353,7 @@ void TemporalUpscaler::RunUiOnly(VideoCore::ImageId color_id, VideoCore::ImageId void TemporalUpscaler::RunScaled() { if (auto* profiler = GpuProfiler::Get()) { - const char* label = SpartanSettings::Get().upscaler == SpartanSettings::UpscalerTaa + const char* label = SpartanSettings::IsTaa(SpartanSettings::Get().upscaler) ? "upscaler RunScaled (TAA)" : "upscaler RunScaled (FSR)"; profiler->Mark(0xF5A0'0000ull ^ std::hash{}(label), [label] { return std::string{label}; }); @@ -2391,13 +2485,13 @@ void TemporalUpscaler::RunScaled() { last_frame = now; // spartanport: FSR 4 writes its HDR-format output, copied into the output-size UI image. - if (UseFsr4() || SpartanSettings::Get().upscaler == SpartanSettings::UpscalerTaa) { + if (UseFsr4() || SpartanSettings::IsTaa(SpartanSettings::Get().upscaler)) { const auto [fw, fh] = std::array{ow, oh}; barrier(vk::Image(output_image), vk::ImageAspectFlagBits::eColor, vk::ImageLayout::eUndefined, all, vk::AccessFlagBits2::eNone, vk::ImageLayout::eGeneral, all, rw); bool ok4 = true; - if (SpartanSettings::Get().upscaler == SpartanSettings::UpscalerTaa) { + if (SpartanSettings::IsTaa(SpartanSettings::Get().upscaler)) { RecordTaa(cmdbuf, color_view, depth_view); } else { ok4 = RecordFsr4(cmdbuf, {color_image, color_view, source_width, source_height}, @@ -2405,7 +2499,7 @@ void TemporalUpscaler::RunScaled() { oh, frame_ms, color.info.pixel_format); } if (ok4) { - if (SpartanSettings::Get().upscaler != SpartanSettings::UpscalerTaa) { + if (!SpartanSettings::IsTaa(SpartanSettings::Get().upscaler)) { ExtraSharpen(cmdbuf, vk::Image(output_image), false, fw, fh); } barrier(vk::Image(output_image), vk::ImageAspectFlagBits::eColor, @@ -2439,7 +2533,7 @@ void TemporalUpscaler::RunScaled() { DumpImages(instance, scheduler, cmdbuf, dump, {{depth_image, source_width, source_height, 4, "depth", "f32", vk::ImageAspectFlagBits::eDepth}}); - if (SpartanSettings::Get().upscaler == SpartanSettings::UpscalerTaa && + if (SpartanSettings::IsTaa(SpartanSettings::Get().upscaler) && std::getenv("SPARTAN_TAA_DIAGNOSTICS")) { DumpImages(instance, scheduler, cmdbuf, dump, {{vk::Image(taa_history[taa_next]),ow,oh,16, diff --git a/gpu/shadps4/video_core/renderer_vulkan/vk_temporal_upscaler.h b/gpu/shadps4/video_core/renderer_vulkan/vk_temporal_upscaler.h index a032949e65..9a1ab102cc 100644 --- a/gpu/shadps4/video_core/renderer_vulkan/vk_temporal_upscaler.h +++ b/gpu/shadps4/video_core/renderer_vulkan/vk_temporal_upscaler.h @@ -23,6 +23,7 @@ #include "video_core/renderer_vulkan/vk_common.h" #include "video_core/renderer_vulkan/vk_frame_generation.h" #include "video_core/renderer_vulkan/vk_fsr4.h" +#include "video_core/renderer_vulkan/vk_xess.h" #include "video_core/texture_cache/image.h" struct FfxVkPortableUpscaleContext; @@ -227,10 +228,23 @@ class TemporalUpscaler { bool RecordFsr4(vk::CommandBuffer cmdbuf, Fsr4Upscaler::Image color, Fsr4Upscaler::Image depth, u32 w, u32 h, u32 ow, u32 oh, float frame_ms, vk::Format ldr_format = vk::Format::eR8G8B8A8Unorm); - void RecordTaa(vk::CommandBuffer cmdbuf, vk::ImageView color, vk::ImageView depth); + /// The images behind the views RecordTaa is given, which XeSS wants as well. + struct XessInputs { + vk::Image color, depth; + vk::Format color_format, depth_format; + u32 width, height; + bool has_mask; ///< the stencil mask is in reactive_image (XeSS's responsive mask) + }; + void RecordTaa(vk::CommandBuffer cmdbuf, vk::ImageView color, vk::ImageView depth, + const XessInputs* xess_inputs = nullptr); + /// XeSS in place of the TAA's accumulation (upscaler xess); false: the TAA runs this frame. + bool RecordXess(vk::CommandBuffer cmdbuf, const XessInputs& inputs, vk::ImageView color, + vk::ImageView depth); /// Sharpness above 1 for FSR 3/4 (their RCAS stops at 1): one more RCAS pass over the target /// (output_image, or the 8-bit UI image with ldr) in General layout after the upscaler. void ExtraSharpen(vk::CommandBuffer cmdbuf, vk::Image target, bool ldr, u32 w, u32 h); + /// RCAS pass of ours over `target` (the output image, or the 8-bit UI image when `ldr`), strength 0..2. + void SharpenImage(vk::CommandBuffer cmdbuf, vk::Image target, bool ldr, u32 w, u32 h, float strength); const Instance& instance; Scheduler& scheduler; @@ -334,6 +348,8 @@ class TemporalUpscaler { bool resources_fsr4 = false; ///< made for FSR 4 (no FSR 3 context) bool resources_taa = false; std::unique_ptr fsr4; + std::unique_ptr xess; + bool xess_active = false; ///< the last frame was made by XeSS (its history is not the TAA's) std::unique_ptr frame_generation; bool fsr4_failed = false; VideoCore::UniqueImage motion_image; diff --git a/gpu/shadps4/video_core/renderer_vulkan/vk_xess.cpp b/gpu/shadps4/video_core/renderer_vulkan/vk_xess.cpp new file mode 100644 index 0000000000..c74eb28ff0 --- /dev/null +++ b/gpu/shadps4/video_core/renderer_vulkan/vk_xess.cpp @@ -0,0 +1,447 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +// spartanport: see vk_xess.h. + +#include +#include +#include +#include +#include +#include +#include "video_core/renderer_vulkan/vk_instance.h" +#include "video_core/renderer_vulkan/vk_scheduler.h" +#include "video_core/renderer_vulkan/vk_xess.h" + +#if defined(_WIN32) && __has_include() +#define SPARTAN_HAS_XESS 1 +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif +#ifndef NOMINMAX +#define NOMINMAX +#endif +#include +#include +#else +#define SPARTAN_HAS_XESS 0 +#endif + +namespace Vulkan { + +#if SPARTAN_HAS_XESS + +namespace { + +/// libxess.dll and the entry points this file calls; loaded once, on first use. +struct Library { + HMODULE module{}; + std::string error; + xess_result_t (*get_version)(xess_version_t*){}; + xess_result_t (*create)(VkInstance, VkPhysicalDevice, VkDevice, xess_context_handle_t*){}; + xess_result_t (*init)(xess_context_handle_t, const xess_vk_init_params_t*){}; + xess_result_t (*execute)(xess_context_handle_t, VkCommandBuffer, + const xess_vk_execute_params_t*){}; + xess_result_t (*destroy)(xess_context_handle_t){}; + xess_result_t (*required_extensions)(VkInstance, VkPhysicalDevice, uint32_t*, + const char* const**){}; + xess_result_t (*set_logging)(xess_context_handle_t, xess_logging_level_t, + xess_app_log_callback_t){}; + xess_result_t (*is_optimal_driver)(xess_context_handle_t){}; + xess_result_t (*set_max_responsive)(xess_context_handle_t, float){}; + xess_result_t (*required_features)(VkInstance, VkPhysicalDevice, void**){}; + + bool Ok() const { + return module && create && init && execute && destroy; + } +}; + +/// The folder of the executable (empty when it cannot be told). +std::wstring ExecutableDirectory() { + wchar_t path[MAX_PATH * 2]; + const DWORD length = GetModuleFileNameW(nullptr, path, DWORD(std::size(path))); + if (length == 0 || length >= std::size(path)) { + return {}; + } + std::wstring wide(path, length); + const auto slash = wide.find_last_of(L"\\/"); + if (slash == std::wstring::npos) { + return {}; + } + wide.resize(slash); + return wide; +} + +/// The device is idle and nothing else is submitting or presenting: the waits below hold the +/// submit lock the presenter and the scheduler take around vkQueueSubmit / vkQueuePresent. +void WaitIdle(const Instance& instance) { + std::scoped_lock lock{Scheduler::submit_mutex}; + (void)instance.GetDevice().waitIdle(); +} + +std::atomic g_device_ready{false}; ///< the device was created for XeSS (SetDeviceReady) +std::string g_device_note; + +template +void Resolve(HMODULE module, const char* name, T& out) { + out = reinterpret_cast(reinterpret_cast(GetProcAddress(module, name))); +} + +Library& GetLibrary() { + static Library library = [] { + Library lib; + const std::wstring directory = ExecutableDirectory(); + // Only the game's own folders, by full path: never the current directory or PATH, where + // another libxess.dll could be planted. The library's dependencies are looked for beside it, + // then in the system folder. + constexpr DWORD flags = LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR | LOAD_LIBRARY_SEARCH_SYSTEM32; + if (!directory.empty()) { + lib.module = LoadLibraryExW((directory + L"\\libxess.dll").c_str(), nullptr, flags); + if (!lib.module) { + lib.module = LoadLibraryExW((directory + L"\\bin\\libxess.dll").c_str(), nullptr, flags); + } + } + if (!lib.module) { + lib.error = "libxess.dll was not found next to the game (Intel's XeSS library)"; + return lib; + } + Resolve(lib.module, "xessGetVersion", lib.get_version); + Resolve(lib.module, "xessVKCreateContext", lib.create); + Resolve(lib.module, "xessVKInit", lib.init); + Resolve(lib.module, "xessVKExecute", lib.execute); + Resolve(lib.module, "xessDestroyContext", lib.destroy); + Resolve(lib.module, "xessVKGetRequiredDeviceExtensions", lib.required_extensions); + Resolve(lib.module, "xessSetLoggingCallback", lib.set_logging); + Resolve(lib.module, "xessIsOptimalDriver", lib.is_optimal_driver); + Resolve(lib.module, "xessSetMaxResponsiveMaskValue", lib.set_max_responsive); + Resolve(lib.module, "xessVKGetRequiredDeviceFeatures", lib.required_features); + if (!lib.Ok()) { + lib.error = "libxess.dll has no Vulkan entry points (not the XeSS SDK library?)"; + } + return lib; + }(); + return library; +} + +void LogCallback(const char* message, xess_logging_level_t level) { + std::printf("XeSS [%d]: %s\n", int(level), message ? message : ""); +} + +const char* ResultName(xess_result_t result) { + switch (result) { + case XESS_RESULT_ERROR_UNSUPPORTED_DEVICE: return "unsupported device"; + case XESS_RESULT_ERROR_UNSUPPORTED_DRIVER: return "unsupported driver"; + case XESS_RESULT_ERROR_UNINITIALIZED: return "not initialised"; + case XESS_RESULT_ERROR_INVALID_ARGUMENT: return "invalid argument"; + case XESS_RESULT_ERROR_DEVICE_OUT_OF_MEMORY: return "out of GPU memory"; + case XESS_RESULT_ERROR_DEVICE: return "device error"; + case XESS_RESULT_ERROR_NOT_IMPLEMENTED: return "not implemented"; + case XESS_RESULT_ERROR_INVALID_CONTEXT: return "invalid context"; + case XESS_RESULT_ERROR_UNSUPPORTED: return "unsupported configuration"; + case XESS_RESULT_ERROR_WRONG_CALL_ORDER: return "wrong call order"; + default: return "error"; + } +} + +bool HasStencil(vk::Format format) { + return format == vk::Format::eD16UnormS8Uint || format == vk::Format::eD24UnormS8Uint || + format == vk::Format::eD32SfloatS8Uint; +} + +xess_vk_image_view_info ViewInfo(const XessAa::Image& image) { + xess_vk_image_view_info info{}; + info.imageView = static_cast(image.view); + info.image = static_cast(image.image); + info.subresourceRange = {static_cast(image.aspect), 0, 1, 0, 1}; + info.format = static_cast(image.format); + info.width = image.width; + info.height = image.height; + return info; +} + +} // namespace + +struct XessAa::Impl { + explicit Impl(const Instance& instance_) : instance(instance_) {} + ~Impl() { + if (context && GetLibrary().destroy) { + WaitIdle(instance); + GetLibrary().destroy(context); + } + } + + const Instance& instance; + xess_context_handle_t context{}; + u32 initialised_width = 0, initialised_height = 0; + bool initialised_mask = false; + float mask_max = -1.0f; ///< the clip value last set on the context + bool fresh = true; ///< the history of the context is empty: the next frame resets it + bool fatal = false; + u32 failures = 0; + std::string problem; + bool logged_running = false; + + void Fail(const char* what, xess_result_t result, bool permanent) { + char text[200]; + std::snprintf(text, sizeof(text), "XeSS %s: %s (%d)", what, ResultName(result), + int(result)); + problem = text; + std::printf("%s\n", text); + if (permanent) { + fatal = true; + } + } + + void Barrier(vk::CommandBuffer cmdbuf, const Image& image, bool to_read) { + vk::ImageAspectFlags aspect = image.aspect; + if (HasStencil(image.format)) { + aspect |= vk::ImageAspectFlagBits::eStencil; // the whole image changes layout together + } + const vk::ImageMemoryBarrier2 barrier{ + .srcStageMask = to_read ? vk::PipelineStageFlagBits2::eAllCommands + : vk::PipelineStageFlagBits2::eComputeShader, + .srcAccessMask = to_read ? vk::AccessFlagBits2::eMemoryRead | + vk::AccessFlagBits2::eMemoryWrite + : vk::AccessFlagBits2::eNone, + .dstStageMask = to_read ? vk::PipelineStageFlagBits2::eComputeShader + : vk::PipelineStageFlagBits2::eAllCommands, + .dstAccessMask = to_read ? vk::AccessFlagBits2::eShaderSampledRead + : vk::AccessFlagBits2::eMemoryRead | + vk::AccessFlagBits2::eMemoryWrite, + .oldLayout = to_read ? vk::ImageLayout::eGeneral : vk::ImageLayout::eShaderReadOnlyOptimal, + .newLayout = to_read ? vk::ImageLayout::eShaderReadOnlyOptimal : vk::ImageLayout::eGeneral, + .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .image = image.image, + .subresourceRange = {aspect, 0, 1, 0, 1}, + }; + cmdbuf.pipelineBarrier2({.imageMemoryBarrierCount = 1, .pImageMemoryBarriers = &barrier}); + } + + bool Record(const Frame& frame) { + if (fatal) { + return false; + } + const Library& lib = GetLibrary(); + if (!lib.Ok()) { + problem = lib.error; + fatal = true; + std::printf("XeSS: %s\n", problem.c_str()); + return false; + } + if (!context && !g_device_ready) { + // The extensions and features are enabled when the device is created, at the start, + // and only when XeSS is chosen then: a context on any other device is undefined. + problem = g_device_note.empty() + ? "XeSS was not chosen when the game started: restart it to use XeSS" + : g_device_note; + fatal = true; + std::printf("XeSS: %s\n", problem.c_str()); + return false; + } + if (!context) { + const xess_result_t result = + lib.create(static_cast(instance.GetInstance()), + static_cast(instance.GetPhysicalDevice()), + static_cast(instance.GetDevice()), &context); + if (result < 0) { + context = nullptr; + Fail("context", result, true); + return false; + } + if (lib.set_logging) { + lib.set_logging(context, XESS_LOGGING_LEVEL_WARNING, &LogCallback); + } + if (lib.get_version) { + xess_version_t version{}; + if (lib.get_version(&version) >= 0) { + std::printf("XeSS: library %u.%u.%u\n", version.major, version.minor, + version.patch); + } + } + if (lib.is_optimal_driver && lib.is_optimal_driver(context) == + XESS_RESULT_WARNING_OLD_DRIVER) { + std::printf("XeSS: the graphics driver is older than XeSS likes (it may run " + "slower or look worse)\n"); + } + } + const bool has_mask = frame.responsive.view && lib.set_max_responsive; + if (initialised_width != frame.output.width || initialised_height != frame.output.height || + initialised_mask != has_mask) { + // A (re)initialisation needs the GPU idle; it happens at the start and when the + // game's picture changes size. + WaitIdle(instance); + xess_vk_init_params_t init{}; + init.outputResolution = {frame.output.width, frame.output.height}; + init.qualitySetting = XESS_QUALITY_SETTING_AA; + // The scene colour is tonemapped (display range), not HDR. + init.initFlags = XESS_INIT_FLAG_LDR_INPUT_COLOR | + (has_mask ? XESS_INIT_FLAG_RESPONSIVE_PIXEL_MASK : 0); + init.creationNodeMask = 1; + init.visibleNodeMask = 1; + const xess_result_t result = lib.init(context, &init); + if (result < 0) { + Fail("initialisation", result, true); + return false; + } + initialised_width = frame.output.width; + initialised_height = frame.output.height; + initialised_mask = has_mask; + mask_max = -1.0f; + fresh = true; + logged_running = false; + } + + xess_vk_execute_params_t params{}; + params.colorTexture = ViewInfo(frame.color); + params.velocityTexture = ViewInfo(frame.motion); + params.depthTexture = ViewInfo(frame.depth); + params.outputTexture = ViewInfo(frame.output); + if (has_mask) { + params.responsivePixelMaskTexture = ViewInfo(frame.responsive); + const float clip = frame.responsive_max < 0.0f ? 0.0f + : frame.responsive_max > 1.0f ? 1.0f : frame.responsive_max; + if (clip != mask_max) { + mask_max = clip; + lib.set_max_responsive(context, clip); + } + } + // XeSS takes the jitter in pixels as the projection was shifted; SPARTAN_XESS_INVERT_JITTER=1 + // flips it (one switch for a test, in case a sign differs from FSR's). + static const bool invert = [] { + const char* value = std::getenv("SPARTAN_XESS_INVERT_JITTER"); + return value && *value == '1'; + }(); + const float sign = invert ? -1.0f : 1.0f; + params.jitterOffsetX = sign * frame.jitter[0]; + params.jitterOffsetY = sign * frame.jitter[1]; + params.exposureScale = 1.0f; + params.resetHistory = frame.reset || fresh ? 1u : 0u; + params.inputWidth = frame.color.width; + params.inputHeight = frame.color.height; + + // Resources in the layouts XeSS documents (shader read only; the output General), back + // to General afterwards for everything else the frame does with them. + const vk::MemoryBarrier2 output_ready{ + .srcStageMask = vk::PipelineStageFlagBits2::eAllCommands, + .srcAccessMask = vk::AccessFlagBits2::eMemoryRead | vk::AccessFlagBits2::eMemoryWrite, + .dstStageMask = vk::PipelineStageFlagBits2::eComputeShader, + .dstAccessMask = vk::AccessFlagBits2::eShaderStorageRead | + vk::AccessFlagBits2::eShaderStorageWrite | + vk::AccessFlagBits2::eShaderSampledRead, + }; + frame.cmdbuf.pipelineBarrier2({.memoryBarrierCount = 1, .pMemoryBarriers = &output_ready}); + Barrier(frame.cmdbuf, frame.color, true); + Barrier(frame.cmdbuf, frame.depth, true); + Barrier(frame.cmdbuf, frame.motion, true); + if (has_mask) { + Barrier(frame.cmdbuf, frame.responsive, true); + } + const xess_result_t result = + lib.execute(context, static_cast(frame.cmdbuf), ¶ms); + Barrier(frame.cmdbuf, frame.color, false); + Barrier(frame.cmdbuf, frame.depth, false); + Barrier(frame.cmdbuf, frame.motion, false); + if (has_mask) { + Barrier(frame.cmdbuf, frame.responsive, false); + } + if (result < 0) { + Fail("execute", result, ++failures >= 3); + return false; + } + failures = 0; + problem.clear(); + fresh = false; + if (!logged_running) { + logged_running = true; + std::printf("XeSS: running, anti-aliasing at %ux%u\n", initialised_width, + initialised_height); + } + return true; + } +}; + +std::vector XessAa::DeviceExtensions(vk::Instance instance, + vk::PhysicalDevice physical_device) { + std::vector names; + const Library& lib = GetLibrary(); + if (!lib.Ok() || !lib.required_extensions) { + return names; + } + uint32_t count = 0; + const char* const* list = nullptr; + if (lib.required_extensions(static_cast(instance), + static_cast(physical_device), &count, + &list) < 0 || + !list) { + return names; + } + names.assign(list, list + count); + return names; +} + +bool XessAa::PatchDeviceFeatures(vk::Instance instance, vk::PhysicalDevice physical_device, + void*& chain) { + const Library& lib = GetLibrary(); + if (!lib.Ok() || !lib.required_features) { + return false; + } + void* head = chain; + if (lib.required_features(static_cast(instance), + static_cast(physical_device), &head) < 0 || + !head) { + return false; + } + chain = head; + return true; +} + +void XessAa::SetDeviceReady(bool ready, const char* why) { + g_device_note = why ? why : ""; + g_device_ready = ready; +} + +#else // no XeSS headers or not Windows + +struct XessAa::Impl { + explicit Impl(const Instance&) {} + bool Record(const Frame&) { + return false; + } +}; + +std::vector XessAa::DeviceExtensions(vk::Instance, vk::PhysicalDevice) { + return {}; +} + +bool XessAa::PatchDeviceFeatures(vk::Instance, vk::PhysicalDevice, void*&) { + return false; +} + +void XessAa::SetDeviceReady(bool, const char*) {} + +#endif + +XessAa::XessAa(const Instance& instance) : impl(std::make_unique(instance)) {} + +XessAa::~XessAa() = default; + +bool XessAa::Record(const Frame& frame) { + return impl->Record(frame); +} + +const char* XessAa::Problem() const noexcept { +#if SPARTAN_HAS_XESS + return impl->problem.empty() ? nullptr : impl->problem.c_str(); +#else + return "XeSS is available only in the Windows build"; +#endif +} + +bool XessAa::Fatal() const noexcept { +#if SPARTAN_HAS_XESS + return impl->fatal; +#else + return true; +#endif +} + +} // namespace Vulkan diff --git a/gpu/shadps4/video_core/renderer_vulkan/vk_xess.h b/gpu/shadps4/video_core/renderer_vulkan/vk_xess.h new file mode 100644 index 0000000000..a104afe154 --- /dev/null +++ b/gpu/shadps4/video_core/renderer_vulkan/vk_xess.h @@ -0,0 +1,80 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +// spartanport: Intel XeSS (XeSS-SR, Vulkan) as the accumulation of the God of War III TAA, at the +// game's own resolution (the AA quality setting: no upscaling). It takes the same inputs as the +// TAA: the jittered scene colour, the scene depth and the motion vectors in render pixels (previous +// minus current position, without the jitter), and writes the result into the TAA's output image. +// +// libxess.dll (Intel's binary, redistributable unmodified under the Intel Simplified Software +// License; packaging/fetch_xess.sh) is loaded at run time next to the executable, so the game runs +// without it and the menu says why XeSS is not available. Windows only: Intel ships no other +// binaries. The headers in third_party/xess are Intel's (MIT). + +#pragma once + +#include +#include +#include +#include "common/types.h" +#include "video_core/renderer_vulkan/vk_common.h" + +namespace Vulkan { + +class Instance; + +class XessAa { +public: + explicit XessAa(const Instance& instance); + ~XessAa(); + + /// An image XeSS reads or writes; `view` covers `aspect` of mip 0, layer 0. + struct Image { + vk::Image image; + vk::ImageView view; + vk::Format format; + vk::ImageAspectFlags aspect; ///< of the view + u32 width, height; + }; + struct Frame { + vk::CommandBuffer cmdbuf; + Image color, depth, motion; + Image output; ///< in layout General, usage storage + /// Optional responsive pixel mask (R8, 1 = distrust the history there; view null = none), + /// clipped to `responsive_max`. Whether there is one is fixed when XeSS is (re)initialised. + Image responsive; + float responsive_max; + std::array jitter; ///< pixels, as the game's projection was shifted + bool reset; + }; + + /// Records XeSS into `frame.cmdbuf`: the inputs go to the shader read-only layout and back to + /// General, the output stays in General. False when XeSS cannot run (Problem() says why). + bool Record(const Frame& frame); + + /// Why the last Record failed, or null. + [[nodiscard]] const char* Problem() const noexcept; + /// XeSS will not run in this session (library missing, device not supported). + [[nodiscard]] bool Fatal() const noexcept; + + /// The device extensions XeSS asks for (empty when the library is not there); for the device + /// creation, which has to enable them. + static std::vector DeviceExtensions(vk::Instance instance, + vk::PhysicalDevice physical_device); + + /// Asks XeSS for the device features it needs and patches them into the feature chain of the + /// device being created: `chain` is the head of that chain (a VkPhysicalDeviceFeatures2) and + /// comes back as the head to create the device with. False when the library is missing or has + /// no features to give; the chain is then left as it was. + static bool PatchDeviceFeatures(vk::Instance instance, vk::PhysicalDevice physical_device, + void*& chain); + + /// The device creation says whether the device has the extensions and features XeSS needs; + /// without them Record fails for good instead of creating a context on a device that lacks them. + /// `why` (kept, may be null) is shown in the menu then. + static void SetDeviceReady(bool ready, const char* why = nullptr); + +private: + struct Impl; + std::unique_ptr impl; +}; + +} // namespace Vulkan diff --git a/gpu/shim/spartanport_overlay.cpp b/gpu/shim/spartanport_overlay.cpp index b1a5dc7356..826b33d5f3 100644 --- a/gpu/shim/spartanport_overlay.cpp +++ b/gpu/shim/spartanport_overlay.cpp @@ -376,6 +376,7 @@ const char* UpscalerLabel(int upscaler) { case SpartanSettings::UpscalerFsr4: return "FSR 4"; case SpartanSettings::UpscalerFsr411: return "FSR 4.1"; case SpartanSettings::UpscalerTaa: return "TAA"; + case SpartanSettings::UpscalerXess: return "XeSS"; default: return ""; } } @@ -574,7 +575,7 @@ void ImageTab() { const bool own_sharpening = SpartanSettings::OwnSharpening(s.upscaler); const bool rcas_host_blocked = s.rcas && !s.rcas_applied; const bool rcas_blocked = rcas_host_blocked && !own_sharpening; - if (s.upscaler == SpartanSettings::UpscalerTaa) { + if (SpartanSettings::IsTaa(s.upscaler)) { DisabledText(s.temporal_applied ? "Temporal anti-aliasing is running." : "Temporal anti-aliasing is selected but not running (see last_run.log)."); } @@ -588,30 +589,47 @@ void ImageTab() { if (s.anti_aliasing != G::AaOff && !s.aa_applied) { DisabledText("Anti-aliasing is not active: this graphics card could not set it up."); } - if (s.upscaler == SpartanSettings::UpscalerTaa) { - Separator("TAA look (God of War III)"); - if (BeginRows("##taa_look")) { + if (SpartanSettings::IsTaa(s.upscaler)) { + const bool xess = s.upscaler == SpartanSettings::UpscalerXess; + Separator(xess ? "XeSS (God of War III)" : "TAA look (God of War III)"); + if (xess) { + if (BeginRows("##xess_look")) { + if (const char* problem = s.xess_problem) InfoRow("XeSS status", problem); + SliderRow("Texture detail", s.taa_lod, 0, 150, "%d%%", + "Sharper textures (a negative mip bias, in percent of one level): XeSS turns the " + "extra detail into a clean picture. Higher: more detail, more shimmer. Default 80%."); + SliderRow("Moving objects", s.xess_objects, 0, 100, "%d%%", + "How much XeSS distrusts its history on characters and objects (a mask from the " + "game's stencil). Higher: less ghosting behind them, rougher edges. 0% = off. " + "Default 95%."); + SliderRow("Sharpening", s.xess_sharpen, 0, 200, "%d%%", + "Sharpening after XeSS, separate from the Sharpening (RCAS) switch below. 0% = off. " + "Default 145%."); + ImGui::EndTable(); + } + } + if (!xess && BeginRows("##taa_look")) { SliderRow("History on still picture", s.taa_static, 0, 99, "%d%%", "Higher: smoother edges on a still picture, a little more trail. Default 99%."); SliderRow("History on moving picture", s.taa_moving, 0, 99, "%d%%", "Higher: smoother while the camera moves, more blur and trail. Default 55%."); SliderRow("Colour tolerance", s.taa_tolerance, 30, 300, "%d%%", - "Lower: less trail and ghosting, more flicker. Default 115%."); + "Lower: less trail and ghosting, more flicker. Default 175%."); SliderRow("Moving objects", s.taa_objects, 0, 100, "%d%%", "How much history a moving character or object loses. Higher: less ghosting there, " - "rougher edges. Default 90%."); + "rougher edges. Default 55%."); SliderRow("Texture detail", s.taa_lod, 0, 150, "%d%%", "Sharper textures (a negative mip bias, in percent of one level): the accumulation " "turns the extra detail into a clean picture. Higher: more detail, more shimmer. " - "Default 75%."); + "Default 80%."); SliderRow("Moving object edges", s.taa_spatial, 0, 100, "%d%%", "Smooths the stair-stepped edges of moving characters, where the history is refused: " - "a spatial filter on those pixels only. Higher: smoother, slightly softer. Default 70%."); + "a spatial filter on those pixels only. Higher: smoother, slightly softer. Default 55%."); CheckRow("Debug view (history)", s.taa_debug, "Shows where the history is used: red = rejected by depth, green = lost to colour " "change, blue = history weight used. For bug reports; not saved."); SliderRow("TAA sharpening", s.taa_sharpen, 0, 200, "%d%%", - "Sharpening after the accumulation, separate from the Sharpening (RCAS) switch below. 0% = off. Default 165%."); + "Sharpening after the accumulation, separate from the Sharpening (RCAS) switch below. 0% = off. Default 130%."); ImGui::EndTable(); } } @@ -649,11 +667,11 @@ void ImageTab() { // The launcher's choices and order (options.rs UPSCALERS, PRESETS); the same values as the // Display menu's rows. #ifdef _WIN32 - static const char* const upscaler_labels[] = {"Off", "FSR 3.1", "FSR 3.1 (native HUD)", "FSR 4", "FSR 4.1", "TAA"}; + static const char* const upscaler_labels[] = {"Off", "FSR 3.1", "FSR 3.1 (native HUD)", "FSR 4", "FSR 4.1", "TAA", "XeSS"}; static const int upscaler_values[] = {SpartanSettings::UpscalerOff, SpartanSettings::UpscalerFsr3, SpartanSettings::UpscalerFsr3Ui, SpartanSettings::UpscalerFsr4, SpartanSettings::UpscalerFsr411, - SpartanSettings::UpscalerTaa}; + SpartanSettings::UpscalerTaa, SpartanSettings::UpscalerXess}; #else static const char* const upscaler_labels[] = {"Off", "FSR 3.1", "FSR 3.1 (native HUD)", "FSR 4", "TAA"}; static const int upscaler_values[] = {SpartanSettings::UpscalerOff, SpartanSettings::UpscalerFsr3, @@ -890,7 +908,8 @@ int RestartChanges() { (s.deferred_readback != s.startup_deferred_readback) + (s.stale_readback != s.startup_stale_readback) + (s.anisotropy != s.startup_anisotropy) + (s.preset != s.startup_preset) + ((s.upscaler == SpartanSettings::UpscalerOff) != (s.startup_upscaler == SpartanSettings::UpscalerOff) || - SpartanSettings::NeedsLivePath(s.upscaler) != SpartanSettings::NeedsLivePath(s.startup_upscaler)); + SpartanSettings::NeedsLivePath(s.upscaler) != SpartanSettings::NeedsLivePath(s.startup_upscaler) || + SpartanSettings::NeedsXessRestart(s.upscaler, s.startup_upscaler)); } // The menu's tabs: words in the title face, the open one in full colour with a red line under it, diff --git a/gpu/shim/spartanport_settings.cpp b/gpu/shim/spartanport_settings.cpp index 910ec02b08..a7ecf7f8a5 100644 --- a/gpu/shim/spartanport_settings.cpp +++ b/gpu/shim/spartanport_settings.cpp @@ -164,6 +164,10 @@ void Set(Values& v, const std::string& key, const std::string& value) { v.taa_lod = std::clamp(i, 0, 150); } else if (key == "taa_spatial") { v.taa_spatial = std::clamp(i, 0, 100); + } else if (key == "xess_sharpen") { + v.xess_sharpen = std::clamp(i, 0, 200); + } else if (key == "xess_objects") { + v.xess_objects = std::clamp(i, 0, 100); } else if (key == "fsr_lod") { v.fsr_lod = std::clamp(i, 0, 150); } else if (key == "fsr_objects") { @@ -438,7 +442,8 @@ bool GraphicsNeedRestart() { // The launcher patches the render size of the preset (or none without an upscaler). v.preset != v.startup_preset || (v.upscaler == UpscalerOff) != (v.startup_upscaler == UpscalerOff) || - NeedsLivePath(v.upscaler) != NeedsLivePath(v.startup_upscaler); + NeedsLivePath(v.upscaler) != NeedsLivePath(v.startup_upscaler) || + NeedsXessRestart(v.upscaler, v.startup_upscaler); } void ConfigureUpscalerSupport(bool fsr4, bool fsr411, const char* fsr411_problem) { @@ -466,7 +471,7 @@ bool FixedRenderSession() { int RenderPreset() { const auto& v = Get(); return FixedRenderSession() ? v.startup_preset : - v.upscaler == UpscalerTaa ? NativeAA : v.preset.load(); + IsTaa(v.upscaler) ? NativeAA : v.preset.load(); } bool ResolutionNeedsRestart() { @@ -475,7 +480,8 @@ bool ResolutionNeedsRestart() { return FixedRenderSession() && (v.preset != v.startup_preset || v.output_res != v.startup_output_res || (v.upscaler == UpscalerOff) != (v.startup_upscaler == UpscalerOff) || - NeedsLivePath(v.upscaler) != NeedsLivePath(v.startup_upscaler)); + NeedsLivePath(v.upscaler) != NeedsLivePath(v.startup_upscaler)) || + NeedsXessRestart(v.upscaler, v.startup_upscaler); } void Save() { @@ -555,6 +561,7 @@ void Save() { v.taa_static.load(), v.taa_moving.load(), v.taa_tolerance.load(), v.taa_objects.load(), v.taa_sharpen.load(), v.taa_lod.load(), v.taa_spatial.load()); std::fprintf(file, "fsr_lod=%d\nfsr_objects=%d\n", v.fsr_lod.load(), v.fsr_objects.load()); + std::fprintf(file, "xess_objects=%d\nxess_sharpen=%d\n", v.xess_objects.load(), v.xess_sharpen.load()); std::fprintf(file, "anti_aliasing=%s\n", SpartanGraphics::AntiAliasingKeys[std::clamp(v.anti_aliasing.load(), 0, int(SpartanGraphics::AaSmaa))].data()); std::fprintf(file, "master_volume=%d\naudio_channels=%s\n", v.master_volume.load(), @@ -596,7 +603,7 @@ const char* PresetName(int preset) { } const char* UpscalerName(int upscaler) { - static constexpr const char* names[UpscalerCount] = {"off", "fsr3", "fsr4", "fsr411", "taa", "fsr3ui"}; + static constexpr const char* names[UpscalerCount] = {"off", "fsr3", "fsr4", "fsr411", "taa", "fsr3ui", "xess"}; return names[std::clamp(upscaler, 0, UpscalerCount - 1)]; } @@ -727,7 +734,7 @@ extern "C" uint64_t spartanportgpu_native_setting(unsigned function) { }; // The launcher's order (options.rs UPSCALERS, PRESETS). #ifdef _WIN32 - const std::vector upscalers{UpscalerOff, UpscalerFsr3, UpscalerFsr3Ui, UpscalerFsr4, UpscalerFsr411, UpscalerTaa}; + const std::vector upscalers{UpscalerOff, UpscalerFsr3, UpscalerFsr3Ui, UpscalerFsr4, UpscalerFsr411, UpscalerTaa, UpscalerXess}; #else const std::vector upscalers{UpscalerOff, UpscalerFsr3, UpscalerFsr3Ui, UpscalerFsr4, UpscalerTaa}; #endif @@ -742,7 +749,7 @@ extern "C" uint64_t spartanportgpu_native_setting(unsigned function) { const int u = v.upscaler; value = u == UpscalerOff ? (pt ? "Desligado" : "Off") : u == UpscalerFsr3 ? "FSR 3.1" : u == UpscalerFsr3Ui ? "FSR 3.1 UI" - : u == UpscalerFsr4 ? "FSR 4" : u == UpscalerFsr411 ? "FSR 4.1" : u == UpscalerTaa ? "TAA" : UpscalerName(u); + : u == UpscalerFsr4 ? "FSR 4" : u == UpscalerFsr411 ? "FSR 4.1" : u == UpscalerTaa ? "TAA" : u == UpscalerXess ? "XeSS" : UpscalerName(u); if ((u == UpscalerFsr4 && !v.fsr4_supported) || (u == UpscalerFsr411 && !v.fsr411_supported)) value += pt ? " (indisponível)" : " (unavailable)"; } else { // The name only: the row has no room for the render size (the Insert menu shows it). diff --git a/gpu/shim/spartanport_settings.h b/gpu/shim/spartanport_settings.h index 06030f993f..825e46a8d8 100644 --- a/gpu/shim/spartanport_settings.h +++ b/gpu/shim/spartanport_settings.h @@ -33,8 +33,14 @@ inline constexpr int MasterVolumeMin = 0, MasterVolumeMax = 200, MasterVolumeDef // UpscalerFsr3Ui (appended: saved numbers keep their meaning) is FSR 3.1 with the game at its own // 1920x1080 targets, so the HUD, text and loading screens are not drawn small and stretched. +// UpscalerXess (Windows only) is Intel XeSS anti-aliasing in place of the TAA's accumulation, at the +// game's own resolution: everything the TAA gets (jitter, motion vectors, live path) with XeSS inside. enum Upscaler : int { UpscalerOff = 0, UpscalerFsr3 = 1, UpscalerFsr4 = 2, UpscalerFsr411 = 3, - UpscalerTaa = 4, UpscalerFsr3Ui = 5, UpscalerCount }; + UpscalerTaa = 4, UpscalerFsr3Ui = 5, UpscalerXess = 6, UpscalerCount }; +/// The scene TAA path: our TAA, or XeSS in place of its accumulation. +inline bool IsTaa(int upscaler) { + return upscaler == UpscalerTaa || upscaler == UpscalerXess; +} /// FSR 3.1, either variant. inline bool IsFsr3(int upscaler) { return upscaler == UpscalerFsr3 || upscaler == UpscalerFsr3Ui; @@ -42,7 +48,12 @@ inline bool IsFsr3(int upscaler) { /// The upscalers that need the game's own 1920x1080 targets (no resolution patch): a switch between /// them and the patched ones needs a restart. inline bool NeedsLivePath(int upscaler) { - return upscaler == UpscalerTaa || upscaler == UpscalerFsr3Ui; + return IsTaa(upscaler) || upscaler == UpscalerFsr3Ui; +} +/// XeSS needs its Vulkan extensions and features when the GPU device is created: choosing it when the +/// game did not start with it needs a restart (leaving it does not). +inline bool NeedsXessRestart(int upscaler, int startup_upscaler) { + return upscaler == UpscalerXess && startup_upscaler != UpscalerXess; } /// The port's own FSR sharpening (the RCAS switch and strength, the extra pass): the native-HUD FSR 3.1. /// The other upscalers keep the upstream behaviour (`sharpen` and `sharpness`). The TAA's sharpening @@ -144,12 +155,12 @@ struct Values { /// taa_tolerance: width of the colour range the history is clipped to; taa_objects: how much /// history a changed patch (a moving object without motion vectors) loses; taa_sharpen: sharpening /// after the accumulation. - std::atomic taa_static{99}, taa_moving{55}, taa_tolerance{115}, taa_objects{90}, taa_sharpen{165}; + std::atomic taa_static{99}, taa_moving{55}, taa_tolerance{175}, taa_objects{55}, taa_sharpen{130}; /// Texture detail of the scene's materials: a negative mip bias of taa_lod / 100 levels, which the /// accumulation (jitter) turns into detail instead of shimmer (the usual TAA texture bias). - std::atomic taa_lod{75}; + std::atomic taa_lod{80}; /// Edge smoothing of the pixels whose history was refused (moving characters): percent. - std::atomic taa_spatial{70}; + std::atomic taa_spatial{55}; /// FSR 3.1 with native HUD and text (UpscalerFsr3Ui), percent, live: fsr_lod is the texture detail /// (a negative mip bias of fsr_lod / 100 levels on top of FSR's own); fsr_objects the reactive /// strength of characters and objects (the stencil mask: 100 is upstream's, lower is sharper but @@ -158,6 +169,14 @@ struct Values { /// TAA debug view (not saved): red = history rejected by depth, green = lost to colour change / /// moving-object detection, blue = history weight used. std::atomic taa_debug{false}; + /// Why XeSS (upscaler=xess; libxess.dll) is not running, or null. The device is created with XeSS's + /// extensions only when it is the saved upscaler at start. + const char* xess_problem = nullptr; + /// XeSS: how far its history is distrusted on characters and objects (the scene stencil as its + /// responsive mask, as FSR 3.1's "moving objects"); 0 = off, saved. Live. + std::atomic xess_objects{95}; + /// XeSS: sharpening after it (the same pass as taa_sharpen, which is the TAA's own), percent, live. + std::atomic xess_sharpen{145}; /// The game's depth of field (spartanport_depth_of_field.h); off keeps the whole picture sharp. Live. std::atomic depth_of_field{true}; /// Anti-aliasing of the finished frame (SpartanGraphics::AntiAliasing: off, FXAA, SMAA). Live. diff --git a/gpu/shim/spartanport_ui_language.h b/gpu/shim/spartanport_ui_language.h index b56eff3389..383f729c5e 100644 --- a/gpu/shim/spartanport_ui_language.h +++ b/gpu/shim/spartanport_ui_language.h @@ -269,12 +269,17 @@ inline constexpr std::pair ChineseText[] = { {"FSR 3.1 (native HUD)", "FSR 3.1(原生 HUD)"}, {"Higher: smoother edges on a still picture, a little more trail. Default 99%.", "数值越高:静止画面边缘越平滑,拖影略多。默认 99%。"}, {"Higher: smoother while the camera moves, more blur and trail. Default 55%.", "数值越高:镜头移动时更平滑,模糊和拖影更多。默认 55%。"}, - {"Lower: less trail and ghosting, more flicker. Default 115%.", "数值越低:拖影和鬼影越少,闪烁越多。默认 115%。"}, - {"How much history a moving character or object loses. Higher: less ghosting there, rougher edges. Default 90%.", "运动的角色或物体丢弃多少历史信息。数值越高:鬼影越少,边缘越粗糙。默认 90%。"}, - {"Sharper textures (a negative mip bias, in percent of one level): the accumulation turns the extra detail into a clean picture. Higher: more detail, more shimmer. Default 75%.", "更锐利的纹理(负 mip 偏置,以一级的百分比表示):累积会把额外细节变成干净的画面。数值越高:细节越多,闪烁越多。默认 75%。"}, - {"Smooths the stair-stepped edges of moving characters, where the history is refused: a spatial filter on those pixels only. Higher: smoother, slightly softer. Default 70%.", "平滑运动角色上因历史被拒绝而出现的锯齿边缘:仅对这些像素使用空间滤波。数值越高:越平滑,略偏软。默认 70%。"}, + {"Lower: less trail and ghosting, more flicker. Default 175%.", "数值越低:拖影和鬼影越少,闪烁越多。默认 175%。"}, + {"How much history a moving character or object loses. Higher: less ghosting there, rougher edges. Default 55%.", "运动的角色或物体丢弃多少历史信息。数值越高:鬼影越少,边缘越粗糙。默认 55%。"}, + {"XeSS (God of War III)", "XeSS(God of War III)"}, + {"XeSS status", "XeSS 状态"}, + {"Sharper textures (a negative mip bias, in percent of one level): XeSS turns the extra detail into a clean picture. Higher: more detail, more shimmer. Default 80%.", "更清晰的纹理(负 mip 偏移,以一级的百分比计):XeSS 会把多出来的细节变成干净的画面。更高:细节更多,闪烁更多。默认 80%。"}, + {"How much XeSS distrusts its history on characters and objects (a mask from the game's stencil). Higher: less ghosting behind them, rougher edges. 0% = off. Default 95%.", "XeSS 对角色和物体上的历史画面有多不信任(来自游戏模板缓冲的遮罩)。更高:它们身后的拖影更少,边缘更粗糙。0% = 关闭。默认 95%。"}, + {"Sharpening after XeSS, separate from the Sharpening (RCAS) switch below. 0% = off. Default 145%.", "XeSS 之后的锐化,独立于下方的“锐化 (RCAS)”开关。0% = 关闭。默认 145%。"}, + {"Sharper textures (a negative mip bias, in percent of one level): the accumulation turns the extra detail into a clean picture. Higher: more detail, more shimmer. Default 80%.", "更锐利的纹理(负 mip 偏置,以一级的百分比表示):累积会把额外细节变成干净的画面。数值越高:细节越多,闪烁越多。默认 80%。"}, + {"Smooths the stair-stepped edges of moving characters, where the history is refused: a spatial filter on those pixels only. Higher: smoother, slightly softer. Default 55%.", "平滑运动角色上因历史被拒绝而出现的锯齿边缘:仅对这些像素使用空间滤波。数值越高:越平滑,略偏软。默认 55%。"}, {"Shows where the history is used: red = rejected by depth, green = lost to colour change, blue = history weight used. For bug reports; not saved.", "显示历史的使用位置:红色 = 因深度被拒绝,绿色 = 因颜色变化而丢失,蓝色 = 使用的历史权重。用于错误报告;不会保存。"}, - {"Sharpening after the accumulation, separate from the Sharpening (RCAS) switch below. 0% = off. Default 165%.", "累积之后的锐化,独立于下方的“锐化 (RCAS)”开关。0% = 关闭。默认 165%。"}, + {"Sharpening after the accumulation, separate from the Sharpening (RCAS) switch below. 0% = off. Default 130%.", "累积之后的锐化,独立于下方的“锐化 (RCAS)”开关。0% = 关闭。默认 130%。"}, {"Sharper textures (a negative mip bias, in percent of one level) on top of FSR's own: the accumulation turns the extra detail into a clean picture. Higher: more detail, more shimmer. Default 0%.", "在 FSR 自带偏置之外的更锐利纹理(负 mip 偏置,以一级的百分比表示):累积会把额外细节变成干净的画面。数值越高:细节越多,闪烁越多。默认 0%。"}, {"How much FSR distrusts its history on characters and objects. Higher: less ghosting behind them, rougher edges. Lower: smoother but more trails. Default 100%.", "FSR 对角色和物体历史信息的不信任程度。数值越高:其身后的鬼影越少,边缘越粗糙。数值越低:越平滑,但拖影更多。默认 100%。"}, {"FSR 3.1 (native HUD) keeps the game at 1920x1080 so the HUD, text and loading screens are not stretched, and has the port's own sharpening. FSR 4.1 needs an AMD Radeon with Adrenalin 26.10.1 or newer.", "FSR 3.1(原生 HUD)让游戏保持 1920x1080,因此 HUD、文字和加载画面不会被拉伸,并带有本移植版自带的锐化。FSR 4.1 需要 AMD Radeon 与 Adrenalin 26.10.1 或更新版本。"}, diff --git a/gpu/shim/ui_language/spartanport_ui_cs.h b/gpu/shim/ui_language/spartanport_ui_cs.h index 3540596e66..5d8792418c 100644 --- a/gpu/shim/ui_language/spartanport_ui_cs.h +++ b/gpu/shim/ui_language/spartanport_ui_cs.h @@ -249,12 +249,17 @@ inline constexpr std::pair CzechText[] = { {"FSR 3.1 (native HUD)", "FSR 3.1 (nativní HUD)"}, {"Higher: smoother edges on a still picture, a little more trail. Default 99%.", "Vyšší: hladší hrany na stojícím obraze, o něco víc šmouh. Výchozí 99 %."}, {"Higher: smoother while the camera moves, more blur and trail. Default 55%.", "Vyšší: hladší obraz při pohybu kamery, víc rozmazání a šmouh. Výchozí 55 %."}, - {"Lower: less trail and ghosting, more flicker. Default 115%.", "Nižší: méně šmouh a duchů, víc blikání. Výchozí 115 %."}, - {"How much history a moving character or object loses. Higher: less ghosting there, rougher edges. Default 90%.", "Kolik historie ztrácí pohybující se postava nebo objekt. Vyšší: méně duchů, drsnější hrany. Výchozí 90 %."}, - {"Sharper textures (a negative mip bias, in percent of one level): the accumulation turns the extra detail into a clean picture. Higher: more detail, more shimmer. Default 75%.", "Ostřejší textury (záporný mip bias v procentech jedné úrovně): akumulace promění přidaný detail v čistý obraz. Vyšší: víc detailu, víc mihotání. Výchozí 75 %."}, - {"Smooths the stair-stepped edges of moving characters, where the history is refused: a spatial filter on those pixels only. Higher: smoother, slightly softer. Default 70%.", "Vyhlazuje zubaté hrany pohybujících se postav, kde se historie odmítá: prostorový filtr jen na těchto pixelech. Vyšší: hladší, o něco měkčí. Výchozí 70 %."}, + {"Lower: less trail and ghosting, more flicker. Default 175%.", "Nižší: méně šmouh a duchů, víc blikání. Výchozí 175 %."}, + {"How much history a moving character or object loses. Higher: less ghosting there, rougher edges. Default 55%.", "Kolik historie ztrácí pohybující se postava nebo objekt. Vyšší: méně duchů, drsnější hrany. Výchozí 55 %."}, + {"XeSS (God of War III)", "XeSS (God of War III)"}, + {"XeSS status", "Stav XeSS"}, + {"Sharper textures (a negative mip bias, in percent of one level): XeSS turns the extra detail into a clean picture. Higher: more detail, more shimmer. Default 80%.", "Ostřejší textury (záporný mip bias v procentech jedné úrovně): XeSS promění přidaný detail v čistý obraz. Vyšší: víc detailu, víc mihotání. Výchozí 80 %."}, + {"How much XeSS distrusts its history on characters and objects (a mask from the game's stencil). Higher: less ghosting behind them, rougher edges. 0% = off. Default 95%.", "Jak moc XeSS nedůvěřuje své historii u postav a objektů (maska ze stencilu hry). Vyšší: méně duchů za nimi, drsnější hrany. 0 % = vypnuto. Výchozí 95 %."}, + {"Sharpening after XeSS, separate from the Sharpening (RCAS) switch below. 0% = off. Default 145%.", "Doostření po XeSS, nezávislé na přepínači Doostření (RCAS) níže. 0 % = vypnuto. Výchozí 145 %."}, + {"Sharper textures (a negative mip bias, in percent of one level): the accumulation turns the extra detail into a clean picture. Higher: more detail, more shimmer. Default 80%.", "Ostřejší textury (záporný mip bias v procentech jedné úrovně): akumulace promění přidaný detail v čistý obraz. Vyšší: víc detailu, víc mihotání. Výchozí 80 %."}, + {"Smooths the stair-stepped edges of moving characters, where the history is refused: a spatial filter on those pixels only. Higher: smoother, slightly softer. Default 55%.", "Vyhlazuje zubaté hrany pohybujících se postav, kde se historie odmítá: prostorový filtr jen na těchto pixelech. Vyšší: hladší, o něco měkčí. Výchozí 55 %."}, {"Shows where the history is used: red = rejected by depth, green = lost to colour change, blue = history weight used. For bug reports; not saved.", "Ukazuje, kde se používá historie: červená = zamítnuto hloubkou, zelená = ztraceno změnou barvy, modrá = použitá váha historie. Pro hlášení chyb; neukládá se."}, - {"Sharpening after the accumulation, separate from the Sharpening (RCAS) switch below. 0% = off. Default 165%.", "Doostření po akumulaci, nezávislé na přepínači Doostření (RCAS) níže. 0 % = vypnuto. Výchozí 165 %."}, + {"Sharpening after the accumulation, separate from the Sharpening (RCAS) switch below. 0% = off. Default 130%.", "Doostření po akumulaci, nezávislé na přepínači Doostření (RCAS) níže. 0 % = vypnuto. Výchozí 130 %."}, {"Sharper textures (a negative mip bias, in percent of one level) on top of FSR's own: the accumulation turns the extra detail into a clean picture. Higher: more detail, more shimmer. Default 0%.", "Ostřejší textury (záporný mip bias v procentech jedné úrovně) navíc k vlastnímu biasu FSR: akumulace promění přidaný detail v čistý obraz. Vyšší: víc detailu, víc mihotání. Výchozí 0 %."}, {"How much FSR distrusts its history on characters and objects. Higher: less ghosting behind them, rougher edges. Lower: smoother but more trails. Default 100%.", "Jak moc FSR nedůvěřuje své historii u postav a objektů. Vyšší: méně duchů za nimi, drsnější hrany. Nižší: hladší, ale víc šmouh. Výchozí 100 %."}, {"FSR 3.1 (native HUD) keeps the game at 1920x1080 so the HUD, text and loading screens are not stretched, and has the port's own sharpening. FSR 4.1 needs an AMD Radeon with Adrenalin 26.10.1 or newer.", "FSR 3.1 (nativní HUD) nechá hru v 1920x1080, takže HUD, text a loadingy se neroztahují, a má vlastní doostření portu. FSR 4.1 vyžaduje AMD Radeon s Adrenalin 26.10.1 nebo novější."}, diff --git a/gpu/shim/ui_language/spartanport_ui_de.h b/gpu/shim/ui_language/spartanport_ui_de.h index 92d0592322..f48cefeb8a 100644 --- a/gpu/shim/ui_language/spartanport_ui_de.h +++ b/gpu/shim/ui_language/spartanport_ui_de.h @@ -249,12 +249,17 @@ inline constexpr std::pair GermanText[] = { {"FSR 3.1 (native HUD)", "FSR 3.1 (natives HUD)"}, {"Higher: smoother edges on a still picture, a little more trail. Default 99%.", "Höher: glattere Kanten bei stehendem Bild, etwas mehr Schlieren. Standard 99%."}, {"Higher: smoother while the camera moves, more blur and trail. Default 55%.", "Höher: glatter, solange sich die Kamera bewegt, mehr Unschärfe und Schlieren. Standard 55%."}, - {"Lower: less trail and ghosting, more flicker. Default 115%.", "Niedriger: weniger Schlieren und Geisterbilder, mehr Flimmern. Standard 115%."}, - {"How much history a moving character or object loses. Higher: less ghosting there, rougher edges. Default 90%.", "Wie viel Verlauf eine bewegte Figur oder ein bewegtes Objekt verliert. Höher: weniger Geisterbilder dort, rauere Kanten. Standard 90%."}, - {"Sharper textures (a negative mip bias, in percent of one level): the accumulation turns the extra detail into a clean picture. Higher: more detail, more shimmer. Default 75%.", "Schärfere Texturen (ein negativer Mip-Bias, in Prozent einer Stufe): die Akkumulation macht aus dem zusätzlichen Detail ein sauberes Bild. Höher: mehr Detail, mehr Flimmern. Standard 75%."}, - {"Smooths the stair-stepped edges of moving characters, where the history is refused: a spatial filter on those pixels only. Higher: smoother, slightly softer. Default 70%.", "Glättet die treppenförmigen Kanten bewegter Figuren, wo der Verlauf verworfen wird: ein räumlicher Filter nur auf diesen Pixeln. Höher: glatter, etwas weicher. Standard 70%."}, + {"Lower: less trail and ghosting, more flicker. Default 175%.", "Niedriger: weniger Schlieren und Geisterbilder, mehr Flimmern. Standard 175%."}, + {"How much history a moving character or object loses. Higher: less ghosting there, rougher edges. Default 55%.", "Wie viel Verlauf eine bewegte Figur oder ein bewegtes Objekt verliert. Höher: weniger Geisterbilder dort, rauere Kanten. Standard 55%."}, + {"XeSS (God of War III)", "XeSS (God of War III)"}, + {"XeSS status", "XeSS-Status"}, + {"Sharper textures (a negative mip bias, in percent of one level): XeSS turns the extra detail into a clean picture. Higher: more detail, more shimmer. Default 80%.", "Schärfere Texturen (negativer Mip-Bias, in Prozent einer Stufe): XeSS macht aus dem zusätzlichen Detail ein sauberes Bild. Höher: mehr Detail, mehr Flimmern. Standard 80 %."}, + {"How much XeSS distrusts its history on characters and objects (a mask from the game's stencil). Higher: less ghosting behind them, rougher edges. 0% = off. Default 95%.", "Wie sehr XeSS seinem Verlauf bei Figuren und Objekten misstraut (eine Maske aus dem Stencil des Spiels). Höher: weniger Geisterbilder dahinter, rauere Kanten. 0 % = aus. Standard 95 %."}, + {"Sharpening after XeSS, separate from the Sharpening (RCAS) switch below. 0% = off. Default 145%.", "Schärfen nach XeSS, unabhängig vom Schalter Schärfen (RCAS) unten. 0 % = aus. Standard 145 %."}, + {"Sharper textures (a negative mip bias, in percent of one level): the accumulation turns the extra detail into a clean picture. Higher: more detail, more shimmer. Default 80%.", "Schärfere Texturen (ein negativer Mip-Bias, in Prozent einer Stufe): die Akkumulation macht aus dem zusätzlichen Detail ein sauberes Bild. Höher: mehr Detail, mehr Flimmern. Standard 80%."}, + {"Smooths the stair-stepped edges of moving characters, where the history is refused: a spatial filter on those pixels only. Higher: smoother, slightly softer. Default 55%.", "Glättet die treppenförmigen Kanten bewegter Figuren, wo der Verlauf verworfen wird: ein räumlicher Filter nur auf diesen Pixeln. Höher: glatter, etwas weicher. Standard 55%."}, {"Shows where the history is used: red = rejected by depth, green = lost to colour change, blue = history weight used. For bug reports; not saved.", "Zeigt, wo der Verlauf verwendet wird: rot = durch Tiefe verworfen, grün = durch Farbänderung verloren, blau = verwendetes Verlaufsgewicht. Für Fehlerberichte; wird nicht gespeichert."}, - {"Sharpening after the accumulation, separate from the Sharpening (RCAS) switch below. 0% = off. Default 165%.", "Schärfen nach der Akkumulation, unabhängig vom Schalter Schärfen (RCAS) unten. 0% = aus. Standard 165%."}, + {"Sharpening after the accumulation, separate from the Sharpening (RCAS) switch below. 0% = off. Default 130%.", "Schärfen nach der Akkumulation, unabhängig vom Schalter Schärfen (RCAS) unten. 0% = aus. Standard 130%."}, {"Sharper textures (a negative mip bias, in percent of one level) on top of FSR's own: the accumulation turns the extra detail into a clean picture. Higher: more detail, more shimmer. Default 0%.", "Schärfere Texturen (ein negativer Mip-Bias, in Prozent einer Stufe) zusätzlich zu dem von FSR: die Akkumulation macht aus dem zusätzlichen Detail ein sauberes Bild. Höher: mehr Detail, mehr Flimmern. Standard 0%."}, {"How much FSR distrusts its history on characters and objects. Higher: less ghosting behind them, rougher edges. Lower: smoother but more trails. Default 100%.", "Wie stark FSR seinem Verlauf bei Figuren und Objekten misstraut. Höher: weniger Geisterbilder hinter ihnen, rauere Kanten. Niedriger: glatter, aber mehr Schlieren. Standard 100%."}, {"FSR 3.1 (native HUD) keeps the game at 1920x1080 so the HUD, text and loading screens are not stretched, and has the port's own sharpening. FSR 4.1 needs an AMD Radeon with Adrenalin 26.10.1 or newer.", "FSR 3.1 (natives HUD) hält das Spiel bei 1920x1080, sodass HUD, Text und Ladebildschirme nicht gestreckt werden, und hat das eigene Schärfen des Ports. FSR 4.1 benötigt eine AMD Radeon mit Adrenalin 26.10.1 oder neuer."}, diff --git a/gpu/shim/ui_language/spartanport_ui_es.h b/gpu/shim/ui_language/spartanport_ui_es.h index 1cfea72280..f2fdf11437 100644 --- a/gpu/shim/ui_language/spartanport_ui_es.h +++ b/gpu/shim/ui_language/spartanport_ui_es.h @@ -249,12 +249,17 @@ inline constexpr std::pair SpanishText[] = { {"FSR 3.1 (native HUD)", "FSR 3.1 (HUD nativo)"}, {"Higher: smoother edges on a still picture, a little more trail. Default 99%.", "Más alto: bordes más suaves con la imagen quieta, un poco más de estela. Predeterminado 99%."}, {"Higher: smoother while the camera moves, more blur and trail. Default 55%.", "Más alto: más suave mientras la cámara se mueve, más desenfoque y estela. Predeterminado 55%."}, - {"Lower: less trail and ghosting, more flicker. Default 115%.", "Más bajo: menos estela y fantasmas, más parpadeo. Predeterminado 115%."}, - {"How much history a moving character or object loses. Higher: less ghosting there, rougher edges. Default 90%.", "Cuánto historial pierde un personaje u objeto en movimiento. Más alto: menos fantasmas ahí, bordes más ásperos. Predeterminado 90%."}, - {"Sharper textures (a negative mip bias, in percent of one level): the accumulation turns the extra detail into a clean picture. Higher: more detail, more shimmer. Default 75%.", "Texturas más nítidas (un sesgo de mip negativo, en porcentaje de un nivel): la acumulación convierte el detalle extra en una imagen limpia. Más alto: más detalle, más parpadeo. Predeterminado 75%."}, - {"Smooths the stair-stepped edges of moving characters, where the history is refused: a spatial filter on those pixels only. Higher: smoother, slightly softer. Default 70%.", "Suaviza los bordes dentados de los personajes en movimiento, donde se rechaza el historial: un filtro espacial solo en esos píxeles. Más alto: más suave, algo más borroso. Predeterminado 70%."}, + {"Lower: less trail and ghosting, more flicker. Default 175%.", "Más bajo: menos estela y fantasmas, más parpadeo. Predeterminado 175%."}, + {"How much history a moving character or object loses. Higher: less ghosting there, rougher edges. Default 55%.", "Cuánto historial pierde un personaje u objeto en movimiento. Más alto: menos fantasmas ahí, bordes más ásperos. Predeterminado 55%."}, + {"XeSS (God of War III)", "XeSS (God of War III)"}, + {"XeSS status", "Estado de XeSS"}, + {"Sharper textures (a negative mip bias, in percent of one level): XeSS turns the extra detail into a clean picture. Higher: more detail, more shimmer. Default 80%.", "Texturas más nítidas (un sesgo de mip negativo, en porcentaje de un nivel): XeSS convierte el detalle extra en una imagen limpia. Más alto: más detalle, más parpadeo. Predeterminado 80 %."}, + {"How much XeSS distrusts its history on characters and objects (a mask from the game's stencil). Higher: less ghosting behind them, rougher edges. 0% = off. Default 95%.", "Cuánto desconfía XeSS de su historial en personajes y objetos (una máscara del stencil del juego). Más alto: menos estela detrás, bordes más ásperos. 0 % = desactivado. Predeterminado 95 %."}, + {"Sharpening after XeSS, separate from the Sharpening (RCAS) switch below. 0% = off. Default 145%.", "Nitidez tras XeSS, independiente del interruptor Nitidez (RCAS) de abajo. 0 % = desactivada. Predeterminado 145 %."}, + {"Sharper textures (a negative mip bias, in percent of one level): the accumulation turns the extra detail into a clean picture. Higher: more detail, more shimmer. Default 80%.", "Texturas más nítidas (un sesgo de mip negativo, en porcentaje de un nivel): la acumulación convierte el detalle extra en una imagen limpia. Más alto: más detalle, más parpadeo. Predeterminado 80%."}, + {"Smooths the stair-stepped edges of moving characters, where the history is refused: a spatial filter on those pixels only. Higher: smoother, slightly softer. Default 55%.", "Suaviza los bordes dentados de los personajes en movimiento, donde se rechaza el historial: un filtro espacial solo en esos píxeles. Más alto: más suave, algo más borroso. Predeterminado 55%."}, {"Shows where the history is used: red = rejected by depth, green = lost to colour change, blue = history weight used. For bug reports; not saved.", "Muestra dónde se usa el historial: rojo = rechazado por la profundidad, verde = perdido por cambio de color, azul = peso del historial usado. Para informes de errores; no se guarda."}, - {"Sharpening after the accumulation, separate from the Sharpening (RCAS) switch below. 0% = off. Default 165%.", "Nitidez tras la acumulación, independiente del interruptor Nitidez (RCAS) de abajo. 0% = desactivada. Predeterminado 165%."}, + {"Sharpening after the accumulation, separate from the Sharpening (RCAS) switch below. 0% = off. Default 130%.", "Nitidez tras la acumulación, independiente del interruptor Nitidez (RCAS) de abajo. 0% = desactivada. Predeterminado 130%."}, {"Sharper textures (a negative mip bias, in percent of one level) on top of FSR's own: the accumulation turns the extra detail into a clean picture. Higher: more detail, more shimmer. Default 0%.", "Texturas más nítidas (un sesgo de mip negativo, en porcentaje de un nivel) además del propio de FSR: la acumulación convierte el detalle extra en una imagen limpia. Más alto: más detalle, más parpadeo. Predeterminado 0%."}, {"How much FSR distrusts its history on characters and objects. Higher: less ghosting behind them, rougher edges. Lower: smoother but more trails. Default 100%.", "Cuánto desconfía FSR de su historial en personajes y objetos. Más alto: menos fantasmas detrás de ellos, bordes más ásperos. Más bajo: más suave pero con más estelas. Predeterminado 100%."}, {"FSR 3.1 (native HUD) keeps the game at 1920x1080 so the HUD, text and loading screens are not stretched, and has the port's own sharpening. FSR 4.1 needs an AMD Radeon with Adrenalin 26.10.1 or newer.", "FSR 3.1 (HUD nativo) mantiene el juego a 1920x1080, así que el HUD, el texto y las pantallas de carga no se estiran, y tiene la nitidez propia del port. FSR 4.1 requiere una AMD Radeon con Adrenalin 26.10.1 o posterior."}, diff --git a/gpu/shim/ui_language/spartanport_ui_fr.h b/gpu/shim/ui_language/spartanport_ui_fr.h index fbb1578841..4814beb393 100644 --- a/gpu/shim/ui_language/spartanport_ui_fr.h +++ b/gpu/shim/ui_language/spartanport_ui_fr.h @@ -249,12 +249,17 @@ inline constexpr std::pair FrenchText[] = { {"FSR 3.1 (native HUD)", "FSR 3.1 (HUD natif)"}, {"Higher: smoother edges on a still picture, a little more trail. Default 99%.", "Plus haut : bords plus lisses sur une image fixe, un peu plus de traînée. Par défaut 99%."}, {"Higher: smoother while the camera moves, more blur and trail. Default 55%.", "Plus haut : plus lisse pendant que la caméra bouge, plus de flou et de traînée. Par défaut 55%."}, - {"Lower: less trail and ghosting, more flicker. Default 115%.", "Plus bas : moins de traînée et de fantômes, plus de scintillement. Par défaut 115%."}, - {"How much history a moving character or object loses. Higher: less ghosting there, rougher edges. Default 90%.", "Quantité d'historique que perd un personnage ou un objet en mouvement. Plus haut : moins de fantômes, bords plus rugueux. Par défaut 90%."}, - {"Sharper textures (a negative mip bias, in percent of one level): the accumulation turns the extra detail into a clean picture. Higher: more detail, more shimmer. Default 75%.", "Textures plus nettes (un biais de mip négatif, en pourcentage d'un niveau) : l'accumulation transforme le détail supplémentaire en une image propre. Plus haut : plus de détail, plus de scintillement. Par défaut 75%."}, - {"Smooths the stair-stepped edges of moving characters, where the history is refused: a spatial filter on those pixels only. Higher: smoother, slightly softer. Default 70%.", "Lisse les bords crénelés des personnages en mouvement, là où l'historique est refusé : un filtre spatial sur ces pixels seulement. Plus haut : plus lisse, légèrement plus flou. Par défaut 70%."}, + {"Lower: less trail and ghosting, more flicker. Default 175%.", "Plus bas : moins de traînée et de fantômes, plus de scintillement. Par défaut 175%."}, + {"How much history a moving character or object loses. Higher: less ghosting there, rougher edges. Default 55%.", "Quantité d'historique que perd un personnage ou un objet en mouvement. Plus haut : moins de fantômes, bords plus rugueux. Par défaut 55%."}, + {"XeSS (God of War III)", "XeSS (God of War III)"}, + {"XeSS status", "État de XeSS"}, + {"Sharper textures (a negative mip bias, in percent of one level): XeSS turns the extra detail into a clean picture. Higher: more detail, more shimmer. Default 80%.", "Textures plus nettes (un biais de mip négatif, en pourcentage d'un niveau) : XeSS transforme le détail supplémentaire en image propre. Plus haut : plus de détail, plus de scintillement. Par défaut 80 %."}, + {"How much XeSS distrusts its history on characters and objects (a mask from the game's stencil). Higher: less ghosting behind them, rougher edges. 0% = off. Default 95%.", "À quel point XeSS se méfie de son historique sur les personnages et les objets (un masque issu du stencil du jeu). Plus haut : moins de traînées derrière eux, bords plus rugueux. 0 % = désactivé. Par défaut 95 %."}, + {"Sharpening after XeSS, separate from the Sharpening (RCAS) switch below. 0% = off. Default 145%.", "Netteté après XeSS, indépendante de l'interrupteur Netteté (RCAS) ci-dessous. 0 % = désactivée. Par défaut 145 %."}, + {"Sharper textures (a negative mip bias, in percent of one level): the accumulation turns the extra detail into a clean picture. Higher: more detail, more shimmer. Default 80%.", "Textures plus nettes (un biais de mip négatif, en pourcentage d'un niveau) : l'accumulation transforme le détail supplémentaire en une image propre. Plus haut : plus de détail, plus de scintillement. Par défaut 80%."}, + {"Smooths the stair-stepped edges of moving characters, where the history is refused: a spatial filter on those pixels only. Higher: smoother, slightly softer. Default 55%.", "Lisse les bords crénelés des personnages en mouvement, là où l'historique est refusé : un filtre spatial sur ces pixels seulement. Plus haut : plus lisse, légèrement plus flou. Par défaut 55%."}, {"Shows where the history is used: red = rejected by depth, green = lost to colour change, blue = history weight used. For bug reports; not saved.", "Montre où l'historique est utilisé : rouge = rejeté par la profondeur, vert = perdu par changement de couleur, bleu = poids de l'historique utilisé. Pour les rapports de bogues ; non enregistré."}, - {"Sharpening after the accumulation, separate from the Sharpening (RCAS) switch below. 0% = off. Default 165%.", "Netteté après l'accumulation, indépendante de l'interrupteur Netteté (RCAS) ci-dessous. 0% = désactivée. Par défaut 165%."}, + {"Sharpening after the accumulation, separate from the Sharpening (RCAS) switch below. 0% = off. Default 130%.", "Netteté après l'accumulation, indépendante de l'interrupteur Netteté (RCAS) ci-dessous. 0% = désactivée. Par défaut 130%."}, {"Sharper textures (a negative mip bias, in percent of one level) on top of FSR's own: the accumulation turns the extra detail into a clean picture. Higher: more detail, more shimmer. Default 0%.", "Textures plus nettes (un biais de mip négatif, en pourcentage d'un niveau) en plus de celui de FSR : l'accumulation transforme le détail supplémentaire en une image propre. Plus haut : plus de détail, plus de scintillement. Par défaut 0%."}, {"How much FSR distrusts its history on characters and objects. Higher: less ghosting behind them, rougher edges. Lower: smoother but more trails. Default 100%.", "Degré de méfiance de FSR envers son historique sur les personnages et les objets. Plus haut : moins de fantômes derrière eux, bords plus rugueux. Plus bas : plus lisse mais plus de traînées. Par défaut 100%."}, {"FSR 3.1 (native HUD) keeps the game at 1920x1080 so the HUD, text and loading screens are not stretched, and has the port's own sharpening. FSR 4.1 needs an AMD Radeon with Adrenalin 26.10.1 or newer.", "FSR 3.1 (HUD natif) garde le jeu en 1920x1080 : le HUD, le texte et les écrans de chargement ne sont pas étirés, et il dispose de la netteté propre au port. FSR 4.1 exige une AMD Radeon avec Adrenalin 26.10.1 ou plus récent."}, diff --git a/gpu/shim/ui_language/spartanport_ui_id.h b/gpu/shim/ui_language/spartanport_ui_id.h index 908201d876..fe4e6362c2 100644 --- a/gpu/shim/ui_language/spartanport_ui_id.h +++ b/gpu/shim/ui_language/spartanport_ui_id.h @@ -249,12 +249,17 @@ inline constexpr std::pair IndonesianText[] = { {"FSR 3.1 (native HUD)", "FSR 3.1 (HUD asli)"}, {"Higher: smoother edges on a still picture, a little more trail. Default 99%.", "Lebih tinggi: tepi lebih halus pada gambar diam, sedikit lebih banyak jejak. Bawaan 99%."}, {"Higher: smoother while the camera moves, more blur and trail. Default 55%.", "Lebih tinggi: lebih halus saat kamera bergerak, lebih banyak blur dan jejak. Bawaan 55%."}, - {"Lower: less trail and ghosting, more flicker. Default 115%.", "Lebih rendah: lebih sedikit jejak dan bayangan hantu, lebih banyak kedipan. Bawaan 115%."}, - {"How much history a moving character or object loses. Higher: less ghosting there, rougher edges. Default 90%.", "Seberapa banyak riwayat yang hilang pada karakter atau objek bergerak. Lebih tinggi: lebih sedikit bayangan hantu di sana, tepi lebih kasar. Bawaan 90%."}, - {"Sharper textures (a negative mip bias, in percent of one level): the accumulation turns the extra detail into a clean picture. Higher: more detail, more shimmer. Default 75%.", "Tekstur lebih tajam (mip bias negatif, dalam persen dari satu level): akumulasi mengubah detail tambahan menjadi gambar yang bersih. Lebih tinggi: lebih banyak detail, lebih banyak kedipan. Bawaan 75%."}, - {"Smooths the stair-stepped edges of moving characters, where the history is refused: a spatial filter on those pixels only. Higher: smoother, slightly softer. Default 70%.", "Menghaluskan tepi bergerigi pada karakter bergerak, tempat riwayat ditolak: filter spasial hanya pada piksel tersebut. Lebih tinggi: lebih halus, sedikit lebih lembut. Bawaan 70%."}, + {"Lower: less trail and ghosting, more flicker. Default 175%.", "Lebih rendah: lebih sedikit jejak dan bayangan hantu, lebih banyak kedipan. Bawaan 175%."}, + {"How much history a moving character or object loses. Higher: less ghosting there, rougher edges. Default 55%.", "Seberapa banyak riwayat yang hilang pada karakter atau objek bergerak. Lebih tinggi: lebih sedikit bayangan hantu di sana, tepi lebih kasar. Bawaan 55%."}, + {"XeSS (God of War III)", "XeSS (God of War III)"}, + {"XeSS status", "Status XeSS"}, + {"Sharper textures (a negative mip bias, in percent of one level): XeSS turns the extra detail into a clean picture. Higher: more detail, more shimmer. Default 80%.", "Tekstur lebih tajam (bias mip negatif, dalam persen satu level): XeSS mengubah detail tambahan menjadi gambar yang bersih. Lebih tinggi: lebih detail, lebih berkedip. Bawaan 80%."}, + {"How much XeSS distrusts its history on characters and objects (a mask from the game's stencil). Higher: less ghosting behind them, rougher edges. 0% = off. Default 95%.", "Seberapa besar XeSS tidak memercayai riwayatnya pada karakter dan objek (masker dari stencil gim). Lebih tinggi: bayangan sisa di belakangnya berkurang, tepi lebih kasar. 0% = mati. Bawaan 95%."}, + {"Sharpening after XeSS, separate from the Sharpening (RCAS) switch below. 0% = off. Default 145%.", "Penajaman setelah XeSS, terpisah dari sakelar Penajaman (RCAS) di bawah. 0% = mati. Bawaan 145%."}, + {"Sharper textures (a negative mip bias, in percent of one level): the accumulation turns the extra detail into a clean picture. Higher: more detail, more shimmer. Default 80%.", "Tekstur lebih tajam (mip bias negatif, dalam persen dari satu level): akumulasi mengubah detail tambahan menjadi gambar yang bersih. Lebih tinggi: lebih banyak detail, lebih banyak kedipan. Bawaan 80%."}, + {"Smooths the stair-stepped edges of moving characters, where the history is refused: a spatial filter on those pixels only. Higher: smoother, slightly softer. Default 55%.", "Menghaluskan tepi bergerigi pada karakter bergerak, tempat riwayat ditolak: filter spasial hanya pada piksel tersebut. Lebih tinggi: lebih halus, sedikit lebih lembut. Bawaan 55%."}, {"Shows where the history is used: red = rejected by depth, green = lost to colour change, blue = history weight used. For bug reports; not saved.", "Menunjukkan di mana riwayat digunakan: merah = ditolak oleh kedalaman, hijau = hilang karena perubahan warna, biru = bobot riwayat yang dipakai. Untuk laporan bug; tidak disimpan."}, - {"Sharpening after the accumulation, separate from the Sharpening (RCAS) switch below. 0% = off. Default 165%.", "Penajaman setelah akumulasi, terpisah dari sakelar Penajaman (RCAS) di bawah. 0% = mati. Bawaan 165%."}, + {"Sharpening after the accumulation, separate from the Sharpening (RCAS) switch below. 0% = off. Default 130%.", "Penajaman setelah akumulasi, terpisah dari sakelar Penajaman (RCAS) di bawah. 0% = mati. Bawaan 130%."}, {"Sharper textures (a negative mip bias, in percent of one level) on top of FSR's own: the accumulation turns the extra detail into a clean picture. Higher: more detail, more shimmer. Default 0%.", "Tekstur lebih tajam (mip bias negatif, dalam persen dari satu level) di atas bias FSR sendiri: akumulasi mengubah detail tambahan menjadi gambar yang bersih. Lebih tinggi: lebih banyak detail, lebih banyak kedipan. Bawaan 0%."}, {"How much FSR distrusts its history on characters and objects. Higher: less ghosting behind them, rougher edges. Lower: smoother but more trails. Default 100%.", "Seberapa besar FSR tidak memercayai riwayatnya pada karakter dan objek. Lebih tinggi: lebih sedikit bayangan hantu di belakangnya, tepi lebih kasar. Lebih rendah: lebih halus tetapi lebih banyak jejak. Bawaan 100%."}, {"FSR 3.1 (native HUD) keeps the game at 1920x1080 so the HUD, text and loading screens are not stretched, and has the port's own sharpening. FSR 4.1 needs an AMD Radeon with Adrenalin 26.10.1 or newer.", "FSR 3.1 (HUD asli) menjaga game tetap di 1920x1080, sehingga HUD, teks, dan layar pemuatan tidak diregangkan, dan memiliki penajaman bawaan port. FSR 4.1 membutuhkan AMD Radeon dengan Adrenalin 26.10.1 atau lebih baru."}, diff --git a/gpu/shim/ui_language/spartanport_ui_it.h b/gpu/shim/ui_language/spartanport_ui_it.h index 370ad5fa4d..ff04f51f9c 100644 --- a/gpu/shim/ui_language/spartanport_ui_it.h +++ b/gpu/shim/ui_language/spartanport_ui_it.h @@ -249,12 +249,17 @@ inline constexpr std::pair ItalianText[] = { {"FSR 3.1 (native HUD)", "FSR 3.1 (HUD nativo)"}, {"Higher: smoother edges on a still picture, a little more trail. Default 99%.", "Più alto: bordi più morbidi a immagine ferma, un po' più di scia. Predefinito 99%."}, {"Higher: smoother while the camera moves, more blur and trail. Default 55%.", "Più alto: più morbido mentre la camera si muove, più sfocatura e scia. Predefinito 55%."}, - {"Lower: less trail and ghosting, more flicker. Default 115%.", "Più basso: meno scia e immagini fantasma, più sfarfallio. Predefinito 115%."}, - {"How much history a moving character or object loses. Higher: less ghosting there, rougher edges. Default 90%.", "Quanta cronologia perde un personaggio o un oggetto in movimento. Più alto: meno immagini fantasma lì, bordi più ruvidi. Predefinito 90%."}, - {"Sharper textures (a negative mip bias, in percent of one level): the accumulation turns the extra detail into a clean picture. Higher: more detail, more shimmer. Default 75%.", "Texture più nitide (un mip bias negativo, in percentuale di un livello): l'accumulo trasforma il dettaglio extra in un'immagine pulita. Più alto: più dettaglio, più sfarfallio. Predefinito 75%."}, - {"Smooths the stair-stepped edges of moving characters, where the history is refused: a spatial filter on those pixels only. Higher: smoother, slightly softer. Default 70%.", "Ammorbidisce i bordi a gradini dei personaggi in movimento, dove la cronologia viene rifiutata: un filtro spaziale solo su quei pixel. Più alto: più morbido, un po' più sfocato. Predefinito 70%."}, + {"Lower: less trail and ghosting, more flicker. Default 175%.", "Più basso: meno scia e immagini fantasma, più sfarfallio. Predefinito 175%."}, + {"How much history a moving character or object loses. Higher: less ghosting there, rougher edges. Default 55%.", "Quanta cronologia perde un personaggio o un oggetto in movimento. Più alto: meno immagini fantasma lì, bordi più ruvidi. Predefinito 55%."}, + {"XeSS (God of War III)", "XeSS (God of War III)"}, + {"XeSS status", "Stato di XeSS"}, + {"Sharper textures (a negative mip bias, in percent of one level): XeSS turns the extra detail into a clean picture. Higher: more detail, more shimmer. Default 80%.", "Texture più nitide (un bias mip negativo, in percentuale di un livello): XeSS trasforma il dettaglio extra in un'immagine pulita. Più alto: più dettaglio, più sfarfallio. Predefinito 80%."}, + {"How much XeSS distrusts its history on characters and objects (a mask from the game's stencil). Higher: less ghosting behind them, rougher edges. 0% = off. Default 95%.", "Quanto XeSS diffida della sua cronologia su personaggi e oggetti (una maschera dallo stencil del gioco). Più alto: meno scie dietro di loro, bordi più ruvidi. 0% = disattivato. Predefinito 95%."}, + {"Sharpening after XeSS, separate from the Sharpening (RCAS) switch below. 0% = off. Default 145%.", "Nitidezza dopo XeSS, indipendente dall'interruttore Nitidezza (RCAS) qui sotto. 0% = disattivata. Predefinito 145%."}, + {"Sharper textures (a negative mip bias, in percent of one level): the accumulation turns the extra detail into a clean picture. Higher: more detail, more shimmer. Default 80%.", "Texture più nitide (un mip bias negativo, in percentuale di un livello): l'accumulo trasforma il dettaglio extra in un'immagine pulita. Più alto: più dettaglio, più sfarfallio. Predefinito 80%."}, + {"Smooths the stair-stepped edges of moving characters, where the history is refused: a spatial filter on those pixels only. Higher: smoother, slightly softer. Default 55%.", "Ammorbidisce i bordi a gradini dei personaggi in movimento, dove la cronologia viene rifiutata: un filtro spaziale solo su quei pixel. Più alto: più morbido, un po' più sfocato. Predefinito 55%."}, {"Shows where the history is used: red = rejected by depth, green = lost to colour change, blue = history weight used. For bug reports; not saved.", "Mostra dove viene usata la cronologia: rosso = scartata per la profondità, verde = persa per cambio di colore, blu = peso della cronologia usato. Per segnalazioni di bug; non viene salvato."}, - {"Sharpening after the accumulation, separate from the Sharpening (RCAS) switch below. 0% = off. Default 165%.", "Nitidezza dopo l'accumulo, separata dall'interruttore Nitidezza (RCAS) qui sotto. 0% = disattivata. Predefinito 165%."}, + {"Sharpening after the accumulation, separate from the Sharpening (RCAS) switch below. 0% = off. Default 130%.", "Nitidezza dopo l'accumulo, separata dall'interruttore Nitidezza (RCAS) qui sotto. 0% = disattivata. Predefinito 130%."}, {"Sharper textures (a negative mip bias, in percent of one level) on top of FSR's own: the accumulation turns the extra detail into a clean picture. Higher: more detail, more shimmer. Default 0%.", "Texture più nitide (un mip bias negativo, in percentuale di un livello) in aggiunta a quello di FSR: l'accumulo trasforma il dettaglio extra in un'immagine pulita. Più alto: più dettaglio, più sfarfallio. Predefinito 0%."}, {"How much FSR distrusts its history on characters and objects. Higher: less ghosting behind them, rougher edges. Lower: smoother but more trails. Default 100%.", "Quanto FSR diffida della propria cronologia su personaggi e oggetti. Più alto: meno immagini fantasma dietro di essi, bordi più ruvidi. Più basso: più morbido ma con più scie. Predefinito 100%."}, {"FSR 3.1 (native HUD) keeps the game at 1920x1080 so the HUD, text and loading screens are not stretched, and has the port's own sharpening. FSR 4.1 needs an AMD Radeon with Adrenalin 26.10.1 or newer.", "FSR 3.1 (HUD nativo) mantiene il gioco a 1920x1080, così HUD, testo e schermate di caricamento non vengono allungati, e ha la nitidezza propria del port. FSR 4.1 richiede una AMD Radeon con Adrenalin 26.10.1 o successivo."}, diff --git a/gpu/shim/ui_language/spartanport_ui_pl.h b/gpu/shim/ui_language/spartanport_ui_pl.h index b519bfb59a..d9c53c033c 100644 --- a/gpu/shim/ui_language/spartanport_ui_pl.h +++ b/gpu/shim/ui_language/spartanport_ui_pl.h @@ -249,12 +249,17 @@ inline constexpr std::pair PolishText[] = { {"FSR 3.1 (native HUD)", "FSR 3.1 (natywny HUD)"}, {"Higher: smoother edges on a still picture, a little more trail. Default 99%.", "Wyżej: gładsze krawędzie przy nieruchomym obrazie, trochę więcej smug. Domyślnie 99%."}, {"Higher: smoother while the camera moves, more blur and trail. Default 55%.", "Wyżej: gładszy obraz podczas ruchu kamery, więcej rozmycia i smug. Domyślnie 55%."}, - {"Lower: less trail and ghosting, more flicker. Default 115%.", "Niżej: mniej smug i duchów, więcej migotania. Domyślnie 115%."}, - {"How much history a moving character or object loses. Higher: less ghosting there, rougher edges. Default 90%.", "Ile historii traci poruszająca się postać lub obiekt. Wyżej: mniej duchów tam, bardziej postrzępione krawędzie. Domyślnie 90%."}, - {"Sharper textures (a negative mip bias, in percent of one level): the accumulation turns the extra detail into a clean picture. Higher: more detail, more shimmer. Default 75%.", "Ostrzejsze tekstury (ujemny bias mip, w procentach jednego poziomu): akumulacja zamienia dodatkowe szczegóły w czysty obraz. Wyżej: więcej szczegółów, więcej migotania. Domyślnie 75%."}, - {"Smooths the stair-stepped edges of moving characters, where the history is refused: a spatial filter on those pixels only. Higher: smoother, slightly softer. Default 70%.", "Wygładza schodkowe krawędzie poruszających się postaci, gdzie historia jest odrzucana: filtr przestrzenny tylko na tych pikselach. Wyżej: gładziej, nieco miękciej. Domyślnie 70%."}, + {"Lower: less trail and ghosting, more flicker. Default 175%.", "Niżej: mniej smug i duchów, więcej migotania. Domyślnie 175%."}, + {"How much history a moving character or object loses. Higher: less ghosting there, rougher edges. Default 55%.", "Ile historii traci poruszająca się postać lub obiekt. Wyżej: mniej duchów tam, bardziej postrzępione krawędzie. Domyślnie 55%."}, + {"XeSS (God of War III)", "XeSS (God of War III)"}, + {"XeSS status", "Stan XeSS"}, + {"Sharper textures (a negative mip bias, in percent of one level): XeSS turns the extra detail into a clean picture. Higher: more detail, more shimmer. Default 80%.", "Ostrzejsze tekstury (ujemny bias mip, w procentach jednego poziomu): XeSS zamienia dodatkowy detal w czysty obraz. Wyżej: więcej detali, więcej migotania. Domyślnie 80%."}, + {"How much XeSS distrusts its history on characters and objects (a mask from the game's stencil). Higher: less ghosting behind them, rougher edges. 0% = off. Default 95%.", "Jak bardzo XeSS nie ufa swojej historii na postaciach i obiektach (maska ze stencila gry). Wyżej: mniej smug za nimi, bardziej chropowate krawędzie. 0% = wyłączone. Domyślnie 95%."}, + {"Sharpening after XeSS, separate from the Sharpening (RCAS) switch below. 0% = off. Default 145%.", "Wyostrzanie po XeSS, niezależne od przełącznika Wyostrzanie (RCAS) poniżej. 0% = wyłączone. Domyślnie 145%."}, + {"Sharper textures (a negative mip bias, in percent of one level): the accumulation turns the extra detail into a clean picture. Higher: more detail, more shimmer. Default 80%.", "Ostrzejsze tekstury (ujemny bias mip, w procentach jednego poziomu): akumulacja zamienia dodatkowe szczegóły w czysty obraz. Wyżej: więcej szczegółów, więcej migotania. Domyślnie 80%."}, + {"Smooths the stair-stepped edges of moving characters, where the history is refused: a spatial filter on those pixels only. Higher: smoother, slightly softer. Default 55%.", "Wygładza schodkowe krawędzie poruszających się postaci, gdzie historia jest odrzucana: filtr przestrzenny tylko na tych pikselach. Wyżej: gładziej, nieco miękciej. Domyślnie 55%."}, {"Shows where the history is used: red = rejected by depth, green = lost to colour change, blue = history weight used. For bug reports; not saved.", "Pokazuje, gdzie używana jest historia: czerwony = odrzucona przez głębię, zielony = utracona przez zmianę koloru, niebieski = użyta waga historii. Do zgłoszeń błędów; nie jest zapisywane."}, - {"Sharpening after the accumulation, separate from the Sharpening (RCAS) switch below. 0% = off. Default 165%.", "Wyostrzanie po akumulacji, niezależne od przełącznika Wyostrzanie (RCAS) poniżej. 0% = wyłączone. Domyślnie 165%."}, + {"Sharpening after the accumulation, separate from the Sharpening (RCAS) switch below. 0% = off. Default 130%.", "Wyostrzanie po akumulacji, niezależne od przełącznika Wyostrzanie (RCAS) poniżej. 0% = wyłączone. Domyślnie 130%."}, {"Sharper textures (a negative mip bias, in percent of one level) on top of FSR's own: the accumulation turns the extra detail into a clean picture. Higher: more detail, more shimmer. Default 0%.", "Ostrzejsze tekstury (ujemny bias mip, w procentach jednego poziomu) ponad własny bias FSR: akumulacja zamienia dodatkowe szczegóły w czysty obraz. Wyżej: więcej szczegółów, więcej migotania. Domyślnie 0%."}, {"How much FSR distrusts its history on characters and objects. Higher: less ghosting behind them, rougher edges. Lower: smoother but more trails. Default 100%.", "Jak bardzo FSR nie ufa swojej historii na postaciach i obiektach. Wyżej: mniej duchów za nimi, bardziej postrzępione krawędzie. Niżej: gładziej, ale więcej smug. Domyślnie 100%."}, {"FSR 3.1 (native HUD) keeps the game at 1920x1080 so the HUD, text and loading screens are not stretched, and has the port's own sharpening. FSR 4.1 needs an AMD Radeon with Adrenalin 26.10.1 or newer.", "FSR 3.1 (natywny HUD) zostawia grę w 1920x1080, więc HUD, tekst i ekrany ładowania nie są rozciągane, i ma własne wyostrzanie portu. FSR 4.1 wymaga karty AMD Radeon ze sterownikiem Adrenalin 26.10.1 lub nowszym."}, diff --git a/gpu/shim/ui_language/spartanport_ui_pt.h b/gpu/shim/ui_language/spartanport_ui_pt.h index 8cc3a44d6d..9502c75a13 100644 --- a/gpu/shim/ui_language/spartanport_ui_pt.h +++ b/gpu/shim/ui_language/spartanport_ui_pt.h @@ -249,12 +249,17 @@ inline constexpr std::pair PortugueseText[] = { {"FSR 3.1 (native HUD)", "FSR 3.1 (HUD nativa)"}, {"Higher: smoother edges on a still picture, a little more trail. Default 99%.", "Maior: bordas mais suaves com a imagem parada, um pouco mais de rastro. Padrão 99%."}, {"Higher: smoother while the camera moves, more blur and trail. Default 55%.", "Maior: mais suave enquanto a câmera se move, mais desfoque e rastro. Padrão 55%."}, - {"Lower: less trail and ghosting, more flicker. Default 115%.", "Menor: menos rastro e fantasmas, mais cintilação. Padrão 115%."}, - {"How much history a moving character or object loses. Higher: less ghosting there, rougher edges. Default 90%.", "Quanto histórico um personagem ou objeto em movimento perde. Maior: menos fantasmas ali, bordas mais ásperas. Padrão 90%."}, - {"Sharper textures (a negative mip bias, in percent of one level): the accumulation turns the extra detail into a clean picture. Higher: more detail, more shimmer. Default 75%.", "Texturas mais nítidas (um mip bias negativo, em porcentagem de um nível): o acúmulo transforma o detalhe extra em uma imagem limpa. Maior: mais detalhe, mais cintilação. Padrão 75%."}, - {"Smooths the stair-stepped edges of moving characters, where the history is refused: a spatial filter on those pixels only. Higher: smoother, slightly softer. Default 70%.", "Suaviza as bordas serrilhadas de personagens em movimento, onde o histórico é recusado: um filtro espacial só nesses pixels. Maior: mais suave, um pouco mais desfocado. Padrão 70%."}, + {"Lower: less trail and ghosting, more flicker. Default 175%.", "Menor: menos rastro e fantasmas, mais cintilação. Padrão 175%."}, + {"How much history a moving character or object loses. Higher: less ghosting there, rougher edges. Default 55%.", "Quanto histórico um personagem ou objeto em movimento perde. Maior: menos fantasmas ali, bordas mais ásperas. Padrão 55%."}, + {"XeSS (God of War III)", "XeSS (God of War III)"}, + {"XeSS status", "Estado do XeSS"}, + {"Sharper textures (a negative mip bias, in percent of one level): XeSS turns the extra detail into a clean picture. Higher: more detail, more shimmer. Default 80%.", "Texturas mais nítidas (um viés de mip negativo, em porcentagem de um nível): o XeSS transforma o detalhe extra em uma imagem limpa. Mais alto: mais detalhe, mais cintilação. Padrão 80%."}, + {"How much XeSS distrusts its history on characters and objects (a mask from the game's stencil). Higher: less ghosting behind them, rougher edges. 0% = off. Default 95%.", "O quanto o XeSS desconfia do seu histórico em personagens e objetos (uma máscara do stencil do jogo). Mais alto: menos rastro atrás deles, bordas mais ásperas. 0% = desligado. Padrão 95%."}, + {"Sharpening after XeSS, separate from the Sharpening (RCAS) switch below. 0% = off. Default 145%.", "Nitidez depois do XeSS, independente do interruptor Nitidez (RCAS) abaixo. 0% = desligada. Padrão 145%."}, + {"Sharper textures (a negative mip bias, in percent of one level): the accumulation turns the extra detail into a clean picture. Higher: more detail, more shimmer. Default 80%.", "Texturas mais nítidas (um mip bias negativo, em porcentagem de um nível): o acúmulo transforma o detalhe extra em uma imagem limpa. Maior: mais detalhe, mais cintilação. Padrão 80%."}, + {"Smooths the stair-stepped edges of moving characters, where the history is refused: a spatial filter on those pixels only. Higher: smoother, slightly softer. Default 55%.", "Suaviza as bordas serrilhadas de personagens em movimento, onde o histórico é recusado: um filtro espacial só nesses pixels. Maior: mais suave, um pouco mais desfocado. Padrão 55%."}, {"Shows where the history is used: red = rejected by depth, green = lost to colour change, blue = history weight used. For bug reports; not saved.", "Mostra onde o histórico é usado: vermelho = rejeitado pela profundidade, verde = perdido por mudança de cor, azul = peso do histórico usado. Para relatórios de erros; não é salvo."}, - {"Sharpening after the accumulation, separate from the Sharpening (RCAS) switch below. 0% = off. Default 165%.", "Nitidez depois do acúmulo, separada da chave Nitidez (RCAS) abaixo. 0% = desligada. Padrão 165%."}, + {"Sharpening after the accumulation, separate from the Sharpening (RCAS) switch below. 0% = off. Default 130%.", "Nitidez depois do acúmulo, separada da chave Nitidez (RCAS) abaixo. 0% = desligada. Padrão 130%."}, {"Sharper textures (a negative mip bias, in percent of one level) on top of FSR's own: the accumulation turns the extra detail into a clean picture. Higher: more detail, more shimmer. Default 0%.", "Texturas mais nítidas (um mip bias negativo, em porcentagem de um nível) além do próprio do FSR: o acúmulo transforma o detalhe extra em uma imagem limpa. Maior: mais detalhe, mais cintilação. Padrão 0%."}, {"How much FSR distrusts its history on characters and objects. Higher: less ghosting behind them, rougher edges. Lower: smoother but more trails. Default 100%.", "Quanto o FSR desconfia do seu histórico em personagens e objetos. Maior: menos fantasmas atrás deles, bordas mais ásperas. Menor: mais suave, mas com mais rastro. Padrão 100%."}, {"FSR 3.1 (native HUD) keeps the game at 1920x1080 so the HUD, text and loading screens are not stretched, and has the port's own sharpening. FSR 4.1 needs an AMD Radeon with Adrenalin 26.10.1 or newer.", "O FSR 3.1 (HUD nativa) mantém o jogo em 1920x1080, então a HUD, o texto e as telas de carregamento não são esticados, e tem a nitidez própria do port. O FSR 4.1 exige uma AMD Radeon com Adrenalin 26.10.1 ou mais recente."}, diff --git a/gpu/shim/ui_language/spartanport_ui_ru.h b/gpu/shim/ui_language/spartanport_ui_ru.h index fb71a3cf1e..c2bd4ba277 100644 --- a/gpu/shim/ui_language/spartanport_ui_ru.h +++ b/gpu/shim/ui_language/spartanport_ui_ru.h @@ -249,12 +249,17 @@ inline constexpr std::pair RussianText[] = { {"FSR 3.1 (native HUD)", "FSR 3.1 (нативный HUD)"}, {"Higher: smoother edges on a still picture, a little more trail. Default 99%.", "Выше: более гладкие края на неподвижной картинке, чуть больше шлейфа. По умолчанию 99%."}, {"Higher: smoother while the camera moves, more blur and trail. Default 55%.", "Выше: глаже при движении камеры, больше размытия и шлейфа. По умолчанию 55%."}, - {"Lower: less trail and ghosting, more flicker. Default 115%.", "Ниже: меньше шлейфа и «призраков», больше мерцания. По умолчанию 115%."}, - {"How much history a moving character or object loses. Higher: less ghosting there, rougher edges. Default 90%.", "Сколько истории теряет движущийся персонаж или объект. Выше: меньше «призраков» там, грубее края. По умолчанию 90%."}, - {"Sharper textures (a negative mip bias, in percent of one level): the accumulation turns the extra detail into a clean picture. Higher: more detail, more shimmer. Default 75%.", "Более чёткие текстуры (отрицательный mip bias, в процентах от одного уровня): накопление превращает лишнюю детализацию в чистую картинку. Выше: больше деталей, больше мерцания. По умолчанию 75%."}, - {"Smooths the stair-stepped edges of moving characters, where the history is refused: a spatial filter on those pixels only. Higher: smoother, slightly softer. Default 70%.", "Сглаживает ступенчатые края движущихся персонажей, где история отвергается: пространственный фильтр только на этих пикселях. Выше: глаже, чуть мягче. По умолчанию 70%."}, + {"Lower: less trail and ghosting, more flicker. Default 175%.", "Ниже: меньше шлейфа и «призраков», больше мерцания. По умолчанию 175%."}, + {"How much history a moving character or object loses. Higher: less ghosting there, rougher edges. Default 55%.", "Сколько истории теряет движущийся персонаж или объект. Выше: меньше «призраков» там, грубее края. По умолчанию 55%."}, + {"XeSS (God of War III)", "XeSS (God of War III)"}, + {"XeSS status", "Состояние XeSS"}, + {"Sharper textures (a negative mip bias, in percent of one level): XeSS turns the extra detail into a clean picture. Higher: more detail, more shimmer. Default 80%.", "Более чёткие текстуры (отрицательное смещение mip, в процентах от одного уровня): XeSS превращает лишнюю детализацию в чистую картинку. Выше: больше деталей, больше мерцания. По умолчанию 80%."}, + {"How much XeSS distrusts its history on characters and objects (a mask from the game's stencil). Higher: less ghosting behind them, rougher edges. 0% = off. Default 95%.", "Насколько XeSS не доверяет своей истории на персонажах и объектах (маска из стенсила игры). Выше: меньше шлейфов за ними, грубее края. 0% = выключено. По умолчанию 95%."}, + {"Sharpening after XeSS, separate from the Sharpening (RCAS) switch below. 0% = off. Default 145%.", "Резкость после XeSS, не зависит от переключателя Резкость (RCAS) ниже. 0% = выключена. По умолчанию 145%."}, + {"Sharper textures (a negative mip bias, in percent of one level): the accumulation turns the extra detail into a clean picture. Higher: more detail, more shimmer. Default 80%.", "Более чёткие текстуры (отрицательный mip bias, в процентах от одного уровня): накопление превращает лишнюю детализацию в чистую картинку. Выше: больше деталей, больше мерцания. По умолчанию 80%."}, + {"Smooths the stair-stepped edges of moving characters, where the history is refused: a spatial filter on those pixels only. Higher: smoother, slightly softer. Default 55%.", "Сглаживает ступенчатые края движущихся персонажей, где история отвергается: пространственный фильтр только на этих пикселях. Выше: глаже, чуть мягче. По умолчанию 55%."}, {"Shows where the history is used: red = rejected by depth, green = lost to colour change, blue = history weight used. For bug reports; not saved.", "Показывает, где используется история: красный = отвергнуто по глубине, зелёный = потеряно из-за смены цвета, синий = использованный вес истории. Для отчётов об ошибках; не сохраняется."}, - {"Sharpening after the accumulation, separate from the Sharpening (RCAS) switch below. 0% = off. Default 165%.", "Резкость после накопления, отдельно от переключателя Резкость (RCAS) ниже. 0% = выкл. По умолчанию 165%."}, + {"Sharpening after the accumulation, separate from the Sharpening (RCAS) switch below. 0% = off. Default 130%.", "Резкость после накопления, отдельно от переключателя Резкость (RCAS) ниже. 0% = выкл. По умолчанию 130%."}, {"Sharper textures (a negative mip bias, in percent of one level) on top of FSR's own: the accumulation turns the extra detail into a clean picture. Higher: more detail, more shimmer. Default 0%.", "Более чёткие текстуры (отрицательный mip bias, в процентах от одного уровня) сверх собственного смещения FSR: накопление превращает лишнюю детализацию в чистую картинку. Выше: больше деталей, больше мерцания. По умолчанию 0%."}, {"How much FSR distrusts its history on characters and objects. Higher: less ghosting behind them, rougher edges. Lower: smoother but more trails. Default 100%.", "Насколько FSR не доверяет своей истории на персонажах и объектах. Выше: меньше «призраков» за ними, грубее края. Ниже: глаже, но больше шлейфов. По умолчанию 100%."}, {"FSR 3.1 (native HUD) keeps the game at 1920x1080 so the HUD, text and loading screens are not stretched, and has the port's own sharpening. FSR 4.1 needs an AMD Radeon with Adrenalin 26.10.1 or newer.", "FSR 3.1 (нативный HUD) оставляет игру в 1920x1080, поэтому HUD, текст и экраны загрузки не растягиваются, и имеет собственную резкость порта. FSR 4.1 требует AMD Radeon с Adrenalin 26.10.1 или новее."}, diff --git a/gpu/shim/ui_language/spartanport_ui_tr.h b/gpu/shim/ui_language/spartanport_ui_tr.h index 3fa365d2c9..9422348130 100644 --- a/gpu/shim/ui_language/spartanport_ui_tr.h +++ b/gpu/shim/ui_language/spartanport_ui_tr.h @@ -249,12 +249,17 @@ inline constexpr std::pair TurkishText[] = { {"FSR 3.1 (native HUD)", "FSR 3.1 (yerel HUD)"}, {"Higher: smoother edges on a still picture, a little more trail. Default 99%.", "Yüksek: durağan görüntüde daha pürüzsüz kenarlar, biraz daha fazla iz. Varsayılan 99%."}, {"Higher: smoother while the camera moves, more blur and trail. Default 55%.", "Yüksek: kamera hareket ederken daha pürüzsüz, daha fazla bulanıklık ve iz. Varsayılan 55%."}, - {"Lower: less trail and ghosting, more flicker. Default 115%.", "Düşük: daha az iz ve hayalet görüntü, daha fazla titreme. Varsayılan 115%."}, - {"How much history a moving character or object loses. Higher: less ghosting there, rougher edges. Default 90%.", "Hareketli bir karakterin veya nesnenin ne kadar geçmişi kaybettiği. Yüksek: orada daha az hayalet görüntü, daha pürüzlü kenarlar. Varsayılan 90%."}, - {"Sharper textures (a negative mip bias, in percent of one level): the accumulation turns the extra detail into a clean picture. Higher: more detail, more shimmer. Default 75%.", "Daha keskin dokular (negatif mip bias, bir seviyenin yüzdesi olarak): birikim ek detayı temiz bir görüntüye dönüştürür. Yüksek: daha fazla detay, daha fazla titreme. Varsayılan 75%."}, - {"Smooths the stair-stepped edges of moving characters, where the history is refused: a spatial filter on those pixels only. Higher: smoother, slightly softer. Default 70%.", "Geçmişin reddedildiği hareketli karakterlerin basamaklı kenarlarını yumuşatır: yalnızca bu pikseller üzerinde uzamsal bir filtre. Yüksek: daha pürüzsüz, biraz daha yumuşak. Varsayılan 70%."}, + {"Lower: less trail and ghosting, more flicker. Default 175%.", "Düşük: daha az iz ve hayalet görüntü, daha fazla titreme. Varsayılan 175%."}, + {"How much history a moving character or object loses. Higher: less ghosting there, rougher edges. Default 55%.", "Hareketli bir karakterin veya nesnenin ne kadar geçmişi kaybettiği. Yüksek: orada daha az hayalet görüntü, daha pürüzlü kenarlar. Varsayılan 55%."}, + {"XeSS (God of War III)", "XeSS (God of War III)"}, + {"XeSS status", "XeSS durumu"}, + {"Sharper textures (a negative mip bias, in percent of one level): XeSS turns the extra detail into a clean picture. Higher: more detail, more shimmer. Default 80%.", "Daha net dokular (bir seviyenin yüzdesi olarak negatif mip önyargısı): XeSS ek ayrıntıyı temiz bir görüntüye dönüştürür. Yüksek: daha çok ayrıntı, daha çok titreme. Varsayılan %80."}, + {"How much XeSS distrusts its history on characters and objects (a mask from the game's stencil). Higher: less ghosting behind them, rougher edges. 0% = off. Default 95%.", "XeSS'in karakterlerde ve nesnelerde geçmişine ne kadar güvenmediği (oyunun stencil'inden bir maske). Yüksek: arkalarında daha az iz, daha pürüzlü kenarlar. %0 = kapalı. Varsayılan %95."}, + {"Sharpening after XeSS, separate from the Sharpening (RCAS) switch below. 0% = off. Default 145%.", "XeSS sonrası keskinleştirme, aşağıdaki Keskinleştirme (RCAS) anahtarından bağımsızdır. %0 = kapalı. Varsayılan %145."}, + {"Sharper textures (a negative mip bias, in percent of one level): the accumulation turns the extra detail into a clean picture. Higher: more detail, more shimmer. Default 80%.", "Daha keskin dokular (negatif mip bias, bir seviyenin yüzdesi olarak): birikim ek detayı temiz bir görüntüye dönüştürür. Yüksek: daha fazla detay, daha fazla titreme. Varsayılan 80%."}, + {"Smooths the stair-stepped edges of moving characters, where the history is refused: a spatial filter on those pixels only. Higher: smoother, slightly softer. Default 55%.", "Geçmişin reddedildiği hareketli karakterlerin basamaklı kenarlarını yumuşatır: yalnızca bu pikseller üzerinde uzamsal bir filtre. Yüksek: daha pürüzsüz, biraz daha yumuşak. Varsayılan 55%."}, {"Shows where the history is used: red = rejected by depth, green = lost to colour change, blue = history weight used. For bug reports; not saved.", "Geçmişin nerede kullanıldığını gösterir: kırmızı = derinlik nedeniyle reddedildi, yeşil = renk değişimi nedeniyle kayboldu, mavi = kullanılan geçmiş ağırlığı. Hata raporları için; kaydedilmez."}, - {"Sharpening after the accumulation, separate from the Sharpening (RCAS) switch below. 0% = off. Default 165%.", "Birikimden sonra keskinleştirme, aşağıdaki Keskinleştirme (RCAS) anahtarından ayrı. 0% = kapalı. Varsayılan 165%."}, + {"Sharpening after the accumulation, separate from the Sharpening (RCAS) switch below. 0% = off. Default 130%.", "Birikimden sonra keskinleştirme, aşağıdaki Keskinleştirme (RCAS) anahtarından ayrı. 0% = kapalı. Varsayılan 130%."}, {"Sharper textures (a negative mip bias, in percent of one level) on top of FSR's own: the accumulation turns the extra detail into a clean picture. Higher: more detail, more shimmer. Default 0%.", "FSR'ın kendi biasına ek olarak daha keskin dokular (negatif mip bias, bir seviyenin yüzdesi olarak): birikim ek detayı temiz bir görüntüye dönüştürür. Yüksek: daha fazla detay, daha fazla titreme. Varsayılan 0%."}, {"How much FSR distrusts its history on characters and objects. Higher: less ghosting behind them, rougher edges. Lower: smoother but more trails. Default 100%.", "FSR'ın karakterlerde ve nesnelerde geçmişine ne kadar güvenmediği. Yüksek: arkalarında daha az hayalet görüntü, daha pürüzlü kenarlar. Düşük: daha pürüzsüz ama daha fazla iz. Varsayılan 100%."}, {"FSR 3.1 (native HUD) keeps the game at 1920x1080 so the HUD, text and loading screens are not stretched, and has the port's own sharpening. FSR 4.1 needs an AMD Radeon with Adrenalin 26.10.1 or newer.", "FSR 3.1 (yerel HUD) oyunu 1920x1080'de tutar, böylece HUD, metin ve yükleme ekranları esnetilmez; ayrıca portun kendi keskinleştirmesi vardır. FSR 4.1, Adrenalin 26.10.1 veya daha yeni sürümlü bir AMD Radeon gerektirir."}, diff --git a/gpu/third_party/xess/xess.h b/gpu/third_party/xess/xess.h new file mode 100644 index 0000000000..5d16b10199 --- /dev/null +++ b/gpu/third_party/xess/xess.h @@ -0,0 +1,426 @@ +/******************************************************************************* + * Copyright (c) 2026 Intel Corporation + * + * SPDX-License-Identifier: MIT + ******************************************************************************/ + +#ifndef XESS_H +#define XESS_H + +#ifdef XESS_SHARED_LIB +#ifdef _WIN32 +#ifdef XESS_EXPORT_API +#define XESS_API __declspec(dllexport) +#else +#define XESS_API __declspec(dllimport) +#endif +#else +#define XESS_API __attribute__((visibility("default"))) +#endif +#else +#define XESS_API +#endif + +#if !defined _MSC_VER || (_MSC_VER >= 1929) +#define XESS_PRAGMA(x) _Pragma(#x) +#else +#define XESS_PRAGMA(x) __pragma(x) +#endif +#define XESS_PACK_B_X(x) XESS_PRAGMA(pack(push, x)) +#define XESS_PACK_E() XESS_PRAGMA(pack(pop)) +#define XESS_PACK_B() XESS_PACK_B_X(8) + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct _xess_context_handle_t* xess_context_handle_t; + +XESS_PACK_B() +/** + * @brief XeSS version. + * + * XeSS uses major.minor.patch version format and Numeric 90+ scheme for development stage builds. + */ +typedef struct _xess_version_t +{ + /** A major version increment indicates a new API and potentially a + * break in functionality. */ + uint16_t major; + /** A minor version increment indicates incremental changes such as + * optional inputs or flags. This does not break existing functionality. */ + uint16_t minor; + /** A patch version increment may include performance or quality tweaks or fixes for known issues. + * There's no change in the interfaces. + * Versions beyond 90 used for development builds to change the interface for the next release. + */ + uint16_t patch; + /** Reserved for future use. */ + uint16_t reserved; +} xess_version_t; +XESS_PACK_E() + +XESS_PACK_B() +/** + * @brief 2D variable. + */ +typedef struct _xess_2d_t +{ + uint32_t x; + uint32_t y; +} xess_2d_t; +XESS_PACK_E() + +/** + * @brief 2D coordinates. + */ +typedef xess_2d_t xess_coord_t; + +/** + * @brief XeSS quality settings. + */ +typedef enum _xess_quality_settings_t +{ + XESS_QUALITY_SETTING_ULTRA_PERFORMANCE = 100, + XESS_QUALITY_SETTING_PERFORMANCE = 101, + XESS_QUALITY_SETTING_BALANCED = 102, + XESS_QUALITY_SETTING_QUALITY = 103, + XESS_QUALITY_SETTING_ULTRA_QUALITY = 104, + XESS_QUALITY_SETTING_ULTRA_QUALITY_PLUS = 105, + XESS_QUALITY_SETTING_AA = 106, +} xess_quality_settings_t; + +/** + * @brief XeSS initialization flags. + */ +typedef enum _xess_init_flags_t +{ + XESS_INIT_FLAG_NONE = 0, + /** Use motion vectors at target resolution. */ + XESS_INIT_FLAG_HIGH_RES_MV = 1 << 0, + /** Use inverted (increased precision) depth encoding */ + XESS_INIT_FLAG_INVERTED_DEPTH = 1 << 1, + /** Use exposure texture to scale input color. */ + XESS_INIT_FLAG_EXPOSURE_SCALE_TEXTURE = 1 << 2, + /** Use responsive pixel mask texture. */ + XESS_INIT_FLAG_RESPONSIVE_PIXEL_MASK = 1 << 3, + /** Use velocity in NDC */ + XESS_INIT_FLAG_USE_NDC_VELOCITY = 1 << 4, + /** Use external descriptor heap */ + XESS_INIT_FLAG_EXTERNAL_DESCRIPTOR_HEAP = 1 << 5, + /** Disable tonemapping for input and output */ + XESS_INIT_FLAG_LDR_INPUT_COLOR = 1 << 6, + /** Remove jitter from input velocity*/ + XESS_INIT_FLAG_JITTERED_MV = 1 << 7, + /** Enable automatic exposure calculation. */ + XESS_INIT_FLAG_ENABLE_AUTOEXPOSURE = 1 << 8 +} xess_init_flags_t; + +XESS_PACK_B() +/** + * @brief Properties for internal XeSS resources. + */ +typedef struct _xess_properties_t +{ + /** Required amount of descriptors for XeSS */ + uint32_t requiredDescriptorCount; + /** The heap size required by XeSS for temporary buffer storage. */ + uint64_t tempBufferHeapSize; + /** The heap size required by XeSS for temporary texture storage. */ + uint64_t tempTextureHeapSize; +} xess_properties_t; +XESS_PACK_E() + +/** + * @brief XeSS return codes. + */ +typedef enum _xess_result_t +{ + /** Warning. Folder to store dump data doesn't exist. Write operation skipped.*/ + XESS_RESULT_WARNING_NONEXISTING_FOLDER = 1, + /** An old or outdated driver. */ + XESS_RESULT_WARNING_OLD_DRIVER = 2, + /** XeSS operation was successful. */ + XESS_RESULT_SUCCESS = 0, + /** XeSS not supported on the GPU. An SM 6.4 capable GPU is required. */ + XESS_RESULT_ERROR_UNSUPPORTED_DEVICE = -1, + /** An unsupported driver. */ + XESS_RESULT_ERROR_UNSUPPORTED_DRIVER = -2, + /** Execute called without initialization. */ + XESS_RESULT_ERROR_UNINITIALIZED = -3, + /** Invalid argument such as descriptor handles. */ + XESS_RESULT_ERROR_INVALID_ARGUMENT = -4, + /** Not enough available GPU memory. */ + XESS_RESULT_ERROR_DEVICE_OUT_OF_MEMORY = -5, + /** Device function failed, such as resource or descriptor creation. */ + XESS_RESULT_ERROR_DEVICE = -6, + /** The function is not implemented */ + XESS_RESULT_ERROR_NOT_IMPLEMENTED = -7, + /** Invalid context. */ + XESS_RESULT_ERROR_INVALID_CONTEXT = -8, + /** Operation not finished yet. */ + XESS_RESULT_ERROR_OPERATION_IN_PROGRESS = -9, + /** Operation not supported in current configuration. */ + XESS_RESULT_ERROR_UNSUPPORTED = -10, + /** The library cannot be loaded. */ + XESS_RESULT_ERROR_CANT_LOAD_LIBRARY = -11, + /** Call to function done in invalid order. */ + XESS_RESULT_ERROR_WRONG_CALL_ORDER = -12, + + /** Unknown internal failure */ + XESS_RESULT_ERROR_UNKNOWN = -1000, +} xess_result_t; + +/** + * @brief XeSS logging level + */ +typedef enum _xess_logging_level_t +{ + XESS_LOGGING_LEVEL_DEBUG = 0, + XESS_LOGGING_LEVEL_INFO = 1, + XESS_LOGGING_LEVEL_WARNING = 2, + XESS_LOGGING_LEVEL_ERROR = 3 +} xess_logging_level_t; + +/** + * A logging callback provided by the application. This callback can be called from other threads. + * Message pointer is only valid inside function and may be invalid right after return call. + * Message is a null-terminated utf-8 string + */ + typedef void (*xess_app_log_callback_t)(const char *message, xess_logging_level_t loggingLevel); + +#ifndef XESS_TYPES_ONLY + +/** @addtogroup xess XeSS API exports + * @{ + */ + +/** + * @brief Gets the XeSS version. This is baked into the XeSS SDK release. + * @param[out] pVersion Returned XeSS version. + * @return XeSS return status code. + */ +XESS_API xess_result_t xessGetVersion(xess_version_t* pVersion); + +/** + * @brief Gets the version of the loaded Intel XeFX library. When running on Intel platforms + * this function will return the version of the loaded Intel XeFX library, for other + * platforms 0.0.0 will be returned. + * @param hContext The XeSS context handle. + * @param[out] pVersion Returned Intel XeFX library version. + * @return XeSS return status code. + */ +XESS_API xess_result_t xessGetIntelXeFXVersion(xess_context_handle_t hContext, + xess_version_t* pVersion); + +/** + * @brief Gets XeSS internal resources properties. + * @param hContext The XeSS context handle. + * @param pOutputResolution Output resolution to calculate properties for. + * @param[out] pBindingProperties Returned properties. + * @return XeSS return status code. + */ +XESS_API xess_result_t xessGetProperties(xess_context_handle_t hContext, + const xess_2d_t* pOutputResolution, xess_properties_t* pBindingProperties); + +/** + * @brief Get the input resolution for a specified output resolution for a given quality setting. + * XeSS expects all the input buffers except motion vectors to be in the returned resolution. + * Motion vectors can be either in output resolution (XESS_INIT_FLAG_HIGH_RES_MV) or + * returned resolution (default). + * + * @param hContext The XeSS context handle. + * @param pOutputResolution Output resolution to calculate input resolution for. + * @param qualitySettings Desired quality setting. + * @param[out] pInputResolution Required input resolution. + * @return XeSS return status code. + */ +XESS_API xess_result_t xessGetInputResolution(xess_context_handle_t hContext, + const xess_2d_t* pOutputResolution, xess_quality_settings_t qualitySettings, + xess_2d_t* pInputResolution); + +/** + * @brief Get the optimal input resolution and possible range for a specified output resolution for a given quality setting. + * XeSS expects all the input buffers except motion vectors to be in the returned resolution range + * and all input buffers to be in the same resolution. + * Motion vectors can be either in output resolution (XESS_INIT_FLAG_HIGH_RES_MV) or + * in the same resolution as other input buffers (by default). + * + * @note Aspect ratio of the input resolution must be the same as for the output resolution. + * + * @param hContext The XeSS context handle. + * @param pOutputResolution Output resolution to calculate input resolution for. + * @param qualitySettings Desired quality setting. + * @param[out] pInputResolutionOptimal Optimal input resolution. + * @param[out] pInputResolutionMin Required minimal input resolution. + * @param[out] pInputResolutionMax Required maximal input resolution. + * @return XeSS return status code. + */ +XESS_API xess_result_t xessGetOptimalInputResolution(xess_context_handle_t hContext, + const xess_2d_t* pOutputResolution, xess_quality_settings_t qualitySettings, + xess_2d_t* pInputResolutionOptimal, xess_2d_t* pInputResolutionMin, xess_2d_t* pInputResolutionMax); + +/** + * @brief Gets jitter scale value. + * @param hContext The XeSS context handle. + * @param[out] pX Jitter scale pointer for the X axis. + * @param[out] pY Jitter scale pointer for the Y axis. + * @return XeSS return status code. + */ +XESS_API xess_result_t xessGetJitterScale(xess_context_handle_t hContext, float* pX, float* pY); + +/** + * @brief Gets velocity scale value. + * @param hContext The XeSS context handle. + * @param[out] pX Velocity scale pointer for the X axis. + * @param[out] pY Velocity scale pointer for the Y axis. + * @return XeSS return status code. + */ +XESS_API xess_result_t xessGetVelocityScale(xess_context_handle_t hContext, float* pX, float* pY); + +/** + * @brief Destroys the XeSS context. + * The user must ensure that any pending command lists are completed before destroying the context. + * @param hContext: The XeSS context handle. + * @return XeSS return status code. + */ +XESS_API xess_result_t xessDestroyContext(xess_context_handle_t hContext); + +/** + * @brief Sets jitter scale value + * + * @param hContext The XeSS context handle. + * @param x scale for the X axis + * @param y scale for the Y axis + * @return XeSS return status code. + */ +XESS_API xess_result_t xessSetJitterScale(xess_context_handle_t hContext, float x, float y); + +/** + * @brief Sets velocity scale value + * + * @param hContext The XeSS context handle. + * @param x scale for the X axis + * @param y scale for the Y axis + * @return XeSS return status code. + */ +XESS_API xess_result_t xessSetVelocityScale(xess_context_handle_t hContext, float x, float y); + +/** + * @brief Sets exposure scale value + * + * This value will be applied on top of any passed exposure value or automatically calculated exposure. + * + * @param hContext The XeSS context handle. + * @param scale scale value. + * @return XeSS return status code. + */ +XESS_API xess_result_t xessSetExposureMultiplier(xess_context_handle_t hContext, float scale); + +/** + * @brief Gets exposure scale value + * + * @param hContext The XeSS context handle. + * @param[out] pScale Exposure scale pointer. + * @return XeSS return status code. + */ +XESS_API xess_result_t xessGetExposureMultiplier(xess_context_handle_t hContext, float *pScale); + +/** + * @brief Sets maximum value for responsive mask + * + * This value used to clip responsive mask values. Final responsive mask value calculated as + * clip(responsive_mask, 0.0, max_value). Value must be within range [0.0; 1.0] + * + * @param hContext The XeSS context handle. + * @param value maximum clip value. + * @return XeSS return status code. + */ +XESS_API xess_result_t xessSetMaxResponsiveMaskValue(xess_context_handle_t hContext, float value); + +/** + * @brief Gets maximum value for responsive mask + * + * @param hContext The XeSS context handle. + * @param[out] pValue maximum clip value pointer. + * @return XeSS return status code. + */ +XESS_API xess_result_t xessGetMaxResponsiveMaskValue(xess_context_handle_t hContext, float *pValue); + +/** + * @brief Sets logging callback + * + * @param hContext The XeSS context handle. + * @param loggingLevel Minimum logging level for logging callback. + * @param loggingCallback Logging callback + * @return XeSS return status code. + */ +XESS_API xess_result_t xessSetLoggingCallback(xess_context_handle_t hContext, + xess_logging_level_t loggingLevel, xess_app_log_callback_t loggingCallback); + +/** + * @brief Indicates if the installed driver supports best XeSS experience. + * + * @param hContext The XeSS context handle. + * @return xessIsOptimalDriver returns XESS_RESULT_SUCCESS, or XESS_RESULT_WARNING_OLD_DRIVER + * if installed driver may result in degraded performance or visual quality. + * xessD3D12CreateContext(..) will return XESS_RESULT_ERROR_UNSUPPORTED_DRIVER if driver does + * not support XeSS at all. + */ +XESS_API xess_result_t xessIsOptimalDriver(xess_context_handle_t hContext); + +/** + * @brief Forces usage of legacy (pre 1.3.0) scale factors + * + * Following scale factors will be applied: + * @li XESS_QUALITY_SETTING_ULTRA_PERFORMANCE: 3.0 + * @li XESS_QUALITY_SETTING_PERFORMANCE: 2.0 + * @li XESS_QUALITY_SETTING_BALANCED: 1.7 + * @li XESS_QUALITY_SETTING_QUALITY: 1.5 + * @li XESS_QUALITY_SETTING_ULTRA_QUALITY: 1.3 + * @li XESS_QUALITY_SETTING_AA: 1.0 + * In order to apply new scale factors application should call xessGetOptimalInputResolution and + * initialization function (xess*Init) + * + * @param hContext The XeSS context handle. + * @param force if set to true legacy scale factors will be forced, if set to false - scale factors + * will be selected by XeSS + * + * @return XeSS return status code. + */ +XESS_API xess_result_t xessForceLegacyScaleFactors(xess_context_handle_t hContext, bool force); + +/** + * @brief Returns current state of pipeline build + * This function can only be called after xess*BuildPipelines and + * before corresponding xess*Init. + * This call returns XESS_RESULT_SUCCESS if pipelines already built, and + * XESS_RESULT_ERROR_OPERATION_IN_PROGRESS if pipeline build is in progress. + * If function called before @ref xess*BuildPipelines or after @ref xess*Init - + * XESS_RESULT_ERROR_WRONG_CALL_ORDER will be returned. + * + * @param hContext The XeSS context handle. + * @return XESS_RESULT_SUCCESS if pipelines already built. + * XESS_RESULT_ERROR_OPERATION_IN_PROGRESS if pipeline build is in progress. + * XESS_RESULT_ERROR_WRONG_CALL_ORDER if the function is called out of order. + */ +XESS_API xess_result_t xessGetPipelineBuildStatus(xess_context_handle_t hContext); + +/** @}*/ + +#endif + +// Enum size checks. All enums must be 4 bytes +typedef char sizecheck__LINE__[ (sizeof(xess_quality_settings_t) == 4) ? 1 : -1]; +typedef char sizecheck__LINE__[ (sizeof(xess_init_flags_t) == 4) ? 1 : -1]; +typedef char sizecheck__LINE__[ (sizeof(xess_result_t) == 4) ? 1 : -1]; +typedef char sizecheck__LINE__[ (sizeof(xess_logging_level_t) == 4) ? 1 : -1]; + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/gpu/third_party/xess/xess_vk.h b/gpu/third_party/xess/xess_vk.h new file mode 100644 index 0000000000..1349d81d44 --- /dev/null +++ b/gpu/third_party/xess/xess_vk.h @@ -0,0 +1,253 @@ +/******************************************************************************* + * Copyright (c) 2026 Intel Corporation + * + * SPDX-License-Identifier: MIT + ******************************************************************************/ + +#ifndef XESS_VK_H +#define XESS_VK_H + +#include + +#include "xess.h" + +#ifdef __cplusplus +extern "C" { +#endif + +XESS_PACK_B() + +typedef struct _xess_vk_image_view_info +{ + VkImageView imageView; + VkImage image; + VkImageSubresourceRange subresourceRange; + VkFormat format; + unsigned int width; + unsigned int height; +} xess_vk_image_view_info; + +XESS_PACK_E() + +XESS_PACK_B() +/** + * @brief Execution parameters for XeSS Vulkan. + */ +typedef struct _xess_vk_execute_params_t +{ + /** Input color texture. Must be in VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL state.*/ + xess_vk_image_view_info colorTexture; + /** Input motion vector texture. Must be in VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL state.*/ + xess_vk_image_view_info velocityTexture; + /** Optional depth texture. Required if XESS_INIT_FLAG_HIGH_RES_MV has not been specified. + * Must be in VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL state.*/ + xess_vk_image_view_info depthTexture; + /** Optional 1x1 exposure scale texture. Required if XESS_INIT_FLAG_EXPOSURE_TEXTURE has been + * specified. Must be in VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL state */ + xess_vk_image_view_info exposureScaleTexture; + /** Optional responsive pixel mask texture. Required if XESS_INIT_FLAG_RESPONSIVE_PIXEL_MASK + * has been specified. Must be in VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL state */ + xess_vk_image_view_info responsivePixelMaskTexture; + /** Output texture in target resolution. Must be in VK_IMAGE_LAYOUT_GENERAL state.*/ + xess_vk_image_view_info outputTexture; + + /** Jitter X coordinate in the range [-0.5, 0.5]. */ + float jitterOffsetX; + /** Jitter Y coordinate in the range [-0.5, 0.5]. */ + float jitterOffsetY; + /** Optional input color scaling. Default is 1. */ + float exposureScale; + /** Resets the history accumulation in this frame. */ + uint32_t resetHistory; + /** Input color width. */ + uint32_t inputWidth; + /** Input color height. */ + uint32_t inputHeight; + /** Base coordinate for the input color in the texture. Default is (0,0). */ + xess_coord_t inputColorBase; + /** Base coordinate for the input motion vector in the texture. Default is (0,0). */ + xess_coord_t inputMotionVectorBase; + /** Base coordinate for the input depth in the texture. Default is (0,0). */ + xess_coord_t inputDepthBase; + /** Base coordinate for the input responsive pixel mask in the texture. Default is (0,0). */ + xess_coord_t inputResponsiveMaskBase; + /** Reserved parameter. */ + xess_coord_t reserved0; + /** Base coordinate for the output color. Default is (0,0). */ + xess_coord_t outputColorBase; +} xess_vk_execute_params_t; +XESS_PACK_E() + +XESS_PACK_B() +/** + * @brief Initialization parameters for XeSS VK. + */ +typedef struct _xess_vk_init_params_t +{ + /** Output width and height. */ + xess_2d_t outputResolution; + /** Quality setting */ + xess_quality_settings_t qualitySetting; + /** Initialization flags. */ + uint32_t initFlags; + /** Specifies the node mask for internally created resources on + * multi-adapter systems. */ + uint32_t creationNodeMask; + /** Specifies the node visibility mask for internally created resources + * on multi-adapter systems. */ + uint32_t visibleNodeMask; + /** Optional externally allocated buffer memory for XeSS. If VK_NULL_HANDLE the + * memory is allocated internally. If provided, the memory must be allocated from + * memory type that supports allocating buffers. The memory type should be DEVICE_LOCAL. + * This memory is not accessed by the CPU. */ + VkDeviceMemory tempBufferHeap; + /** Offset in the externally allocated memory for temporary buffer storage. */ + uint64_t bufferHeapOffset; + /** Optional externally allocated texture memory for XeSS. If VK_NULL_HANDLE the + * memory is allocated internally. If provided, the memory must be allocated from + * memory type that supports allocating textures. The memory type should be DEVICE_LOCAL. + * This memory is not accessed by the CPU. */ + VkDeviceMemory tempTextureHeap; + /** Offset in the externally allocated memory for temporary texture storage. */ + uint64_t textureHeapOffset; + /** Optional pipeline cache. If not VK_NULL_HANDLE will be used for pipeline creation. */ + VkPipelineCache pipelineCache; +} xess_vk_init_params_t; +XESS_PACK_E() + +/** @addtogroup xess-vulkan XeSS VK API exports + * @{ + */ + /** + * @brief Get required extensions for Vulkan instance that would run XeSS. + * This function must be called to get instance extensions need by XeSS. These + * extensions must be enabled in subsequent vkCreateInstance call, that would create a VkInstance + * object to be passed to @ref xessVKCreateContext + * @param[out] instanceExtensionsCount returns a count of instance extensions to be enabled in Vulkan instance + * @param[out] instanceExtensions returns a pointer to an array of \p instanceExtensionsCount required extension names. + * The memory used by the array is owned by the XeSS library and should not be freed by the application. + * @param[out] minVkApiVersion The Vulkan API version that XeSS would use. When calling vkCreateInstance, the application + * should set VkApplicationInfo.apiVersion to value greater or equal to \p minVkApiVersion + * @return XeSS return status code. + */ +XESS_API xess_result_t xessVKGetRequiredInstanceExtensions(uint32_t* instanceExtensionsCount, const char* const** instanceExtensions, uint32_t* minVkApiVersion); + + + /** + * @brief Get required extensions for Vulkan device that would run XeSS. + * This function must be called to get device extensions need by XeSS. These + * extensions must be enabled in subsequent vkCreateDevice call, that would create a VkDevice + * object to be passed to @ref xessVKCreateContext + * @param instance A VkInstance object created by the user + * @param physicalDevice A VkPhysicalDevice selected by the user from instance + * @param[out] deviceExtensionsCount returns a count of device extensions to be enabled in Vulkan device + * @param[out] deviceExtensions returns a pointer to an array of \p deviceExtensionsCount required extension names + * The memory used by the array is owned by the XeSS library and should not be freed by the application. + * @return XeSS return status code. + */ +XESS_API xess_result_t xessVKGetRequiredDeviceExtensions(VkInstance instance, VkPhysicalDevice physicalDevice, + uint32_t* deviceExtensionsCount, const char* const** deviceExtensions); + + + /** + * @brief Get required features for Vulkan device that would run XeSS. + * This function must be called to get device features need by XeSS. These + * features must be enabled in subsequent vkCreateDevice call, that would create a VkDevice + * object to be passed to @ref xessVKCreateContext. + * @param instance A VkInstance object created by the user + * @param physicalDevice A VkPhysicalDevice selected by the user from instance + * @param[out] features a pointer to writable chain of feature structures, that this function would patch + * with required features, by filling required fields and attaching new structures to the chain if needed. + * The returned pointer should be passed to vkCreateDevice as pNext chain of VkDeviceCreateInfo structure. + * If null is passed, than the function constructs a new structure chain that should be merged + * into the chain that application would use with VkDeviceCreateInfo, with application responsibility to + * avoid any duplicates with its own structures. + * + * It is an error to chain VkDeviceCreateInfo structure with not null pEnabledFeatures field, as this field is const + * and cannot be patched by this function. VkPhysicalDeviceFeatures2 structure should be used instead. + * + * The memory used by the structures added by this funtion to the chain is owned by the XeSS library and + * should not be freed by the application. + * @return XeSS return status code. + */ +XESS_API xess_result_t xessVKGetRequiredDeviceFeatures(VkInstance instance, VkPhysicalDevice physicalDevice, void** features); + + +/** + * @brief Create an XeSS VK context. + * @param instance A VkInstance object created by the user + * @param physicalDevice A VkPhysicalDevice selected by the user from instance + * @param device A VK device created by the user from physicalDevice + * @param[out] phContext Returned xess context handle. + * @return XeSS return status code. + */ +XESS_API xess_result_t xessVKCreateContext(VkInstance instance, VkPhysicalDevice physicalDevice, VkDevice device, + xess_context_handle_t* phContext); + +/** + * @brief Initiates pipeline build process + * This function can only be called between @ref xessVKCreateContext and + * @ref xessVKInit + * This call initiates build of Vulkan pipelines and kernel compilation + * This call can be blocking (if @p blocking set to true) or non-blocking. + * In case of non-blocking call library will wait for pipeline build on call to + * @ref xessVKInit + * If @p pipelineCache passed to this call - same pipeline library must be passed + * to @ref xessVKInit + * + * @param hContext The XeSS context handle. + * @param pipelineCache Optional pointer to pipeline library for pipeline caching. + * @param blocking Wait for kernel compilation and pipeline creation to finish or not + * @param initFlags Initialization flags. *Must* be identical to flags passed to @ref xessVKInit + */ +XESS_API xess_result_t xessVKBuildPipelines(xess_context_handle_t hContext, + VkPipelineCache pipelineCache, bool blocking, uint32_t initFlags); + +/** + * @brief Initialize XeSS VK. + * This is a blocking call that initializes XeSS and triggers internal + * resources allocation and JIT for the XeSS kernels. The user must ensure that + * any pending command lists are completed before re-initialization. When + * During initialization, XeSS can create staging buffers and copy queues to + * upload internal data. These will be destroyed at the end of initialization. + * + * @note XeSS supports devices starting from VK_RESOURCE_HEAP_TIER_1, which means + * that buffers and textures can not live in the same resource heap. + * + * @param hContext: The XeSS context handle. + * @param pInitParams: Initialization parameters. + * @return XeSS return status code. + */ +XESS_API xess_result_t xessVKInit( + xess_context_handle_t hContext, const xess_vk_init_params_t* pInitParams); + +/** + * @brief Get XeSS VK initialization parameters. + * + * @note This function will return @ref XESS_RESULT_ERROR_UNINITIALIZED if @ref xessVKInit has not been called. + * + * @param hContext: The XeSS context handle. + * @param[out] pInitParams: Returned initialization parameters. + * @return XeSS return status code. + */ +XESS_API xess_result_t xessVKGetInitParams( + xess_context_handle_t hContext, xess_vk_init_params_t* pInitParams); + +/** + * @brief Record XeSS upscaling commands into the command list. + * @param hContext: The XeSS context handle. + * @param commandBuffer: The command buffer for XeSS commands. + * @param pExecParams: Execution parameters. + * @return XeSS return status code. + */ + +XESS_API xess_result_t xessVKExecute(xess_context_handle_t hContext, + VkCommandBuffer commandBuffer, const xess_vk_execute_params_t* pExecParams); +/** @}*/ + +#ifdef __cplusplus +} +#endif + + +#endif // XESS_VK_H diff --git a/launcher-rust/src/core/graphics_options.rs b/launcher-rust/src/core/graphics_options.rs index d45e8b5abb..e12ba958ce 100644 --- a/launcher-rust/src/core/graphics_options.rs +++ b/launcher-rust/src/core/graphics_options.rs @@ -494,7 +494,7 @@ pub fn upscaler_render_size( pick("SPARTAN_UPSCALER", "upscaler", "none").as_str(), "fsr3" | "fsr4" | "fsr411" ) { - // "fsr3ui" and "taa" run on the game's own targets: no resolution patch. + // "fsr3ui", "taa" and "xess" run on the game's own targets: no resolution patch. return None; } let output = crate::core::options::resolution_size( diff --git a/launcher-rust/src/core/i18n.rs b/launcher-rust/src/core/i18n.rs index 1a7361b58a..3c1cb5117b 100644 --- a/launcher-rust/src/core/i18n.rs +++ b/launcher-rust/src/core/i18n.rs @@ -847,6 +847,16 @@ static UI_EXTRA: &[(&str, &[(&str, &str)])] = &[ ("id", "Eksperimental. Stik kanan atau mouse memutar kamera sepenuhnya di sekitar Kratos, dan Kratos bergerak ke arah pandangan kamera; L1 + stik kanan untuk menghindar. Dalam permainan, tombol Kamera bebas (bawaan G) atau ketukan R3 pada gamepad mematikan dan menyalakannya, untuk pertarungan bos; quick-time event dan potongan kamera game kembali ke kamera game. Juga tersedia di menu dalam game."), ], ), + ( + "XeSS (Intel): anti-aliasing at the game's own resolution, in place of the TAA's accumulation. Needs libxess.dll next to the game (the Windows package includes it). Texture detail and sharpening are in the in-game menu. Experimental.", + &[ + ("pt", "XeSS (Intel): anti-aliasing na resolução própria do jogo, no lugar da acumulação do TAA. Precisa do libxess.dll ao lado do jogo (o pacote do Windows já o inclui). O detalhe das texturas e o aumento de nitidez ficam no menu do jogo. Experimental."), + ("cs", "XeSS (Intel): vyhlazování hran ve vlastním rozlišení hry místo akumulace TAA. Potřebuje libxess.dll vedle hry (balíček pro Windows ho obsahuje). Detail textur a doostření jsou v herním menu. Experimentální."), + ("zh", "XeSS(Intel):在游戏自身分辨率下进行抗锯齿,取代 TAA 的累积。需要游戏旁边有 libxess.dll(Windows 安装包已包含)。纹理细节和锐化在游戏内菜单中设置。实验性功能。"), + ("es", "XeSS (Intel): antialiasing a la resolución propia del juego, en lugar de la acumulación del TAA. Necesita libxess.dll junto al juego (el paquete de Windows lo incluye). El detalle de texturas y la nitidez están en el menú del juego. Experimental."), + ("id", "XeSS (Intel): anti-aliasing pada resolusi asli gim, menggantikan akumulasi TAA. Membutuhkan libxess.dll di samping gim (paket Windows sudah menyertakannya). Detail tekstur dan penajaman ada di menu dalam gim. Eksperimental."), + ], + ), ]; fn ui_extra(lang: &str, en: &str) -> Option<&'static str> { diff --git a/launcher-rust/src/core/options.rs b/launcher-rust/src/core/options.rs index e10cfe6e74..afcf19aca9 100644 --- a/launcher-rust/src/core/options.rs +++ b/launcher-rust/src/core/options.rs @@ -160,6 +160,9 @@ pub static UPSCALERS: &[Choice] = &[ "TAA (native resolution anti-aliasing)", "TAA (нативное сглаживание)", ), + // Intel's library (libxess.dll) ships for Windows only. + #[cfg(windows)] + c("xess", "XeSS (Intel)"), ]; /// Spatial anti-aliasing of the finished frame (`anti_aliasing` in spartanport.ini): FXAA or SMAA. diff --git a/launcher-rust/src/ui/pages/graphics.rs b/launcher-rust/src/ui/pages/graphics.rs index e5d0d04446..e17b6ab7f5 100644 --- a/launcher-rust/src/ui/pages/graphics.rs +++ b/launcher-rust/src/ui/pages/graphics.rs @@ -113,6 +113,8 @@ pub fn view(state: &State) -> Element<'_, Message> { select("upscaler", UPSCALERS, &ini("upscaler"), lang), Some(&hint(if ini("upscaler") == "fsr3ui" { "FSR 3.1 (native HUD and text): the game keeps its own 1920x1080 targets, so the HUD, text and loading screens are not stretched (FSR 3.1 draws everything at 1918x1078 with Native AA). Has the port's own sharpening in the in-game menu. Experimental." + } else if ini("upscaler") == "xess" { + "XeSS (Intel): anti-aliasing at the game's own resolution, in place of the TAA's accumulation. Needs libxess.dll next to the game (the Windows package includes it). Texture detail and sharpening are in the in-game menu. Experimental." } else { "FSR 4.1 requires AMD Adrenalin 26.10.1 or newer. The log shows the active provider; fallback to FSR 3.1 is not FSR 4.1." })), diff --git a/packaging/fetch_xess.sh b/packaging/fetch_xess.sh new file mode 100755 index 0000000000..788bf096d8 --- /dev/null +++ b/packaging/fetch_xess.sh @@ -0,0 +1,26 @@ +#!/usr/bin/env bash +# Puts Intel's XeSS runtime (libxess.dll, the Intel Simplified Software License lets it be +# redistributed unmodified with its license) in out/xess, where package.sh takes it from. The +# headers the code is built with are in gpu/third_party/xess (MIT). +set -euo pipefail +cd -- "$(dirname -- "$0")/.." +commit=de0fb9c1c510661c571164e1418ceca8101dab69 +sha256=251659dd84a3e84de67c886a4186e01f3eca49b00641906fe38bb6b807e5d5b7 +target=out/xess +# A folder already there is kept only when it is complete and the library is the pinned one. +if [[ -f $target/libxess.dll && -f $target/LICENSE.txt && -f $target/third-party-programs.txt ]] && + [[ $(sha256sum "$target/libxess.dll" | cut -d' ' -f1) == "$sha256" ]]; then + echo "XeSS: $target is ready" + exit 0 +fi +work=out/intel-xess +rm -rf "$work" +git clone -q --filter=blob:none --no-checkout https://github.com/intel/xess "$work" +git -C "$work" sparse-checkout set --no-cone bin/libxess.dll LICENSE.txt third-party-programs.txt +git -C "$work" checkout -q "$commit" +[[ $(sha256sum "$work/bin/libxess.dll" | cut -d' ' -f1) == "$sha256" ]] || { echo 'XeSS: libxess.dll does not match the pinned release' >&2; exit 1; } +rm -rf "$target" +mkdir -p "$target" +cp "$work/bin/libxess.dll" "$work/LICENSE.txt" "$work/third-party-programs.txt" "$target/" +rm -rf "$work" +echo "XeSS: libxess.dll and its license in $target" diff --git a/packaging/windows/package.sh b/packaging/windows/package.sh index 452cd375dd..1ded349480 100644 --- a/packaging/windows/package.sh +++ b/packaging/windows/package.sh @@ -4,7 +4,7 @@ # spartanport-probe.exe with the MSYS2 CLANG64 DLLs it needs and the controller diagrams the runner reads. # Run from an MSYS2 CLANG64 shell after `bash build.sh` and the cargo build (for a test build, set # SPARTAN_RELEASE_TAG for cargo too: launcher-rust/README.md). No Python is packaged. -# The open FSR 4 model ships with its license in LICENSES/. +# The open FSR 4 model and Intel's XeSS library ship with their licenses in LICENSES/. set -euo pipefail cd -- "$(dirname -- "$0")/../.." source ./msys2-env.sh @@ -13,6 +13,7 @@ source ./msys2-env.sh launcher=launcher-rust/target/release/spartanport-launcher.exe [[ -f $launcher ]] || { echo 'Build the launcher first, outside MSYS2: cd launcher-rust && cargo build --release --locked (SPARTAN_RELEASE_TAG for a test build: launcher-rust/README.md)' >&2; exit 1; } bash packaging/fetch_fsr4_model.sh +bash packaging/fetch_xess.sh # The package is assembled in a fresh staging folder and zipped from there; dist/spartanport-windows # (a playable copy that may hold saves and settings) is only refreshed afterwards. @@ -42,6 +43,10 @@ mkdir -p "$dest/LICENSES" cp -r out/fsr4_shaders "$dest/fsr4_shaders" cp out/fsr4_shaders/LICENSE-FSR4-v07.txt "$dest/LICENSES/FSR4-v07-model-MIT.txt" cp gpu/third_party/fsr-vulkan/LICENSE.txt "$dest/LICENSES/FSR-Vulkan.txt" +# Intel XeSS (the menu's XeSS option): the library is loaded at run time, next to the game. +cp out/xess/libxess.dll "$dest/bin/libxess.dll" +cp out/xess/LICENSE.txt "$dest/LICENSES/XeSS-Intel-Simplified-Software-License.txt" +cp out/xess/third-party-programs.txt "$dest/LICENSES/XeSS-third-party-programs.txt" # No game files and nothing a player made (saves, shader caches built from the game's shaders, # settings, logs) may ship: stop when one is found. forbidden=$(find "$dest" -path "$dest/fsr4_shaders" -prune -o \( -iname eboot.bin -o -iname sce_module -o -iname sce_sys -o -iname savedata \ diff --git a/tests/test_upscaler_support.cpp b/tests/test_upscaler_support.cpp index 82135d3c55..c1f53f6304 100644 --- a/tests/test_upscaler_support.cpp +++ b/tests/test_upscaler_support.cpp @@ -111,6 +111,13 @@ int main() { assert(OwnSharpening(UpscalerFsr3Ui) && !OwnSharpening(UpscalerTaa)); assert(!OwnSharpening(UpscalerFsr3) && !OwnSharpening(UpscalerFsr4) && !OwnSharpening(UpscalerOff)); assert(std::string_view(UpscalerName(UpscalerFsr3Ui)) == "fsr3ui"); + assert(std::string_view(UpscalerName(UpscalerXess)) == "xess"); + assert(IsTaa(UpscalerTaa) && IsTaa(UpscalerXess) && !IsTaa(UpscalerFsr3Ui) && !IsTaa(UpscalerOff)); + assert(NeedsLivePath(UpscalerXess) && !OwnSharpening(UpscalerXess)); + // XeSS needs the device made for it: a restart when it is chosen (not when it is left). + assert(NeedsXessRestart(UpscalerXess, UpscalerTaa) && NeedsXessRestart(UpscalerXess, UpscalerOff)); + assert(!NeedsXessRestart(UpscalerXess, UpscalerXess) && !NeedsXessRestart(UpscalerTaa, UpscalerXess)); + assert(!NeedsXessRestart(UpscalerFsr3, UpscalerOff)); s.upscaler = UpscalerFsr4; const int output = s.startup_output_res; s.output_res = (output + 1) % OutputCount;