Skip to main content

supasim_types/
lib.rs

1/* BEGIN LICENSE
2  SupaSim, a GPGPU and simulation toolkit.
3  Copyright (C) 2025 SupaMaggie70 (Magnus Larsson)
4
5
6  SupaSim is free software; you can redistribute it and/or
7  modify it under the terms of the GNU General Public License
8  as published by the Free Software Foundation; either version 3
9  of the License, or (at your option) any later version.
10
11  SupaSim is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  GNU General Public License for more details.
15
16  You should have received a copy of the GNU General Public License
17  along with this program.  If not, see <http://www.gnu.org/licenses/>.
18END LICENSE */
19
20use serde::{Deserialize, Serialize};
21
22#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize, Default)]
23pub enum HalBufferType {
24    /// Used for kernel access. Memory type on GPU that can be copied around on GPU but is optimized for local access.
25    #[default]
26    Storage,
27    /// Best for uploading data to GPU. Memory type on GPU that can be written to from CPU and copied from on GPU.
28    Upload,
29    /// Best for downloading data from GPU. Memory type on GPU that can be copied to from GPU and read from CPU.
30    Download,
31    UploadDownload,
32}
33#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
34pub struct HalBufferDescriptor {
35    pub size: u64,
36    pub memory_type: HalBufferType,
37    pub min_alignment: usize,
38}
39
40#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Serialize, Deserialize, PartialOrd, Ord)]
41pub enum SpirvVersion {
42    V1_0,
43    V1_1,
44    V1_2,
45    V1_3,
46    #[default]
47    V1_4,
48    V1_5,
49    V1_6,
50    Cl1_2,
51    Cl2_0,
52    Cl2_1,
53    Cl2_2,
54}
55#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
56pub enum ShaderModel {
57    #[default]
58    Sm6_0,
59    Sm6_1,
60    Sm6_2,
61    Sm6_3,
62    Sm6_4,
63    Sm6_5,
64    Sm6_6,
65    Sm6_7,
66}
67impl ShaderModel {
68    pub fn to_str(&self) -> &str {
69        use ShaderModel::*;
70        match self {
71            Sm6_0 => "cs_6_0",
72            Sm6_1 => "cs_6_1",
73            Sm6_2 => "cs_6_2",
74            Sm6_3 => "cs_6_3",
75            Sm6_4 => "cs_6_4",
76            Sm6_5 => "cs_6_5",
77            Sm6_6 => "cs_6_6",
78            Sm6_7 => "cs_6_7",
79        }
80    }
81}
82#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
83pub enum MetalVersion {
84    #[default]
85    Prior,
86    V2_3,
87    V3_1,
88    V4_0,
89}
90impl MetalVersion {
91    pub fn to_metallib_str(&self) -> Option<&str> {
92        use MetalVersion::*;
93        match self {
94            Prior => None,
95            V2_3 => Some("metallib_2_3"),
96            V3_1 => Some("metallib_3_1"),
97            V4_0 => Some("metallib_4_0"),
98        }
99    }
100    pub fn to_msl_str(&self) -> Option<&str> {
101        use MetalVersion::*;
102        match self {
103            Prior => None,
104            V2_3 => Some("METAL_2_3"),
105            V3_1 => Some("METAL_3_1"),
106            V4_0 => Some("METAL_4_0"),
107        }
108    }
109    pub fn to_tuple(&self) -> (u8, u8) {
110        match self {
111            Self::Prior => (2, 0),
112            Self::V2_3 => (2, 3),
113            Self::V3_1 => (3, 1),
114            Self::V4_0 => (4, 0),
115        }
116    }
117}
118#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
119pub enum KernelTarget {
120    CudaCpp,
121    Ptx,
122    Wgsl,
123    Glsl,
124    Spirv { version: SpirvVersion },
125    Hlsl,
126    Dxil { shader_model: ShaderModel },
127    Msl { version: MetalVersion },
128    MetalLib { version: MetalVersion },
129}
130impl KernelTarget {
131    pub fn file_extension(&self) -> &str {
132        use KernelTarget::*;
133        match self {
134            CudaCpp => "cu",
135            Ptx => "ptx",
136            Spirv { .. } => "spv",
137            Msl { .. } => "metal",
138            Hlsl => "hlsl",
139            Glsl => "glsl",
140            Wgsl => "wgsl",
141            Dxil { .. } => "dxil",
142            MetalLib { .. } => "metallib",
143        }
144    }
145    pub fn metal_version(&self) -> Option<MetalVersion> {
146        match self {
147            Self::MetalLib { version } | Self::Msl { version } => Some(*version),
148            _ => None,
149        }
150    }
151}
152#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
153pub enum SyncMode {
154    VulkanStyle,
155    SerialStreams,
156    Automatic,
157}
158#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
159pub enum SyncOperations {
160    ComputeDispatch,
161    Transfer,
162    Both,
163    None,
164}
165#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
166pub struct HalInstanceProperties {
167    /// What synchronization requirements the backend has
168    pub sync_mode: SyncMode,
169    /// Whether the backend supports pipeline caches
170    pub pipeline_cache: bool,
171    /// What kernel langauge the backend takes
172    pub kernel_lang: KernelTarget,
173    /// Whether the backend supports bind groups that are updated while commands are already recorded. This makes bind groups far cheaper to use
174    pub easily_update_bind_groups: bool,
175    /// Whether the backend supports CPU->GPU synchronization using CPU-side semaphore signalling.
176    pub semaphore_signal: bool,
177    /// Whether the backend supports directly mapping host memory on the CPU instead of just reads/writes.
178    /// This is likely false only on some wgpu backends such as WebGPU itself. Currently it is true everywhere.
179    pub map_buffers: bool,
180    /// Whether the system has unified memory, which provides opportunities for optimization, particularly on apple, mobile, or other devices with integrated GPUs
181    pub is_unified_memory: bool,
182    /// Whether you can map buffers while they are in use on the GPU(even if the slices don't overlap)
183    pub map_buffer_while_gpu_use: bool,
184    /// Whether it supports dual upload-download buffers
185    pub upload_download_buffers: bool,
186}
187/// # Safety
188/// This is undefined behavior lol
189pub unsafe fn to_static_lifetime<T>(r: &T) -> &'static T
190where
191    T: ?Sized,
192{
193    unsafe {
194        let r = r as *const T;
195        &*r
196    }
197}
198/// # Safety
199/// This is undefined behavior lol
200pub unsafe fn to_static_lifetime_mut<T>(r: &mut T) -> &'static mut T {
201    unsafe {
202        let r = r as *mut T;
203        &mut *r
204    }
205}
206#[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
207pub struct KernelReflectionInfo {
208    pub entry_point_name: String,
209    pub workgroup_size: [u32; 3],
210    pub subgroup_size: u32,
211    /// bool is for whether it is writeable
212    pub buffers: Vec<bool>,
213    pub push_constants_size: u64,
214}
215
216#[derive(Clone, Debug)]
217pub enum BackendOptions {
218    Wgpu { backends: wgpu::Backends },
219    Vulkan,
220}
221pub struct InstanceDescriptor {
222    pub backend_options: BackendOptions,
223    pub max_host_memory: Option<u64>,
224    pub max_device_memory: Option<u64>,
225    pub force_embedded: Option<bool>,
226    pub full_debug: bool,
227}
228
229pub enum Backend {
230    Vulkan,
231    Metal,
232    Wgpu,
233}