#define WIN32_LEAN_AND_MEAN #include #include #include "nvsdk_ngx.h" #include "ngx_param_abi_probe_shared.h" #include #include #include #include #include #include #include #include extern "C" void d4r_ngx_parameter_set_ull(void*, const char*, unsigned long long); extern "C" void d4r_ngx_parameter_set_float(void*, const char*, float); extern "C" void d4r_ngx_parameter_set_double(void*, const char*, double); extern "C" void d4r_ngx_parameter_set_uint(void*, const char*, unsigned int); extern "C" void d4r_ngx_parameter_set_int(void*, const char*, int); extern "C" void d4r_ngx_parameter_set_void(void*, const char*, void*); extern "C" unsigned int d4r_ngx_parameter_get_ull(void*, const char*, unsigned long long*); extern "C" unsigned int d4r_ngx_parameter_get_float(void*, const char*, float*); extern "C" unsigned int d4r_ngx_parameter_get_double(void*, const char*, double*); extern "C" unsigned int d4r_ngx_parameter_get_uint(void*, const char*, unsigned int*); extern "C" unsigned int d4r_ngx_parameter_get_int(void*, const char*, int*); extern "C" unsigned int d4r_ngx_parameter_get_void(void*, const char*, void**); extern "C" unsigned int d4r_ngx_parameter_float_roundtrip(void*, const char*, float, float*); extern "C" unsigned int d4r_ngx_parameter_uint_roundtrip(void*, const char*, unsigned int, unsigned int*); extern "C" unsigned int d4r_ngx_parameter_proxy_size(); extern "C" void d4r_ngx_parameter_proxy_construct(void*, void*); extern "C" unsigned int d4r_ngx_parameter_proxy_count(const void*); extern "C" unsigned int d4r_ngx_parameter_proxy_dropped(const void*); extern "C" int d4r_ngx_parameter_proxy_copy_record( const void*, unsigned int, D4rNgxParamLogRecord*); template Target copy_function_pointer(Source source) { static_assert(sizeof(Target) == sizeof(Source), "function pointer sizes differ"); Target target{}; std::memcpy(&target, &source, sizeof(target)); return target; } template Function load_export(HMODULE module, const char* name) { FARPROC raw = GetProcAddress(module, name); return raw ? copy_function_pointer(raw) : nullptr; } static std::wstring utf8_to_wide(const char* input) { const int required = MultiByteToWideChar(CP_UTF8, 0, input, -1, nullptr, 0); if (required <= 1) return {}; std::wstring output(static_cast(required), L'\0'); MultiByteToWideChar(CP_UTF8, 0, input, -1, output.data(), required); output.resize(static_cast(required - 1)); return output; } static const char* ngx_result_name(NVSDK_NGX_Result result) { switch (result) { case NVSDK_NGX_Result_Success: return "Success"; case NVSDK_NGX_Result_FAIL_FeatureNotSupported: return "FeatureNotSupported"; case NVSDK_NGX_Result_FAIL_PlatformError: return "PlatformError"; case NVSDK_NGX_Result_FAIL_InvalidParameter: return "InvalidParameter"; case NVSDK_NGX_Result_FAIL_NotInitialized: return "NotInitialized"; case NVSDK_NGX_Result_FAIL_UnableToInitializeFeature: return "UnableToInitializeFeature"; case NVSDK_NGX_Result_FAIL_OutOfDate: return "OutOfDate"; default: return "Other"; } } static void print_ngx_result(const char* stage, NVSDK_NGX_Result result) { std::printf("%s: result=0x%08x (%s)\n", stage, static_cast(result), ngx_result_name(result)); } using D4rCudaDevicePtr = unsigned long long; using D4rCudaArray = void*; using D4rCudaTextureObject = unsigned long long; using D4rCuMemAlloc = int(WINAPI*)(D4rCudaDevicePtr*, size_t); using D4rCuMemFree = int(WINAPI*)(D4rCudaDevicePtr); using D4rCuMemcpyHtoDAsync = int(WINAPI*)(D4rCudaDevicePtr, const void*, size_t, void*); using D4rCuMemcpyDtoH = int(WINAPI*)(void*, D4rCudaDevicePtr, size_t); using D4rCuCtxSynchronize = int(WINAPI*)(); struct D4rCudaArrayDescriptor { size_t Width; size_t Height; uint32_t Format; uint32_t NumChannels; }; static_assert(sizeof(D4rCudaArrayDescriptor) == 24); struct D4rCudaArray3DDescriptor { size_t Width; size_t Height; size_t Depth; uint32_t Format; uint32_t NumChannels; uint32_t Flags; }; static_assert(sizeof(D4rCudaArray3DDescriptor) == 40); struct D4rCudaMemcpy2D { size_t srcXInBytes; size_t srcY; uint32_t srcMemoryType; uint32_t srcAlignment; const void* srcHost; D4rCudaDevicePtr srcDevice; D4rCudaArray srcArray; size_t srcPitch; size_t dstXInBytes; size_t dstY; uint32_t dstMemoryType; uint32_t dstAlignment; void* dstHost; D4rCudaDevicePtr dstDevice; D4rCudaArray dstArray; size_t dstPitch; size_t WidthInBytes; size_t Height; }; static_assert(sizeof(D4rCudaMemcpy2D) == 128); struct D4rCudaResourceDesc { uint32_t resType; uint32_t alignment; union { struct { D4rCudaArray hArray; } array; int reserved[32]; } res; uint32_t flags; uint32_t reserved; }; static_assert(sizeof(D4rCudaResourceDesc) == 144); struct D4rCudaTextureDesc { uint32_t addressMode[3]; uint32_t filterMode; uint32_t flags; uint32_t maxAnisotropy; uint32_t mipmapFilterMode; float mipmapLevelBias; float minMipmapLevelClamp; float maxMipmapLevelClamp; float borderColor[4]; int32_t reserved[12]; }; static_assert(sizeof(D4rCudaTextureDesc) == 104); using D4rCuArrayCreate = int(WINAPI*)(D4rCudaArray*, const D4rCudaArrayDescriptor*); using D4rCuArray3DCreate = int(WINAPI*)(D4rCudaArray*, const D4rCudaArray3DDescriptor*); using D4rCuArrayDestroy = int(WINAPI*)(D4rCudaArray); using D4rCuMemcpy2D = int(WINAPI*)(const D4rCudaMemcpy2D*); using D4rCuTexObjectCreate = int(WINAPI*)(D4rCudaTextureObject*, const D4rCudaResourceDesc*, const D4rCudaTextureDesc*, const void*); using D4rCuTexObjectDestroy = int(WINAPI*)(D4rCudaTextureObject); using D4rCuTexObjectGetResourceDesc = int(WINAPI*)(D4rCudaResourceDesc*, D4rCudaTextureObject); using D4rCudaSurfaceObject = unsigned long long; using D4rCuSurfObjectCreate = int(WINAPI*)(D4rCudaSurfaceObject*, const D4rCudaResourceDesc*); using D4rCuSurfObjectDestroy = int(WINAPI*)(D4rCudaSurfaceObject); using D4rCuSurfObjectGetResourceDesc = int(WINAPI*)(D4rCudaResourceDesc*, D4rCudaSurfaceObject); using D4rNgxGetParameters = NVSDK_NGX_Result(NVSDK_CONV*)(NVSDK_NGX_Parameter**); struct NgxParameterApi { PFN_NVSDK_NGX_Parameter_SetULL setULL = nullptr; PFN_NVSDK_NGX_Parameter_SetF setF = nullptr; PFN_NVSDK_NGX_Parameter_SetD setD = nullptr; PFN_NVSDK_NGX_Parameter_SetUI setUI = nullptr; PFN_NVSDK_NGX_Parameter_SetI setI = nullptr; PFN_NVSDK_NGX_Parameter_SetVoidPointer setVoidPointer = nullptr; PFN_NVSDK_NGX_Parameter_GetULL getULL = nullptr; PFN_NVSDK_NGX_Parameter_GetF getF = nullptr; PFN_NVSDK_NGX_Parameter_GetD getD = nullptr; PFN_NVSDK_NGX_Parameter_GetUI getUI = nullptr; PFN_NVSDK_NGX_Parameter_GetI getI = nullptr; PFN_NVSDK_NGX_Parameter_GetVoidPointer getVoidPointer = nullptr; }; static NgxParameterApi g_ngxParameterApi; static void ngx_set(NVSDK_NGX_Parameter* parameters, const char* name, unsigned long long value) { if (g_ngxParameterApi.setULL != nullptr) g_ngxParameterApi.setULL(parameters, name, value); else d4r_ngx_parameter_set_ull(parameters, name, value); } static void ngx_set(NVSDK_NGX_Parameter* parameters, const char* name, float value) { if (g_ngxParameterApi.setF != nullptr) g_ngxParameterApi.setF(parameters, name, value); else d4r_ngx_parameter_set_float(parameters, name, value); } static void ngx_set(NVSDK_NGX_Parameter* parameters, const char* name, double value) { if (g_ngxParameterApi.setD != nullptr) g_ngxParameterApi.setD(parameters, name, value); else d4r_ngx_parameter_set_double(parameters, name, value); } static void ngx_set(NVSDK_NGX_Parameter* parameters, const char* name, unsigned int value) { if (g_ngxParameterApi.setUI != nullptr) g_ngxParameterApi.setUI(parameters, name, value); else d4r_ngx_parameter_set_uint(parameters, name, value); } static void ngx_set(NVSDK_NGX_Parameter* parameters, const char* name, int value) { if (g_ngxParameterApi.setI != nullptr) g_ngxParameterApi.setI(parameters, name, value); else d4r_ngx_parameter_set_int(parameters, name, value); } static void ngx_set(NVSDK_NGX_Parameter* parameters, const char* name, void* value) { if (g_ngxParameterApi.setVoidPointer != nullptr) g_ngxParameterApi.setVoidPointer(parameters, name, value); else d4r_ngx_parameter_set_void(parameters, name, value); } static NVSDK_NGX_Result ngx_get_ull(NVSDK_NGX_Parameter* parameters, const char* name, unsigned long long* value) { if (g_ngxParameterApi.getULL != nullptr) return g_ngxParameterApi.getULL(parameters, name, value); return static_cast(d4r_ngx_parameter_get_ull(parameters, name, value)); } static NVSDK_NGX_Result ngx_get_float(NVSDK_NGX_Parameter* parameters, const char* name, float* value) { if (g_ngxParameterApi.getF != nullptr) return g_ngxParameterApi.getF(parameters, name, value); return static_cast(d4r_ngx_parameter_get_float(parameters, name, value)); } static NVSDK_NGX_Result ngx_get_double(NVSDK_NGX_Parameter* parameters, const char* name, double* value) { if (g_ngxParameterApi.getD != nullptr) return g_ngxParameterApi.getD(parameters, name, value); return static_cast(d4r_ngx_parameter_get_double(parameters, name, value)); } static NVSDK_NGX_Result ngx_get_ui(NVSDK_NGX_Parameter* parameters, const char* name, unsigned int* value) { if (g_ngxParameterApi.getUI != nullptr) return g_ngxParameterApi.getUI(parameters, name, value); return static_cast(d4r_ngx_parameter_get_uint(parameters, name, value)); } static NVSDK_NGX_Result ngx_get_i(NVSDK_NGX_Parameter* parameters, const char* name, int* value) { if (g_ngxParameterApi.getI != nullptr) return g_ngxParameterApi.getI(parameters, name, value); return static_cast(d4r_ngx_parameter_get_int(parameters, name, value)); } static NVSDK_NGX_Result ngx_get_void(NVSDK_NGX_Parameter* parameters, const char* name, void** value) { if (g_ngxParameterApi.getVoidPointer != nullptr) return g_ngxParameterApi.getVoidPointer(parameters, name, value); return static_cast(d4r_ngx_parameter_get_void(parameters, name, value)); } static void* ngx_pointer_from_handle(uint64_t handle) { return reinterpret_cast(static_cast(handle)); } static float half_to_float(uint16_t half) { const uint32_t sign = static_cast(half & 0x8000u) << 16; const uint32_t exponent = (half >> 10) & 0x1fu; const uint32_t mantissa = half & 0x03ffu; uint32_t bits = 0; if (exponent == 0) { if (mantissa == 0) bits = sign; else { const float subnormal = std::ldexp(static_cast(mantissa), -24); return (sign != 0 ? -subnormal : subnormal); } } else if (exponent == 0x1fu) bits = sign | 0x7f800000u | (mantissa << 13); else bits = sign | ((exponent + 112u) << 23) | (mantissa << 13); float value = 0.0f; std::memcpy(&value, &bits, sizeof(value)); return value; } static bool write_file(const std::wstring& path, const void* data, size_t bytes) { HANDLE file = CreateFileW(path.c_str(), GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr); if (file == INVALID_HANDLE_VALUE) return false; const auto* source = static_cast(data); size_t offset = 0; bool success = true; while (offset < bytes) { const DWORD chunk = static_cast(std::min(bytes - offset, 0x7fffffffu)); DWORD written = 0; if (!WriteFile(file, source + offset, chunk, &written, nullptr) || written != chunk) { success = false; break; } offset += written; } CloseHandle(file); return success; } static void evaluate_synthetic_frame(NVSDK_NGX_Parameter* parameters, const NVSDK_NGX_Handle* featureHandle, decltype(&NVSDK_NGX_CUDA_EvaluateFeature) evaluateFeature, decltype(&NVSDK_NGX_CUDA_EvaluateFeature_C) evaluateFeatureC, bool useCEvaluate, const std::wstring& appData, D4rCudaDevicePtr scratchDevice, size_t scratchBytes) { constexpr unsigned int inputWidth = 640; constexpr unsigned int inputHeight = 360; constexpr unsigned int outputWidth = 1280; constexpr unsigned int outputHeight = 720; const size_t inputPixels = static_cast(inputWidth) * inputHeight; const size_t outputPixels = static_cast(outputWidth) * outputHeight; const size_t colorBytes = inputPixels * 4 * sizeof(uint16_t); const size_t depthBytes = inputPixels * sizeof(float); const size_t motionBytes = inputPixels * 2 * sizeof(float); const size_t outputBytes = outputPixels * 4 * sizeof(uint16_t); HMODULE cuda = LoadLibraryA("nvcuda.dll"); if (cuda == nullptr) { std::printf("Synthetic DLSS evaluate: LoadLibraryA(nvcuda.dll) failed: %lu\n", GetLastError()); return; } const auto alloc = load_export(cuda, "cuMemAlloc"); const auto free = load_export(cuda, "cuMemFree"); const auto copyHtoD = load_export(cuda, "cuMemcpyHtoDAsync"); const auto copyDtoH = load_export(cuda, "cuMemcpyDtoH"); const auto synchronize = load_export(cuda, "cuCtxSynchronize"); const auto arrayCreate = load_export(cuda, "cuArrayCreate"); const auto arrayDestroy = load_export(cuda, "cuArrayDestroy"); const auto copy2D = load_export(cuda, "cuMemcpy2D"); const auto textureCreate = load_export(cuda, "cuTexObjectCreate"); const auto textureDestroy = load_export(cuda, "cuTexObjectDestroy"); const auto textureGetResourceDesc = load_export( cuda, "cuTexObjectGetResourceDesc"); const auto array3DCreate = load_export(cuda, "cuArray3DCreate"); const auto surfaceCreate = load_export(cuda, "cuSurfObjectCreate"); const auto surfaceDestroy = load_export(cuda, "cuSurfObjectDestroy"); const auto surfaceGetResourceDesc = load_export( cuda, "cuSurfObjectGetResourceDesc"); const char* resourceMode = std::getenv("D4R_NGX_RESOURCE_MODE"); const bool textureMode = resourceMode != nullptr && (std::strcmp(resourceMode, "texture") == 0 || std::strcmp(resourceMode, "surface") == 0); const bool surfaceMode = resourceMode != nullptr && std::strcmp(resourceMode, "surface") == 0; if (alloc == nullptr || free == nullptr || copyHtoD == nullptr || copyDtoH == nullptr || synchronize == nullptr) { std::printf("Synthetic DLSS evaluate: CUDA driver bridge is missing a required memory export\n"); FreeLibrary(cuda); return; } if (textureMode && (arrayCreate == nullptr || arrayDestroy == nullptr || copy2D == nullptr || textureCreate == nullptr || textureDestroy == nullptr)) { std::printf("Synthetic DLSS evaluate: CUDA array/texture bridge exports are missing\n"); FreeLibrary(cuda); return; } if (surfaceMode && (array3DCreate == nullptr || surfaceCreate == nullptr || surfaceDestroy == nullptr)) { std::printf("Synthetic DLSS evaluate: CUDA surface bridge exports are missing\n"); FreeLibrary(cuda); return; } std::vector color(inputPixels * 4); std::vector depth(inputPixels, 0.5f); std::vector motion(inputPixels * 2, 0.0f); std::vector output(outputPixels * 4, 0); constexpr uint16_t dark = 0x2a66u; // half 0.05 constexpr uint16_t mid = 0x3400u; // half 0.25 constexpr uint16_t bright = 0x3a66u; // half 0.8 constexpr uint16_t white = 0x3c00u; // half 1.0 for (unsigned int y = 0; y < inputHeight; ++y) { for (unsigned int x = 0; x < inputWidth; ++x) { const size_t pixel = static_cast(y) * inputWidth + x; const bool fence = (x % 24u == 0u) || (y % 24u == 0u); const bool checker = (((x / 4u) + (y / 4u)) & 1u) != 0; color[pixel * 4 + 0] = fence ? white : (checker ? mid : dark); color[pixel * 4 + 1] = ((x + y) % 32u < 2u) ? bright : (checker ? dark : mid); color[pixel * 4 + 2] = (((x / 8u) ^ (y / 8u)) & 1u) ? bright : dark; color[pixel * 4 + 3] = white; } } D4rCudaArray colorArray = nullptr; D4rCudaArray depthArray = nullptr; D4rCudaArray motionArray = nullptr; D4rCudaArray exposureArray = nullptr; D4rCudaArray outputArray = nullptr; D4rCudaTextureObject colorTexture = 0; D4rCudaTextureObject depthTexture = 0; D4rCudaTextureObject motionTexture = 0; D4rCudaTextureObject exposureTexture = 0; D4rCudaSurfaceObject outputSurface = 0; int textureSetupResult = 0; if (textureMode) { auto create_and_upload_array = [&](const char* label, size_t width, size_t height, uint32_t format, uint32_t channels, const void* source, size_t pitch, D4rCudaArray& array) { const D4rCudaArrayDescriptor descriptor{width, height, format, channels}; int result = arrayCreate(&array, &descriptor); std::printf("Synthetic DLSS eval cuArrayCreate(%s): result=%d array=%p\n", label, result, array); if (result != 0) return result; D4rCudaMemcpy2D copy{}; copy.srcMemoryType = 1; // CUDA_MEMORYTYPE_HOST copy.srcHost = source; copy.srcPitch = pitch; copy.dstMemoryType = 3; // CUDA_MEMORYTYPE_ARRAY copy.dstArray = array; copy.WidthInBytes = pitch; copy.Height = height; result = copy2D(©); std::printf("Synthetic DLSS eval array upload(%s): result=%d bytesPerRow=%zu\n", label, result, pitch); return result; }; auto create_texture = [&](const char* label, D4rCudaArray array, uint32_t filterMode, D4rCudaTextureObject& texture) { D4rCudaResourceDesc resource{}; resource.resType = 0; // CUDA_RESOURCE_TYPE_ARRAY resource.res.array.hArray = array; D4rCudaTextureDesc sampler{}; sampler.addressMode[0] = 1; // clamp sampler.addressMode[1] = 1; sampler.addressMode[2] = 0; sampler.filterMode = filterMode; sampler.flags = 2; // CU_TRSF_NORMALIZED_COORDINATES, matching NGX-created textures sampler.maxAnisotropy = 0; int result = textureCreate(&texture, &resource, &sampler, nullptr); std::printf("Synthetic DLSS eval cuTexObjectCreate(%s): result=%d object=0x%llx\n", label, result, texture); return result; }; const std::vector motionHalf(inputPixels * 2, 0); const float exposureValue = 1.0f; textureSetupResult = create_and_upload_array( "Color RGBA16F", inputWidth, inputHeight, 16, 4, color.data(), inputWidth * 4 * sizeof(uint16_t), colorArray); if (textureSetupResult == 0) textureSetupResult = create_and_upload_array( "Depth R32F", inputWidth, inputHeight, 32, 1, depth.data(), inputWidth * sizeof(float), depthArray); if (textureSetupResult == 0) textureSetupResult = create_and_upload_array( "Motion RG16F", inputWidth, inputHeight, 16, 2, motionHalf.data(), inputWidth * 2 * sizeof(uint16_t), motionArray); if (textureSetupResult == 0) textureSetupResult = create_and_upload_array( "Exposure R32F", 1, 1, 32, 1, &exposureValue, sizeof(exposureValue), exposureArray); if (textureSetupResult == 0) textureSetupResult = create_texture("Color", colorArray, 1, colorTexture); if (textureSetupResult == 0) textureSetupResult = create_texture("Depth", depthArray, 0, depthTexture); if (textureSetupResult == 0) textureSetupResult = create_texture("MotionVectors", motionArray, 0, motionTexture); if (textureSetupResult == 0) textureSetupResult = create_texture("Exposure", exposureArray, 0, exposureTexture); if (textureSetupResult == 0 && surfaceMode) { const D4rCudaArray3DDescriptor descriptor{ outputWidth, outputHeight, 0, 16, 4, 2u // RGBA16F with CUDA_ARRAY3D_SURFACE_LDST }; textureSetupResult = array3DCreate(&outputArray, &descriptor); std::printf("Synthetic DLSS eval cuArray3DCreate(Output RGBA16F): result=%d array=%p\n", textureSetupResult, outputArray); if (textureSetupResult == 0) { D4rCudaResourceDesc resource{}; resource.resType = 0; // CUDA_RESOURCE_TYPE_ARRAY resource.res.array.hArray = outputArray; textureSetupResult = surfaceCreate(&outputSurface, &resource); std::printf("Synthetic DLSS eval cuSurfObjectCreate(Output): result=%d object=0x%llx\n", textureSetupResult, outputSurface); } } if (textureSetupResult == 0 && textureMode) { D4rCudaResourceDesc descriptor{}; const int descriptorResult = textureGetResourceDesc != nullptr ? textureGetResourceDesc(&descriptor, colorTexture) : 801; std::printf("Synthetic DLSS cuTexObjectGetResourceDesc(Color): result=%d type=%u array=%p\n", descriptorResult, descriptor.resType, descriptor.res.array.hArray); } if (textureSetupResult == 0 && surfaceMode) { D4rCudaResourceDesc descriptor{}; const int descriptorResult = surfaceGetResourceDesc != nullptr ? surfaceGetResourceDesc(&descriptor, outputSurface) : 801; std::printf("Synthetic DLSS cuSurfObjectGetResourceDesc(Output): result=%d type=%u array=%p\n", descriptorResult, descriptor.resType, descriptor.res.array.hArray); } std::printf("Synthetic DLSS texture resource setup: CUDA result=%d\n", textureSetupResult); } D4rCudaDevicePtr colorDevice = 0; D4rCudaDevicePtr depthDevice = 0; D4rCudaDevicePtr motionDevice = 0; D4rCudaDevicePtr outputDevice = 0; auto allocate_and_upload = [&](const char* label, D4rCudaDevicePtr& device, const void* source, size_t bytes) { int result = alloc(&device, bytes); std::printf("Synthetic DLSS eval cuMemAlloc(%s): result=%d ptr=0x%llx bytes=%zu\n", label, result, device, bytes); if (result == 0) result = copyHtoD(device, source, bytes, nullptr); std::printf("Synthetic DLSS eval upload(%s): result=%d\n", label, result); return result; }; int cudaResult = textureMode ? textureSetupResult : 0; if (cudaResult == 0 && !textureMode) cudaResult = allocate_and_upload("Color", colorDevice, color.data(), colorBytes); if (cudaResult == 0 && !textureMode) cudaResult = allocate_and_upload("Depth", depthDevice, depth.data(), depthBytes); if (cudaResult == 0 && !textureMode) cudaResult = allocate_and_upload("MotionVectors", motionDevice, motion.data(), motionBytes); if (cudaResult == 0 && !surfaceMode) cudaResult = allocate_and_upload("Output", outputDevice, output.data(), outputBytes); if (cudaResult == 0) cudaResult = synchronize(); std::printf("Synthetic DLSS eval input upload/sync: CUDA result=%d\n", cudaResult); if (cudaResult == 0) { if (scratchDevice != 0 && scratchBytes != 0) { ngx_set(parameters, NVSDK_NGX_Parameter_Scratch, ngx_pointer_from_handle(scratchDevice)); ngx_set(parameters, NVSDK_NGX_Parameter_Scratch_SizeInBytes, static_cast(scratchBytes)); } ngx_set(parameters, NVSDK_NGX_EParameter_EvaluationNode, 0u); ngx_set(parameters, NVSDK_NGX_Parameter_Width, inputWidth); ngx_set(parameters, NVSDK_NGX_Parameter_Height, inputHeight); ngx_set(parameters, NVSDK_NGX_Parameter_OutWidth, outputWidth); ngx_set(parameters, NVSDK_NGX_Parameter_OutHeight, outputHeight); ngx_set(parameters, NVSDK_NGX_Parameter_PerfQualityValue, static_cast(NVSDK_NGX_PerfQuality_Value_MaxQuality)); ngx_set(parameters, NVSDK_NGX_Parameter_DLSS_Feature_Create_Flags, static_cast(NVSDK_NGX_DLSS_Feature_Flags_None)); ngx_set(parameters, NVSDK_NGX_Parameter_DLSS_Enable_Output_Subrects, 0); void* colorResource = textureMode ? static_cast(&colorTexture) : static_cast(&colorDevice); void* depthResource = textureMode ? static_cast(&depthTexture) : static_cast(&depthDevice); void* motionResource = textureMode ? static_cast(&motionTexture) : static_cast(&motionDevice); void* exposureResource = textureMode ? static_cast(&exposureTexture) : static_cast(nullptr); void* outputResource = surfaceMode ? static_cast(&outputSurface) : static_cast(&outputDevice); ngx_set(parameters, NVSDK_NGX_Parameter_Color, colorResource); ngx_set(parameters, NVSDK_NGX_Parameter_Color_Format, static_cast(NVSDK_NGX_Buffer_Format_RGBA16F)); ngx_set(parameters, NVSDK_NGX_Parameter_Color_SizeInBytes, static_cast(colorBytes)); ngx_set(parameters, NVSDK_NGX_Parameter_Output, outputResource); if (!surfaceMode) { ngx_set(parameters, NVSDK_NGX_Parameter_Output_Format, static_cast(NVSDK_NGX_Buffer_Format_RGBA16F)); ngx_set(parameters, NVSDK_NGX_Parameter_Output_SizeInBytes, static_cast(outputBytes)); } ngx_set(parameters, NVSDK_NGX_Parameter_Depth, depthResource); ngx_set(parameters, NVSDK_NGX_Parameter_MotionVectors, motionResource); ngx_set(parameters, NVSDK_NGX_Parameter_Sharpness, 0.0f); ngx_set(parameters, NVSDK_NGX_Parameter_Jitter_Offset_X, 0.0f); ngx_set(parameters, NVSDK_NGX_Parameter_Jitter_Offset_Y, 0.0f); ngx_set(parameters, NVSDK_NGX_Parameter_MV_Scale_X, 1.0f); ngx_set(parameters, NVSDK_NGX_Parameter_MV_Scale_Y, 1.0f); ngx_set(parameters, NVSDK_NGX_Parameter_Reset, 1); ngx_set(parameters, NVSDK_NGX_Parameter_TransparencyMask, static_cast(nullptr)); ngx_set(parameters, NVSDK_NGX_Parameter_ExposureTexture, exposureResource); ngx_set(parameters, NVSDK_NGX_Parameter_DLSS_Input_Bias_Current_Color_Mask, static_cast(nullptr)); ngx_set(parameters, NVSDK_NGX_Parameter_GBuffer_Albedo, static_cast(nullptr)); ngx_set(parameters, NVSDK_NGX_Parameter_GBuffer_Roughness, static_cast(nullptr)); ngx_set(parameters, NVSDK_NGX_Parameter_GBuffer_Metallic, static_cast(nullptr)); ngx_set(parameters, NVSDK_NGX_Parameter_GBuffer_Specular, static_cast(nullptr)); ngx_set(parameters, NVSDK_NGX_Parameter_GBuffer_Subsurface, static_cast(nullptr)); ngx_set(parameters, NVSDK_NGX_Parameter_GBuffer_Normals, static_cast(nullptr)); ngx_set(parameters, NVSDK_NGX_Parameter_GBuffer_ShadingModelId, static_cast(nullptr)); ngx_set(parameters, NVSDK_NGX_Parameter_GBuffer_MaterialId, static_cast(nullptr)); ngx_set(parameters, NVSDK_NGX_Parameter_GBuffer_Atrrib_8, static_cast(nullptr)); ngx_set(parameters, NVSDK_NGX_Parameter_GBuffer_Atrrib_9, static_cast(nullptr)); ngx_set(parameters, NVSDK_NGX_Parameter_GBuffer_Atrrib_10, static_cast(nullptr)); ngx_set(parameters, NVSDK_NGX_Parameter_GBuffer_Atrrib_11, static_cast(nullptr)); ngx_set(parameters, NVSDK_NGX_Parameter_GBuffer_Atrrib_12, static_cast(nullptr)); ngx_set(parameters, NVSDK_NGX_Parameter_GBuffer_Atrrib_13, static_cast(nullptr)); ngx_set(parameters, NVSDK_NGX_Parameter_GBuffer_Atrrib_14, static_cast(nullptr)); ngx_set(parameters, NVSDK_NGX_Parameter_GBuffer_Atrrib_15, static_cast(nullptr)); ngx_set(parameters, NVSDK_NGX_Parameter_TonemapperType, 0u); ngx_set(parameters, NVSDK_NGX_Parameter_MotionVectors3D, static_cast(nullptr)); ngx_set(parameters, NVSDK_NGX_Parameter_IsParticleMask, static_cast(nullptr)); ngx_set(parameters, NVSDK_NGX_Parameter_AnimatedTextureMask, static_cast(nullptr)); ngx_set(parameters, NVSDK_NGX_Parameter_DepthHighRes, static_cast(nullptr)); ngx_set(parameters, NVSDK_NGX_Parameter_Position_ViewSpace, static_cast(nullptr)); ngx_set(parameters, NVSDK_NGX_Parameter_FrameTimeDeltaInMsec, 16.666667f); ngx_set(parameters, NVSDK_NGX_Parameter_RayTracingHitDistance, static_cast(nullptr)); ngx_set(parameters, NVSDK_NGX_Parameter_MotionVectorsReflection, static_cast(nullptr)); ngx_set(parameters, NVSDK_NGX_Parameter_DLSS_Input_Color_Subrect_Base_X, 0u); ngx_set(parameters, NVSDK_NGX_Parameter_DLSS_Input_Color_Subrect_Base_Y, 0u); ngx_set(parameters, NVSDK_NGX_Parameter_DLSS_Input_Depth_Subrect_Base_X, 0u); ngx_set(parameters, NVSDK_NGX_Parameter_DLSS_Input_Depth_Subrect_Base_Y, 0u); ngx_set(parameters, NVSDK_NGX_Parameter_DLSS_Input_MV_SubrectBase_X, 0u); ngx_set(parameters, NVSDK_NGX_Parameter_DLSS_Input_MV_SubrectBase_Y, 0u); ngx_set(parameters, NVSDK_NGX_Parameter_DLSS_Input_Translucency_SubrectBase_X, 0u); ngx_set(parameters, NVSDK_NGX_Parameter_DLSS_Input_Translucency_SubrectBase_Y, 0u); ngx_set(parameters, NVSDK_NGX_Parameter_DLSS_Input_Bias_Current_Color_SubrectBase_X, 0u); ngx_set(parameters, NVSDK_NGX_Parameter_DLSS_Input_Bias_Current_Color_SubrectBase_Y, 0u); ngx_set(parameters, NVSDK_NGX_Parameter_DLSS_Output_Subrect_Base_X, 0u); ngx_set(parameters, NVSDK_NGX_Parameter_DLSS_Output_Subrect_Base_Y, 0u); ngx_set(parameters, NVSDK_NGX_Parameter_DLSS_Render_Subrect_Dimensions_Width, inputWidth); ngx_set(parameters, NVSDK_NGX_Parameter_DLSS_Render_Subrect_Dimensions_Height, inputHeight); ngx_set(parameters, NVSDK_NGX_Parameter_DLSS_Pre_Exposure, 1.0f); ngx_set(parameters, NVSDK_NGX_Parameter_DLSS_Exposure_Scale, 1.0f); ngx_set(parameters, NVSDK_NGX_Parameter_DLSS_Indicator_Invert_X_Axis, 0); ngx_set(parameters, NVSDK_NGX_Parameter_DLSS_Indicator_Invert_Y_Axis, 0); const char* doubleFloatTest = std::getenv("D4R_NGX_DOUBLE_FLOAT_TEST"); if (doubleFloatTest != nullptr && std::strcmp(doubleFloatTest, "1") == 0) ngx_set(parameters, NVSDK_NGX_Parameter_MV_Scale_X, static_cast(1.0)); void* checkColor = nullptr; unsigned long long checkColorAsUll = 0; float checkMvScale = 0.0f; double checkMvScaleDouble = 0.0; const NVSDK_NGX_Result colorGet = ngx_get_void( parameters, NVSDK_NGX_Parameter_Color, &checkColor); const NVSDK_NGX_Result colorUllGet = ngx_get_ull( parameters, NVSDK_NGX_Parameter_Color, &checkColorAsUll); const NVSDK_NGX_Result mvScaleGet = ngx_get_float( parameters, NVSDK_NGX_Parameter_MV_Scale_X, &checkMvScale); const NVSDK_NGX_Result mvScaleDoubleGet = ngx_get_double( parameters, NVSDK_NGX_Parameter_MV_Scale_X, &checkMvScaleDouble); std::printf("Synthetic DLSS parameter round-trip: Color=%p result=0x%08x asULL=0x%llx result=0x%08x MV.Scale.X=%g result=0x%08x asDouble=%g result=0x%08x\n", checkColor, static_cast(colorGet), checkColorAsUll, static_cast(colorUllGet), checkMvScale, static_cast(mvScaleGet), checkMvScaleDouble, static_cast(mvScaleDoubleGet)); float msvcAbiMvScale = 0.0f; unsigned int msvcAbiWidth = 0; const unsigned int msvcAbiMvScaleResult = d4r_ngx_parameter_float_roundtrip( parameters, NVSDK_NGX_Parameter_MV_Scale_X, 1.0f, &msvcAbiMvScale); const unsigned int msvcAbiWidthResult = d4r_ngx_parameter_uint_roundtrip( parameters, NVSDK_NGX_Parameter_Width, inputWidth, &msvcAbiWidth); std::printf("MSVC ABI parameter round-trip: MV.Scale.X=%g result=0x%08x Width=%u result=0x%08x\n", msvcAbiMvScale, msvcAbiMvScaleResult, msvcAbiWidth, msvcAbiWidthResult); const char* proxyMode = std::getenv("D4R_NGX_PARAMETER_PROXY"); const bool useParameterProxy = proxyMode != nullptr && std::strcmp(proxyMode, "1") == 0; NVSDK_NGX_Parameter* evalParameters = parameters; std::vector proxyStorage; if (useParameterProxy) { const size_t proxyBytes = d4r_ngx_parameter_proxy_size(); proxyStorage.resize((proxyBytes + sizeof(unsigned long long) - 1) / sizeof(unsigned long long)); d4r_ngx_parameter_proxy_construct(proxyStorage.data(), parameters); evalParameters = reinterpret_cast(proxyStorage.data()); std::printf("Synthetic DLSS parameter proxy: %zu bytes\n", proxyBytes); } const NVSDK_NGX_Result evalResult = useCEvaluate ? evaluateFeatureC(featureHandle, evalParameters, nullptr) : evaluateFeature(featureHandle, evalParameters, nullptr); print_ngx_result(useCEvaluate ? "CUDA_EvaluateFeature_C(DLSS SR; synthetic RGBA16F test pattern)" : "CUDA_EvaluateFeature(DLSS SR; synthetic RGBA16F test pattern)", evalResult); if (useParameterProxy) { const unsigned int traceCount = d4r_ngx_parameter_proxy_count(proxyStorage.data()); const unsigned int droppedCount = d4r_ngx_parameter_proxy_dropped(proxyStorage.data()); std::printf("Synthetic DLSS parameter proxy trace: %u records, %u dropped\n", traceCount, droppedCount); for (unsigned int index = 0; index < traceCount && index < 128; ++index) { D4rNgxParamLogRecord record{}; if (d4r_ngx_parameter_proxy_copy_record(proxyStorage.data(), index, &record)) std::printf("NGX parameter trace[%u]: %c/%c %s result=0x%08x value=0x%llx\n", index, record.operation, record.valueType, record.name, record.result, record.value); } } if (evalResult == NVSDK_NGX_Result_Success) { cudaResult = synchronize(); std::printf("Synthetic DLSS eval cuCtxSynchronize: CUDA result=%d\n", cudaResult); if (cudaResult == 0 && surfaceMode) { D4rCudaMemcpy2D copyBack{}; copyBack.srcMemoryType = 3; // CUDA_MEMORYTYPE_ARRAY copyBack.srcArray = outputArray; copyBack.dstMemoryType = 1; // CUDA_MEMORYTYPE_HOST copyBack.dstHost = output.data(); copyBack.dstPitch = outputWidth * 4 * sizeof(uint16_t); copyBack.WidthInBytes = outputWidth * 4 * sizeof(uint16_t); copyBack.Height = outputHeight; cudaResult = copy2D(©Back); } else if (cudaResult == 0) cudaResult = copyDtoH(output.data(), outputDevice, outputBytes); std::printf("Synthetic DLSS eval output readback: CUDA result=%d bytes=%zu\n", cudaResult, outputBytes); if (cudaResult == 0) { const std::wstring rawPath = appData + L"\\dlss-synthetic-output.rgba16f"; const std::wstring ppmPath = appData + L"\\dlss-synthetic-output.ppm"; const bool rawWritten = write_file(rawPath, output.data(), outputBytes); char ppmHeader[32]{}; const int headerLength = std::snprintf(ppmHeader, sizeof(ppmHeader), "P6\n%u %u\n255\n", outputWidth, outputHeight); std::vector ppm(static_cast(headerLength) + outputPixels * 3); std::memcpy(ppm.data(), ppmHeader, static_cast(headerLength)); size_t ppmOffset = static_cast(headerLength); size_t nonzero = 0; double sum = 0.0; for (size_t pixel = 0; pixel < outputPixels; ++pixel) { for (size_t channel = 0; channel < 3; ++channel) { float value = half_to_float(output[pixel * 4 + channel]); if (!std::isfinite(value)) value = 0.0f; if (value > 0.0f) ++nonzero; sum += value; value = std::clamp(value, 0.0f, 1.0f); const float srgb = value <= 0.0031308f ? value * 12.92f : 1.055f * std::pow(value, 1.0f / 2.4f) - 0.055f; ppm[ppmOffset++] = static_cast(std::lround(srgb * 255.0f)); } } const bool ppmWritten = write_file(ppmPath, ppm.data(), ppmOffset); std::printf("Synthetic DLSS output: raw=%s preview=%s positiveRGB=%zu/%zu meanRGB=%f\n", rawWritten ? "written" : "failed", ppmWritten ? "written" : "failed", nonzero, outputPixels * 3, sum / static_cast(outputPixels * 3)); } } } if (textureMode) { if (outputSurface != 0) surfaceDestroy(outputSurface); if (colorTexture != 0) textureDestroy(colorTexture); if (depthTexture != 0) textureDestroy(depthTexture); if (motionTexture != 0) textureDestroy(motionTexture); if (exposureTexture != 0) textureDestroy(exposureTexture); if (colorArray != nullptr) arrayDestroy(colorArray); if (depthArray != nullptr) arrayDestroy(depthArray); if (motionArray != nullptr) arrayDestroy(motionArray); if (exposureArray != nullptr) arrayDestroy(exposureArray); if (outputArray != nullptr) arrayDestroy(outputArray); } for (D4rCudaDevicePtr pointer : {outputDevice, motionDevice, depthDevice, colorDevice}) { if (pointer != 0) std::printf("Synthetic DLSS eval cuMemFree(0x%llx): result=%d\n", pointer, free(pointer)); } FreeLibrary(cuda); } static void set_cuda_luid_from_amd_dxgi_adapter() { HMODULE dxgi = LoadLibraryA("dxgi.dll"); if (dxgi == nullptr) { std::printf("DXGI unavailable for CUDA LUID matching: GetLastError=%lu\n", GetLastError()); return; } using CreateFactoryFn = HRESULT(WINAPI*)(REFIID, void**); auto createFactory = load_export(dxgi, "CreateDXGIFactory1"); if (createFactory == nullptr) { std::printf("CreateDXGIFactory1 unavailable for CUDA LUID matching\n"); FreeLibrary(dxgi); return; } constexpr GUID iidFactory1 = {0x770aae78, 0xf26f, 0x4dba, {0xa8, 0x29, 0x25, 0x3c, 0x83, 0xd1, 0xb3, 0x87}}; IDXGIFactory1* factory = nullptr; HRESULT hr = createFactory(iidFactory1, reinterpret_cast(&factory)); if (FAILED(hr) || factory == nullptr) { std::printf("CreateDXGIFactory1 failed while matching CUDA LUID: HRESULT=0x%08lx\n", static_cast(hr)); FreeLibrary(dxgi); return; } bool found = false; IDXGIAdapter1* adapter = nullptr; for (UINT index = 0; factory->EnumAdapters1(index, &adapter) != DXGI_ERROR_NOT_FOUND; ++index) { DXGI_ADAPTER_DESC1 description{}; if (SUCCEEDED(adapter->GetDesc1(&description)) && description.VendorId == 0x1002) { char low[24]{}; char high[24]{}; std::snprintf(low, sizeof(low), "0x%08lx", static_cast(description.AdapterLuid.LowPart)); std::snprintf(high, sizeof(high), "0x%08lx", static_cast(description.AdapterLuid.HighPart)); SetEnvironmentVariableA("D4R_CUDA_LUID_LOW", low); SetEnvironmentVariableA("D4R_CUDA_LUID_HIGH", high); SetEnvironmentVariableA("D4R_CUDA_NODE_MASK", "1"); std::printf("CUDA device LUID override from AMD DXGI adapter: %08lx:%08lx nodeMask=1\n", static_cast(description.AdapterLuid.HighPart), static_cast(description.AdapterLuid.LowPart)); found = true; adapter->Release(); adapter = nullptr; break; } adapter->Release(); adapter = nullptr; } if (!found) std::printf("No AMD DXGI adapter found for CUDA LUID matching\n"); factory->Release(); FreeLibrary(dxgi); } int main(int argc, char** argv) { if (argc != 4) { std::fprintf(stderr, "usage: ngx_cuda_probe.exe PATH_TO_NGX_CORE_DLL PATH_TO_NVNGX_DLSS_DLL WRITABLE_APPDATA_DIRECTORY\n"); return 2; } SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX); set_cuda_luid_from_amd_dxgi_adapter(); const char* corePath = argv[1]; const char* featureDllPath = argv[2]; std::wstring appData = utf8_to_wide(argv[3]); std::wstring featureDirectory = utf8_to_wide(featureDllPath); if (appData.empty() || featureDirectory.empty()) { std::fprintf(stderr, "Invalid UTF-8 feature-DLL path or appdata path argument\n"); return 2; } const size_t separator = featureDirectory.find_last_of(L"\\/"); if (separator == std::wstring::npos) featureDirectory = L"."; else featureDirectory.resize(separator); const wchar_t* featurePaths[] = {featureDirectory.c_str()}; NVSDK_NGX_FeatureCommonInfo commonInfo{}; commonInfo.PathListInfo.Path = featurePaths; commonInfo.PathListInfo.Length = 1; HMODULE core = LoadLibraryA(corePath); if (core == nullptr) { std::fprintf(stderr, "LoadLibraryA(%s) failed: GetLastError=%lu\n", corePath, GetLastError()); return 1; } std::printf("Loaded NGX core: %s\n", corePath); std::printf("DLSS SR feature search directory: %ls\n", featureDirectory.c_str()); auto init = load_export(core, "NVSDK_NGX_CUDA_Init"); auto shutdown = load_export(core, "NVSDK_NGX_CUDA_Shutdown"); auto getCapabilityParameters = load_export( core, "NVSDK_NGX_CUDA_GetCapabilityParameters"); const auto getLegacyParameters = load_export(core, "NVSDK_NGX_CUDA_GetParameters"); auto destroyParameters = load_export( core, "NVSDK_NGX_CUDA_DestroyParameters"); auto getScratchBufferSize = load_export( core, "NVSDK_NGX_CUDA_GetScratchBufferSize"); auto createFeature = load_export(core, "NVSDK_NGX_CUDA_CreateFeature"); auto releaseFeature = load_export(core, "NVSDK_NGX_CUDA_ReleaseFeature"); auto evaluateFeature = load_export(core, "NVSDK_NGX_CUDA_EvaluateFeature"); auto evaluateFeatureC = load_export( core, "NVSDK_NGX_CUDA_EvaluateFeature_C"); const char* evaluateApiMode = std::getenv("D4R_NGX_USE_C_EVALUATE"); const bool useCEvaluate = evaluateApiMode != nullptr && std::strcmp(evaluateApiMode, "1") == 0; g_ngxParameterApi.setULL = load_export(core, "NVSDK_NGX_Parameter_SetULL"); g_ngxParameterApi.setF = load_export(core, "NVSDK_NGX_Parameter_SetF"); g_ngxParameterApi.setD = load_export(core, "NVSDK_NGX_Parameter_SetD"); g_ngxParameterApi.setUI = load_export(core, "NVSDK_NGX_Parameter_SetUI"); g_ngxParameterApi.setI = load_export(core, "NVSDK_NGX_Parameter_SetI"); g_ngxParameterApi.setVoidPointer = load_export( core, "NVSDK_NGX_Parameter_SetVoidPointer"); g_ngxParameterApi.getULL = load_export(core, "NVSDK_NGX_Parameter_GetULL"); g_ngxParameterApi.getF = load_export(core, "NVSDK_NGX_Parameter_GetF"); g_ngxParameterApi.getD = load_export(core, "NVSDK_NGX_Parameter_GetD"); g_ngxParameterApi.getUI = load_export(core, "NVSDK_NGX_Parameter_GetUI"); g_ngxParameterApi.getI = load_export(core, "NVSDK_NGX_Parameter_GetI"); g_ngxParameterApi.getVoidPointer = load_export( core, "NVSDK_NGX_Parameter_GetVoidPointer"); std::printf("NGX parameter C wrappers: SetULL=%p SetF=%p SetUI=%p SetI=%p SetPtr=%p GetI=%p\n", reinterpret_cast(g_ngxParameterApi.setULL), reinterpret_cast(g_ngxParameterApi.setF), reinterpret_cast(g_ngxParameterApi.setUI), reinterpret_cast(g_ngxParameterApi.setI), reinterpret_cast(g_ngxParameterApi.setVoidPointer), reinterpret_cast(g_ngxParameterApi.getI)); std::printf("NGX CUDA EvaluateFeature C export: %p\n", reinterpret_cast(evaluateFeatureC)); const char* parameterMode = std::getenv("D4R_NGX_USE_LEGACY_PARAMETERS"); const bool useLegacyParameters = parameterMode != nullptr && std::strcmp(parameterMode, "1") == 0; if (init == nullptr || (!useLegacyParameters && getCapabilityParameters == nullptr) || (useLegacyParameters && getLegacyParameters == nullptr) || destroyParameters == nullptr || getScratchBufferSize == nullptr || createFeature == nullptr || releaseFeature == nullptr || evaluateFeature == nullptr || (useCEvaluate && evaluateFeatureC == nullptr)) { std::fprintf(stderr, "The NGX core is missing one or more CUDA API exports\n"); FreeLibrary(core); return 1; } NVSDK_NGX_FeatureDiscoveryInfo discovery{}; discovery.SDKVersion = static_cast(0x13); if (const char* apiVersion = std::getenv("D4R_NGX_API_VERSION")) discovery.SDKVersion = static_cast(std::strtoul(apiVersion, nullptr, 0)); discovery.FeatureID = NVSDK_NGX_Feature_SuperSampling; discovery.Identifier.IdentifierType = NVSDK_NGX_Application_Identifier_Type_Application_Id; discovery.Identifier.v.ApplicationId = 241534723ULL; discovery.ApplicationDataPath = appData.c_str(); discovery.FeatureInfo = &commonInfo; std::printf("NGX API version passed to core: 0x%08x\n", static_cast(discovery.SDKVersion)); NVSDK_NGX_Result result = init(discovery.Identifier.v.ApplicationId, discovery.ApplicationDataPath, &commonInfo, discovery.SDKVersion); print_ngx_result("CUDA_Init(DLSS SR)", result); if (result == NVSDK_NGX_Result_Success) { NVSDK_NGX_Parameter* parameters = nullptr; NVSDK_NGX_Result paramsResult = useLegacyParameters ? getLegacyParameters(¶meters) : getCapabilityParameters(¶meters); print_ngx_result(useLegacyParameters ? "CUDA_GetParameters(legacy)" : "CUDA_GetCapabilityParameters", paramsResult); if (paramsResult == NVSDK_NGX_Result_Success && parameters != nullptr) { int available = -1; NVSDK_NGX_Result availabilityResult = ngx_get_i(parameters, NVSDK_NGX_Parameter_SuperSampling_Available, &available); print_ngx_result("Parameters.Get(SuperSampling.Available)", availabilityResult); std::printf("DLSS SR availability value: %d\n", available); int featureInitResult = -1; NVSDK_NGX_Result initStateResult = ngx_get_i(parameters, NVSDK_NGX_Parameter_SuperSampling_FeatureInitResult, &featureInitResult); print_ngx_result("Parameters.Get(SuperSampling.FeatureInitResult)", initStateResult); std::printf("DLSS SR recorded feature-init result: 0x%08x\n", static_cast(featureInitResult)); int needsUpdatedDriver = -1; NVSDK_NGX_Result driverStateResult = ngx_get_i(parameters, NVSDK_NGX_Parameter_SuperSampling_NeedsUpdatedDriver, &needsUpdatedDriver); print_ngx_result("Parameters.Get(SuperSampling.NeedsUpdatedDriver)", driverStateResult); std::printf("DLSS SR needs updated driver: %d\n", needsUpdatedDriver); ngx_set(parameters, NVSDK_NGX_Parameter_Width, 640u); ngx_set(parameters, NVSDK_NGX_Parameter_Height, 360u); ngx_set(parameters, NVSDK_NGX_Parameter_OutWidth, 1280u); ngx_set(parameters, NVSDK_NGX_Parameter_OutHeight, 720u); ngx_set(parameters, NVSDK_NGX_Parameter_PerfQualityValue, static_cast(NVSDK_NGX_PerfQuality_Value_MaxQuality)); ngx_set(parameters, NVSDK_NGX_Parameter_DLSS_Feature_Create_Flags, static_cast(NVSDK_NGX_DLSS_Feature_Flags_None)); ngx_set(parameters, NVSDK_NGX_Parameter_DLSS_Enable_Output_Subrects, 0); unsigned int widthCheck = 0; unsigned int outWidthCheck = 0; const NVSDK_NGX_Result widthCheckResult = ngx_get_ui( parameters, NVSDK_NGX_Parameter_Width, &widthCheck); const NVSDK_NGX_Result outWidthCheckResult = ngx_get_ui( parameters, NVSDK_NGX_Parameter_OutWidth, &outWidthCheck); std::printf("NGX create parameter round-trip: Width=%u result=0x%08x OutWidth=%u result=0x%08x\n", widthCheck, static_cast(widthCheckResult), outWidthCheck, static_cast(outWidthCheckResult)); size_t scratchSize = 0; NVSDK_NGX_Result scratchResult = getScratchBufferSize( NVSDK_NGX_Feature_SuperSampling, parameters, &scratchSize); print_ngx_result("CUDA_GetScratchBufferSize(DLSS SR)", scratchResult); std::printf("DLSS SR scratch size: %llu bytes\n", static_cast(scratchSize)); const char* evaluate = std::getenv("D4R_NGX_EVALUATE"); const bool evaluateRequested = evaluate != nullptr && std::strcmp(evaluate, "1") == 0; HMODULE scratchCuda = nullptr; D4rCudaDevicePtr scratchDevice = 0; size_t scratchBytes = scratchSize; D4rCuMemFree scratchFree = nullptr; if (evaluateRequested) { if (scratchBytes == 0) scratchBytes = 64u * 1024u * 1024u; scratchCuda = LoadLibraryA("nvcuda.dll"); if (scratchCuda != nullptr) { const auto scratchAlloc = load_export(scratchCuda, "cuMemAlloc"); scratchFree = load_export(scratchCuda, "cuMemFree"); const int scratchAllocResult = scratchAlloc != nullptr ? scratchAlloc(&scratchDevice, scratchBytes) : 801; std::printf("Synthetic DLSS scratch allocation before create: CUDA result=%d ptr=0x%llx bytes=%zu\n", scratchAllocResult, scratchDevice, scratchBytes); if (scratchAllocResult == 0) { ngx_set(parameters, NVSDK_NGX_Parameter_Scratch, reinterpret_cast(static_cast(scratchDevice))); ngx_set(parameters, NVSDK_NGX_Parameter_Scratch_SizeInBytes, static_cast(scratchBytes)); } else { scratchDevice = 0; scratchBytes = 0; } } else { std::printf("Synthetic DLSS scratch allocation: LoadLibraryA(nvcuda.dll) failed: %lu\n", GetLastError()); scratchBytes = 0; } } NVSDK_NGX_Handle* featureHandle = nullptr; NVSDK_NGX_Result createResult = createFeature( NVSDK_NGX_Feature_SuperSampling, parameters, &featureHandle); print_ngx_result("CUDA_CreateFeature(DLSS SR)", createResult); std::printf("DLSS SR feature handle: %s\n", featureHandle != nullptr ? "created" : "null"); if (createResult == NVSDK_NGX_Result_Success && featureHandle != nullptr) { if (evaluateRequested) evaluate_synthetic_frame(parameters, featureHandle, evaluateFeature, evaluateFeatureC, useCEvaluate, appData, scratchDevice, scratchBytes); NVSDK_NGX_Result releaseResult = releaseFeature(featureHandle); print_ngx_result("CUDA_ReleaseFeature", releaseResult); } if (scratchDevice != 0 && scratchFree != nullptr) std::printf("Synthetic DLSS scratch free: CUDA result=%d\n", scratchFree(scratchDevice)); if (scratchCuda != nullptr) FreeLibrary(scratchCuda); if (useLegacyParameters) std::printf("CUDA_GetParameters map lifetime is managed by NGX; skipping DestroyParameters\n"); else { NVSDK_NGX_Result destroyResult = destroyParameters(parameters); print_ngx_result("CUDA_DestroyParameters", destroyResult); } } if (shutdown != nullptr) { NVSDK_NGX_Result shutdownResult = shutdown(); print_ngx_result("CUDA_Shutdown1", shutdownResult); } } FreeLibrary(core); return 0; }