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
278 changes: 145 additions & 133 deletions Cargo.lock

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions crates/lambda-rs-platform/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,14 @@ path = "src/lib.rs"

[dependencies]
winit = "=0.29.15"
naga = { version = "=28.0.0", optional = true, default-features = false, features = [
naga = { version = "=29.0.0", optional = true, default-features = false, features = [
"spv-out",
"glsl-in",
"wgsl-in",
] }
rand = "=0.8.5"
obj-rs = "=0.7.4"
wgpu = { version = "=28.0.0", optional = true, features = ["wgsl", "spirv"] }
wgpu = { version = "=29.0.0", optional = true, features = ["wgsl", "spirv"] }
pollster = { version = "=0.4.0", optional = true }
lambda-rs-logging = { path = "../lambda-rs-logging", version = "2023.1.30" }
cpal = { version = "=0.17.2", optional = true }
Expand Down
3 changes: 1 addition & 2 deletions crates/lambda-rs-platform/src/wgpu/gpu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -246,8 +246,7 @@ impl Gpu {
return GpuLimits {
max_uniform_buffer_binding_size: self
.limits
.max_uniform_buffer_binding_size
.into(),
.max_uniform_buffer_binding_size,
max_bind_groups: self.limits.max_bind_groups,
max_vertex_buffers: self.limits.max_vertex_buffers,
max_vertex_attributes: self.limits.max_vertex_attributes,
Expand Down
3 changes: 2 additions & 1 deletion crates/lambda-rs-platform/src/wgpu/instance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -167,11 +167,12 @@ impl InstanceBuilder {
flags: self.flags.to_wgpu(),
memory_budget_thresholds: self.memory_budget_thresholds,
backend_options: self.backend_options,
display: None,
};

Instance {
label: self.label,
instance: wgpu::Instance::new(&descriptor),
instance: wgpu::Instance::new(descriptor),
}
}
}
Expand Down
33 changes: 18 additions & 15 deletions crates/lambda-rs-platform/src/wgpu/pipeline.rs
Original file line number Diff line number Diff line change
Expand Up @@ -305,7 +305,7 @@ fn align_up_u32(value: u32, alignment: u32) -> u32 {

/// Validate immediate ranges and calculate the minimum allocation size.
///
/// wgpu v28 uses a single byte region of size `immediate_size`, addressed by
/// wgpu uses a single byte region of size `immediate_size`, addressed by
/// `set_immediates(offset, data)`. This function enforces that the provided
/// ranges:
/// - Start at byte offset 0 (as a union)
Expand Down Expand Up @@ -408,10 +408,13 @@ impl<'a> PipelineLayoutBuilder<'a> {

/// Build the layout.
pub fn build(self, gpu: &Gpu) -> PipelineLayout {
let layouts_raw: Vec<&wgpu::BindGroupLayout> =
self.layouts.iter().map(|l| l.raw()).collect();
let layouts_raw: Vec<Option<&wgpu::BindGroupLayout>> = self
.layouts
.iter()
.map(|layout| Some(layout.raw()))
.collect();

// wgpu v28 allocates a single immediate byte region sized by
// wgpu allocates a single immediate byte region sized by
// `PipelineLayoutDescriptor::immediate_size`. If callers provide multiple
// ranges, they are treated as sub-ranges of the same contiguous allocation.
//
Expand Down Expand Up @@ -442,7 +445,7 @@ impl<'a> PipelineLayoutBuilder<'a> {
.device()
.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
label: self.label.as_deref(),
bind_group_layouts: &layouts_raw,
bind_group_layouts: layouts_raw.as_slice(),
immediate_size,
});
if fallback_used {
Expand Down Expand Up @@ -625,8 +628,8 @@ impl<'a> RenderPipelineBuilder<'a> {
pub fn with_depth_stencil(mut self, format: DepthFormat) -> Self {
self.depth_stencil = Some(wgpu::DepthStencilState {
format: format.to_wgpu(),
depth_write_enabled: true,
depth_compare: wgpu::CompareFunction::Less,
depth_write_enabled: Some(true),
depth_compare: Some(wgpu::CompareFunction::Less),
stencil: wgpu::StencilState::default(),
bias: wgpu::DepthBiasState::default(),
});
Expand All @@ -637,34 +640,34 @@ impl<'a> RenderPipelineBuilder<'a> {
pub fn with_depth_compare(mut self, compare: CompareFunction) -> Self {
let ds = self.depth_stencil.get_or_insert(wgpu::DepthStencilState {
format: wgpu::TextureFormat::Depth32Float,
depth_write_enabled: true,
depth_compare: wgpu::CompareFunction::Less,
depth_write_enabled: Some(true),
depth_compare: Some(wgpu::CompareFunction::Less),
stencil: wgpu::StencilState::default(),
bias: wgpu::DepthBiasState::default(),
});
ds.depth_compare = compare.to_wgpu();
ds.depth_compare = Some(compare.to_wgpu());
return self;
}

/// Enable or disable depth writes. Requires depth-stencil enabled.
pub fn with_depth_write_enabled(mut self, enabled: bool) -> Self {
let ds = self.depth_stencil.get_or_insert(wgpu::DepthStencilState {
format: wgpu::TextureFormat::Depth32Float,
depth_write_enabled: true,
depth_compare: wgpu::CompareFunction::Less,
depth_write_enabled: Some(true),
depth_compare: Some(wgpu::CompareFunction::Less),
stencil: wgpu::StencilState::default(),
bias: wgpu::DepthBiasState::default(),
});
ds.depth_write_enabled = enabled;
ds.depth_write_enabled = Some(enabled);
return self;
}

/// Configure stencil state (front/back ops and masks). Requires depth-stencil enabled.
pub fn with_stencil(mut self, stencil: StencilState) -> Self {
let ds = self.depth_stencil.get_or_insert(wgpu::DepthStencilState {
format: wgpu::TextureFormat::Depth24PlusStencil8,
depth_write_enabled: true,
depth_compare: wgpu::CompareFunction::Less,
depth_write_enabled: Some(true),
depth_compare: Some(wgpu::CompareFunction::Less),
stencil: wgpu::StencilState::default(),
bias: wgpu::DepthBiasState::default(),
});
Expand Down
2 changes: 1 addition & 1 deletion crates/lambda-rs-platform/src/wgpu/render_pass.rs
Original file line number Diff line number Diff line change
Expand Up @@ -431,7 +431,7 @@ impl<'a> RenderPass<'a> {

/// Set immediate data for subsequent draw calls.
///
/// This is the wgpu v28 replacement for push constants. The `offset` and
/// This is the current wgpu replacement for push constants. The `offset` and
/// `data` length MUST be multiples of 4 bytes (IMMEDIATE_DATA_ALIGNMENT).
pub fn set_immediates(&mut self, offset: u32, data: &[u8]) {
self.raw.set_immediates(offset, data);
Expand Down
52 changes: 34 additions & 18 deletions crates/lambda-rs-platform/src/wgpu/surface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,23 +97,14 @@ pub enum SurfaceError {
OutOfMemory,
/// Timed out waiting for a frame.
Timeout,
/// The window is occluded and cannot currently present.
Occluded,
/// Surface acquisition triggered a validation error.
Validation,
/// Other/unclassified error (opaque).
Other(String),
}

impl From<wgpu::SurfaceError> for SurfaceError {
fn from(error: wgpu::SurfaceError) -> Self {
use wgpu::SurfaceError as We;
match error {
We::Lost => return SurfaceError::Lost,
We::Outdated => return SurfaceError::Outdated,
We::OutOfMemory => return SurfaceError::OutOfMemory,
We::Timeout => return SurfaceError::Timeout,
_ => return SurfaceError::Other(format!("{:?}", error)),
}
}
}

/// Builder for creating a `Surface` bound to a `winit` window.
#[derive(Debug, Clone)]
pub struct SurfaceBuilder {
Expand Down Expand Up @@ -160,7 +151,7 @@ impl SurfaceBuilder {
instance
.raw()
.create_surface_unsafe(wgpu::SurfaceTargetUnsafe::RawHandle {
raw_display_handle,
raw_display_handle: Some(raw_display_handle),
raw_window_handle,
})
.map_err(CreateSurfaceError::from)?
Expand Down Expand Up @@ -298,15 +289,34 @@ impl<'window> Surface<'window> {

/// Acquire the next swapchain texture and a default view.
pub fn acquire_next_frame(&self) -> Result<Frame, SurfaceError> {
let texture = match self.surface.get_current_texture() {
Ok(t) => t,
Err(e) => return Err(SurfaceError::from(e)),
let (texture, suboptimal) = match self.surface.get_current_texture() {
wgpu::CurrentSurfaceTexture::Success(texture) => (texture, false),
wgpu::CurrentSurfaceTexture::Suboptimal(texture) => (texture, true),
wgpu::CurrentSurfaceTexture::Timeout => {
return Err(SurfaceError::Timeout);
}
wgpu::CurrentSurfaceTexture::Outdated => {
return Err(SurfaceError::Outdated);
}
wgpu::CurrentSurfaceTexture::Lost => {
return Err(SurfaceError::Lost);
}
wgpu::CurrentSurfaceTexture::Occluded => {
return Err(SurfaceError::Occluded);
}
wgpu::CurrentSurfaceTexture::Validation => {
return Err(SurfaceError::Validation);
}
};
let view = texture
.texture
.create_view(&wgpu::TextureViewDescriptor::default());

return Ok(Frame { texture, view });
return Ok(Frame {
texture,
view,
suboptimal,
});
}
}

Expand Down Expand Up @@ -383,6 +393,7 @@ fn select_present_mode(
pub struct Frame {
texture: wgpu::SurfaceTexture,
view: wgpu::TextureView,
suboptimal: bool,
}

/// Borrowed reference to a texture view used for render passes.
Expand All @@ -397,6 +408,11 @@ impl Frame {
return TextureViewRef { raw: &self.view };
}

/// Whether this frame was acquired in a suboptimal surface state.
pub fn is_suboptimal(&self) -> bool {
return self.suboptimal;
}

/// Present the frame to the swapchain.
pub fn present(self) {
self.texture.present();
Expand Down
14 changes: 14 additions & 0 deletions crates/lambda-rs/src/render/surface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,10 @@ pub enum SurfaceError {
OutOfMemory,
/// Timed out waiting for a frame.
Timeout,
/// The window is occluded and cannot currently present.
Occluded,
/// Surface acquisition triggered a validation error.
Validation,
/// Other/unclassified error.
Other(String),
}
Expand All @@ -188,6 +192,8 @@ impl From<platform_surface::SurfaceError> for SurfaceError {
platform_surface::SurfaceError::Outdated => SurfaceError::Outdated,
platform_surface::SurfaceError::OutOfMemory => SurfaceError::OutOfMemory,
platform_surface::SurfaceError::Timeout => SurfaceError::Timeout,
platform_surface::SurfaceError::Occluded => SurfaceError::Occluded,
platform_surface::SurfaceError::Validation => SurfaceError::Validation,
platform_surface::SurfaceError::Other(msg) => SurfaceError::Other(msg),
};
}
Expand Down Expand Up @@ -236,6 +242,14 @@ mod tests {
SurfaceError::from(platform_surface::SurfaceError::Timeout),
SurfaceError::Timeout
));
assert!(matches!(
SurfaceError::from(platform_surface::SurfaceError::Occluded),
SurfaceError::Occluded
));
assert!(matches!(
SurfaceError::from(platform_surface::SurfaceError::Validation),
SurfaceError::Validation
));

let other = SurfaceError::from(platform_surface::SurfaceError::Other(
"opaque".to_string(),
Expand Down
14 changes: 14 additions & 0 deletions crates/lambda-rs/src/render/targets/surface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,10 @@ pub enum SurfaceError {
OutOfMemory,
/// Timed out waiting for a frame.
Timeout,
/// The window is occluded and cannot currently present.
Occluded,
/// Surface acquisition triggered a validation error.
Validation,
/// Other/unclassified error.
Other(String),
}
Expand All @@ -210,6 +214,8 @@ impl From<platform::surface::SurfaceError> for SurfaceError {
platform::surface::SurfaceError::Outdated => SurfaceError::Outdated,
platform::surface::SurfaceError::OutOfMemory => SurfaceError::OutOfMemory,
platform::surface::SurfaceError::Timeout => SurfaceError::Timeout,
platform::surface::SurfaceError::Occluded => SurfaceError::Occluded,
platform::surface::SurfaceError::Validation => SurfaceError::Validation,
platform::surface::SurfaceError::Other(msg) => SurfaceError::Other(msg),
};
}
Expand Down Expand Up @@ -415,6 +421,14 @@ mod tests {
SurfaceError::from(platform::surface::SurfaceError::Timeout),
SurfaceError::Timeout
));
assert!(matches!(
SurfaceError::from(platform::surface::SurfaceError::Occluded),
SurfaceError::Occluded
));
assert!(matches!(
SurfaceError::from(platform::surface::SurfaceError::Validation),
SurfaceError::Validation
));
let other = SurfaceError::from(platform::surface::SurfaceError::Other(
"opaque".to_string(),
));
Expand Down
Loading