diff options
| author | MrPurple666 <antoniosacramento666usa@gmail.com> | 2025-04-12 03:20:42 -0300 |
|---|---|---|
| committer | MrPurple666 <antoniosacramento666usa@gmail.com> | 2025-04-12 22:54:32 -0300 |
| commit | 2a793d610d2a245fec7d3e4a6a100e0b26418cc1 (patch) | |
| tree | fbce826fe0feff2c475cbcafec8f6be628d02d3a /src | |
| parent | 38737f26e51bba30d96772b00df6a34d1a28ab7b (diff) | |
RenderVulkan Experiments: DO-NOT-MERGE: Introduce functionality to frame interpolation
The functionality acts much more like a real-time downscale since the FSR1 used by Yuzu is not compatible with a real interpolation and is just upscale and downscale.
Diffstat (limited to 'src')
| -rw-r--r-- | src/video_core/renderer_vulkan/renderer_vulkan.cpp | 65 |
1 files changed, 61 insertions, 4 deletions
diff --git a/src/video_core/renderer_vulkan/renderer_vulkan.cpp b/src/video_core/renderer_vulkan/renderer_vulkan.cpp index 6948682ef1..d5058fdd89 100644 --- a/src/video_core/renderer_vulkan/renderer_vulkan.cpp +++ b/src/video_core/renderer_vulkan/renderer_vulkan.cpp @@ -172,13 +172,70 @@ class BooleanSetting { } void RendererVulkan::InterpolateFrames(Frame* prev_frame, Frame* interpolated_frame) { - if (prev_frame && interpolated_frame) { - *interpolated_frame = std::move(*prev_frame); // Use move assignment to avoid copy issues + if (!prev_frame || !interpolated_frame || !prev_frame->image || !interpolated_frame->image) { + return; + } + + const auto& framebuffer_layout = render_window.GetFramebufferLayout(); + // Fixed aggressive downscale (50%) + VkExtent2D dst_extent{ + .width = framebuffer_layout.width / 2, + .height = framebuffer_layout.height / 2 + }; + + // Check if we need to recreate the destination frame + bool needs_recreation = true; + if (interpolated_frame->image_view) { + // Get image extent from framebuffer layout since we can't query it directly + needs_recreation = (framebuffer_layout.width / 2 != dst_extent.width) || + (framebuffer_layout.height / 2 != dst_extent.height); + } - // TODO: Implement actual interpolation logic here + if (needs_recreation) { + interpolated_frame->image = CreateWrappedImage(memory_allocator, dst_extent, swapchain.GetImageViewFormat()); + interpolated_frame->image_view = CreateWrappedImageView(device, interpolated_frame->image, swapchain.GetImageViewFormat()); + interpolated_frame->framebuffer = blit_swapchain.CreateFramebuffer( + Layout::FramebufferLayout{dst_extent.width, dst_extent.height}, + *interpolated_frame->image_view, + swapchain.GetImageViewFormat()); } + + scheduler.RequestOutsideRenderPassOperationContext(); + scheduler.Record([&](vk::CommandBuffer cmdbuf) { + // Transition images to transfer layouts + TransitionImageLayout(cmdbuf, *prev_frame->image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); + TransitionImageLayout(cmdbuf, *interpolated_frame->image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); + + // Perform the downscale blit + VkImageBlit blit_region{}; + blit_region.srcSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1}; + blit_region.srcOffsets[0] = {0, 0, 0}; + blit_region.srcOffsets[1] = { + static_cast<int32_t>(framebuffer_layout.width), + static_cast<int32_t>(framebuffer_layout.height), + 1 + }; + blit_region.dstSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1}; + blit_region.dstOffsets[0] = {0, 0, 0}; + blit_region.dstOffsets[1] = { + static_cast<int32_t>(dst_extent.width), + static_cast<int32_t>(dst_extent.height), + 1 + }; + + // Using the wrapper's BlitImage with proper parameters + cmdbuf.BlitImage( + *prev_frame->image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, + *interpolated_frame->image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + blit_region, VK_FILTER_LINEAR + ); + + // Transition back to general layout + TransitionImageLayout(cmdbuf, *prev_frame->image, VK_IMAGE_LAYOUT_GENERAL); + TransitionImageLayout(cmdbuf, *interpolated_frame->image, VK_IMAGE_LAYOUT_GENERAL); + }); } - #endif +#endif void RendererVulkan::Composite(std::span<const Tegra::FramebufferConfig> framebuffers) { #ifdef __ANDROID__ |
