demo_vk/graphics/vulkan/raii/
device_resources.rs1use {
2 crate::{graphics::vulkan::raii, trace},
3 anyhow::{Context, Result},
4 ash::vk::{self, Handle},
5 std::{ffi::CString, sync::Arc},
6};
7
8macro_rules! resource {
9 (
10 $name: ident,
11 $raw_type: ty,
12 $object_type: expr,
13 $create_info_type: ty,
14 $create: ident,
15 $destroy: ident
16 ) => {
17 resource_constructor!(
18 $name,
19 $raw_type,
20 $create_info_type,
21 $create,
22 $destroy
23 );
24 resource_impl!($name, $raw_type, $object_type, $destroy);
25 };
26}
27
28macro_rules! resource_constructor {
29 (
30 $name: ident,
31 $raw_type: ty,
32 $create_info_type: ty,
33 $create: ident,
34 $destroy: ident
35 ) => {
36 impl $name {
37 #[doc = "Creates a new instance."]
38 pub fn new(
39 name: impl Into<String>,
40 device: Arc<raii::Device>,
41 create_info: &$create_info_type,
42 ) -> Result<Self> {
43 let raw = unsafe { device.$create(&create_info, None)? };
44 let instance = Self { device, raw };
45 instance.set_debug_name(name)?;
46 Ok(instance)
47 }
48 }
49 };
50}
51
52macro_rules! resource_impl {
53 (
54 $name: ident,
55 $raw_type: ty,
56 $object_type: expr,
57 $destroy: ident
58 ) => {
59 pub struct $name {
64 pub raw: $raw_type,
65 pub device: Arc<raii::Device>,
66 }
67
68 impl $name {
69 #[doc = "Sets the debug name used for validation layer logging."]
70 pub fn set_debug_name(
71 &self,
72 name: impl Into<String>,
73 ) -> Result<()> {
74 let object_type = $object_type;
75 let name =
76 CString::new(format!("{:?}: {}", object_type, name.into()))
77 .unwrap();
78
79 self.device
80 .set_debug_name(&vk::DebugUtilsObjectNameInfoEXT {
81 object_type,
82 object_handle: self.raw.as_raw(),
83 p_object_name: name.as_ptr(),
84 ..Default::default()
85 })
86 }
87 }
88
89 impl std::fmt::Debug for $name {
90 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
91 f.debug_struct(stringify!($name))
92 .field("raw", &self.raw)
93 .field("device", &self.device)
94 .finish()
95 }
96 }
97
98 impl std::ops::Deref for $name {
99 type Target = $raw_type;
100
101 fn deref(&self) -> &Self::Target {
102 &self.raw
103 }
104 }
105
106 impl Drop for $name {
107 fn drop(&mut self) {
108 unsafe { self.device.$destroy(self.raw, None) }
109 }
110 }
111 };
112}
113
114resource!(
115 Sampler,
116 vk::Sampler,
117 vk::Sampler::TYPE,
118 vk::SamplerCreateInfo,
119 create_sampler,
120 destroy_sampler
121);
122
123resource!(
124 Image,
125 vk::Image,
126 vk::Image::TYPE,
127 vk::ImageCreateInfo,
128 create_image,
129 destroy_image
130);
131
132resource!(
133 Fence,
134 vk::Fence,
135 vk::Fence::TYPE,
136 vk::FenceCreateInfo,
137 create_fence,
138 destroy_fence
139);
140
141resource!(
142 DeviceMemory,
143 vk::DeviceMemory,
144 vk::DeviceMemory::TYPE,
145 vk::MemoryAllocateInfo,
146 allocate_memory,
147 free_memory
148);
149
150resource!(
151 Buffer,
152 vk::Buffer,
153 vk::Buffer::TYPE,
154 vk::BufferCreateInfo,
155 create_buffer,
156 destroy_buffer
157);
158
159resource!(
160 DescriptorPool,
161 vk::DescriptorPool,
162 vk::DescriptorPool::TYPE,
163 vk::DescriptorPoolCreateInfo,
164 create_descriptor_pool,
165 destroy_descriptor_pool
166);
167
168resource!(
169 DescriptorSetLayout,
170 vk::DescriptorSetLayout,
171 vk::DescriptorSetLayout::TYPE,
172 vk::DescriptorSetLayoutCreateInfo,
173 create_descriptor_set_layout,
174 destroy_descriptor_set_layout
175);
176
177resource!(
178 ImageView,
179 vk::ImageView,
180 vk::ImageView::TYPE,
181 vk::ImageViewCreateInfo,
182 create_image_view,
183 destroy_image_view
184);
185
186resource!(
187 Semaphore,
188 vk::Semaphore,
189 vk::Semaphore::TYPE,
190 vk::SemaphoreCreateInfo,
191 create_semaphore,
192 destroy_semaphore
193);
194
195resource!(
196 CommandPool,
197 vk::CommandPool,
198 vk::CommandPool::TYPE,
199 vk::CommandPoolCreateInfo,
200 create_command_pool,
201 destroy_command_pool
202);
203
204resource!(
205 RenderPass,
206 vk::RenderPass,
207 vk::RenderPass::TYPE,
208 vk::RenderPassCreateInfo,
209 create_render_pass,
210 destroy_render_pass
211);
212
213resource!(
214 Framebuffer,
215 vk::Framebuffer,
216 vk::Framebuffer::TYPE,
217 vk::FramebufferCreateInfo,
218 create_framebuffer,
219 destroy_framebuffer
220);
221
222resource!(
223 ShaderModule,
224 vk::ShaderModule,
225 vk::ShaderModule::TYPE,
226 vk::ShaderModuleCreateInfo,
227 create_shader_module,
228 destroy_shader_module
229);
230
231resource!(
232 PipelineLayout,
233 vk::PipelineLayout,
234 vk::PipelineLayout::TYPE,
235 vk::PipelineLayoutCreateInfo,
236 create_pipeline_layout,
237 destroy_pipeline_layout
238);
239
240resource_impl!(Pipeline, vk::Pipeline, vk::Pipeline::TYPE, destroy_pipeline);
243
244impl Pipeline {
245 pub fn new_graphics_pipeline(
246 device: Arc<raii::Device>,
247 create_info: &vk::GraphicsPipelineCreateInfo,
248 ) -> Result<Self> {
249 let result = unsafe {
250 device.create_graphics_pipelines(
251 vk::PipelineCache::null(),
252 &[*create_info],
253 None,
254 )
255 };
256 let raw = match result {
257 Ok(pipelines) => pipelines[0],
258 Err((_, result)) => {
259 return Err(result).with_context(trace!(
260 "Error while creating graphics pipeline!"
261 ));
262 }
263 };
264 Ok(Self { device, raw })
265 }
266
267 pub fn new_compute_pipeline(
268 device: Arc<raii::Device>,
269 create_info: &vk::ComputePipelineCreateInfo,
270 ) -> Result<Self> {
271 let result = unsafe {
272 device.create_compute_pipelines(
273 vk::PipelineCache::null(),
274 &[*create_info],
275 None,
276 )
277 };
278 let raw = match result {
279 Ok(pipelines) => pipelines[0],
280 Err((_, result)) => {
281 return Err(result).with_context(trace!(
282 "Error while creating compute pipeline!"
283 ));
284 }
285 };
286 Ok(Self { device, raw })
287 }
288}