threecrate_gpu/
device.rs

1//! GPU device management
2
3use threecrate_core::Result;
4use wgpu::util::DeviceExt;
5
6/// GPU context for managing compute and rendering operations
7pub 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    /// Create a new GPU context
16    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    /// Create a buffer from data
53    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    /// Create an empty buffer
62    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    /// Create a compute pipeline
72    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    /// Create a shader module from WGSL source
84    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    /// Create a bind group layout
92    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    /// Create a bind group
100    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}