1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
use super::*;

#[cfg(target_os = "windows")]
fn platform_prefered() -> Vec<Api> {
    vec![
        #[cfg(feature = "vulkan")]
        Api::Vulkan,
    ]
}

#[cfg(target_os = "macos")]
fn platform_prefered() -> Vec<Api> {
    vec![
        #[cfg(feature = "vulkan")]
        Api::Vulkan,
    ]
}

#[cfg(all(not(target_os = "macos"), target_family = "unix"))]
fn platform_prefered() -> Vec<Api> {
    vec![
        #[cfg(feature = "vulkan")]
        Api::Vulkan,
    ]
}

#[cfg(all(target_arch = "wasm32", target_os = "unknown"))]
fn platform_prefered() -> Vec<Api> {
    vec![Api::WebGpu]
}

impl Context {
    /// Create a context with extensions and either the default list of prefered apis or your own.
    /// See [Extensions] for the list of extensions as well as their support on platforms.
    /// An error is thrown only after all apis have failed to initialize.
    pub fn new(
        extensions: Extensions,
        prefered_apis: Option<Vec<Api>>,
    ) -> Result<Self, Vec<GpuError>>
    where
        Self: Sized,
    {
        let mut fails = vec![];
        for api in prefered_apis.unwrap_or(platform_prefered()) {
            match api {
                #[cfg(all(
                    not(all(target_arch = "wasm32", target_os = "unknown")),
                    feature = "vulkan"
                ))]
                Api::Vulkan => match VkContext::new(extensions.clone()) {
                    Ok(context) => return Ok(Context::Vulkan(context)),
                    Err(fail) => fails.push(fail),
                },
                #[cfg(all(feature = "webgpu", target_arch = "wasm32", target_os = "unknown"))]
                Api::WebGpu => match WebGpuContext::new(extensions.clone()) {
                    Ok(context) => return Ok(Context::WebGpu(context)),
                    Err(fail) => fails.push(fail),
                },
                _ => continue,
            }
        }

        Err(fails)
    }

    /// Create a context asynchronously with extensions and either the default list of prefered apis or your own.
    /// See [Extensions] for the list of extensions as well as their support on platforms.
    /// An error is thrown only after all apis have failed to initialize.
    /// This method is recommended if you want proper web support.
    pub async fn async_new(
        extensions: Extensions,
        prefered_apis: Option<Vec<Api>>,
    ) -> Result<Self, Vec<GpuError>>
    where
        Self: Sized,
    {
        let mut fails = vec![];
        for api in prefered_apis.unwrap_or(platform_prefered()) {
            match api {
                #[cfg(all(
                    not(all(target_arch = "wasm32", target_os = "unknown")),
                    feature = "vulkan"
                ))]
                Api::Vulkan => match VkContext::async_new(extensions.clone()).await {
                    Ok(context) => return Ok(Context::Vulkan(context)),
                    Err(fail) => fails.push(fail),
                },
                #[cfg(all(feature = "webgpu", target_arch = "wasm32", target_os = "unknown"))]
                Api::WebGpu => match WebGpuContext::async_new(extensions.clone()).await {
                    Ok(context) => return Ok(Context::WebGpu(context)),
                    Err(fail) => fails.push(fail),
                },
                _ => continue,
            }
        }

        Err(fails)
    }
}