1use threecrate_core::Result;
4use wgpu::util::DeviceExt;
5
6pub struct GpuContext {
8 pub instance: wgpu::Instance,
9 pub device: wgpu::Device,
10 pub queue: wgpu::Queue,
11 pub adapter: wgpu::Adapter,
12}
13
14impl GpuContext {
15 pub async fn new() -> Result<Self> {
17 let instance = wgpu::Instance::new(&wgpu::InstanceDescriptor {
18 backends: wgpu::Backends::all(),
19 flags: wgpu::InstanceFlags::default(),
20 ..Default::default()
21 });
22
23 let adapter = instance
24 .request_adapter(&wgpu::RequestAdapterOptions {
25 power_preference: wgpu::PowerPreference::HighPerformance,
26 compatible_surface: None,
27 force_fallback_adapter: false,
28 })
29 .await
30 .map_err(|e| threecrate_core::Error::Gpu(format!("Failed to find suitable adapter: {:?}", e)))?;
31
32 let (device, queue) = adapter
33 .request_device(
34 &wgpu::DeviceDescriptor {
35 label: Some("ThreeCrate GPU Device"),
36 required_features: wgpu::Features::empty(),
37 required_limits: wgpu::Limits::default(),
38 ..Default::default()
39 }
40 )
41 .await
42 .map_err(|e| threecrate_core::Error::Gpu(format!("Failed to create device: {}", e)))?;
43
44 Ok(Self {
45 instance,
46 device,
47 queue,
48 adapter,
49 })
50 }
51
52 pub fn create_buffer_init<T: bytemuck::Pod>(&self, label: &str, data: &[T], usage: wgpu::BufferUsages) -> wgpu::Buffer {
54 self.device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
55 label: Some(label),
56 contents: bytemuck::cast_slice(data),
57 usage,
58 })
59 }
60
61 pub fn create_buffer(&self, label: &str, size: u64, usage: wgpu::BufferUsages) -> wgpu::Buffer {
63 self.device.create_buffer(&wgpu::BufferDescriptor {
64 label: Some(label),
65 size,
66 usage,
67 mapped_at_creation: false,
68 })
69 }
70
71 pub fn create_compute_pipeline(&self, label: &str, shader: &wgpu::ShaderModule, entry_point: &str) -> wgpu::ComputePipeline {
73 self.device.create_compute_pipeline(&wgpu::ComputePipelineDescriptor {
74 label: Some(label),
75 layout: None,
76 module: shader,
77 entry_point: Some(entry_point),
78 compilation_options: wgpu::PipelineCompilationOptions::default(),
79 cache: None,
80 })
81 }
82
83 pub fn create_shader_module(&self, label: &str, source: &str) -> wgpu::ShaderModule {
85 self.device.create_shader_module(wgpu::ShaderModuleDescriptor {
86 label: Some(label),
87 source: wgpu::ShaderSource::Wgsl(source.into()),
88 })
89 }
90
91 pub fn create_bind_group_layout(&self, label: &str, entries: &[wgpu::BindGroupLayoutEntry]) -> wgpu::BindGroupLayout {
93 self.device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
94 label: Some(label),
95 entries,
96 })
97 }
98
99 pub fn create_bind_group(&self, label: &str, layout: &wgpu::BindGroupLayout, entries: &[wgpu::BindGroupEntry]) -> wgpu::BindGroup {
101 self.device.create_bind_group(&wgpu::BindGroupDescriptor {
102 label: Some(label),
103 layout,
104 entries,
105 })
106 }
107}