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
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
use super::internal::*;
use crate::{RafxApiDef, RafxResult, RafxValidationMode};
use ash::vk;
use raw_window_handle::HasRawWindowHandle;
use std::sync::Arc;
use crate::vulkan::{RafxDeviceContextVulkan, RafxDeviceContextVulkanInner};
use std::ffi::CString;
#[derive(Copy, Clone, Debug)]
pub enum VulkanLinkMethod {
Dynamic,
#[cfg(feature = "static-vulkan")]
Static,
}
impl Default for VulkanLinkMethod {
fn default() -> Self {
VulkanLinkMethod::Dynamic
}
}
#[derive(Default)]
pub struct RafxApiDefVulkan {
pub app_name: Option<CString>,
pub link_method: Option<VulkanLinkMethod>,
}
pub struct RafxApiVulkan {
instance: VkInstance,
device_context: Option<RafxDeviceContextVulkan>,
}
impl Drop for RafxApiVulkan {
fn drop(&mut self) {
self.destroy().unwrap();
}
}
impl RafxApiVulkan {
pub fn device_context(&self) -> &RafxDeviceContextVulkan {
self.device_context.as_ref().unwrap()
}
pub fn vk_instance(&self) -> &ash::Instance {
&self.instance.instance
}
pub fn new(
window: &dyn HasRawWindowHandle,
api_def: &RafxApiDef,
vk_api_def: &RafxApiDefVulkan,
) -> RafxResult<Self> {
let link_method = vk_api_def.link_method.clone().unwrap_or_default();
let app_name = vk_api_def
.app_name
.clone()
.unwrap_or_else(|| CString::new("Rafx Application").unwrap());
let (require_validation_layers_present, validation_layer_debug_report_flags) =
match api_def.validation_mode {
RafxValidationMode::Disabled => (false, vk::DebugReportFlagsEXT::empty()),
RafxValidationMode::EnabledIfAvailable => (false, vk::DebugReportFlagsEXT::all()),
RafxValidationMode::Enabled => (true, vk::DebugReportFlagsEXT::all()),
};
log::info!("Link method for vulkan: {:?}", link_method);
let entry = match link_method {
VulkanLinkMethod::Dynamic => VkEntry::new_dynamic(),
#[cfg(feature = "static-vulkan")]
VulkanLinkMethod::Static => VkEntry::new_static(),
}?;
let instance = VkInstance::new(
entry,
window,
&app_name,
require_validation_layers_present,
validation_layer_debug_report_flags,
)?;
let inner = Arc::new(RafxDeviceContextVulkanInner::new(&instance)?);
let device_context = RafxDeviceContextVulkan::new(inner)?;
Ok(RafxApiVulkan {
instance,
device_context: Some(device_context),
})
}
pub(crate) fn destroy(&mut self) -> RafxResult<()> {
if let Some(device_context) = self.device_context.take() {
let inner = device_context.inner.clone();
inner.descriptor_heap.clear_pools(device_context.device());
inner.resource_cache.clear_caches();
#[cfg(debug_assertions)]
#[cfg(feature = "track-device-contexts")]
let _create_index = device_context.create_index;
std::mem::drop(device_context);
let _strong_count = Arc::strong_count(&inner);
match Arc::try_unwrap(inner) {
Ok(inner) => std::mem::drop(inner),
Err(_arc) => {
Err(format!(
"Could not destroy device, {} references to it exist",
_strong_count
))?;
#[cfg(debug_assertions)]
#[cfg(feature = "track-device-contexts")]
{
let mut all_contexts = _arc.all_contexts.lock().unwrap();
all_contexts.remove(&_create_index);
for (k, v) in all_contexts.iter_mut() {
v.resolve();
println!("context allocation: {}\n{:?}", k, v);
}
}
}
}
}
Ok(())
}
}