mirror of
https://github.com/jamesstringer90/appsandbox.git
synced 2026-10-19 01:31:28 -05:00
Enable NVIDIA DLSS in Windows VMs
Enabled NVIDIA DLSS in supported 64-bit games running in Windows VMs on x64 Windows hosts with compatible NVIDIA GPUs.
This commit is contained in:
14 files changed
+557
-29
No files matched your search
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
@@ -625,14 +629,14 @@ BOOL gpu_append_nvidia_gl_vk_shim_share(const GpuList *gpu_list, GpuDriverShareL
|
||||
slash = wcsrchr(exe, L'\\');
|
||||
if (!slash) return FALSE;
|
||||
*slash = 0;
|
||||
if (wcslen(exe) + wcslen(L"\\resources\\nvidia\\AppSandbox-NVIDIA-VK-GL-shim32.dll") >= MAX_PATH)
|
||||
if (wcslen(exe) + wcslen(L"\\resources\\nvidia\\appsandbox-nvidia-vk-gl-shim32.dll") >= MAX_PATH)
|
||||
return FALSE;
|
||||
swprintf_s(path, MAX_PATH, L"%s\\resources\\nvidia", exe);
|
||||
swprintf_s(file, MAX_PATH, L"%s\\AppSandbox-NVIDIA-VK-GL-shim.dll", path);
|
||||
swprintf_s(file, MAX_PATH, L"%s\\appsandbox-nvidia-vk-gl-shim.dll", path);
|
||||
attributes = GetFileAttributesW(file);
|
||||
if (attributes == INVALID_FILE_ATTRIBUTES || (attributes & FILE_ATTRIBUTE_DIRECTORY)) {
|
||||
swprintf_s(path, MAX_PATH, L"%s\\nvidia", exe);
|
||||
swprintf_s(file, MAX_PATH, L"%s\\AppSandbox-NVIDIA-VK-GL-shim.dll", path);
|
||||
swprintf_s(file, MAX_PATH, L"%s\\appsandbox-nvidia-vk-gl-shim.dll", path);
|
||||
attributes = GetFileAttributesW(file);
|
||||
}
|
||||
if (attributes == INVALID_FILE_ATTRIBUTES || (attributes & FILE_ATTRIBUTE_DIRECTORY))
|
||||
@@ -642,11 +646,15 @@ BOOL gpu_append_nvidia_gl_vk_shim_share(const GpuList *gpu_list, GpuDriverShareL
|
||||
wcscpy_s(share->share_name, 128, L"AppSandbox.Nvidia");
|
||||
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");
|
||||
wcscpy_s(share->file_filter, 4096, L"appsandbox-nvidia-vk-gl-shim.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
|
||||
|
||||
@@ -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
@@ -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) {
|
||||
|
||||
+207
-11
@@ -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++;
|
||||
@@ -669,7 +838,7 @@ static BOOL provision_gl_vk_for_arch(const wchar_t *dir, const wchar_t *native_d
|
||||
{
|
||||
wchar_t manifests[32][MAX_PATH], backend[MAX_PATH], previous[MAX_PATH];
|
||||
const wchar_t *payload = machine == IMAGE_FILE_MACHINE_I386 ?
|
||||
L"AppSandbox-NVIDIA-VK-GL-shim32.dll" : L"AppSandbox-NVIDIA-VK-GL-shim.dll";
|
||||
L"appsandbox-nvidia-vk-gl-shim32.dll" : L"appsandbox-nvidia-vk-gl-shim.dll";
|
||||
const wchar_t *manifest = machine == IMAGE_FILE_MACHINE_I386 ?
|
||||
L"nv-vk32.json" : L"nv-vk64.json";
|
||||
UINT count = 0, i;
|
||||
@@ -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) &&
|
||||
@@ -753,7 +922,7 @@ BOOL gl_vk_provision_runtime(const wchar_t *dir, const wchar_t *native_dir,
|
||||
if (GetSystemWow64DirectoryW(wow, MAX_PATH)) {
|
||||
payload[0] = 0;
|
||||
if (native_dir && native_dir[0])
|
||||
swprintf_s(payload, MAX_PATH, L"%s\\AppSandbox-NVIDIA-VK-GL-shim32.dll", native_dir);
|
||||
swprintf_s(payload, MAX_PATH, L"%s\\appsandbox-nvidia-vk-gl-shim32.dll", native_dir);
|
||||
swprintf_s(runtime, MAX_PATH, L"%s\\opengl32.dll", wow);
|
||||
if (system_runtime ||
|
||||
(payload[0] && GetFileAttributesW(payload) != INVALID_FILE_ATTRIBUTES) ||
|
||||
@@ -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
|
||||
}
|
||||
@@ -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>
|
||||
@@ -48,7 +48,7 @@
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<PropertyGroup>
|
||||
<SolutionDir Condition="'$(SolutionDir)'=='' Or '$(SolutionDir)'=='*Undefined*'">$(MSBuildThisFileDirectory)..\..\</SolutionDir>
|
||||
<TargetName>AppSandbox-NVIDIA-VK-GL-shim</TargetName>
|
||||
<TargetName>appsandbox-nvidia-vk-gl-shim</TargetName>
|
||||
<NvidiaMachine>$(Platform)</NvidiaMachine>
|
||||
<NvidiaExports>shim_exports.def</NvidiaExports>
|
||||
<DisableFastUpToDateCheck>true</DisableFastUpToDateCheck>
|
||||
@@ -62,7 +62,7 @@
|
||||
<IntDir>$(SolutionDir)obj\nvidia\$(Configuration)-ARM64\</IntDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Platform)'=='Win32'">
|
||||
<TargetName>AppSandbox-NVIDIA-VK-GL-shim32</TargetName>
|
||||
<TargetName>appsandbox-nvidia-vk-gl-shim32</TargetName>
|
||||
<NvidiaMachine>X86</NvidiaMachine>
|
||||
<NvidiaExports>shim_exports_x86.def</NvidiaExports>
|
||||
<OutDir>$(SolutionDir)bin\$(Configuration)\nvidia\</OutDir>
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
EXPORTS
|
||||
nvapi_QueryInterface
|
||||
appsandbox_nvapi
|
||||
@@ -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,4 +1,4 @@
|
||||
LIBRARY AppSandbox-NVIDIA-VK-GL-shim
|
||||
LIBRARY appsandbox-nvidia-vk-gl-shim
|
||||
EXPORTS
|
||||
GlmfBeginGlsBlock=appsandbox-opengl32.GlmfBeginGlsBlock @1
|
||||
GlmfCloseMetaFile=appsandbox-opengl32.GlmfCloseMetaFile @2
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
LIBRARY AppSandbox-NVIDIA-VK-GL-shim32
|
||||
LIBRARY appsandbox-nvidia-vk-gl-shim32
|
||||
EXPORTS
|
||||
GlmfBeginGlsBlock=appsandbox-opengl32.GlmfBeginGlsBlock @1
|
||||
GlmfCloseMetaFile=appsandbox-opengl32.GlmfCloseMetaFile @2
|
||||
|
||||
@@ -407,7 +407,8 @@ $required = @(
|
||||
'headless-api\asb.py', 'headless-api\README.md', 'headless-api\examples', 'headless-api\tests'
|
||||
)
|
||||
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-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 ', ')" }
|
||||
|
||||
Reference in new issue
Block a user