use std::sync::Arc;
use wgpu::{
Instance, Adapter, Device, Queue, Surface,
DeviceDescriptor, Features, Limits, PowerPreference, RequestAdapterOptions,
InstanceDescriptor, Backends, TextureFormat,
};
use winit::window::Window;
use log::{info, debug};
use anvilkit_core::error::{AnvilKitError, Result};
pub struct RenderDevice {
instance: Instance,
adapter: Adapter,
device: Device,
queue: Queue,
features: Features,
limits: Limits,
}
impl RenderDevice {
pub async fn new(window: &Arc<Window>) -> Result<Self> {
info!("初始化 GPU 渲染设备");
let instance = Self::create_instance()?;
let surface = Self::create_surface(&instance, window)?;
let adapter = Self::request_adapter(&instance, &surface).await?;
let (device, queue) = Self::request_device(&adapter).await?;
let features = adapter.features();
let limits = adapter.limits();
info!("GPU 渲染设备初始化完成");
info!("适配器信息: {:?}", adapter.get_info());
info!("支持的特性: {:?}", features);
Ok(Self {
instance,
adapter,
device,
queue,
features,
limits,
})
}
fn create_instance() -> Result<Instance> {
debug!("创建 wgpu 实例");
let instance = Instance::new(InstanceDescriptor {
backends: Backends::all(),
..Default::default()
});
Ok(instance)
}
fn create_surface<'w>(instance: &Instance, window: &'w Arc<Window>) -> Result<Surface<'w>> {
debug!("创建窗口表面");
let surface = instance.create_surface(window.clone())
.map_err(|e| AnvilKitError::render(format!("创建表面失败: {}", e)))?;
Ok(surface)
}
async fn request_adapter(instance: &Instance, surface: &Surface<'_>) -> Result<Adapter> {
debug!("请求 GPU 适配器");
let adapter = instance.request_adapter(&RequestAdapterOptions {
power_preference: PowerPreference::HighPerformance,
compatible_surface: Some(surface),
force_fallback_adapter: false,
}).await
.ok_or_else(|| AnvilKitError::render("未找到兼容的 GPU 适配器".to_string()))?;
let info = adapter.get_info();
info!("选择的 GPU 适配器: {} ({:?})", info.name, info.backend);
Ok(adapter)
}
async fn request_device(adapter: &Adapter) -> Result<(Device, Queue)> {
debug!("请求 GPU 设备和队列");
let (device, queue) = adapter.request_device(
&DeviceDescriptor {
label: Some("AnvilKit Render Device"),
required_features: Features::empty(),
required_limits: Limits::default(),
},
None, ).await
.map_err(|e| AnvilKitError::render(format!("创建设备失败: {}", e)))?;
info!("GPU 设备和队列创建成功");
Ok((device, queue))
}
pub fn instance(&self) -> &Instance {
&self.instance
}
pub fn adapter(&self) -> &Adapter {
&self.adapter
}
pub fn device(&self) -> &Device {
&self.device
}
pub fn queue(&self) -> &Queue {
&self.queue
}
pub fn features(&self) -> Features {
self.features
}
pub fn limits(&self) -> &Limits {
&self.limits
}
pub fn supports_feature(&self, feature: Features) -> bool {
self.features.contains(feature)
}
pub fn get_preferred_format(&self, surface: &Surface<'_>) -> TextureFormat {
surface.get_capabilities(&self.adapter).formats[0]
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_instance_creation() {
let instance = RenderDevice::create_instance();
assert!(instance.is_ok());
}
#[test]
fn test_feature_support() {
let features = Features::empty();
assert!(!features.contains(Features::TIMESTAMP_QUERY));
assert!(features.is_empty());
}
#[test]
fn test_instance_backends() {
let instance = Instance::new(InstanceDescriptor {
backends: Backends::all(),
..Default::default()
});
let _ = instance;
}
#[test]
fn test_device_limits_defaults() {
let limits = Limits::default();
assert!(limits.max_texture_dimension_2d > 0);
assert!(limits.max_bind_groups > 0);
}
}