Skip to main content

oximedia_gpu/backend/
vulkan.rs

1//! Vulkan compute backend implementation
2//!
3//! This module provides Vulkan-based GPU compute acceleration using wgpu.
4//! wgpu abstracts the low-level Vulkan API and provides a safe Rust interface.
5
6use super::{Backend, BackendCapabilities, BackendType};
7use crate::{GpuDevice, Result};
8
9/// Vulkan backend for GPU compute
10pub struct VulkanBackend {
11    capabilities: BackendCapabilities,
12    device: Option<GpuDevice>,
13}
14
15impl VulkanBackend {
16    /// Create a new Vulkan backend
17    pub fn new() -> Result<Self> {
18        let device = GpuDevice::new(None)?;
19        let capabilities = Self::query_capabilities(&device);
20
21        Ok(Self {
22            capabilities,
23            device: Some(device),
24        })
25    }
26
27    /// Query backend capabilities from the device
28    fn query_capabilities(device: &GpuDevice) -> BackendCapabilities {
29        let info = device.info();
30
31        // Determine backend type from device info
32        let backend_type = match info.backend.as_str() {
33            "Vulkan" => BackendType::Vulkan,
34            "Metal" => BackendType::Metal,
35            "DirectX 12" => BackendType::DX12,
36            _ => BackendType::Vulkan, // Default
37        };
38
39        // wgpu provides reasonable defaults
40        BackendCapabilities {
41            backend_type,
42            max_workgroup_size: (256, 256, 64),
43            max_workgroup_invocations: 256,
44            max_buffer_size: 1024 * 1024 * 1024, // 1 GB default
45            compute_shaders: true,
46            subgroups: false,
47            push_constants: false,
48        }
49    }
50
51    /// Get the device
52    #[must_use]
53    pub fn device(&self) -> Option<&GpuDevice> {
54        self.device.as_ref()
55    }
56
57    /// Check if Vulkan is the active backend
58    #[must_use]
59    pub fn is_vulkan(&self) -> bool {
60        matches!(self.capabilities.backend_type, BackendType::Vulkan)
61    }
62
63    /// Get device information
64    #[must_use]
65    pub fn device_info(&self) -> Option<String> {
66        self.device.as_ref().map(|d| {
67            let info = d.info();
68            format!("{} ({}) - {}", info.name, info.device_type, info.backend)
69        })
70    }
71}
72
73impl Backend for VulkanBackend {
74    fn capabilities(&self) -> &BackendCapabilities {
75        &self.capabilities
76    }
77
78    fn is_available() -> bool {
79        // Try to create a device to check if Vulkan is available
80        GpuDevice::new(None).is_ok()
81    }
82
83    fn initialize() -> Result<Self> {
84        Self::new()
85    }
86}
87
88impl Default for VulkanBackend {
89    fn default() -> Self {
90        Self::new().expect("Failed to initialize Vulkan backend")
91    }
92}
93
94/// Vulkan-specific features and extensions
95pub struct VulkanFeatures {
96    /// Descriptor indexing support
97    pub descriptor_indexing: bool,
98    /// Buffer device address support
99    pub buffer_device_address: bool,
100    /// Shader subgroup support
101    pub subgroup_operations: bool,
102    /// Ray tracing support
103    pub ray_tracing: bool,
104}
105
106impl VulkanFeatures {
107    /// Query available Vulkan features
108    #[must_use]
109    pub fn query() -> Self {
110        // In wgpu, feature detection is abstracted
111        // We would need to query wgpu::Features for available features
112        Self {
113            descriptor_indexing: false,
114            buffer_device_address: false,
115            subgroup_operations: false,
116            ray_tracing: false,
117        }
118    }
119
120    /// Check if any advanced features are available
121    #[must_use]
122    pub fn has_advanced_features(&self) -> bool {
123        self.descriptor_indexing
124            || self.buffer_device_address
125            || self.subgroup_operations
126            || self.ray_tracing
127    }
128}
129
130#[cfg(test)]
131mod tests {
132    use super::*;
133
134    #[test]
135    #[ignore] // Requires GPU hardware probe; run with --ignored
136    fn test_vulkan_backend_available() {
137        // This test will pass if Vulkan is available on the system
138        let available = VulkanBackend::is_available();
139        println!("Vulkan available: {available}");
140    }
141
142    #[test]
143    fn test_vulkan_features() {
144        let features = VulkanFeatures::query();
145        println!("Vulkan features: {:?}", features.has_advanced_features());
146    }
147}