vulkan: run the engine on the game's device, without staging
Native Vulkan NGX callers now get d4r's own network for presets K, M and L, recorded straight into the caller's command buffer on the game's VkDevice with the same GameUpscaler/GameUpscalerM adapters the D3D12 path uses through vkd3d-proton. No CPU staging, CUDA evaluation or host wait. D4R_VULKAN_ENGINE=0 keeps the staging path, and anything the engine does not cover still goes there with a logged reason. - Inputs are sampled through the caller's views (SHADER_READ_ONLY_OPTIMAL, or GENERAL with D4R_VULKAN_INPUT_GENERAL=1); depth/stencil views get a depth-only view. The output must be an RGBA16F (or RGB10A2 with an RGB10 model) storage image the engine writes directly, since the resource contract gives STORAGE usage only. - Every recording ends with an event; engine objects of a released feature are destroyed once all recorded events fired, or at shutdown. - GetFeatureDeviceExtensionRequirements reports VK_KHR_cooperative_matrix and VK_EXT_shader_float8 where available. It applies d4r.ini first: games ask before NGX init, and engine_requested() would otherwise cache "off". - The engine accepts R16G16_SNORM motion vectors (Enshrouded). - Engine model loaders accept a native device (VulkanInterop::native). - Harness: D4R_HARNESS_ENGINE_DEVICE=1 (1.3 device with the engine's features), D4R_HARNESS_ALLOW_BLACK=1 (staging K's black reset frame). Harness vs the staging path (RX 9070, GE-Proton11-7, 640x360 -> 1280x720): K 99.6 % bit-identical, rest within one half-float ulp; M 52.7 dB, L 54.3 dB PSNR; dynamic, recreate and discard pass for K and M. In game, Enshrouded runs preset M on this path (docs/vulkan.md, SUPPORTED_GAMES.md). Signed-off-by: itchyfeetleech <[email protected]>
This commit is contained in:
1 parent
0e851b7f90
commit
60da7b9019
6 files changed
+508
-29
No files matched your search
@@ -3385,6 +3385,8 @@ struct VulkanInterop
|
||||
// VK_EXT_shader_float8 (vkd3d-proton enables it when the GPU has it): M's and L's engine layers are FP8
|
||||
// cooperative-matrix shaders, which RADV's compiler crashes on without it (RDNA3)
|
||||
bool float8 = false;
|
||||
// The engine runs on the game's own Vulkan device (native Vulkan NGX frontend): no vkd3d interop objects.
|
||||
bool native = false;
|
||||
PFN_vkGetPhysicalDeviceFormatProperties formatProperties = nullptr;
|
||||
PFN_vkCreateBuffer createBuffer = nullptr;
|
||||
PFN_vkDestroyBuffer destroyBuffer = nullptr;
|
||||
@@ -9332,7 +9334,7 @@ static void init_engine_backend()
|
||||
WideCharToMultiByte(CP_ACP, 0, (g_portable.dir + L"\\engine\\k").c_str(), -1, folder, sizeof(folder), nullptr, nullptr);
|
||||
directory = folder;
|
||||
}
|
||||
if (g_vk.interop == nullptr || g_vk.lifetime == nullptr || g_vk.device == VK_NULL_HANDLE || d4r::vkTable.CreateBuffer == nullptr)
|
||||
if ((!g_vk.native && (g_vk.interop == nullptr || g_vk.lifetime == nullptr)) || g_vk.device == VK_NULL_HANDLE || d4r::vkTable.CreateBuffer == nullptr)
|
||||
return;
|
||||
// A Unix path names the same file through Wine's Z: drive.
|
||||
const std::string path = directory[0] == '/' ? "Z:" + directory : directory;
|
||||
@@ -9361,7 +9363,7 @@ static void init_engine_backend_ldr()
|
||||
WideCharToMultiByte(CP_ACP, 0, (g_portable.dir + L"\\engine\\k-ldr").c_str(), -1, folder, sizeof(folder), nullptr, nullptr);
|
||||
directory = folder;
|
||||
}
|
||||
if (g_vk.interop == nullptr || g_vk.lifetime == nullptr || g_vk.device == VK_NULL_HANDLE || d4r::vkTable.CreateBuffer == nullptr)
|
||||
if ((!g_vk.native && (g_vk.interop == nullptr || g_vk.lifetime == nullptr)) || g_vk.device == VK_NULL_HANDLE || d4r::vkTable.CreateBuffer == nullptr)
|
||||
return;
|
||||
const std::string path = directory[0] == '/' ? "Z:" + directory : directory;
|
||||
try
|
||||
@@ -9457,7 +9459,7 @@ static void init_engine_backend_m_variant(bool presetL, bool ldr)
|
||||
WideCharToMultiByte(CP_ACP, 0, (g_portable.dir + sub).c_str(), -1, folder, sizeof(folder), nullptr, nullptr);
|
||||
directory = folder;
|
||||
}
|
||||
if (g_vk.interop == nullptr || g_vk.lifetime == nullptr || g_vk.device == VK_NULL_HANDLE || d4r::vkTable.CreateBuffer == nullptr)
|
||||
if ((!g_vk.native && (g_vk.interop == nullptr || g_vk.lifetime == nullptr)) || g_vk.device == VK_NULL_HANDLE || d4r::vkTable.CreateBuffer == nullptr)
|
||||
{
|
||||
logf("engine backend (%s): Vulkan interop is unavailable", name);
|
||||
return;
|
||||
@@ -10303,7 +10305,7 @@ static std::string rr_model_directory(int slot)
|
||||
static void init_engine_backend_rr(int slot)
|
||||
{
|
||||
const std::string path = rr_model_directory(slot);
|
||||
if (g_vk.interop == nullptr || g_vk.lifetime == nullptr || g_vk.device == VK_NULL_HANDLE || d4r::vkTable.CreateBuffer == nullptr)
|
||||
if ((!g_vk.native && (g_vk.interop == nullptr || g_vk.lifetime == nullptr)) || g_vk.device == VK_NULL_HANDLE || d4r::vkTable.CreateBuffer == nullptr)
|
||||
{
|
||||
logf("engine backend (Ray Reconstruction): Vulkan interop is unavailable");
|
||||
g_engineR.state[slot] = 3;
|
||||
|
||||
Reference in new issue
Block a user