Enable NVIDIA DLSS in Windows GPU VMs

This commit is contained in:
James Stringer committed 2026-09-13 19:29:20 -04:00
1 parent 62d7a0a002
commit 66095f03e7
11 files changed
+546 -18

No files matched your search

+12
View File
@@ -9,12 +9,15 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AppSandbox", "AppSandbox.vc
{1A2B3C4D-5E6F-7890-ABCD-111222333444} = {1A2B3C4D-5E6F-7890-ABCD-111222333444}
{D4E5F6A7-B8C9-0123-4567-89ABCDEF0123} = {D4E5F6A7-B8C9-0123-4567-89ABCDEF0123}
{31D821AC-8E4A-4CC7-AE30-FB0E5F431F22} = {31D821AC-8E4A-4CC7-AE30-FB0E5F431F22}
{B689C521-58F9-47E4-92FC-E110A39D51C8} = {B689C521-58F9-47E4-92FC-E110A39D51C8}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "agent", "tools\agent\agent.vcxproj", "{D4E5F6A7-B8C9-0123-4567-89ABCDEF0123}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AppSandbox-NVIDIA-VK-GL-shim", "tools\nvidia\AppSandbox-NVIDIA-VK-GL-shim.vcxproj", "{31D821AC-8E4A-4CC7-AE30-FB0E5F431F22}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AppSandbox-NVIDIA-DLSS-shim", "tools\nvidia\AppSandbox-NVIDIA-DLSS-shim.vcxproj", "{B689C521-58F9-47E4-92FC-E110A39D51C8}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "iso-patch", "tools\iso-patch\iso-patch.vcxproj", "{A1B2C3D4-5678-9ABC-DEF0-123456789ABC}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AppSandboxVDD", "tools\vdd\AppSandboxVDD.vcxproj", "{E1F2A3B4-C5D6-7890-ABCD-EF1234567890}"
@@ -46,6 +49,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AppSandboxPackage", "tools\
{D4E5F6A7-B8C9-0123-4567-89ABCDEF0123} = {D4E5F6A7-B8C9-0123-4567-89ABCDEF0123}
{31D821AC-8E4A-4CC7-AE30-FB0E5F431F22} = {31D821AC-8E4A-4CC7-AE30-FB0E5F431F22}
{A1B2C3D4-5678-9ABC-DEF0-123456789ABC} = {A1B2C3D4-5678-9ABC-DEF0-123456789ABC}
{B689C521-58F9-47E4-92FC-E110A39D51C8} = {B689C521-58F9-47E4-92FC-E110A39D51C8}
{E1F2A3B4-C5D6-7890-ABCD-EF1234567890} = {E1F2A3B4-C5D6-7890-ABCD-EF1234567890}
{F2E3D4C5-B6A7-8901-CDEF-234567890ABC} = {F2E3D4C5-B6A7-8901-CDEF-234567890ABC}
{A1B2C3D4-5678-9ABC-DEF0-AABBCCDDEEFF} = {A1B2C3D4-5678-9ABC-DEF0-AABBCCDDEEFF}
@@ -67,6 +71,14 @@ Global
Release|x64 = Release|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{B689C521-58F9-47E4-92FC-E110A39D51C8}.Debug|ARM64.ActiveCfg = Debug|ARM64
{B689C521-58F9-47E4-92FC-E110A39D51C8}.Debug|ARM64.Build.0 = Debug|ARM64
{B689C521-58F9-47E4-92FC-E110A39D51C8}.Debug|x64.ActiveCfg = Debug|x64
{B689C521-58F9-47E4-92FC-E110A39D51C8}.Debug|x64.Build.0 = Debug|x64
{B689C521-58F9-47E4-92FC-E110A39D51C8}.Release|ARM64.ActiveCfg = Release|ARM64
{B689C521-58F9-47E4-92FC-E110A39D51C8}.Release|ARM64.Build.0 = Release|ARM64
{B689C521-58F9-47E4-92FC-E110A39D51C8}.Release|x64.ActiveCfg = Release|x64
{B689C521-58F9-47E4-92FC-E110A39D51C8}.Release|x64.Build.0 = Release|x64
{31D821AC-8E4A-4CC7-AE30-FB0E5F431F22}.Debug|ARM64.ActiveCfg = Debug|ARM64
{31D821AC-8E4A-4CC7-AE30-FB0E5F431F22}.Debug|ARM64.Build.0 = Debug|ARM64
{31D821AC-8E4A-4CC7-AE30-FB0E5F431F22}.Debug|x64.ActiveCfg = Debug|x64
+2 -2
View File
@@ -1052,7 +1052,7 @@ static DWORD WINAPI start_vm_thread(LPVOID param)
else if (_wcsicmp(args->config.os_type, L"Windows") == 0) {
gpu_append_amd_gl_vk_driver_shares(&g_gpu_list, &args->config.gpu_shares);
gpu_append_nvidia_drs_share(&g_gpu_list, &args->config.gpu_shares);
gpu_append_nvidia_gl_vk_shim_share(&g_gpu_list, &args->config.gpu_shares);
gpu_append_nvidia_graphics_shim_share(&g_gpu_list, &args->config.gpu_shares);
prepare_gl_layers_share(&args->config.gpu_shares);
}
}
@@ -3210,7 +3210,7 @@ ASB_API HRESULT asb_vm_create(const AsbVmConfig *config)
else if (_wcsicmp(cfg.os_type, L"Windows") == 0) {
gpu_append_amd_gl_vk_driver_shares(&g_gpu_list, &cfg.gpu_shares);
gpu_append_nvidia_drs_share(&g_gpu_list, &cfg.gpu_shares);
gpu_append_nvidia_gl_vk_shim_share(&g_gpu_list, &cfg.gpu_shares);
gpu_append_nvidia_graphics_shim_share(&g_gpu_list, &cfg.gpu_shares);
prepare_gl_layers_share(&cfg.gpu_shares);
}
}
+13 -5
View File
@@ -600,9 +600,13 @@ BOOL gpu_append_nvidia_drs_share(const GpuList *gpu_list, GpuDriverShareList *li
return TRUE;
}
BOOL gpu_append_nvidia_gl_vk_shim_share(const GpuList *gpu_list, GpuDriverShareList *list)
BOOL gpu_append_nvidia_graphics_shim_share(const GpuList *gpu_list, GpuDriverShareList *list)
{
#if defined(_M_X64)
static const wchar_t *const additional[] = {
L"AppSandbox-NVIDIA-VK-GL-shim32.dll",
L"AppSandbox-NVIDIA-DLSS-shim.dll"
};
wchar_t exe[MAX_PATH], path[MAX_PATH], file[MAX_PATH], *slash;
GpuDriverShare *share;
DWORD length, attributes;
@@ -643,10 +647,14 @@ BOOL gpu_append_nvidia_gl_vk_shim_share(const GpuList *gpu_list, GpuDriverShareL
wcscpy_s(share->host_path, MAX_PATH, path);
wcscpy_s(share->guest_path, MAX_PATH, L"C:\\Windows\\AppSandbox\\nvidia");
wcscpy_s(share->file_filter, 4096, L"AppSandbox-NVIDIA-VK-GL-shim.dll");
swprintf_s(file, MAX_PATH, L"%s\\AppSandbox-NVIDIA-VK-GL-shim32.dll", path);
attributes = GetFileAttributesW(file);
if (attributes != INVALID_FILE_ATTRIBUTES && !(attributes & FILE_ATTRIBUTE_DIRECTORY))
wcscat_s(share->file_filter, 4096, L";AppSandbox-NVIDIA-VK-GL-shim32.dll");
for (i = 0; i < ARRAYSIZE(additional); i++) {
swprintf_s(file, MAX_PATH, L"%s\\%s", path, additional[i]);
attributes = GetFileAttributesW(file);
if (attributes != INVALID_FILE_ATTRIBUTES && !(attributes & FILE_ATTRIBUTE_DIRECTORY)) {
wcscat_s(share->file_filter, 4096, L";");
wcscat_s(share->file_filter, 4096, additional[i]);
}
}
list->count++;
return TRUE;
#else
+1 -1
View File
@@ -53,7 +53,7 @@ BOOL gpu_get_driver_shares(GpuList *gpu_list, GpuDriverShareList *out);
/* Windows guests only; callers gate on guest OS and GPU mode. */
BOOL gpu_append_amd_gl_vk_driver_shares(const GpuList *gpu_list, GpuDriverShareList *list);
BOOL gpu_append_nvidia_drs_share(const GpuList *gpu_list, GpuDriverShareList *list);
BOOL gpu_append_nvidia_gl_vk_shim_share(const GpuList *gpu_list, GpuDriverShareList *list);
BOOL gpu_append_nvidia_graphics_shim_share(const GpuList *gpu_list, GpuDriverShareList *list);
/* Append the host's lxss\lib directory as a synthetic Plan9 share entry
(name "AppSandbox.HostLxssLib") to a share list. Linux guests need
+4 -1
View File
@@ -613,7 +613,8 @@ static DWORD WINAPI gpu_copy_thread(LPVOID param)
rc = P9_ERR_IO;
} else if (strcmp(si->share_name, "AppSandbox.Nvidia") == 0) {
const P9CopyOptions options = {
FALSE, NULL, "AppSandbox-NVIDIA-VK-GL-shim.dll;AppSandbox-NVIDIA-VK-GL-shim32.dll"
FALSE, NULL, "AppSandbox-NVIDIA-VK-GL-shim.dll;AppSandbox-NVIDIA-VK-GL-shim32.dll;"
"AppSandbox-NVIDIA-DLSS-shim.dll"
};
rc = p9_copy_share_ex(50001, si->share_name, dest_wide,
si->filter[0] ? si->filter : NULL,
@@ -657,6 +658,8 @@ static DWORD WINAPI gpu_copy_thread(LPVOID param)
if (failed_shares == 0 && (gl_dir[0] || native_dir[0] || gpu_prefers_system_opengl()))
gl_provision(gl_dir, native_dir);
if (failed_shares == 0 && !nvidia_dlss_provision(native_dir))
failed_shares++;
/* Send final result to host */
if (failed_shares == 0) {
+205 -9
View File
@@ -7,6 +7,8 @@
#include <wincrypt.h>
#include <mscat.h>
#include <aclapi.h>
#include <winioctl.h>
#include <winternl.h>
#pragma warning(pop)
#include <stdio.h>
#include <stdlib.h>
@@ -290,7 +292,7 @@ static BOOL grant_system_file_control(const wchar_t *path)
}
#if defined(_M_X64)
static BOOL validate_opengl_dll(const wchar_t *path, WORD machine, BOOL native)
static BOOL validate_dll_export(const wchar_t *path, WORD machine, const char *required_export)
{
HMODULE module = LoadLibraryExW(path, NULL, LOAD_LIBRARY_AS_IMAGE_RESOURCE);
BYTE *base;
@@ -298,6 +300,7 @@ static BOOL validate_opengl_dll(const wchar_t *path, WORD machine, BOOL native)
IMAGE_DATA_DIRECTORY directory;
IMAGE_EXPORT_DIRECTORY *exports;
DWORD *names, i, size;
size_t export_length = required_export ? strlen(required_export) + 1 : 0;
BOOL found = FALSE;
if (!module) return FALSE;
@@ -314,7 +317,7 @@ static BOOL validate_opengl_dll(const wchar_t *path, WORD machine, BOOL native)
size = nt32->OptionalHeader.SizeOfImage;
directory = nt32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];
} else goto done;
if (!native) { found = TRUE; goto done; }
if (!required_export) { found = TRUE; goto done; }
if (!directory.VirtualAddress || size < sizeof(*exports) ||
directory.VirtualAddress > size - sizeof(*exports)) goto done;
exports = (IMAGE_EXPORT_DIRECTORY *)(base + directory.VirtualAddress);
@@ -322,8 +325,8 @@ static BOOL validate_opengl_dll(const wchar_t *path, WORD machine, BOOL native)
exports->AddressOfNames > size - exports->NumberOfNames * sizeof(DWORD)) goto done;
names = (DWORD *)(base + exports->AddressOfNames);
for (i = 0; i < exports->NumberOfNames; i++) {
if (names[i] <= size - sizeof("appsandbox_nvidia") &&
!memcmp(base + names[i], "appsandbox_nvidia", sizeof("appsandbox_nvidia"))) {
if (export_length <= size && names[i] <= size - export_length &&
!memcmp(base + names[i], required_export, export_length)) {
found = TRUE;
break;
}
@@ -333,8 +336,13 @@ done:
return found;
}
static UINT find_nvidia_vulkan_manifests(wchar_t paths[32][MAX_PATH], const wchar_t *sys,
const wchar_t *manifest)
static BOOL validate_opengl_dll(const wchar_t *path, WORD machine, BOOL native)
{
return validate_dll_export(path, machine, native ? "appsandbox_nvidia" : NULL);
}
static UINT find_nvidia_driver_files(wchar_t paths[32][MAX_PATH], const wchar_t *sys,
const wchar_t *filename)
{
typedef NTSTATUS (APIENTRY *EnumAdaptersFn)(const D3DKMT_ENUMADAPTERS2 *);
typedef NTSTATUS (APIENTRY *QueryAdapterFn)(const D3DKMT_QUERYADAPTERINFO *);
@@ -401,11 +409,11 @@ static UINT find_nvidia_vulkan_manifests(wchar_t paths[32][MAX_PATH], const wcha
if (!slash || _wcsicmp(slash + 1, L"nvoglv64.dll") ||
GetFileAttributesW(driver) == INVALID_FILE_ATTRIBUTES) goto next;
*slash = 0;
if (!_wcsicmp(manifest, L"nv-vk32.json")) {
if (!_wcsicmp(filename, L"nv-vk32.json")) {
swprintf_s(path, MAX_PATH, L"%s\\nvoglv32.dll", driver);
if (GetFileAttributesW(path) == INVALID_FILE_ATTRIBUTES) goto next;
}
swprintf_s(path, MAX_PATH, L"%s\\%s", driver, manifest);
swprintf_s(path, MAX_PATH, L"%s\\%s", driver, filename);
if (GetFileAttributesW(path) == INVALID_FILE_ATTRIBUTES) goto next;
for (j = 0; j < count; j++)
if (!_wcsicmp(paths[j], path)) break;
@@ -426,6 +434,167 @@ done:
return count;
}
typedef struct {
DWORD tag;
USHORT data_length, reserved;
USHORT substitute_offset, substitute_length, print_offset, print_length;
wchar_t paths[(MAX_PATH + 4) * 2];
} NvidiaNgxJunction;
static HANDLE create_ngx_junction_directory(const wchar_t *path, BOOL *created)
{
typedef NTSTATUS (NTAPI *CreateFileFn)(PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES,
PIO_STATUS_BLOCK, PLARGE_INTEGER, ULONG, ULONG, ULONG, ULONG, PVOID, ULONG);
CreateFileFn create;
HANDLE directory = INVALID_HANDLE_VALUE, token;
TOKEN_PRIVILEGES privileges = { 1 }, previous = { 0 };
DWORD previous_size = sizeof(previous), error;
wchar_t native[MAX_PATH + 4];
UNICODE_STRING name;
OBJECT_ATTRIBUTES attributes = { sizeof(attributes) };
IO_STATUS_BLOCK status;
*created = CreateDirectoryW(path, NULL);
if (*created) {
directory = CreateFileW(path, GENERIC_WRITE | DELETE,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, NULL);
if (directory != INVALID_HANDLE_VALUE) return directory;
}
error = GetLastError();
if (error != ERROR_ACCESS_DENIED) return INVALID_HANDLE_VALUE;
create = (CreateFileFn)GetProcAddress(GetModuleHandleW(L"ntdll.dll"), "NtCreateFile");
if (!create || swprintf_s(native, ARRAYSIZE(native), L"\\??\\%s", path) < 0 ||
!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
&token)) return INVALID_HANDLE_VALUE;
if (!LookupPrivilegeValueW(NULL, SE_RESTORE_NAME, &privileges.Privileges[0].Luid)) {
CloseHandle(token);
return INVALID_HANDLE_VALUE;
}
privileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
SetLastError(ERROR_SUCCESS);
if (AdjustTokenPrivileges(token, FALSE, &privileges, sizeof(previous),
&previous, &previous_size) && GetLastError() == ERROR_SUCCESS) {
name.Buffer = native;
name.Length = (USHORT)(wcslen(native) * sizeof(wchar_t));
name.MaximumLength = (USHORT)(name.Length + sizeof(wchar_t));
attributes.ObjectName = &name;
attributes.Attributes = OBJ_CASE_INSENSITIVE;
if (create(&directory, GENERIC_WRITE | DELETE | SYNCHRONIZE, &attributes, &status,
NULL, FILE_ATTRIBUTE_DIRECTORY, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
*created ? FILE_OPEN : FILE_CREATE,
FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT |
FILE_OPEN_FOR_BACKUP_INTENT | FILE_OPEN_REPARSE_POINT, NULL, 0) >= 0)
*created = TRUE;
else
directory = INVALID_HANDLE_VALUE;
}
if (previous.PrivilegeCount)
AdjustTokenPrivileges(token, FALSE, &previous, 0, NULL, NULL);
CloseHandle(token);
return directory;
}
static BOOL nvidia_ngx_junction(const wchar_t *sys, const wchar_t *package)
{
wchar_t host_prefix[MAX_PATH], driver_prefix[MAX_PATH], target[MAX_PATH];
wchar_t link[MAX_PATH], file[MAX_PATH], native[MAX_PATH + 4];
const wchar_t *leaf;
NvidiaNgxJunction reparse = { 0 };
HANDLE directory;
DWORD attributes, bytes;
size_t target_length, native_length;
BOOL created = FALSE, result;
if (swprintf_s(host_prefix, MAX_PATH, L"%s\\HostDriverStore\\FileRepository\\", sys) < 0 ||
swprintf_s(driver_prefix, MAX_PATH, L"%s\\DriverStore\\FileRepository\\", sys) < 0)
return FALSE;
if (!_wcsnicmp(package, host_prefix, wcslen(host_prefix)))
leaf = package + wcslen(host_prefix);
else if (!_wcsnicmp(package, driver_prefix, wcslen(driver_prefix)))
leaf = package + wcslen(driver_prefix);
else return FALSE;
if (!leaf[0] || !wcscmp(leaf, L".") || !wcscmp(leaf, L"..") || wcspbrk(leaf, L"\\/:") ||
swprintf_s(target, MAX_PATH, L"%s%s", host_prefix, leaf) < 0 ||
swprintf_s(link, MAX_PATH, L"%s%s", driver_prefix, leaf) < 0 ||
swprintf_s(native, ARRAYSIZE(native), L"\\??\\%s", target) < 0)
return FALSE;
attributes = GetFileAttributesW(link);
if (attributes != INVALID_FILE_ATTRIBUTES && !(attributes & FILE_ATTRIBUTE_REPARSE_POINT)) {
wchar_t host_file[MAX_PATH];
if (!(attributes & FILE_ATTRIBUTE_DIRECTORY) ||
swprintf_s(file, MAX_PATH, L"%s\\_nvngx.dll", link) < 0 ||
swprintf_s(host_file, MAX_PATH, L"%s\\_nvngx.dll", target) < 0 ||
!validate_dll_export(file, IMAGE_FILE_MACHINE_AMD64, NULL)) return FALSE;
return GetFileAttributesW(host_file) == INVALID_FILE_ATTRIBUTES || files_equal(file, host_file);
}
if (swprintf_s(file, MAX_PATH, L"%s\\_nvngx.dll", target) < 0 ||
!validate_dll_export(file, IMAGE_FILE_MACHINE_AMD64, NULL)) return FALSE;
native_length = wcslen(native) * sizeof(wchar_t);
target_length = wcslen(target) * sizeof(wchar_t);
if (attributes != INVALID_FILE_ATTRIBUTES) {
directory = CreateFileW(link, 0, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, NULL);
if (directory == INVALID_HANDLE_VALUE) return FALSE;
result = DeviceIoControl(directory, FSCTL_GET_REPARSE_POINT, NULL, 0,
&reparse, sizeof(reparse), &bytes, NULL);
CloseHandle(directory);
return result && bytes >= (DWORD)FIELD_OFFSET(NvidiaNgxJunction, paths) &&
reparse.tag == IO_REPARSE_TAG_MOUNT_POINT &&
reparse.substitute_offset % sizeof(wchar_t) == 0 &&
reparse.substitute_length == native_length &&
(DWORD)reparse.substitute_offset + reparse.substitute_length <=
bytes - (DWORD)FIELD_OFFSET(NvidiaNgxJunction, paths) &&
!_wcsnicmp(reparse.paths + reparse.substitute_offset / sizeof(wchar_t),
native, native_length / sizeof(wchar_t));
}
directory = create_ngx_junction_directory(link, &created);
if (directory == INVALID_HANDLE_VALUE) {
if (created) RemoveDirectoryW(link);
return FALSE;
}
reparse.tag = IO_REPARSE_TAG_MOUNT_POINT;
reparse.substitute_length = (USHORT)native_length;
reparse.print_offset = (USHORT)(native_length + sizeof(wchar_t));
reparse.print_length = (USHORT)target_length;
reparse.data_length = (USHORT)(8 + native_length + target_length + 2 * sizeof(wchar_t));
memcpy(reparse.paths, native, native_length + sizeof(wchar_t));
memcpy((BYTE *)reparse.paths + reparse.print_offset, target, target_length + sizeof(wchar_t));
result = DeviceIoControl(directory, FSCTL_SET_REPARSE_POINT, &reparse,
reparse.data_length + 8, NULL, 0, &bytes, NULL);
if (!result) {
FILE_DISPOSITION_INFO disposition = { TRUE };
SetFileInformationByHandle(directory, FileDispositionInfo, &disposition, sizeof(disposition));
}
CloseHandle(directory);
return result;
}
static BOOL provision_nvapi(const wchar_t *native_dir, const wchar_t *sys,
wchar_t packages[32][MAX_PATH], UINT count)
{
wchar_t payload[MAX_PATH], original[MAX_PATH], other[MAX_PATH], backup[MAX_PATH], runtime[MAX_PATH];
UINT i;
if (!count || swprintf_s(payload, MAX_PATH, L"%s\\AppSandbox-NVIDIA-DLSS-shim.dll", native_dir) < 0 ||
swprintf_s(original, MAX_PATH, L"%s\\nvapi64.dll", packages[0]) < 0 ||
swprintf_s(runtime, MAX_PATH, L"%s\\nvapi64.dll", sys) < 0 ||
swprintf_s(backup, MAX_PATH, L"%s\\appsandbox-nvapi64.dll", sys) < 0)
return FALSE;
if (!validate_dll_export(payload, IMAGE_FILE_MACHINE_AMD64, "appsandbox_nvapi") ||
!validate_dll_export(payload, IMAGE_FILE_MACHINE_AMD64, "nvapi_QueryInterface") ||
!validate_dll_export(original, IMAGE_FILE_MACHINE_AMD64, "nvapi_QueryInterface") ||
validate_dll_export(original, IMAGE_FILE_MACHINE_AMD64, "appsandbox_nvapi")) return FALSE;
for (i = 1; i < count; i++) {
if (swprintf_s(other, MAX_PATH, L"%s\\nvapi64.dll", packages[i]) < 0 ||
!files_equal(original, other)) return FALSE;
}
if (!replace_file(original, backup)) return FALSE;
return files_equal(payload, runtime) ||
((GetFileAttributesW(runtime) == INVALID_FILE_ATTRIBUTES || grant_system_file_control(runtime)) &&
replace_file(payload, runtime));
}
static const char *json_skip_whitespace(const char *p)
{
while (*p == ' ' || *p == '\r' || *p == '\n' || *p == '\t') p++;
@@ -677,7 +846,7 @@ static BOOL provision_gl_vk_for_arch(const wchar_t *dir, const wchar_t *native_d
if (native_dir && native_dir[0])
swprintf_s(src, MAX_PATH, L"%s\\%s", native_dir, payload);
if (src[0] && validate_opengl_dll(src, machine, TRUE) &&
(count = find_nvidia_vulkan_manifests(manifests, driver_sys, manifest)) != 0 &&
(count = find_nvidia_driver_files(manifests, driver_sys, manifest)) != 0 &&
is_microsoft_opengl(backup) && validate_opengl_dll(backup, machine, FALSE)) {
swprintf_s(backend, MAX_PATH, L"%s\\appsandbox-opengl32.dll", sys);
if (replace_file(backup, backend) &&
@@ -769,3 +938,30 @@ BOOL gl_vk_provision_runtime(const wchar_t *dir, const wchar_t *native_dir,
native_runtime);
#endif
}
BOOL nvidia_dlss_provision(const wchar_t *native_dir)
{
#if defined(_M_X64)
wchar_t sys[MAX_PATH], payload[MAX_PATH], packages[32][MAX_PATH];
UINT count, i, length;
if (!native_dir || !native_dir[0]) return TRUE;
if (swprintf_s(payload, MAX_PATH, L"%s\\AppSandbox-NVIDIA-DLSS-shim.dll", native_dir) < 0)
return FALSE;
if (GetFileAttributesW(payload) == INVALID_FILE_ATTRIBUTES) return TRUE;
length = GetSystemDirectoryW(sys, MAX_PATH);
if (!length || length >= MAX_PATH) return FALSE;
count = find_nvidia_driver_files(packages, sys, L"_nvngx.dll");
if (!count) return TRUE;
for (i = 0; i < count; i++) {
wchar_t *slash = wcsrchr(packages[i], L'\\');
if (!slash) return FALSE;
*slash = 0;
if (!nvidia_ngx_junction(sys, packages[i])) return FALSE;
}
return provision_nvapi(native_dir, sys, packages, count);
#else
(void)native_dir;
return TRUE;
#endif
}
+1
View File
@@ -6,5 +6,6 @@
BOOL gpu_prefers_system_opengl(void);
BOOL gl_vk_provision_runtime(const wchar_t *dir, const wchar_t *native_dir,
const wchar_t *sys, BOOL *native_runtime);
BOOL nvidia_dlss_provision(const wchar_t *native_dir);
#endif
@@ -0,0 +1,102 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|ARM64">
<Configuration>Debug</Configuration>
<Platform>ARM64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|ARM64">
<Configuration>Release</Configuration>
<Platform>ARM64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>17.0</VCProjectVersion>
<ProjectGuid>{B689C521-58F9-47E4-92FC-E110A39D51C8}</ProjectGuid>
<RootNamespace>nvidia_dlss</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration">
<UseDebugLibraries>true</UseDebugLibraries>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)'=='Release'" Label="Configuration">
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<PropertyGroup>
<SolutionDir Condition="'$(SolutionDir)'=='' Or '$(SolutionDir)'=='*Undefined*'">$(MSBuildThisFileDirectory)..\..\</SolutionDir>
<TargetName>AppSandbox-NVIDIA-DLSS-shim</TargetName>
<DisableFastUpToDateCheck>true</DisableFastUpToDateCheck>
</PropertyGroup>
<PropertyGroup Condition="'$(Platform)'=='x64'">
<OutDir>$(SolutionDir)bin\$(Configuration)\nvidia\</OutDir>
<IntDir>$(SolutionDir)obj\nvidia-dlss\$(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Platform)'=='ARM64'">
<OutDir>$(SolutionDir)bin\$(Configuration)-ARM64\nvidia\</OutDir>
<IntDir>$(SolutionDir)obj\nvidia-dlss\$(Configuration)-ARM64\</IntDir>
</PropertyGroup>
<ItemDefinitionGroup>
<ClCompile>
<WarningLevel>Level4</WarningLevel>
<PreprocessorDefinitions>UNICODE;_UNICODE;WIN32_LEAN_AND_MEAN;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
<ConformanceMode>true</ConformanceMode>
<CompileAs>CompileAsC</CompileAs>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<ModuleDefinitionFile>nvapi_exports.def</ModuleDefinitionFile>
<AdditionalDependencies>dxgi.lib;dxguid.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)'=='Debug'">
<ClCompile>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)'=='Release'">
<ClCompile>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
</ClCompile>
<Link>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="nvapi_shim.c" />
</ItemGroup>
<ItemGroup>
<None Include="nvapi_exports.def" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<Target Name="StageNvapiRuntime" AfterTargets="Build" Condition="'$(Platform)'=='x64'">
<Copy SourceFiles="$(TargetPath)" DestinationFolder="$(OutDir)..\resources\nvidia\" SkipUnchangedFiles="true" />
</Target>
<Target Name="CleanNvapiRuntime" AfterTargets="Clean" Condition="'$(Platform)'=='x64'">
<Delete Files="$(OutDir)..\resources\nvidia\$(TargetFileName)" />
</Target>
</Project>
+3
View File
@@ -0,0 +1,3 @@
EXPORTS
nvapi_QueryInterface
appsandbox_nvapi
+202
View File
@@ -0,0 +1,202 @@
#define COBJMACROS
#include <windows.h>
#include <string.h>
typedef void *(__cdecl *QueryInterfaceFn)(UINT id);
static INIT_ONCE g_once = INIT_ONCE_STATIC_INIT;
static QueryInterfaceFn g_query;
#if defined(_M_X64)
#pragma warning(push)
#pragma warning(disable: 4201)
#include <dxgi.h>
#include <d3d12.h>
#pragma warning(pop)
#define NVAPI_OK 0
#define NVAPI_NOT_SUPPORTED (-104)
#define NVAPI_MAX_PHYSICAL_GPUS 64
#define NVAPI_LOGICAL_GPU_INFO 0x842b066e
#define NVAPI_PHYSICAL_GPU_ADAPTER 0x0ff07fde
#define NVAPI_D3D11_FATBIN 0x6086bd93
#define NVAPI_D3D12_FATBIN 0x70c07832
typedef struct {
UINT version;
void *adapter_id;
UINT physical_count;
void *physical_gpus[NVAPI_MAX_PHYSICAL_GPUS];
UINT reserved[8];
} LogicalGpuInfo;
typedef int (__cdecl *EnumPhysicalFn)(void **gpus, UINT *count);
typedef int (__cdecl *LogicalInfoFn)(void *gpu, LogicalGpuInfo *info);
typedef int (__cdecl *PhysicalAdapterFn)(void *gpu, void *luid);
typedef int (__cdecl *FatbinFn)(IUnknown *device, BYTE *supported);
static LogicalInfoFn g_logical_info;
static PhysicalAdapterFn g_physical_adapter;
static FatbinFn g_d3d11_fatbin;
static FatbinFn g_d3d12_fatbin;
static SRWLOCK g_identity_lock = SRWLOCK_INIT;
static LUID g_device_luid;
static BOOL g_have_device_luid;
static BOOL find_nvidia_adapter(const LUID *wanted, LUID *luid)
{
IDXGIFactory1 *factory = NULL;
BOOL found = FALSE;
UINT i;
if (FAILED(CreateDXGIFactory1(&IID_IDXGIFactory1, (void **)&factory))) return FALSE;
for (i = 0; !found; i++) {
IDXGIAdapter1 *adapter = NULL;
DXGI_ADAPTER_DESC1 desc;
HRESULT result;
if (IDXGIFactory1_EnumAdapters1(factory, i, &adapter) != S_OK) break;
result = IDXGIAdapter1_GetDesc1(adapter, &desc);
IDXGIAdapter1_Release(adapter);
if (FAILED(result) || desc.VendorId != 0x10de ||
(desc.Flags & DXGI_ADAPTER_FLAG_SOFTWARE)) continue;
if (wanted && (wanted->LowPart != desc.AdapterLuid.LowPart ||
wanted->HighPart != desc.AdapterLuid.HighPart)) continue;
if (luid) *luid = desc.AdapterLuid;
found = TRUE;
}
IDXGIFactory1_Release(factory);
return found;
}
static void capture_device_identity(IUnknown *device)
{
IDXGIDevice *dxgi = NULL;
ID3D12Device *d3d12 = NULL;
LUID luid = {0};
BOOL found = FALSE;
if (!device) return;
if (SUCCEEDED(IUnknown_QueryInterface(device, &IID_IDXGIDevice, (void **)&dxgi))) {
IDXGIAdapter *adapter = NULL;
if (SUCCEEDED(IDXGIDevice_GetAdapter(dxgi, &adapter))) {
DXGI_ADAPTER_DESC desc;
if (SUCCEEDED(IDXGIAdapter_GetDesc(adapter, &desc))) {
luid = desc.AdapterLuid;
found = TRUE;
}
IDXGIAdapter_Release(adapter);
}
IDXGIDevice_Release(dxgi);
} else if (SUCCEEDED(IUnknown_QueryInterface(device, &IID_ID3D12Device, (void **)&d3d12))) {
ID3D12Device_GetAdapterLuid(d3d12, &luid);
ID3D12Device_Release(d3d12);
found = TRUE;
}
if (!found || !find_nvidia_adapter(&luid, NULL)) return;
AcquireSRWLockExclusive(&g_identity_lock);
g_device_luid = luid;
g_have_device_luid = TRUE;
ReleaseSRWLockExclusive(&g_identity_lock);
}
static BOOL current_device_luid(LUID *luid)
{
BOOL found;
AcquireSRWLockShared(&g_identity_lock);
found = g_have_device_luid;
if (found) *luid = g_device_luid;
ReleaseSRWLockShared(&g_identity_lock);
return found || find_nvidia_adapter(NULL, luid);
}
static int __cdecl logical_gpu_info_hook(void *gpu, LogicalGpuInfo *info)
{
int result = g_logical_info ? g_logical_info(gpu, info) : NVAPI_NOT_SUPPORTED;
EnumPhysicalFn enumerate;
void *physical[NVAPI_MAX_PHYSICAL_GPUS] = {0};
UINT count = 0;
LUID luid;
if (result == NVAPI_OK || !info ||
(info->version & 0xffff) < sizeof(*info)) return result;
enumerate = (EnumPhysicalFn)g_query(0xe5ac921f);
if (!enumerate || enumerate(physical, &count) != NVAPI_OK || !count ||
!current_device_luid(&luid)) return result;
info->physical_count = 1;
info->physical_gpus[0] = physical[0];
if (info->adapter_id) memcpy(info->adapter_id, &luid, sizeof(luid));
return NVAPI_OK;
}
static int __cdecl physical_gpu_adapter_hook(void *gpu, void *adapter_id)
{
int result = g_physical_adapter ? g_physical_adapter(gpu, adapter_id) : NVAPI_NOT_SUPPORTED;
LUID luid;
if (result == NVAPI_OK || !adapter_id || !current_device_luid(&luid)) return result;
memcpy(adapter_id, &luid, sizeof(luid));
return NVAPI_OK;
}
static int __cdecl d3d11_fatbin_hook(IUnknown *device, BYTE *supported)
{
capture_device_identity(device);
return g_d3d11_fatbin ? g_d3d11_fatbin(device, supported) : NVAPI_NOT_SUPPORTED;
}
static int __cdecl d3d12_fatbin_hook(IUnknown *device, BYTE *supported)
{
capture_device_identity(device);
return g_d3d12_fatbin ? g_d3d12_fatbin(device, supported) : NVAPI_NOT_SUPPORTED;
}
#endif
static BOOL CALLBACK load_nvapi(PINIT_ONCE once, PVOID parameter, PVOID *context)
{
HMODULE module;
(void)once;
(void)parameter;
(void)context;
module = LoadLibraryExW(L"appsandbox-nvapi64.dll", NULL, LOAD_LIBRARY_SEARCH_SYSTEM32);
if (!module) return TRUE;
if (GetProcAddress(module, "appsandbox_nvapi")) {
FreeLibrary(module);
return TRUE;
}
g_query = (QueryInterfaceFn)GetProcAddress(module, "nvapi_QueryInterface");
return TRUE;
}
void *__cdecl nvapi_QueryInterface(UINT id)
{
void *original;
InitOnceExecuteOnce(&g_once, load_nvapi, NULL, NULL);
if (!g_query) return NULL;
original = g_query(id);
#if defined(_M_X64)
switch (id) {
case NVAPI_LOGICAL_GPU_INFO:
g_logical_info = (LogicalInfoFn)original;
return (void *)logical_gpu_info_hook;
case NVAPI_PHYSICAL_GPU_ADAPTER:
g_physical_adapter = (PhysicalAdapterFn)original;
return (void *)physical_gpu_adapter_hook;
case NVAPI_D3D11_FATBIN:
g_d3d11_fatbin = (FatbinFn)original;
return (void *)d3d11_fatbin_hook;
case NVAPI_D3D12_FATBIN:
g_d3d12_fatbin = (FatbinFn)original;
return (void *)d3d12_fatbin_hook;
}
#endif
return original;
}
DWORD __cdecl appsandbox_nvapi(void)
{
return 0x41534201;
}
+1
View File
@@ -408,6 +408,7 @@ $required = @(
)
if ($Platform -eq 'x64') {
$required += 'resources\nvidia\AppSandbox-NVIDIA-VK-GL-shim.dll', 'resources\nvidia\AppSandbox-NVIDIA-VK-GL-shim32.dll'
$required += 'resources\nvidia\AppSandbox-NVIDIA-DLSS-shim.dll'
}
$missing = @($required | Where-Object { -not (Test-Path (Join-Path $stage $_)) })
if ($missing.Count) { throw "Refusing to package - missing expected artifacts: $($missing -join ', ')" }