aboutsummaryrefslogtreecommitdiff
path: root/src/video_core/texture_cache/texture_cache.h
diff options
context:
space:
mode:
authornowhere02 <140357165+nowhere02@users.noreply.github.com>2026-11-02 20:59:00 -0300
committerGitHub <noreply@github.com>2026-11-02 20:59:00 -0300
commit3c499c582cfa27585b3acd4593ede3e9c9f3b5e1 (patch)
tree2f19414a5e89a067ed9c3f600217ae408e8918fd /src/video_core/texture_cache/texture_cache.h
parentaae778edce69f18513e952d3d267518b0f7d3f72 (diff)
parent9acd36eb9a291e0631346f5b17d69d0e8eb26cc5 (diff)
Merge pull request #346 from Duck912/fe-fsr31
FSR 3.1 implementation for DLSS games
Diffstat (limited to 'src/video_core/texture_cache/texture_cache.h')
-rw-r--r--src/video_core/texture_cache/texture_cache.h63
1 files changed, 57 insertions, 6 deletions
diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h
index 4929c2df44..abb22b9bfb 100644
--- a/src/video_core/texture_cache/texture_cache.h
+++ b/src/video_core/texture_cache/texture_cache.h
@@ -1098,6 +1098,7 @@ template <class P>
bool TextureCache<P>::TemporalUpscale(const Tegra::Engines::Fermi2D::Surface& dst,
const Tegra::Engines::Fermi2D::Surface& src,
const Tegra::Engines::Fermi2D::Surface& motion_vectors,
+ const Tegra::Texture::TICEntry* depth,
std::array<f32, 2> jitter, std::array<f32, 2> motion_scale) {
if constexpr (FRAMEBUFFER_BLITS) {
return false;
@@ -1123,6 +1124,12 @@ bool TextureCache<P>::TemporalUpscale(const Tegra::Engines::Fermi2D::Surface& ds
has_deleted_images = false;
const ImageId motion_id =
FindOrInsertImage(motion_info, motion_vectors.Address(), RelaxedOptions{});
+ // The depth only feeds FSR 3.1 (looked up only when FSR can run); without it the stand-in
+ // runs.
+ ImageId depth_id{};
+ if (depth && motion_id && runtime.WantsTemporalUpscaleDepth()) {
+ depth_id = FindOrInsertImage(ImageInfo(*depth), depth->Address(), RelaxedOptions{});
+ }
if (has_deleted_images || !motion_id) {
return false; // the colour and output ids may be stale; the caller blits instead
}
@@ -1131,12 +1138,47 @@ bool TextureCache<P>::TemporalUpscale(const Tegra::Engines::Fermi2D::Surface& ds
PrepareImage(src_id, false, false);
PrepareImage(motion_id, false, false);
PrepareImage(dst_id, true, false);
+ if (depth_id) {
+ PrepareImage(depth_id, false, false);
+ if (slot_images[depth_id].info.num_samples != 1 ||
+ slot_images[depth_id].info.format != PixelFormat::D32_FLOAT) {
+ depth_id = {};
+ }
+ }
for (const ImageId id : {src_id, motion_id, dst_id}) {
- if (True(slot_images[id].flags & ImageFlagBits::Rescaled) ||
- slot_images[id].info.num_samples != 1) {
+ if (slot_images[id].info.num_samples != 1) {
return false;
}
}
+ // With resolution scaling, bring the images that can follow to the same scale, as BlitImage
+ // does; the stand-in reads each image at its own size, so any left behind still work.
+ const auto rescaled = [&](ImageId id) {
+ return True(slot_images[id].flags & ImageFlagBits::Rescaled);
+ };
+ if (rescaled(src_id) || rescaled(motion_id) || rescaled(dst_id) ||
+ (depth_id && rescaled(depth_id))) {
+ for (const ImageId id : {src_id, motion_id, dst_id, depth_id}) {
+ if (id && !rescaled(id) && ImageCanRescale(slot_images[id])) {
+ ScaleUp(slot_images[id]);
+ }
+ }
+ }
+ // FSR 3.1 reads colour, motion and depth texel for texel: all at the colour's scale.
+ if (depth_id && (rescaled(depth_id) != rescaled(src_id) ||
+ rescaled(motion_id) != rescaled(src_id))) {
+ depth_id = {};
+ }
+ const Extent3D src_size = slot_images[src_id].info.size;
+ const std::array<u32, 2> render_size =
+ rescaled(src_id)
+ ? std::array{Settings::values.resolution_info.ScaleUp(src_size.width),
+ Settings::values.resolution_info.ScaleUp(src_size.height)}
+ : std::array{src_size.width, src_size.height};
+ // The jitter is in the input's guest pixels.
+ if (rescaled(src_id)) {
+ const f32 factor = Settings::values.resolution_info.up_factor;
+ jitter = {jitter[0] * factor, jitter[1] * factor};
+ }
const auto view = [&](ImageId id, const Tegra::Engines::Fermi2D::Surface& surface,
PixelFormat format) -> std::optional<std::pair<FramebufferId, ImageViewId>> {
const std::optional base = slot_images[id].TryFindBase(surface.Address());
@@ -1152,12 +1194,21 @@ bool TextureCache<P>::TemporalUpscale(const Tegra::Engines::Fermi2D::Surface& ds
if (!src_view || !motion_view || !dst_view) {
return false;
}
+ ImageViewId depth_view{};
+ if (depth_id) {
+ if (const std::optional base = slot_images[depth_id].TryFindBase(depth->Address())) {
+ const SubresourceRange range{.base = *base, .extent = {1, 1}};
+ depth_view = FindOrEmplaceImageView(
+ depth_id, ImageViewInfo(ImageViewType::e2D, PixelFormat::D32_FLOAT, range));
+ }
+ }
// After the views: creating them may reallocate the framebuffer slots.
Framebuffer* const dst_framebuffer = &slot_framebuffers[dst_view->first];
- return runtime.TemporalUpscale(dst_framebuffer, slot_image_views[dst_view->second],
- slot_image_views[src_view->second],
- slot_image_views[motion_view->second], jitter,
- motion_scale);
+ return runtime.TemporalUpscale(
+ dst_framebuffer, slot_image_views[dst_view->second], slot_image_views[src_view->second],
+ slot_image_views[motion_view->second],
+ depth_view ? &slot_image_views[depth_view] : nullptr, render_size, jitter,
+ motion_scale);
}
}