mirror of
https://github.com/storytold/effectcraft.git
synced 2026-10-24 10:09:32 -06:00
GPU: devices favour memory use, so Purge and Close give video memory back
Both devices EffectCraft creates now ask for `MemoryHints::MemoryUsage`: - the window device (`apps/effectcraft/src/main.rs`, through a new `device_descriptor` helper); - the headless compositor device (`crates/gpu/src/context.rs`). The limits, labels, features and error paths are unchanged. The devices tests create stay as they were. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
9db7f3b217
commit
2b3732153b
@@ -371,15 +371,22 @@ fn wgpu_options(backends: Option<eframe::wgpu::Backends>) -> eframe::WgpuConfigu
|
||||
// Iris Pro: the device is lost and the window never opens.
|
||||
// `WGPU_VALIDATION_INDIRECT_CALL=1` turns the check back on.
|
||||
setup.instance_descriptor.flags = setup.instance_descriptor.flags.difference(eframe::wgpu::InstanceFlags::VALIDATION_INDIRECT_CALL).with_env();
|
||||
setup.device_descriptor = std::sync::Arc::new(|adapter| eframe::wgpu::DeviceDescriptor {
|
||||
label: Some("EffectCraft device"),
|
||||
required_limits: device_limits(adapter.limits()),
|
||||
..Default::default()
|
||||
});
|
||||
setup.device_descriptor = std::sync::Arc::new(|adapter| device_descriptor(adapter.limits()));
|
||||
}
|
||||
config
|
||||
}
|
||||
|
||||
/// The window device's descriptor: the adapter's limits ([`device_limits`]) and `MemoryUsage`,
|
||||
/// so memory the compositor frees on the shared device goes back to the driver.
|
||||
fn device_descriptor(adapter: eframe::wgpu::Limits) -> eframe::wgpu::DeviceDescriptor<'static> {
|
||||
eframe::wgpu::DeviceDescriptor {
|
||||
label: Some("EffectCraft device"),
|
||||
required_limits: device_limits(adapter),
|
||||
memory_hints: eframe::wgpu::MemoryHints::MemoryUsage,
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
/// The limits to request from an adapter that offers `adapter`: all of them, with textures
|
||||
/// capped at 16384 px like the headless renderer's device.
|
||||
fn device_limits(adapter: eframe::wgpu::Limits) -> eframe::wgpu::Limits {
|
||||
@@ -539,6 +546,17 @@ mod tests {
|
||||
assert_eq!(super::device_limits(big).max_texture_dimension_2d, 16384);
|
||||
}
|
||||
|
||||
/// The window device asks for `MemoryUsage`: the adapter's limits, unchanged.
|
||||
#[test]
|
||||
fn the_window_device_favours_memory_usage() {
|
||||
use eframe::wgpu::Limits;
|
||||
let big = Limits { max_texture_dimension_2d: 32768, ..Limits::default() };
|
||||
let d = super::device_descriptor(big);
|
||||
assert!(matches!(d.memory_hints, eframe::wgpu::MemoryHints::MemoryUsage));
|
||||
assert_eq!(d.required_limits.max_texture_dimension_2d, 16384);
|
||||
assert_eq!(d.label, Some("EffectCraft device"));
|
||||
}
|
||||
|
||||
/// A positional .ecprojx is a project file, not an unsupported media import (#528).
|
||||
#[test]
|
||||
fn launch_classifies_xml_and_json_projects_as_projects() {
|
||||
|
||||
@@ -462,6 +462,12 @@ pub(crate) fn buffer_init(device: &wgpu::Device, queue: &wgpu::Queue, label: Opt
|
||||
buffer
|
||||
}
|
||||
|
||||
/// The descriptor for a device the compositor owns: `MemoryUsage` so freed textures give their
|
||||
/// allocator blocks back instead of a few long-lived objects pinning large ones.
|
||||
pub(crate) fn device_descriptor(required_limits: wgpu::Limits) -> wgpu::DeviceDescriptor<'static> {
|
||||
wgpu::DeviceDescriptor { label: Some("effectcraft gpu"), required_limits, memory_hints: wgpu::MemoryHints::MemoryUsage, ..Default::default() }
|
||||
}
|
||||
|
||||
impl GpuContext {
|
||||
/// [`buffer_init`] on this context's device.
|
||||
pub(crate) fn buffer_init(&self, label: Option<&str>, contents: &[u8], usage: wgpu::BufferUsages) -> wgpu::Buffer {
|
||||
@@ -870,10 +876,7 @@ impl GpuContext {
|
||||
max_buffer_size: limits.max_buffer_size,
|
||||
..wgpu::Limits::default()
|
||||
};
|
||||
let (device, queue) = adapter
|
||||
.request_device(&wgpu::DeviceDescriptor { label: Some("effectcraft gpu"), required_limits, ..Default::default() })
|
||||
.await
|
||||
.map_err(|e| match by_name {
|
||||
let (device, queue) = adapter.request_device(&device_descriptor(required_limits)).await.map_err(|e| match by_name {
|
||||
true => format!("no device on {} (picked by WGPU_ADAPTER_NAME): {e}", adapter.get_info().name),
|
||||
false => format!("no device: {e}"),
|
||||
})?;
|
||||
|
||||
@@ -1071,3 +1071,13 @@ fn upload_cache_drops_textures_of_freed_buffers() {
|
||||
let kept = g.ctx.upload_entries();
|
||||
assert!(kept <= before + 1, "the upload cache kept {kept} textures of freed buffers (had {before})");
|
||||
}
|
||||
|
||||
/// The device the compositor owns asks for `MemoryUsage` so freed textures give
|
||||
/// their allocator blocks back, while its label and limits stay as they were.
|
||||
#[test]
|
||||
fn owned_devices_favour_memory_usage() {
|
||||
let d = crate::context::device_descriptor(wgpu::Limits::default());
|
||||
assert!(matches!(d.memory_hints, wgpu::MemoryHints::MemoryUsage));
|
||||
assert_eq!(d.label, Some("effectcraft gpu"));
|
||||
assert_eq!(d.required_limits.max_texture_dimension_2d, wgpu::Limits::default().max_texture_dimension_2d);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user