use threecrate_core::Result;
use wgpu::util::DeviceExt;
pub struct GpuContext {
pub instance: wgpu::Instance,
pub device: wgpu::Device,
pub queue: wgpu::Queue,
pub adapter: wgpu::Adapter,
}
impl GpuContext {
pub async fn new() -> Result<Self> {
let instance = wgpu::Instance::new(wgpu::InstanceDescriptor {
backends: wgpu::Backends::all(),
flags: wgpu::InstanceFlags::default(),
..wgpu::InstanceDescriptor::new_without_display_handle_from_env()
});
let adapter = instance
.request_adapter(&wgpu::RequestAdapterOptions {
power_preference: wgpu::PowerPreference::HighPerformance,
compatible_surface: None,
force_fallback_adapter: false,
})
.await
.map_err(|e| threecrate_core::Error::Gpu(format!("Failed to find suitable adapter: {:?}", e)))?;
let (device, queue) = adapter
.request_device(
&wgpu::DeviceDescriptor {
label: Some("ThreeCrate GPU Device"),
required_features: wgpu::Features::empty(),
required_limits: wgpu::Limits::default(),
..Default::default()
}
)
.await
.map_err(|e| threecrate_core::Error::Gpu(format!("Failed to create device: {}", e)))?;
Ok(Self {
instance,
device,
queue,
adapter,
})
}
pub fn create_buffer_init<T: bytemuck::Pod>(&self, label: &str, data: &[T], usage: wgpu::BufferUsages) -> wgpu::Buffer {
self.device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: Some(label),
contents: bytemuck::cast_slice(data),
usage,
})
}
pub fn create_buffer(&self, label: &str, size: u64, usage: wgpu::BufferUsages) -> wgpu::Buffer {
self.device.create_buffer(&wgpu::BufferDescriptor {
label: Some(label),
size,
usage,
mapped_at_creation: false,
})
}
pub fn create_compute_pipeline(&self, label: &str, shader: &wgpu::ShaderModule, entry_point: &str) -> wgpu::ComputePipeline {
self.device.create_compute_pipeline(&wgpu::ComputePipelineDescriptor {
label: Some(label),
layout: None,
module: shader,
entry_point: Some(entry_point),
compilation_options: wgpu::PipelineCompilationOptions::default(),
cache: None,
})
}
pub fn create_shader_module(&self, label: &str, source: &str) -> wgpu::ShaderModule {
self.device.create_shader_module(wgpu::ShaderModuleDescriptor {
label: Some(label),
source: wgpu::ShaderSource::Wgsl(source.into()),
})
}
pub fn create_bind_group_layout(&self, label: &str, entries: &[wgpu::BindGroupLayoutEntry]) -> wgpu::BindGroupLayout {
self.device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
label: Some(label),
entries,
})
}
pub fn create_bind_group(&self, label: &str, layout: &wgpu::BindGroupLayout, entries: &[wgpu::BindGroupEntry]) -> wgpu::BindGroup {
self.device.create_bind_group(&wgpu::BindGroupDescriptor {
label: Some(label),
layout,
entries,
})
}
}