Files
d4r/tools/d4r_vulkan_depth.h
T
ayo 694a7a0126 Add experimental native Vulkan DLSS frontend
Implement NGX's Vulkan API over the existing CUDA backend. Compute shaders
pack the game's sampled images into buffers shared with CUDA (device-local
memory exported through the Wine bridge), and a device event in the game's
command buffer holds its queue until the result is written back, keeping
frame age at zero. DLSS reads inputs through pitch-linear textures and its
native output kernel writes the shared buffer directly; input and
completion waits are adaptive.

Make it work across engines: shared buffers are concurrent over every
compute-capable queue family (Indiana Jones records DLSS on async compute),
depth kept in an R32F colour image is accepted under a depth aspect, and the
extension-requirement query allows a null list. Spare buffer sets are
imported on the first frame and never while a frame is pending, since an
import can block on GPU work that is waiting for us; host staging covers any
shortfall.

Fix two exit hazards. A game quitting without NGX shutdown left the GPU
waiting on an event that only a killed thread would set, resetting the ring
10 s later: the bridge now runs a shim hook before teardown and skips all
CUDA destroy/sync calls once Wine is shutting the process down. The shim's
own entry point skips CRT static destructors at process termination, where
locks held by killed threads made the exit spin forever.

Add a Vulkan DLSS harness (dynamic, recreate, discard, invalid, exit,
compute-queue and in-flight modes), staging/depth probes, ABI/config tests,
and an OptiScaler settings overlay for Vulkan games.
2026-10-09 02:57:23 -04:00

43 lines
1.7 KiB
C++

#pragma once
#include <vulkan/vulkan_core.h>
#include <cstddef>
// Image-to-buffer depth copies use the depth aspect's scalar representation,
// not the size of a packed depth+stencil texel.
constexpr size_t d4r_vk_depth_bytes(VkFormat format)
{
switch (format)
{
case VK_FORMAT_D16_UNORM:
case VK_FORMAT_D16_UNORM_S8_UINT: return 2;
case VK_FORMAT_X8_D24_UNORM_PACK32:
case VK_FORMAT_D24_UNORM_S8_UINT:
case VK_FORMAT_D32_SFLOAT:
case VK_FORMAT_D32_SFLOAT_S8_UINT: return 4;
default: return 0;
}
}
constexpr bool d4r_vk_has_stencil(VkFormat format)
{
return format == VK_FORMAT_D16_UNORM_S8_UINT || format == VK_FORMAT_D24_UNORM_S8_UINT ||
format == VK_FORMAT_D32_SFLOAT_S8_UINT;
}
constexpr VkImageAspectFlags d4r_vk_copy_aspect(VkFormat format, VkImageAspectFlags requested)
{
if (d4r_vk_depth_bytes(format))
{
const auto allowed = VK_IMAGE_ASPECT_DEPTH_BIT |
(d4r_vk_has_stencil(format) ? VK_IMAGE_ASPECT_STENCIL_BIT : 0);
return (requested & VK_IMAGE_ASPECT_DEPTH_BIT) && !(requested & ~allowed)
? static_cast<VkImageAspectFlags>(VK_IMAGE_ASPECT_DEPTH_BIT) : 0;
}
// Depth kept in a colour image (R32_SFLOAT in Indiana Jones) arrives labelled with the depth
// aspect by Streamline/OptiScaler; the caller's view is still a colour view, so sample it as one.
return requested == VK_IMAGE_ASPECT_COLOR_BIT || requested == VK_IMAGE_ASPECT_DEPTH_BIT
? static_cast<VkImageAspectFlags>(VK_IMAGE_ASPECT_COLOR_BIT) : 0;
}
constexpr VkImageAspectFlags d4r_vk_barrier_aspect(VkFormat format, VkImageAspectFlags requested)
{
return d4r_vk_has_stencil(format) ? VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT : requested;
}