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    /// Creates a Vulkan backend with default settings.
90    ///
91    /// # Panics
92    ///
93    /// Panics if no Vulkan-capable GPU device is available. Prefer
94    /// [`VulkanBackend::new()`] for fallible construction.
95    fn default() -> Self {
96        match Self::new() {
97            Ok(backend) => backend,
98            Err(e) => panic!("Failed to initialize Vulkan backend: {e}"),
99        }
100    }
101}
102
103/// Vulkan-specific features and extensions
104pub struct VulkanFeatures {
105    /// Descriptor indexing support
106    pub descriptor_indexing: bool,
107    /// Buffer device address support
108    pub buffer_device_address: bool,
109    /// Shader subgroup support
110    pub subgroup_operations: bool,
111    /// Ray tracing support
112    pub ray_tracing: bool,
113}
114
115impl VulkanFeatures {
116    /// Query available Vulkan features
117    #[must_use]
118    pub fn query() -> Self {
119        // In wgpu, feature detection is abstracted
120        // We would need to query wgpu::Features for available features
121        Self {
122            descriptor_indexing: false,
123            buffer_device_address: false,
124            subgroup_operations: false,
125            ray_tracing: false,
126        }
127    }
128
129    /// Check if any advanced features are available
130    #[must_use]
131    pub fn has_advanced_features(&self) -> bool {
132        self.descriptor_indexing
133            || self.buffer_device_address
134            || self.subgroup_operations
135            || self.ray_tracing
136    }
137}
138
139#[cfg(test)]
140mod tests {
141    use super::*;
142
143    #[test]
144    #[ignore] // Requires GPU hardware probe; run with --ignored
145    fn test_vulkan_backend_available() {
146        // This test will pass if Vulkan is available on the system
147        let available = VulkanBackend::is_available();
148        println!("Vulkan available: {available}");
149    }
150
151    #[test]
152    fn test_vulkan_features() {
153        let features = VulkanFeatures::query();
154        println!("Vulkan features: {:?}", features.has_advanced_features());
155    }
156}