Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ version = "1.0.0"
edition = "2024"

[dependencies]
wgpu = { version = "25", default-features = false, features = ["vulkan"] }
wgpu = { version = "26", default-features = false, features = ["vulkan"] }
ash = "0.38"
glam = "0.29"
uuid = "1"
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ A wrapper for using [DLSS](https://www.nvidia.com/en-us/geforce/technologies/dls

| dlss_wgpu | dlss | wgpu |
|:---------:|:--------:|:----:|
| v1.0 | v310.3.0 | v25 |
| v1.0 | v310.3.0 | v26 |

## Downloading The DLSS SDK
The DLSS SDK cannot be redistributed by this crate. You will need to download the SDK as follows:
Expand Down
39 changes: 22 additions & 17 deletions src/context.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
use crate::{DlssExposure, DlssRenderParameters, DlssSdk, nvsdk_ngx::*};
use crate::{
DlssExposure, DlssRenderParameters, DlssSdk, nvsdk_ngx::*,
render_parameters::texture_to_ngx_resource,
};
use glam::{UVec2, Vec2};
use std::{
iter,
Expand Down Expand Up @@ -122,7 +125,7 @@ impl DlssContext {
exposure_scale,
pre_exposure,
} => (
&mut exposure.as_resource(adapter) as *mut _,
&mut texture_to_ngx_resource(exposure, adapter) as *mut _,
exposure_scale.unwrap_or(1.0),
pre_exposure.unwrap_or(0.0),
),
Expand All @@ -131,12 +134,16 @@ impl DlssContext {

let mut dlss_eval_params = NVSDK_NGX_VK_DLSS_Eval_Params {
Feature: NVSDK_NGX_VK_Feature_Eval_Params {
pInColor: &mut render_parameters.color.as_resource(adapter),
pInOutput: &mut render_parameters.dlss_output.as_resource(adapter),
pInColor: &mut texture_to_ngx_resource(render_parameters.color, adapter) as *mut _,
pInOutput: &mut texture_to_ngx_resource(render_parameters.dlss_output, adapter)
as *mut _,
InSharpness: 0.0,
},
pInDepth: &mut render_parameters.depth.as_resource(adapter),
pInMotionVectors: &mut render_parameters.motion_vectors.as_resource(adapter),
pInDepth: &mut texture_to_ngx_resource(render_parameters.depth, adapter) as *mut _,
pInMotionVectors: &mut texture_to_ngx_resource(
render_parameters.motion_vectors,
adapter,
) as *mut _,
InJitterOffsetX: render_parameters.jitter_offset.x,
InJitterOffsetY: render_parameters.jitter_offset.y,
InRenderSubrectDimensions: NVSDK_NGX_Dimensions {
Expand All @@ -149,7 +156,7 @@ impl DlssContext {
pInTransparencyMask: ptr::null_mut(),
pInExposureTexture: exposure,
pInBiasCurrentColorMask: match &render_parameters.bias {
Some(bias) => &mut bias.as_resource(adapter),
Some(bias) => &mut texture_to_ngx_resource(bias, adapter) as *mut _,
None => ptr::null_mut(),
},
InColorSubrectBase: NVSDK_NGX_Coordinates { X: 0, Y: 0 },
Expand Down Expand Up @@ -225,16 +232,14 @@ impl DlssContext {
impl Drop for DlssContext {
fn drop(&mut self) {
unsafe {
self.device.as_hal::<Vulkan, _, _>(|device| {
device
.unwrap()
.raw_device()
.device_wait_idle()
.expect("Failed to wait for idle device when destroying DlssContext");

check_ngx_result(NVSDK_NGX_VULKAN_ReleaseFeature(self.feature))
.expect("Failed to destroy DlssContext feature");
});
let hal_device = self.device.as_hal::<Vulkan>().unwrap();
hal_device
.raw_device()
.device_wait_idle()
.expect("Failed to wait for idle device when destroying DlssContext");

check_ngx_result(NVSDK_NGX_VULKAN_ReleaseFeature(self.feature))
.expect("Failed to destroy DlssContext feature");
}
}
}
Expand Down
168 changes: 168 additions & 0 deletions src/initialization.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
use crate::{
feature_info::with_feature_info,
nvsdk_ngx::{
DlssError, NVSDK_NGX_VULKAN_GetFeatureDeviceExtensionRequirements,
NVSDK_NGX_VULKAN_GetFeatureInstanceExtensionRequirements, check_ngx_result,
},
};
use ash::{Entry, vk::PhysicalDevice};
use std::{ffi::CStr, ptr, slice};
use uuid::Uuid;
use wgpu::{
Adapter, Device, DeviceDescriptor, Instance, InstanceDescriptor, Queue, RequestDeviceError,
hal::{DeviceError, InstanceError, api::Vulkan},
};

/// Creates a wgpu [`Instance`] with the extensions required for DLSS.
///
/// If the system does not support DLSS, it will set `dlss_supported` to false.
pub fn create_instance(
project_id: Uuid,
instance_descriptor: &InstanceDescriptor,
dlss_supported: &mut bool,
) -> Result<Instance, InitializationError> {
unsafe {
let mut result = Ok(());
let raw_instance = wgpu::hal::vulkan::Instance::init_with_callback(
&wgpu::hal::InstanceDescriptor {
name: "wgpu",
flags: instance_descriptor.flags,
memory_budget_thresholds: instance_descriptor.memory_budget_thresholds,
backend_options: instance_descriptor.backend_options.clone(),
},
Some(Box::new(|args| {
match required_instance_extensions(project_id, args.entry) {
Ok((extensions, true)) => args.extensions.extend(extensions),
Ok((_, false)) => *dlss_supported = false,
Err(err) => result = Err(err),
}
})),
)?;
result?;

Ok(Instance::from_hal::<Vulkan>(raw_instance))
}
}

/// Creates a wgpu [`Device`] and [`Queue`] with the extensions required for DLSS.
///
/// If the system does not support DLSS, it will set `dlss_supported` to false.
///
/// The provided [`Adapter`] must be using the Vulkan backend.
pub fn request_device(
project_id: Uuid,
adapter: &Adapter,
device_descriptor: &DeviceDescriptor,
dlss_supported: &mut bool,
) -> Result<(Device, Queue), InitializationError> {
unsafe {
let raw_adapter = adapter
.as_hal::<Vulkan>()
.ok_or(InitializationError::UnsupportedBackend)?;
let raw_instance = raw_adapter.shared_instance().raw_instance();
let raw_physical_device = raw_adapter.raw_physical_device();

let mut result = Ok(());
let open_device = raw_adapter.open_with_callback(
device_descriptor.required_features,
&device_descriptor.memory_hints,
Some(Box::new(|args| {
match required_device_extensions(
project_id,
&raw_adapter,
raw_instance.handle(),
raw_physical_device,
) {
Ok((extensions, true)) => args.extensions.extend(extensions),
Ok((_, false)) => *dlss_supported = false,
Err(err) => result = Err(err),
}
})),
)?;
result?;

Ok(adapter.create_device_from_hal::<Vulkan>(open_device, device_descriptor)?)
}
}

fn required_instance_extensions(
project_id: Uuid,
entry: &Entry,
) -> Result<(impl Iterator<Item = &'static CStr>, bool), InitializationError> {
with_feature_info(project_id, |feature_info| unsafe {
// Get required extension names
let mut required_extensions = ptr::null_mut();
let mut required_extension_count = 0;
check_ngx_result(NVSDK_NGX_VULKAN_GetFeatureInstanceExtensionRequirements(
feature_info,
&mut required_extension_count,
&mut required_extensions,
))?;
let required_extensions =
slice::from_raw_parts(required_extensions, required_extension_count as usize);
let required_extensions = required_extensions
.iter()
.map(|extension| CStr::from_ptr(extension.extension_name.as_ptr()));

// Check that the required extensions are supported
let supported_extensions = entry.enumerate_instance_extension_properties(None)?;
let extensions_supported = required_extensions.clone().all(|required_extension| {
supported_extensions
.iter()
.any(|extension| extension.extension_name_as_c_str() == Ok(required_extension))
});

Ok((required_extensions, extensions_supported))
})
}

fn required_device_extensions(
project_id: Uuid,
raw_adapter: &wgpu::hal::vulkan::Adapter,
raw_instance: ash::vk::Instance,
raw_physical_device: PhysicalDevice,
) -> Result<(impl Iterator<Item = &'static CStr>, bool), InitializationError> {
with_feature_info(project_id, |feature_info| unsafe {
// Get required extension names
let mut required_extensions = ptr::null_mut();
let mut required_extension_count = 0;
check_ngx_result(NVSDK_NGX_VULKAN_GetFeatureDeviceExtensionRequirements(
raw_instance,
raw_physical_device,
feature_info,
&mut required_extension_count,
&mut required_extensions,
))?;
let required_extensions =
slice::from_raw_parts(required_extensions, required_extension_count as usize);
let required_extensions = required_extensions
.iter()
.map(|extension| CStr::from_ptr(extension.extension_name.as_ptr()));

// Check that the required extensions are supported
let extensions_supported = required_extensions.clone().all(|required_extension| {
raw_adapter
.physical_device_capabilities()
.supports_extension(required_extension)
});

Ok((required_extensions, extensions_supported))
})
}

/// Error returned by [`request_device`].
#[derive(thiserror::Error, Debug)]
pub enum InitializationError {
#[error(transparent)]
InstanceError(#[from] InstanceError),
#[error(transparent)]
RequestDeviceError(#[from] RequestDeviceError),
#[error(transparent)]
DeviceError(#[from] DeviceError),
#[error(transparent)]
VulkanError(#[from] ash::vk::Result),
#[error(transparent)]
DlssError(#[from] DlssError),
#[error("Provided adapter is not using the Vulkan backend")]
UnsupportedBackend,
}
22 changes: 11 additions & 11 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,15 @@
//! use dlss_wgpu::{DlssSdk, DlssContext, DlssPerfQualityMode, DlssFeatureFlags, DlssRenderParameters};
//!
//! let project_id = Uuid::parse_str("...").unwrap();
//! let mut dlss_supported = true;
//!
//! // Request a wgpu device and queue
//! let ((device, queue), dlss_supported) = {
//! match dlss_wgpu::request_device(project_id, &adapter, &device_descriptor) {
//! Ok(x) => (x, true),
//! // Fallback to standard device request if DLSS is not supported
//! Err(_) => (adapter.request_device(&device_descriptor).await.unwrap(), false),
//! }
//! };
//! // Initialize wgpu
//! let instance = dlss_wgpu::create_instance(project_id, &instance_descriptor, &mut dlss_supported).unwrap();
//! let adapter = instance.request_adapter(&adapter_options).await.unwrap();
//! let (device, queue) = dlss_wgpu::request_device(project_id, &adapter, &device_descriptor, &mut dlss_supported).unwrap();
//!
//! // Check `dlss_supported`, if false don't create DLSS resources
//! println!("DLSS supported: {dlss_supported}");
//!
//! // Create the SDK once per application
//! let sdk = DlssSdk::new(project_id, device).expect("Failed to create DLSS SDK");
Expand Down Expand Up @@ -51,13 +51,13 @@

mod context;
mod feature_info;
mod initialization;
mod nvsdk_ngx;
mod render_parameters;
mod request_device;
mod sdk;

pub use context::DlssContext;
pub use initialization::{InitializationError, create_instance, request_device};
pub use nvsdk_ngx::{DlssError, DlssFeatureFlags, DlssPerfQualityMode};
pub use render_parameters::{DlssExposure, DlssRenderParameters, DlssTexture};
pub use request_device::{RequestDeviceError, request_device};
pub use render_parameters::{DlssExposure, DlssRenderParameters};
pub use sdk::DlssSdk;
Loading