Skip to main content

anvilkit_render/renderer/
device.rs

1//! # GPU 设备和适配器管理
2//! 
3//! 提供 wgpu 设备、适配器和实例的创建和管理功能。
4
5use std::sync::Arc;
6use wgpu::{
7    Instance, Adapter, Device, Queue, Surface,
8    DeviceDescriptor, Features, Limits, PowerPreference, RequestAdapterOptions,
9    InstanceDescriptor, Backends, TextureFormat,
10};
11use winit::window::Window;
12use log::{info, debug};
13
14use anvilkit_core::error::{AnvilKitError, Result};
15
16/// GPU 渲染设备
17/// 
18/// 封装 wgpu 的实例、适配器、设备和队列,提供统一的 GPU 资源管理。
19/// 
20/// # 设计理念
21/// 
22/// - **自动选择**: 自动选择最佳的 GPU 适配器
23/// - **特性检测**: 检测和启用可用的 GPU 特性
24/// - **错误处理**: 完善的错误处理和回退机制
25/// - **跨平台**: 支持多种图形后端
26/// 
27/// # 示例
28/// 
29/// ```rust,no_run
30/// use anvilkit_render::renderer::RenderDevice;
31/// use std::sync::Arc;
32/// use winit::window::Window;
33/// 
34/// # async fn example() -> anvilkit_core::error::Result<()> {
35/// // 创建窗口(示例)
36/// // let window = Arc::new(window);
37/// 
38/// // 创建渲染设备
39/// // let device = RenderDevice::new(&window).await?;
40/// 
41/// // 获取设备和队列
42/// // let wgpu_device = device.device();
43/// // let queue = device.queue();
44/// # Ok(())
45/// # }
46/// ```
47pub struct RenderDevice {
48    /// wgpu 实例
49    instance: Instance,
50    /// GPU 适配器
51    adapter: Adapter,
52    /// GPU 设备
53    device: Device,
54    /// 命令队列
55    queue: Queue,
56    /// 支持的特性
57    features: Features,
58    /// 设备限制
59    limits: Limits,
60}
61
62impl RenderDevice {
63    /// 创建新的渲染设备
64    /// 
65    /// # 参数
66    /// 
67    /// - `window`: 窗口实例,用于创建兼容的表面
68    /// 
69    /// # 返回
70    /// 
71    /// 成功时返回 RenderDevice 实例,失败时返回错误
72    /// 
73    /// # 示例
74    /// 
75    /// ```rust,no_run
76    /// use anvilkit_render::renderer::RenderDevice;
77    /// use std::sync::Arc;
78    /// use winit::window::Window;
79    /// 
80    /// # async fn example() -> anvilkit_core::error::Result<()> {
81    /// // let window = Arc::new(window);
82    /// // let device = RenderDevice::new(&window).await?;
83    /// # Ok(())
84    /// # }
85    /// ```
86    pub async fn new(window: &Arc<Window>) -> Result<Self> {
87        info!("初始化 GPU 渲染设备");
88        
89        // 创建 wgpu 实例
90        let instance = Self::create_instance()?;
91        
92        // 创建表面
93        let surface = Self::create_surface(&instance, window)?;
94        
95        // 请求适配器
96        let adapter = Self::request_adapter(&instance, &surface).await?;
97        
98        // 请求设备和队列
99        let (device, queue) = Self::request_device(&adapter).await?;
100        
101        let features = adapter.features();
102        let limits = adapter.limits();
103        
104        info!("GPU 渲染设备初始化完成");
105        info!("适配器信息: {:?}", adapter.get_info());
106        info!("支持的特性: {:?}", features);
107        
108        Ok(Self {
109            instance,
110            adapter,
111            device,
112            queue,
113            features,
114            limits,
115        })
116    }
117    
118    /// 创建 wgpu 实例
119    /// 
120    /// # 返回
121    /// 
122    /// 成功时返回 Instance,失败时返回错误
123    fn create_instance() -> Result<Instance> {
124        debug!("创建 wgpu 实例");
125        
126        let instance = Instance::new(InstanceDescriptor {
127            backends: Backends::all(),
128            ..Default::default()
129        });
130        
131        Ok(instance)
132    }
133    
134    /// 创建窗口表面
135    /// 
136    /// # 参数
137    /// 
138    /// - `instance`: wgpu 实例
139    /// - `window`: 窗口实例
140    /// 
141    /// # 返回
142    /// 
143    /// 成功时返回 Surface,失败时返回错误
144    fn create_surface<'w>(instance: &Instance, window: &'w Arc<Window>) -> Result<Surface<'w>> {
145        debug!("创建窗口表面");
146
147        let surface = instance.create_surface(window.clone())
148            .map_err(|e| AnvilKitError::render(format!("创建表面失败: {}", e)))?;
149
150        Ok(surface)
151    }
152    
153    /// 请求 GPU 适配器
154    /// 
155    /// # 参数
156    /// 
157    /// - `instance`: wgpu 实例
158    /// - `surface`: 窗口表面
159    /// 
160    /// # 返回
161    /// 
162    /// 成功时返回 Adapter,失败时返回错误
163    async fn request_adapter(instance: &Instance, surface: &Surface<'_>) -> Result<Adapter> {
164        debug!("请求 GPU 适配器");
165        
166        let adapter = instance.request_adapter(&RequestAdapterOptions {
167            power_preference: PowerPreference::HighPerformance,
168            compatible_surface: Some(surface),
169            force_fallback_adapter: false,
170        }).await
171        .ok_or_else(|| AnvilKitError::render("未找到兼容的 GPU 适配器".to_string()))?;
172        
173        let info = adapter.get_info();
174        info!("选择的 GPU 适配器: {} ({:?})", info.name, info.backend);
175        
176        Ok(adapter)
177    }
178    
179    /// 请求 GPU 设备和队列
180    /// 
181    /// # 参数
182    /// 
183    /// - `adapter`: GPU 适配器
184    /// 
185    /// # 返回
186    /// 
187    /// 成功时返回 (Device, Queue),失败时返回错误
188    async fn request_device(adapter: &Adapter) -> Result<(Device, Queue)> {
189        debug!("请求 GPU 设备和队列");
190        
191        let (device, queue) = adapter.request_device(
192            &DeviceDescriptor {
193                label: Some("AnvilKit Render Device"),
194                required_features: Features::empty(),
195                required_limits: Limits::default(),
196            },
197            None, // 不使用跟踪路径
198        ).await
199        .map_err(|e| AnvilKitError::render(format!("创建设备失败: {}", e)))?;
200        
201        info!("GPU 设备和队列创建成功");
202        
203        Ok((device, queue))
204    }
205    
206    /// 获取 wgpu 实例
207    /// 
208    /// # 返回
209    /// 
210    /// 返回 wgpu 实例的引用
211    /// 
212    /// # 示例
213    /// 
214    /// ```rust,no_run
215    /// # use anvilkit_render::renderer::RenderDevice;
216    /// # async fn example(device: &RenderDevice) {
217    /// let instance = device.instance();
218    /// # }
219    /// ```
220    pub fn instance(&self) -> &Instance {
221        &self.instance
222    }
223    
224    /// 获取 GPU 适配器
225    /// 
226    /// # 返回
227    /// 
228    /// 返回 GPU 适配器的引用
229    /// 
230    /// # 示例
231    /// 
232    /// ```rust,no_run
233    /// # use anvilkit_render::renderer::RenderDevice;
234    /// # async fn example(device: &RenderDevice) {
235    /// let adapter = device.adapter();
236    /// let info = adapter.get_info();
237    /// println!("GPU: {}", info.name);
238    /// # }
239    /// ```
240    pub fn adapter(&self) -> &Adapter {
241        &self.adapter
242    }
243    
244    /// 获取 GPU 设备
245    /// 
246    /// # 返回
247    /// 
248    /// 返回 GPU 设备的引用
249    /// 
250    /// # 示例
251    /// 
252    /// ```rust,no_run
253    /// # use anvilkit_render::renderer::RenderDevice;
254    /// # async fn example(device: &RenderDevice) {
255    /// let wgpu_device = device.device();
256    /// // 使用设备创建资源
257    /// # }
258    /// ```
259    pub fn device(&self) -> &Device {
260        &self.device
261    }
262    
263    /// 获取命令队列
264    /// 
265    /// # 返回
266    /// 
267    /// 返回命令队列的引用
268    /// 
269    /// # 示例
270    /// 
271    /// ```rust,no_run
272    /// # use anvilkit_render::renderer::RenderDevice;
273    /// # async fn example(device: &RenderDevice) {
274    /// let queue = device.queue();
275    /// // 使用队列提交命令
276    /// # }
277    /// ```
278    pub fn queue(&self) -> &Queue {
279        &self.queue
280    }
281    
282    /// 获取支持的特性
283    /// 
284    /// # 返回
285    /// 
286    /// 返回 GPU 支持的特性集合
287    /// 
288    /// # 示例
289    /// 
290    /// ```rust,no_run
291    /// # use anvilkit_render::renderer::RenderDevice;
292    /// # use wgpu::Features;
293    /// # async fn example(device: &RenderDevice) {
294    /// let features = device.features();
295    /// if features.contains(Features::TIMESTAMP_QUERY) {
296    ///     println!("支持时间戳查询");
297    /// }
298    /// # }
299    /// ```
300    pub fn features(&self) -> Features {
301        self.features
302    }
303    
304    /// 获取设备限制
305    /// 
306    /// # 返回
307    /// 
308    /// 返回 GPU 设备的限制参数
309    /// 
310    /// # 示例
311    /// 
312    /// ```rust,no_run
313    /// # use anvilkit_render::renderer::RenderDevice;
314    /// # async fn example(device: &RenderDevice) {
315    /// let limits = device.limits();
316    /// println!("最大纹理大小: {}", limits.max_texture_dimension_2d);
317    /// # }
318    /// ```
319    pub fn limits(&self) -> &Limits {
320        &self.limits
321    }
322    
323    /// 检查是否支持指定特性
324    /// 
325    /// # 参数
326    /// 
327    /// - `feature`: 要检查的特性
328    /// 
329    /// # 返回
330    /// 
331    /// 如果支持指定特性则返回 true
332    /// 
333    /// # 示例
334    /// 
335    /// ```rust,no_run
336    /// # use anvilkit_render::renderer::RenderDevice;
337    /// # use wgpu::Features;
338    /// # async fn example(device: &RenderDevice) {
339    /// if device.supports_feature(Features::MULTI_DRAW_INDIRECT) {
340    ///     println!("支持多重间接绘制");
341    /// }
342    /// # }
343    /// ```
344    pub fn supports_feature(&self, feature: Features) -> bool {
345        self.features.contains(feature)
346    }
347    
348    /// 获取首选的表面纹理格式
349    /// 
350    /// # 参数
351    /// 
352    /// - `surface`: 窗口表面
353    /// 
354    /// # 返回
355    /// 
356    /// 返回首选的纹理格式
357    /// 
358    /// # 示例
359    /// 
360    /// ```rust,no_run
361    /// # use anvilkit_render::renderer::RenderDevice;
362    /// # use wgpu::Surface;
363    /// # async fn example(device: &RenderDevice, surface: &Surface<'_>) {
364    /// let format = device.get_preferred_format(surface);
365    /// println!("首选格式: {:?}", format);
366    /// # }
367    /// ```
368    pub fn get_preferred_format(&self, surface: &Surface<'_>) -> TextureFormat {
369        surface.get_capabilities(&self.adapter).formats[0]
370    }
371}
372
373#[cfg(test)]
374mod tests {
375    use super::*;
376    
377    #[test]
378    fn test_instance_creation() {
379        // 测试实例创建
380        let instance = RenderDevice::create_instance();
381        assert!(instance.is_ok());
382    }
383    
384    #[test]
385    fn test_feature_support() {
386        // 创建一个模拟的设备用于测试
387        let features = Features::empty();
388
389        // 测试特性检查逻辑
390        assert!(!features.contains(Features::TIMESTAMP_QUERY));
391        assert!(features.is_empty());
392    }
393
394    #[test]
395    fn test_instance_backends() {
396        let instance = Instance::new(InstanceDescriptor {
397            backends: Backends::all(),
398            ..Default::default()
399        });
400        // Instance should be created successfully
401        let _ = instance;
402    }
403
404    #[test]
405    fn test_device_limits_defaults() {
406        let limits = Limits::default();
407        assert!(limits.max_texture_dimension_2d > 0);
408        assert!(limits.max_bind_groups > 0);
409    }
410}