This is page 7 of 9. Use http://codebase.md/mehmetoguzderin/shaderc-vkrunner-mcp?lines=true&page={x} to view the full context.
# Directory Structure
```
├── .devcontainer
│ ├── devcontainer.json
│ ├── docker-compose.yml
│ └── Dockerfile
├── .gitattributes
├── .github
│ └── workflows
│ └── build-push-image.yml
├── .gitignore
├── .vscode
│ └── mcp.json
├── Cargo.lock
├── Cargo.toml
├── Dockerfile
├── LICENSE
├── README.adoc
├── shaderc-vkrunner-mcp.jpg
├── src
│ └── main.rs
└── vkrunner
├── .editorconfig
├── .gitignore
├── .gitlab-ci.yml
├── build.rs
├── Cargo.toml
├── COPYING
├── examples
│ ├── compute-shader.shader_test
│ ├── cooperative-matrix.shader_test
│ ├── depth-buffer.shader_test
│ ├── desc_set_and_binding.shader_test
│ ├── entrypoint.shader_test
│ ├── float-framebuffer.shader_test
│ ├── frexp.shader_test
│ ├── geometry.shader_test
│ ├── indices.shader_test
│ ├── layouts.shader_test
│ ├── properties.shader_test
│ ├── push-constants.shader_test
│ ├── require-subgroup-size.shader_test
│ ├── row-major.shader_test
│ ├── spirv.shader_test
│ ├── ssbo.shader_test
│ ├── tolerance.shader_test
│ ├── tricolore.shader_test
│ ├── ubo.shader_test
│ ├── vertex-data-piglit.shader_test
│ └── vertex-data.shader_test
├── include
│ ├── vk_video
│ │ ├── vulkan_video_codec_av1std_decode.h
│ │ ├── vulkan_video_codec_av1std_encode.h
│ │ ├── vulkan_video_codec_av1std.h
│ │ ├── vulkan_video_codec_h264std_decode.h
│ │ ├── vulkan_video_codec_h264std_encode.h
│ │ ├── vulkan_video_codec_h264std.h
│ │ ├── vulkan_video_codec_h265std_decode.h
│ │ ├── vulkan_video_codec_h265std_encode.h
│ │ ├── vulkan_video_codec_h265std.h
│ │ └── vulkan_video_codecs_common.h
│ └── vulkan
│ ├── vk_platform.h
│ ├── vulkan_core.h
│ └── vulkan.h
├── precompile-script.py
├── README.md
├── scripts
│ └── update-vulkan.sh
├── src
│ └── main.rs
├── test-build.sh
└── vkrunner
├── allocate_store.rs
├── buffer.rs
├── compiler
│ └── fake_process.rs
├── compiler.rs
├── config.rs
├── context.rs
├── enum_table.rs
├── env_var_test.rs
├── executor.rs
├── fake_vulkan.rs
├── features.rs
├── flush_memory.rs
├── format_table.rs
├── format.rs
├── half_float.rs
├── hex.rs
├── inspect.rs
├── lib.rs
├── logger.rs
├── make-enums.py
├── make-features.py
├── make-formats.py
├── make-pipeline-key-data.py
├── make-vulkan-funcs-data.py
├── parse_num.rs
├── pipeline_key_data.rs
├── pipeline_key.rs
├── pipeline_set.rs
├── requirements.rs
├── result.rs
├── script.rs
├── shader_stage.rs
├── slot.rs
├── small_float.rs
├── source.rs
├── stream.rs
├── temp_file.rs
├── tester.rs
├── tolerance.rs
├── util.rs
├── vbo.rs
├── vk.rs
├── vulkan_funcs_data.rs
├── vulkan_funcs.rs
├── window_format.rs
└── window.rs
```
# Files
--------------------------------------------------------------------------------
/vkrunner/vkrunner/fake_vulkan.rs:
--------------------------------------------------------------------------------
```rust
1 | // vkrunner
2 | //
3 | // Copyright 2023 Neil Roberts
4 | //
5 | // Permission is hereby granted, free of charge, to any person obtaining a
6 | // copy of this software and associated documentation files (the "Software"),
7 | // to deal in the Software without restriction, including without limitation
8 | // the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 | // and/or sell copies of the Software, and to permit persons to whom the
10 | // Software is furnished to do so, subject to the following conditions:
11 | //
12 | // The above copyright notice and this permission notice (including the next
13 | // paragraph) shall be included in all copies or substantial portions of the
14 | // Software.
15 | //
16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 | // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 | // DEALINGS IN THE SOFTWARE.
23 |
24 | //! Sets up a fake Vulkan driver which can be manipulated to report
25 | //! different extensions and features. This is only build in test
26 | //! configurations and it is intended to help unit testing.
27 |
28 | use crate::vk;
29 | use crate::vulkan_funcs;
30 | use crate::requirements;
31 | use std::cell::Cell;
32 | use std::mem;
33 | use std::mem::transmute;
34 | use std::ffi::{c_char, CStr, c_void};
35 | use std::ptr;
36 | use std::cmp::min;
37 | use std::collections::{HashMap, VecDeque};
38 |
39 | // Pointer to the current FakeVulkan instance that was created in
40 | // this thread. There can only be one instance per thread.
41 | thread_local! {
42 | static CURRENT_FAKE_VULKAN: Cell<Option<*mut FakeVulkan>> = Cell::new(None);
43 | }
44 |
45 | fn add_extension_to_vec(
46 | extension_vec: &mut Vec<vk::VkExtensionProperties>,
47 | ext: &str,
48 | ) {
49 | let old_len = extension_vec.len();
50 | extension_vec.resize(old_len + 1, Default::default());
51 | let props = extension_vec.last_mut().unwrap();
52 | for (i, b) in ext
53 | .bytes()
54 | .take(min(props.extensionName.len() - 1, ext.len()))
55 | .enumerate()
56 | {
57 | props.extensionName[i] = b as c_char;
58 | }
59 | }
60 |
61 | /// A structure containing the physical device infos that will be
62 | /// reported by the driver.
63 | #[derive(Debug, Clone)]
64 | pub struct PhysicalDeviceInfo {
65 | pub properties: vk::VkPhysicalDeviceProperties,
66 | pub memory_properties: vk::VkPhysicalDeviceMemoryProperties,
67 | pub features: vk::VkPhysicalDeviceFeatures,
68 | pub queue_families: Vec<vk::VkQueueFamilyProperties>,
69 | pub extensions: Vec<vk::VkExtensionProperties>,
70 | pub format_properties: HashMap<vk::VkFormat, vk::VkFormatProperties>,
71 | // Two random extension feature sets to report when asked
72 | pub shader_atomic: vk::VkPhysicalDeviceShaderAtomicInt64FeaturesKHR,
73 | pub multiview: vk::VkPhysicalDeviceMultiviewFeaturesKHR,
74 | }
75 |
76 | impl PhysicalDeviceInfo {
77 | pub fn add_extension(&mut self, ext: &str) {
78 | add_extension_to_vec(&mut self.extensions, ext);
79 | }
80 | }
81 |
82 | impl Default for PhysicalDeviceInfo {
83 | fn default() -> PhysicalDeviceInfo {
84 | PhysicalDeviceInfo {
85 | properties: vk::VkPhysicalDeviceProperties {
86 | apiVersion: requirements::make_version(1, 0, 0),
87 | driverVersion: 0,
88 | vendorID: 0xfa4eed,
89 | deviceID: 0xfa4ede,
90 | deviceType: vk::VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU,
91 | deviceName: [0; 256],
92 | pipelineCacheUUID: *b"fakevulkan123456",
93 | limits: Default::default(),
94 | sparseProperties: Default::default(),
95 | },
96 | memory_properties: Default::default(),
97 | format_properties: HashMap::new(),
98 | features: Default::default(),
99 | queue_families: vec![vk::VkQueueFamilyProperties {
100 | queueFlags: vk::VK_QUEUE_GRAPHICS_BIT,
101 | queueCount: 1,
102 | timestampValidBits: 32,
103 | minImageTransferGranularity: Default::default(),
104 | }],
105 | extensions: Vec::new(),
106 | shader_atomic: Default::default(),
107 | multiview: Default::default(),
108 | }
109 | }
110 | }
111 |
112 | const ATOMIC_TYPE: vk::VkStructureType =
113 | vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_INT64_FEATURES_KHR;
114 | const MULTIVIEW_TYPE: vk::VkStructureType =
115 | vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES_KHR;
116 |
117 | #[derive(Debug, Clone)]
118 | pub struct GraphicsPipelineCreateInfo {
119 | pub create_info: vk::VkGraphicsPipelineCreateInfo,
120 | pub bindings: Vec<vk::VkVertexInputBindingDescription>,
121 | pub attribs: Vec<vk::VkVertexInputAttributeDescription>,
122 | }
123 |
124 | impl GraphicsPipelineCreateInfo {
125 | fn new(
126 | create_info: &vk::VkGraphicsPipelineCreateInfo
127 | ) -> GraphicsPipelineCreateInfo {
128 | let vertex_input_state = unsafe {
129 | &*create_info.pVertexInputState
130 | };
131 | let bindings = vec_from_raw_parts(
132 | vertex_input_state.pVertexBindingDescriptions,
133 | vertex_input_state.vertexBindingDescriptionCount as usize,
134 | );
135 | let attribs = vec_from_raw_parts(
136 | vertex_input_state.pVertexAttributeDescriptions,
137 | vertex_input_state.vertexAttributeDescriptionCount as usize,
138 | );
139 |
140 | GraphicsPipelineCreateInfo {
141 | create_info: create_info.clone(),
142 | bindings,
143 | attribs,
144 | }
145 | }
146 | }
147 |
148 | #[derive(Debug)]
149 | pub enum PipelineCreateInfo {
150 | Graphics(GraphicsPipelineCreateInfo),
151 | Compute(vk::VkComputePipelineCreateInfo),
152 | }
153 |
154 | #[derive(Debug, Clone)]
155 | pub struct PipelineLayoutCreateInfo {
156 | pub create_info: vk::VkPipelineLayoutCreateInfo,
157 | pub push_constant_ranges: Vec<vk::VkPushConstantRange>,
158 | pub layouts: Vec<vk::VkDescriptorSetLayout>,
159 | }
160 |
161 | #[derive(Debug)]
162 | // It would be nice to just store the VkClearAttachment directly but
163 | // that can’t derive Debug because it is a union and it would be
164 | // annoying to have to manually implement Debug.
165 | pub enum ClearAttachment {
166 | Color {
167 | attachment: u32,
168 | value: [f32; 4],
169 | },
170 | DepthStencil {
171 | aspect_mask: vk::VkImageAspectFlags,
172 | value: vk::VkClearDepthStencilValue,
173 | },
174 | }
175 |
176 | #[derive(Debug)]
177 | #[allow(dead_code)]
178 | pub enum Command {
179 | BeginRenderPass(vk::VkRenderPassBeginInfo),
180 | EndRenderPass,
181 | BindPipeline {
182 | bind_point: vk::VkPipelineBindPoint,
183 | pipeline: vk::VkPipeline,
184 | },
185 | BindVertexBuffers {
186 | first_binding: u32,
187 | buffers: Vec<vk::VkBuffer>,
188 | offsets: Vec<vk::VkDeviceSize>,
189 | },
190 | BindIndexBuffer {
191 | buffer: vk::VkBuffer,
192 | offset: vk::VkDeviceSize,
193 | index_type: vk::VkIndexType,
194 | },
195 | Draw {
196 | vertex_count: u32,
197 | instance_count: u32,
198 | first_vertex: u32,
199 | first_instance: u32,
200 | },
201 | DrawIndexed {
202 | index_count: u32,
203 | instance_count: u32,
204 | first_index: u32,
205 | vertex_offset: i32,
206 | first_instance: u32,
207 | },
208 | Dispatch {
209 | x: u32,
210 | y: u32,
211 | z: u32,
212 | },
213 | ClearAttachments {
214 | attachments: Vec<ClearAttachment>,
215 | rects: Vec<vk::VkClearRect>,
216 | },
217 | PipelineBarrier {
218 | src_stage_mask: vk::VkPipelineStageFlags,
219 | dst_stage_mask: vk::VkPipelineStageFlags,
220 | dependency_flags: vk::VkDependencyFlags,
221 | memory_barriers: Vec<vk::VkMemoryBarrier>,
222 | buffer_memory_barriers: Vec<vk::VkBufferMemoryBarrier>,
223 | image_memory_barriers: Vec<vk::VkImageMemoryBarrier>,
224 | },
225 | CopyImageToBuffer {
226 | src_image: vk::VkImage,
227 | src_image_layout: vk::VkImageLayout,
228 | dst_buffer: vk::VkBuffer,
229 | regions: Vec<vk::VkBufferImageCopy>,
230 | },
231 | PushConstants {
232 | layout: vk::VkPipelineLayout,
233 | stage_flags: vk::VkShaderStageFlags,
234 | offset: u32,
235 | values: Vec<u8>,
236 | },
237 | BindDescriptorSets {
238 | pipeline_bind_point: vk::VkPipelineBindPoint,
239 | layout: vk::VkPipelineLayout,
240 | first_set: u32,
241 | descriptor_sets: Vec<vk::VkDescriptorSet>,
242 | },
243 | }
244 |
245 | #[derive(Debug)]
246 | pub enum HandleType {
247 | Instance,
248 | Device,
249 | CommandPool,
250 | CommandBuffer {
251 | command_pool: usize,
252 | commands: Vec<Command>,
253 | begun: bool,
254 | },
255 | Fence {
256 | reset_count: usize,
257 | wait_count: usize,
258 | },
259 | Memory {
260 | contents: Vec<u8>,
261 | mapped: bool,
262 | },
263 | RenderPass { attachments: Vec<vk::VkAttachmentDescription> },
264 | Image,
265 | ImageView,
266 | Buffer {
267 | create_info: vk::VkBufferCreateInfo,
268 | memory: Option<vk::VkDeviceMemory>,
269 | },
270 | Framebuffer,
271 | ShaderModule { code: Vec<u32> },
272 | PipelineCache,
273 | DescriptorPool,
274 | DescriptorSetLayout { bindings: Vec<vk::VkDescriptorSetLayoutBinding> },
275 | PipelineLayout(PipelineLayoutCreateInfo),
276 | Pipeline(PipelineCreateInfo),
277 | DescriptorSet { bindings: HashMap<u32, Binding> },
278 | }
279 |
280 | #[derive(Debug)]
281 | pub struct Binding {
282 | pub descriptor_type: vk::VkDescriptorType,
283 | pub info: vk::VkDescriptorBufferInfo,
284 | }
285 |
286 | #[derive(Debug)]
287 | pub struct Handle {
288 | pub freed: bool,
289 | pub data: HandleType,
290 | }
291 |
292 | fn vec_from_raw_parts<T: std::clone::Clone>(data: *const T, len: usize) -> Vec<T> {
293 | if len > 0 {
294 | unsafe {
295 | std::slice::from_raw_parts(data, len).to_vec()
296 | }
297 | } else {
298 | Vec::new()
299 | }
300 | }
301 |
302 | /// A fake Vulkan driver. Note that there can only be one FakeVulkan
303 | /// instance per-thread because it needs to use thread-local storage
304 | /// to figure out the current fake driver when the fake
305 | /// vkCreateInstance is called. The FakeVulkan should always be stored
306 | /// in a box so that its address can be tracked in
307 | /// [CURRENT_FAKE_VULKAN].
308 | #[derive(Debug)]
309 | pub struct FakeVulkan {
310 | pub physical_devices: Vec<PhysicalDeviceInfo>,
311 | pub instance_extensions: Vec<vk::VkExtensionProperties>,
312 |
313 | // A fake set of requirements to return from the next call to
314 | // vkGetBufferMemoryRequirements or vkGetImageMemoryRequirements.
315 | pub memory_requirements: vk::VkMemoryRequirements,
316 |
317 | /// Whether to claim that the vkEnumerateInstanceVersion function
318 | /// is available.
319 | pub has_enumerate_instance_version: bool,
320 |
321 | /// Log of calls to vkFlushMappedMemoryRanges
322 | pub memory_flushes: Vec<vk::VkMappedMemoryRange>,
323 | /// Log of calls to vkInvalidateMappedMemoryRanges
324 | pub memory_invalidations: Vec<vk::VkMappedMemoryRange>,
325 |
326 | /// All of the commands from command queues that were submitted
327 | /// with vkQueueSubmit
328 | pub commands: Vec<Command>,
329 |
330 | handles: Vec<Handle>,
331 |
332 | // Queue of values to return instead of VK_SUCCESS to simulate
333 | // function call failures. This is indexed by the function name
334 | // and the value is a queue of override values to return.
335 | result_queue: HashMap<String, VecDeque<vk::VkResult>>,
336 | }
337 |
338 | impl FakeVulkan {
339 | pub fn new() -> Box<FakeVulkan> {
340 | let mut fake_vulkan = Box::new(FakeVulkan {
341 | physical_devices: Vec::new(),
342 | instance_extensions: Vec::new(),
343 | memory_requirements: Default::default(),
344 | handles: Vec::new(),
345 | has_enumerate_instance_version: false,
346 | result_queue: HashMap::new(),
347 | memory_flushes: Vec::new(),
348 | memory_invalidations: Vec::new(),
349 | commands: Vec::new(),
350 | });
351 |
352 | CURRENT_FAKE_VULKAN.with(|f| {
353 | let old_value = f.replace(Some(
354 | fake_vulkan.as_mut() as *mut FakeVulkan
355 | ));
356 |
357 | // There can only be one FakeVulkan instance per thread at a time
358 | assert!(old_value.is_none());
359 | });
360 |
361 | fake_vulkan
362 | }
363 |
364 | pub fn current() -> &'static mut FakeVulkan {
365 | unsafe { &mut *CURRENT_FAKE_VULKAN.with(|f| f.get().unwrap()) }
366 | }
367 |
368 | fn next_result(&mut self, func_name: &str) -> vk::VkResult {
369 | match self.result_queue.get_mut(func_name) {
370 | Some(queue) => match queue.pop_front() {
371 | Some(res) => res,
372 | None => vk::VK_SUCCESS,
373 | },
374 | None => vk::VK_SUCCESS,
375 | }
376 | }
377 |
378 | /// Queue a VkResult to return the next time the named function is
379 | /// called. The value will be used only once and after that the
380 | /// function will revert to always returning VK_SUCCESS. This can
381 | /// be called multiple times to queue multiple results before
382 | /// reverting.
383 | pub fn queue_result(&mut self, func_name: String, result: vk::VkResult) {
384 | self.result_queue
385 | .entry(func_name)
386 | .or_insert_with(Default::default)
387 | .push_back(result);
388 | }
389 |
390 | /// Sets the get_proc_addr override on the [vulkan_funcs] so that
391 | /// it will use this FakeVulkan driver the next time a
392 | /// [Library](vulkan_funcs::Library) is created.
393 | pub fn set_override(&self) {
394 | vulkan_funcs::override_get_instance_proc_addr(
395 | ptr::addr_of!(*self).cast(),
396 | Some(FakeVulkan::get_instance_proc_addr),
397 | );
398 | }
399 |
400 | pub fn add_instance_extension(&mut self, ext: &str) {
401 | add_extension_to_vec(&mut self.instance_extensions, ext);
402 | }
403 |
404 | pub fn get_function(&self, name: *const c_char) -> vk::PFN_vkVoidFunction {
405 | let name = unsafe { CStr::from_ptr(name).to_str().unwrap() };
406 |
407 | match name {
408 | "vkGetDeviceProcAddr" => unsafe {
409 | transmute::<vk::PFN_vkGetDeviceProcAddr, _>(
410 | Some(FakeVulkan::get_device_proc_addr)
411 | )
412 | },
413 | "vkCreateInstance" => unsafe {
414 | transmute::<vk::PFN_vkCreateInstance, _>(
415 | Some(FakeVulkan::create_instance)
416 | )
417 | },
418 | "vkEnumeratePhysicalDevices" => unsafe {
419 | transmute::<vk::PFN_vkEnumeratePhysicalDevices, _>(
420 | Some(FakeVulkan::enumerate_physical_devices)
421 | )
422 | },
423 | "vkGetPhysicalDeviceMemoryProperties" => unsafe {
424 | transmute::<vk::PFN_vkGetPhysicalDeviceMemoryProperties, _>(
425 | Some(FakeVulkan::get_physical_device_memory_properties)
426 | )
427 | },
428 | "vkGetPhysicalDeviceFormatProperties" => unsafe {
429 | transmute::<vk::PFN_vkGetPhysicalDeviceFormatProperties, _>(
430 | Some(FakeVulkan::get_physical_device_format_properties)
431 | )
432 | },
433 | "vkGetPhysicalDeviceProperties" => unsafe {
434 | transmute::<vk::PFN_vkGetPhysicalDeviceProperties, _>(
435 | Some(FakeVulkan::get_physical_device_properties)
436 | )
437 | },
438 | "vkGetPhysicalDeviceProperties2" => unsafe {
439 | transmute::<vk::PFN_vkGetPhysicalDeviceProperties2, _>(
440 | Some(FakeVulkan::get_physical_device_properties2)
441 | )
442 | },
443 | "vkGetPhysicalDeviceFeatures" => unsafe {
444 | transmute::<vk::PFN_vkGetPhysicalDeviceFeatures, _>(
445 | Some(FakeVulkan::get_physical_device_features)
446 | )
447 | },
448 | "vkGetPhysicalDeviceQueueFamilyProperties" => unsafe {
449 | type T = vk::PFN_vkGetPhysicalDeviceQueueFamilyProperties;
450 | transmute::<T, _>(Some(
451 | FakeVulkan::get_physical_device_queue_family_properties
452 | ))
453 | },
454 | "vkGetDeviceQueue" => unsafe {
455 | transmute::<vk::PFN_vkGetDeviceQueue, _>(
456 | Some(FakeVulkan::get_device_queue)
457 | )
458 | },
459 | "vkEnumerateInstanceExtensionProperties" => unsafe {
460 | transmute::<vk::PFN_vkEnumerateInstanceExtensionProperties, _>(
461 | Some(FakeVulkan::enumerate_instance_extension_properties)
462 | )
463 | },
464 | "vkEnumerateDeviceExtensionProperties" => unsafe {
465 | transmute::<vk::PFN_vkEnumerateDeviceExtensionProperties, _>(
466 | Some(FakeVulkan::enumerate_device_extension_properties)
467 | )
468 | },
469 | "vkCreateDevice" => unsafe {
470 | transmute::<vk::PFN_vkCreateDevice, _>(
471 | Some(FakeVulkan::create_device)
472 | )
473 | },
474 | "vkDestroyInstance" => unsafe {
475 | transmute::<vk::PFN_vkDestroyInstance, _>(
476 | Some(FakeVulkan::destroy_instance)
477 | )
478 | },
479 | "vkDestroyDevice" => unsafe {
480 | transmute::<vk::PFN_vkDestroyDevice, _>(
481 | Some(FakeVulkan::destroy_device)
482 | )
483 | },
484 | "vkCreateCommandPool" => unsafe {
485 | transmute::<vk::PFN_vkCreateCommandPool, _>(
486 | Some(FakeVulkan::create_command_pool)
487 | )
488 | },
489 | "vkDestroyCommandPool" => unsafe {
490 | transmute::<vk::PFN_vkDestroyCommandPool, _>(
491 | Some(FakeVulkan::destroy_command_pool)
492 | )
493 | },
494 | "vkAllocateCommandBuffers" => unsafe {
495 | transmute::<vk::PFN_vkAllocateCommandBuffers, _>(
496 | Some(FakeVulkan::allocate_command_buffers)
497 | )
498 | },
499 | "vkFreeCommandBuffers" => unsafe {
500 | transmute::<vk::PFN_vkFreeCommandBuffers, _>(
501 | Some(FakeVulkan::free_command_buffers)
502 | )
503 | },
504 | "vkCreateFence" => unsafe {
505 | transmute::<vk::PFN_vkCreateFence, _>(
506 | Some(FakeVulkan::create_fence)
507 | )
508 | },
509 | "vkDestroyFence" => unsafe {
510 | transmute::<vk::PFN_vkDestroyFence, _>(
511 | Some(FakeVulkan::destroy_fence)
512 | )
513 | },
514 | "vkCreateRenderPass" => unsafe {
515 | transmute::<vk::PFN_vkCreateRenderPass, _>(
516 | Some(FakeVulkan::create_render_pass)
517 | )
518 | },
519 | "vkDestroyRenderPass" => unsafe {
520 | transmute::<vk::PFN_vkDestroyRenderPass, _>(
521 | Some(FakeVulkan::destroy_render_pass)
522 | )
523 | },
524 | "vkCreateImageView" => unsafe {
525 | transmute::<vk::PFN_vkCreateImageView, _>(
526 | Some(FakeVulkan::create_image_view)
527 | )
528 | },
529 | "vkDestroyImageView" => unsafe {
530 | transmute::<vk::PFN_vkDestroyImageView, _>(
531 | Some(FakeVulkan::destroy_image_view)
532 | )
533 | },
534 | "vkCreateImage" => unsafe {
535 | transmute::<vk::PFN_vkCreateImage, _>(
536 | Some(FakeVulkan::create_image)
537 | )
538 | },
539 | "vkDestroyImage" => unsafe {
540 | transmute::<vk::PFN_vkDestroyImage, _>(
541 | Some(FakeVulkan::destroy_image)
542 | )
543 | },
544 | "vkCreateBuffer" => unsafe {
545 | transmute::<vk::PFN_vkCreateBuffer, _>(
546 | Some(FakeVulkan::create_buffer)
547 | )
548 | },
549 | "vkDestroyBuffer" => unsafe {
550 | transmute::<vk::PFN_vkDestroyBuffer, _>(
551 | Some(FakeVulkan::destroy_buffer)
552 | )
553 | },
554 | "vkCreateFramebuffer" => unsafe {
555 | transmute::<vk::PFN_vkCreateFramebuffer, _>(
556 | Some(FakeVulkan::create_framebuffer)
557 | )
558 | },
559 | "vkDestroyFramebuffer" => unsafe {
560 | transmute::<vk::PFN_vkDestroyFramebuffer, _>(
561 | Some(FakeVulkan::destroy_framebuffer)
562 | )
563 | },
564 | "vkEnumerateInstanceVersion" => unsafe {
565 | if self.has_enumerate_instance_version {
566 | transmute::<vk::PFN_vkEnumerateInstanceVersion, _>(
567 | Some(FakeVulkan::enumerate_instance_version)
568 | )
569 | } else {
570 | None
571 | }
572 | },
573 | "vkGetPhysicalDeviceFeatures2KHR" => unsafe {
574 | transmute::<vk::PFN_vkGetPhysicalDeviceFeatures2, _>(
575 | Some(FakeVulkan::get_physical_device_features2)
576 | )
577 | },
578 | "vkGetImageMemoryRequirements" => unsafe {
579 | transmute::<vk::PFN_vkGetImageMemoryRequirements, _>(
580 | Some(FakeVulkan::get_image_memory_requirements)
581 | )
582 | },
583 | "vkGetBufferMemoryRequirements" => unsafe {
584 | transmute::<vk::PFN_vkGetBufferMemoryRequirements, _>(
585 | Some(FakeVulkan::get_buffer_memory_requirements)
586 | )
587 | },
588 | "vkBindBufferMemory" => unsafe {
589 | transmute::<vk::PFN_vkBindBufferMemory, _>(
590 | Some(FakeVulkan::bind_buffer_memory)
591 | )
592 | },
593 | "vkBindImageMemory" => unsafe {
594 | transmute::<vk::PFN_vkBindImageMemory, _>(
595 | Some(FakeVulkan::bind_image_memory)
596 | )
597 | },
598 | "vkAllocateMemory" => unsafe {
599 | transmute::<vk::PFN_vkAllocateMemory, _>(
600 | Some(FakeVulkan::allocate_memory)
601 | )
602 | },
603 | "vkFreeMemory" => unsafe {
604 | transmute::<vk::PFN_vkFreeMemory, _>(
605 | Some(FakeVulkan::free_memory)
606 | )
607 | },
608 | "vkMapMemory" => unsafe {
609 | transmute::<vk::PFN_vkMapMemory, _>(
610 | Some(FakeVulkan::map_memory)
611 | )
612 | },
613 | "vkUnmapMemory" => unsafe {
614 | transmute::<vk::PFN_vkUnmapMemory, _>(
615 | Some(FakeVulkan::unmap_memory)
616 | )
617 | },
618 | "vkCreateShaderModule" => unsafe {
619 | transmute::<vk::PFN_vkCreateShaderModule, _>(
620 | Some(FakeVulkan::create_shader_module)
621 | )
622 | },
623 | "vkDestroyShaderModule" => unsafe {
624 | transmute::<vk::PFN_vkDestroyShaderModule, _>(
625 | Some(FakeVulkan::destroy_shader_module)
626 | )
627 | },
628 | "vkCreatePipelineCache" => unsafe {
629 | transmute::<vk::PFN_vkCreatePipelineCache, _>(
630 | Some(FakeVulkan::create_pipeline_cache)
631 | )
632 | },
633 | "vkDestroyPipelineCache" => unsafe {
634 | transmute::<vk::PFN_vkDestroyPipelineCache, _>(
635 | Some(FakeVulkan::destroy_pipeline_cache)
636 | )
637 | },
638 | "vkCreateDescriptorPool" => unsafe {
639 | transmute::<vk::PFN_vkCreateDescriptorPool, _>(
640 | Some(FakeVulkan::create_descriptor_pool)
641 | )
642 | },
643 | "vkDestroyDescriptorPool" => unsafe {
644 | transmute::<vk::PFN_vkDestroyDescriptorPool, _>(
645 | Some(FakeVulkan::destroy_descriptor_pool)
646 | )
647 | },
648 | "vkCreateDescriptorSetLayout" => unsafe {
649 | transmute::<vk::PFN_vkCreateDescriptorSetLayout, _>(
650 | Some(FakeVulkan::create_descriptor_set_layout)
651 | )
652 | },
653 | "vkDestroyDescriptorSetLayout" => unsafe {
654 | transmute::<vk::PFN_vkDestroyDescriptorSetLayout, _>(
655 | Some(FakeVulkan::destroy_descriptor_set_layout)
656 | )
657 | },
658 | "vkCreatePipelineLayout" => unsafe {
659 | transmute::<vk::PFN_vkCreatePipelineLayout, _>(
660 | Some(FakeVulkan::create_pipeline_layout)
661 | )
662 | },
663 | "vkDestroyPipelineLayout" => unsafe {
664 | transmute::<vk::PFN_vkDestroyPipelineLayout, _>(
665 | Some(FakeVulkan::destroy_pipeline_layout)
666 | )
667 | },
668 | "vkCreateGraphicsPipelines" => unsafe {
669 | transmute::<vk::PFN_vkCreateGraphicsPipelines, _>(
670 | Some(FakeVulkan::create_graphics_pipelines)
671 | )
672 | },
673 | "vkCreateComputePipelines" => unsafe {
674 | transmute::<vk::PFN_vkCreateComputePipelines, _>(
675 | Some(FakeVulkan::create_compute_pipelines)
676 | )
677 | },
678 | "vkDestroyPipeline" => unsafe {
679 | transmute::<vk::PFN_vkDestroyPipeline, _>(
680 | Some(FakeVulkan::destroy_pipeline)
681 | )
682 | },
683 | "vkFlushMappedMemoryRanges" => unsafe {
684 | transmute::<vk::PFN_vkFlushMappedMemoryRanges, _>(
685 | Some(FakeVulkan::flush_mapped_memory_ranges)
686 | )
687 | },
688 | "vkInvalidateMappedMemoryRanges" => unsafe {
689 | transmute::<vk::PFN_vkInvalidateMappedMemoryRanges, _>(
690 | Some(FakeVulkan::invalidate_mapped_memory_ranges)
691 | )
692 | },
693 | "vkQueueSubmit" => unsafe {
694 | transmute::<vk::PFN_vkQueueSubmit, _>(
695 | Some(FakeVulkan::queue_submit)
696 | )
697 | },
698 | "vkAllocateDescriptorSets" => unsafe {
699 | transmute::<vk::PFN_vkAllocateDescriptorSets, _>(
700 | Some(FakeVulkan::allocate_descriptor_sets)
701 | )
702 | },
703 | "vkFreeDescriptorSets" => unsafe {
704 | transmute::<vk::PFN_vkFreeDescriptorSets, _>(
705 | Some(FakeVulkan::free_descriptor_sets)
706 | )
707 | },
708 | "vkUpdateDescriptorSets" => unsafe {
709 | transmute::<vk::PFN_vkUpdateDescriptorSets, _>(
710 | Some(FakeVulkan::update_descriptor_sets)
711 | )
712 | },
713 | "vkBeginCommandBuffer" => unsafe {
714 | transmute::<vk::PFN_vkBeginCommandBuffer, _>(
715 | Some(FakeVulkan::begin_command_buffer)
716 | )
717 | },
718 | "vkEndCommandBuffer" => unsafe {
719 | transmute::<vk::PFN_vkEndCommandBuffer, _>(
720 | Some(FakeVulkan::end_command_buffer)
721 | )
722 | },
723 | "vkCmdBeginRenderPass" => unsafe {
724 | transmute::<vk::PFN_vkCmdBeginRenderPass, _>(
725 | Some(FakeVulkan::begin_render_pass)
726 | )
727 | },
728 | "vkCmdEndRenderPass" => unsafe {
729 | transmute::<vk::PFN_vkCmdEndRenderPass, _>(
730 | Some(FakeVulkan::end_render_pass)
731 | )
732 | },
733 | "vkCmdBindPipeline" => unsafe {
734 | transmute::<vk::PFN_vkCmdBindPipeline, _>(
735 | Some(FakeVulkan::bind_pipeline)
736 | )
737 | },
738 | "vkCmdBindVertexBuffers" => unsafe {
739 | transmute::<vk::PFN_vkCmdBindVertexBuffers, _>(
740 | Some(FakeVulkan::bind_vertex_buffers)
741 | )
742 | },
743 | "vkCmdBindIndexBuffer" => unsafe {
744 | transmute::<vk::PFN_vkCmdBindIndexBuffer, _>(
745 | Some(FakeVulkan::bind_index_buffer)
746 | )
747 | },
748 | "vkCmdDraw" => unsafe {
749 | transmute::<vk::PFN_vkCmdDraw, _>(
750 | Some(FakeVulkan::draw)
751 | )
752 | },
753 | "vkCmdDrawIndexed" => unsafe {
754 | transmute::<vk::PFN_vkCmdDrawIndexed, _>(
755 | Some(FakeVulkan::draw_indexed)
756 | )
757 | },
758 | "vkCmdDispatch" => unsafe {
759 | transmute::<vk::PFN_vkCmdDispatch, _>(
760 | Some(FakeVulkan::dispatch)
761 | )
762 | },
763 | "vkCmdClearAttachments" => unsafe {
764 | transmute::<vk::PFN_vkCmdClearAttachments, _>(
765 | Some(FakeVulkan::clear_attachments)
766 | )
767 | },
768 | "vkCmdPipelineBarrier" => unsafe {
769 | transmute::<vk::PFN_vkCmdPipelineBarrier, _>(
770 | Some(FakeVulkan::pipeline_barrier)
771 | )
772 | },
773 | "vkCmdCopyImageToBuffer" => unsafe {
774 | transmute::<vk::PFN_vkCmdCopyImageToBuffer, _>(
775 | Some(FakeVulkan::copy_image_to_buffer)
776 | )
777 | },
778 | "vkCmdPushConstants" => unsafe {
779 | transmute::<vk::PFN_vkCmdPushConstants, _>(
780 | Some(FakeVulkan::push_constants)
781 | )
782 | },
783 | "vkCmdBindDescriptorSets" => unsafe {
784 | transmute::<vk::PFN_vkCmdBindDescriptorSets, _>(
785 | Some(FakeVulkan::bind_descriptor_sets)
786 | )
787 | },
788 | "vkResetFences" => unsafe {
789 | transmute::<vk::PFN_vkResetFences, _>(
790 | Some(FakeVulkan::reset_fences)
791 | )
792 | },
793 | "vkWaitForFences" => unsafe {
794 | transmute::<vk::PFN_vkWaitForFences, _>(
795 | Some(FakeVulkan::wait_for_fences)
796 | )
797 | },
798 | _ => None,
799 | }
800 | }
801 |
802 | extern "C" fn get_instance_proc_addr(
803 | _instance: vk::VkInstance,
804 | name: *const c_char,
805 | ) -> vk::PFN_vkVoidFunction {
806 | let fake_vulkan = FakeVulkan::current();
807 |
808 | fake_vulkan.get_function(name)
809 | }
810 |
811 | extern "C" fn get_device_proc_addr(
812 | _device: vk::VkDevice,
813 | name: *const c_char,
814 | ) -> vk::PFN_vkVoidFunction {
815 | let fake_vulkan = FakeVulkan::current();
816 |
817 | fake_vulkan.get_function(name)
818 | }
819 |
820 | fn copy_with_count<T>(
821 | values: &[T],
822 | count_ptr: *mut u32,
823 | array_ptr: *mut T,
824 | ) where
825 | T: Clone,
826 | {
827 | if array_ptr.is_null() {
828 | unsafe {
829 | *count_ptr = values.len() as u32;
830 | }
831 |
832 | return;
833 | }
834 |
835 | let count = min(
836 | unsafe { *count_ptr } as usize,
837 | values.len(),
838 | );
839 |
840 | for (i, value) in values.iter().take(count).enumerate() {
841 | unsafe {
842 | *array_ptr.add(i) = value.clone();
843 | }
844 | }
845 | }
846 |
847 | extern "C" fn enumerate_physical_devices(
848 | _instance: vk::VkInstance,
849 | physical_device_count: *mut u32,
850 | physical_devices: *mut vk::VkPhysicalDevice,
851 | ) -> vk::VkResult {
852 | let fake_vulkan = FakeVulkan::current();
853 |
854 | if physical_devices.is_null() {
855 | unsafe {
856 | *physical_device_count =
857 | fake_vulkan.physical_devices.len() as u32;
858 | }
859 |
860 | return fake_vulkan.next_result("vkEnumeratePhysicalDevices");
861 | }
862 |
863 | let count = min(
864 | unsafe { *physical_device_count as usize },
865 | fake_vulkan.physical_devices.len()
866 | );
867 |
868 | for i in 0..count {
869 | unsafe {
870 | // Store the device index as a pointer. We add 1 so
871 | // that it won’t be null.
872 | *physical_devices.add(i) =
873 | fake_vulkan.index_to_physical_device(i);
874 | }
875 | }
876 |
877 | unsafe {
878 | *physical_device_count = count as u32;
879 | }
880 |
881 | fake_vulkan.next_result("vkEnumeratePhysicalDevices")
882 | }
883 |
884 | /// Get the physical device that would point to the device at the
885 | /// given index.
886 | pub fn index_to_physical_device(
887 | &self,
888 | index: usize,
889 | ) -> vk::VkPhysicalDevice {
890 | assert!(index < self.physical_devices.len());
891 | unsafe { transmute(index + 1) }
892 | }
893 |
894 | /// Get the index of the physical device represented by the
895 | /// VkPhysicalDevice pointer.
896 | pub fn physical_device_to_index(
897 | &self,
898 | physical_device: vk::VkPhysicalDevice
899 | ) -> usize {
900 | assert!(!physical_device.is_null());
901 | let index = unsafe { transmute::<_, usize>(physical_device) - 1 };
902 | assert!(index < self.physical_devices.len());
903 | index
904 | }
905 |
906 | extern "C" fn get_physical_device_memory_properties(
907 | physical_device: vk::VkPhysicalDevice,
908 | memory_properties_out: *mut vk::VkPhysicalDeviceMemoryProperties,
909 | ) {
910 | let fake_vulkan = FakeVulkan::current();
911 |
912 | unsafe {
913 | let device_num =
914 | fake_vulkan.physical_device_to_index(physical_device);
915 | let device = &fake_vulkan.physical_devices[device_num];
916 | *memory_properties_out = device.memory_properties.clone();
917 | }
918 | }
919 |
920 | extern "C" fn get_physical_device_properties(
921 | physical_device: vk::VkPhysicalDevice,
922 | properties_out: *mut vk::VkPhysicalDeviceProperties,
923 | ) {
924 | let fake_vulkan = FakeVulkan::current();
925 |
926 | unsafe {
927 | let device_num =
928 | fake_vulkan.physical_device_to_index(physical_device);
929 | let device = &fake_vulkan.physical_devices[device_num];
930 | *properties_out = device.properties.clone();
931 | }
932 | }
933 |
934 | extern "C" fn get_physical_device_properties2(
935 | physical_device: vk::VkPhysicalDevice,
936 | properties_out: *mut vk::VkPhysicalDeviceProperties2,
937 | ) {
938 | let fake_vulkan = FakeVulkan::current();
939 | let device_num = fake_vulkan.physical_device_to_index(physical_device);
940 | let device = &fake_vulkan.physical_devices[device_num];
941 |
942 | unsafe {
943 | assert_eq!(
944 | (*properties_out).sType,
945 | vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2
946 | );
947 |
948 | (*properties_out).properties = device.properties.clone();
949 | }
950 | }
951 |
952 | extern "C" fn get_physical_device_features(
953 | physical_device: vk::VkPhysicalDevice,
954 | features_out: *mut vk::VkPhysicalDeviceFeatures,
955 | ) {
956 | let fake_vulkan = FakeVulkan::current();
957 |
958 | unsafe {
959 | let device_num =
960 | fake_vulkan.physical_device_to_index(physical_device);
961 | let device = &fake_vulkan.physical_devices[device_num];
962 | *features_out = device.features.clone();
963 | }
964 | }
965 |
966 | extern "C" fn get_physical_device_format_properties(
967 | physical_device: vk::VkPhysicalDevice,
968 | format: vk::VkFormat,
969 | properties: *mut vk::VkFormatProperties,
970 | ) {
971 | let fake_vulkan = FakeVulkan::current();
972 |
973 | let device_num =
974 | fake_vulkan.physical_device_to_index(physical_device);
975 | let device = &fake_vulkan.physical_devices[device_num];
976 |
977 | unsafe {
978 | *properties = device.format_properties[&format];
979 | }
980 | }
981 |
982 | fn extract_struct_data(
983 | ptr: *mut u8
984 | ) -> (vk::VkStructureType, *mut u8) {
985 | let mut type_bytes =
986 | [0u8; mem::size_of::<vk::VkStructureType>()];
987 | unsafe {
988 | ptr.copy_to(type_bytes.as_mut_ptr(), type_bytes.len());
989 | }
990 | let mut next_bytes =
991 | [0u8; mem::size_of::<*mut u8>()];
992 | unsafe {
993 | ptr.add(vulkan_funcs::NEXT_PTR_OFFSET).copy_to(
994 | next_bytes.as_mut_ptr(), next_bytes.len()
995 | );
996 | }
997 |
998 | (
999 | vk::VkStructureType::from_ne_bytes(type_bytes),
1000 | usize::from_ne_bytes(next_bytes) as *mut u8,
1001 | )
1002 | }
1003 |
1004 | extern "C" fn get_physical_device_features2(
1005 | physical_device: vk::VkPhysicalDevice,
1006 | features: *mut vk::VkPhysicalDeviceFeatures2,
1007 | ) {
1008 | let fake_vulkan = FakeVulkan::current();
1009 |
1010 | let device_num = fake_vulkan.physical_device_to_index(physical_device);
1011 | let device = &fake_vulkan.physical_devices[device_num];
1012 |
1013 | let (struct_type, mut struct_ptr) =
1014 | FakeVulkan::extract_struct_data(features.cast());
1015 |
1016 | assert_eq!(
1017 | struct_type,
1018 | vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2
1019 | );
1020 |
1021 | while !struct_ptr.is_null() {
1022 | let (struct_type, next_ptr) =
1023 | FakeVulkan::extract_struct_data(struct_ptr);
1024 |
1025 | let to_copy = match struct_type {
1026 | ATOMIC_TYPE => vec![
1027 | device.shader_atomic.shaderBufferInt64Atomics,
1028 | device.shader_atomic.shaderSharedInt64Atomics,
1029 | ],
1030 | MULTIVIEW_TYPE => vec![
1031 | device.multiview.multiview,
1032 | device.multiview.multiviewGeometryShader,
1033 | device.multiview.multiviewTessellationShader,
1034 | ],
1035 | _ => unreachable!("unexpected struct type {}", struct_type),
1036 | };
1037 |
1038 | unsafe {
1039 | std::ptr::copy(
1040 | to_copy.as_ptr(),
1041 | struct_ptr.add(vulkan_funcs::FIRST_FEATURE_OFFSET).cast(),
1042 | to_copy.len(),
1043 | );
1044 | }
1045 |
1046 | struct_ptr = next_ptr;
1047 | }
1048 | }
1049 |
1050 | extern "C" fn get_physical_device_queue_family_properties(
1051 | physical_device: vk::VkPhysicalDevice,
1052 | property_count_out: *mut u32,
1053 | properties: *mut vk::VkQueueFamilyProperties,
1054 | ) {
1055 | let fake_vulkan = FakeVulkan::current();
1056 |
1057 | let device_num = fake_vulkan.physical_device_to_index(physical_device);
1058 | let device = &fake_vulkan.physical_devices[device_num];
1059 |
1060 | FakeVulkan::copy_with_count(
1061 | &device.queue_families,
1062 | property_count_out,
1063 | properties,
1064 | );
1065 | }
1066 |
1067 | #[inline]
1068 | pub fn make_queue(
1069 | queue_family_index: u32,
1070 | queue_index: u32
1071 | ) -> vk::VkQueue {
1072 | let queue =
1073 | ((queue_family_index << 9) | (queue_index << 1) | 1) as usize;
1074 | queue as vk::VkQueue
1075 | }
1076 |
1077 | #[inline]
1078 | pub fn unmake_queue(
1079 | queue: vk::VkQueue,
1080 | ) -> (u32, u32) {
1081 | let queue = queue as usize;
1082 | ((queue >> 9) as u32, ((queue >> 1) & 0xff) as u32)
1083 | }
1084 |
1085 | extern "C" fn get_device_queue(
1086 | _device: vk::VkDevice,
1087 | queue_family_index: u32,
1088 | queue_index: u32,
1089 | queue_out: *mut vk::VkQueue,
1090 | ) {
1091 | unsafe {
1092 | *queue_out = FakeVulkan::make_queue(
1093 | queue_family_index,
1094 | queue_index
1095 | );
1096 | }
1097 | }
1098 |
1099 | extern "C" fn enumerate_instance_extension_properties(
1100 | _layer_name: *const c_char,
1101 | property_count: *mut u32,
1102 | properties: *mut vk::VkExtensionProperties,
1103 | ) -> vk::VkResult {
1104 | let fake_vulkan = FakeVulkan::current();
1105 |
1106 | FakeVulkan::copy_with_count(
1107 | &fake_vulkan.instance_extensions,
1108 | property_count,
1109 | properties,
1110 | );
1111 |
1112 | fake_vulkan.next_result("vkEnumerateInstanceExtensionProperties")
1113 | }
1114 |
1115 | extern "C" fn enumerate_device_extension_properties(
1116 | physical_device: vk::VkPhysicalDevice,
1117 | _layer_name: *const c_char,
1118 | property_count: *mut u32,
1119 | properties: *mut vk::VkExtensionProperties,
1120 | ) -> vk::VkResult {
1121 | let fake_vulkan = FakeVulkan::current();
1122 |
1123 | let device_num = fake_vulkan.physical_device_to_index(physical_device);
1124 | let device = &fake_vulkan.physical_devices[device_num];
1125 |
1126 | FakeVulkan::copy_with_count(
1127 | &device.extensions,
1128 | property_count,
1129 | properties,
1130 | );
1131 |
1132 | fake_vulkan.next_result("vkEnumerateDeviceExtensionProperties")
1133 | }
1134 |
1135 | pub fn add_dispatchable_handle<T>(&mut self, data: HandleType) -> *mut T {
1136 | self.handles.push(Handle {
1137 | freed: false,
1138 | data,
1139 | });
1140 |
1141 | self.handles.len() as *mut T
1142 | }
1143 |
1144 | #[cfg(target_pointer_width = "64")]
1145 | pub fn add_handle<T>(&mut self, data: HandleType) -> *mut T {
1146 | self.add_dispatchable_handle(data)
1147 | }
1148 |
1149 | #[cfg(not(target_pointer_width = "64"))]
1150 | pub fn add_handle(&mut self, data: HandleType) -> u64 {
1151 | self.handles.push(Handle {
1152 | freed: false,
1153 | data,
1154 | });
1155 |
1156 | self.handles.len() as u64
1157 | }
1158 |
1159 | pub fn dispatchable_handle_to_index<T>(handle: *mut T) -> usize {
1160 | let handle_num = handle as usize;
1161 |
1162 | assert!(handle_num > 0);
1163 |
1164 | handle_num - 1
1165 | }
1166 |
1167 | #[cfg(target_pointer_width = "64")]
1168 | pub fn handle_to_index<T>(handle: *mut T) -> usize {
1169 | FakeVulkan::dispatchable_handle_to_index(handle)
1170 | }
1171 |
1172 | #[cfg(not(target_pointer_width = "64"))]
1173 | pub fn handle_to_index(handle: u64) -> usize {
1174 | assert!(handle > 0);
1175 |
1176 | (handle - 1) as usize
1177 | }
1178 |
1179 | pub fn get_dispatchable_handle<T>(&self, handle: *mut T) -> &Handle {
1180 | let index = FakeVulkan::dispatchable_handle_to_index(handle);
1181 | let handle = &self.handles[index];
1182 |
1183 | assert!(!handle.freed);
1184 |
1185 | handle
1186 | }
1187 |
1188 | pub fn get_dispatchable_handle_mut<T>(
1189 | &mut self,
1190 | handle: *mut T,
1191 | ) -> &mut Handle {
1192 | let index = FakeVulkan::dispatchable_handle_to_index(handle);
1193 | let handle = &mut self.handles[index];
1194 |
1195 | assert!(!handle.freed);
1196 |
1197 | handle
1198 | }
1199 |
1200 | #[cfg(target_pointer_width = "64")]
1201 | pub fn get_handle<T>(&self, handle: *mut T) -> &Handle {
1202 | let handle = &self.handles[FakeVulkan::handle_to_index(handle)];
1203 |
1204 | assert!(!handle.freed);
1205 |
1206 | handle
1207 | }
1208 |
1209 | #[cfg(not(target_pointer_width = "64"))]
1210 | pub fn get_handle(&self, handle: u64) -> &Handle {
1211 | let handle = &self.handles[FakeVulkan::handle_to_index(handle)];
1212 |
1213 | assert!(!handle.freed);
1214 |
1215 | handle
1216 | }
1217 |
1218 | #[cfg(target_pointer_width = "64")]
1219 | pub fn get_freed_handle<T>(&self, handle: *mut T) -> &Handle {
1220 | &self.handles[FakeVulkan::handle_to_index(handle)]
1221 | }
1222 |
1223 | #[cfg(not(target_pointer_width = "64"))]
1224 | pub fn get_freed_handle(&self, handle: u64) -> &Handle {
1225 | &self.handles[FakeVulkan::handle_to_index(handle)]
1226 | }
1227 |
1228 | #[cfg(target_pointer_width = "64")]
1229 | pub fn get_handle_mut<T>(&mut self, handle: *mut T) -> &mut Handle {
1230 | let handle = &mut self.handles[FakeVulkan::handle_to_index(handle)];
1231 |
1232 | assert!(!handle.freed);
1233 |
1234 | handle
1235 | }
1236 |
1237 | #[cfg(not(target_pointer_width = "64"))]
1238 | pub fn get_handle_mut(&mut self, handle: u64) -> &mut Handle {
1239 | let handle = &mut self.handles[FakeVulkan::handle_to_index(handle)];
1240 |
1241 | assert!(!handle.freed);
1242 |
1243 | handle
1244 | }
1245 |
1246 | fn check_device(&self, device: vk::VkDevice) {
1247 | let handle = self.get_dispatchable_handle(device);
1248 | assert!(matches!(handle.data, HandleType::Device));
1249 | }
1250 |
1251 | fn check_command_pool(&self, command_pool: vk::VkCommandPool) {
1252 | let handle = self.get_handle(command_pool);
1253 | assert!(matches!(handle.data, HandleType::CommandPool));
1254 | }
1255 |
1256 | fn check_image(&self, image: vk::VkImage) {
1257 | let handle = self.get_handle(image);
1258 | assert!(matches!(handle.data, HandleType::Image));
1259 | }
1260 |
1261 | fn check_descriptor_pool(&self, descriptor_pool: vk::VkDescriptorPool) {
1262 | let handle = self.get_handle(descriptor_pool);
1263 | assert!(matches!(handle.data, HandleType::DescriptorPool));
1264 | }
1265 |
1266 | fn check_image_view(&self, image_view: vk::VkImageView) {
1267 | let handle = self.get_handle(image_view);
1268 | assert!(matches!(handle.data, HandleType::ImageView));
1269 | }
1270 |
1271 | fn check_pipeline_cache(&self, pipeline_cache: vk::VkPipelineCache) {
1272 | let handle = self.get_handle(pipeline_cache);
1273 | assert!(matches!(handle.data, HandleType::PipelineCache));
1274 | }
1275 |
1276 | fn check_fence(&self, fence: vk::VkFence) {
1277 | let handle = self.get_handle(fence);
1278 | assert!(matches!(handle.data, HandleType::Fence { .. }));
1279 | }
1280 |
1281 | fn check_framebuffer(&self, framebuffer: vk::VkFramebuffer) {
1282 | let handle = self.get_handle(framebuffer);
1283 | assert!(matches!(handle.data, HandleType::Framebuffer));
1284 | }
1285 |
1286 | fn check_render_pass(&self, render_pass: vk::VkRenderPass) {
1287 | let handle = self.get_handle(render_pass);
1288 | assert!(matches!(handle.data, HandleType::RenderPass { .. }));
1289 | }
1290 |
1291 | fn check_pipeline(&self, pipeline: vk::VkPipeline) {
1292 | let handle = self.get_handle(pipeline);
1293 | assert!(matches!(handle.data, HandleType::Pipeline { .. }));
1294 | }
1295 |
1296 | fn check_buffer(&self, buffer: vk::VkBuffer) {
1297 | let handle = self.get_handle(buffer);
1298 | assert!(matches!(handle.data, HandleType::Buffer { .. }));
1299 | }
1300 |
1301 | fn check_memory(&self, memory: vk::VkDeviceMemory) {
1302 | let handle = self.get_handle(memory);
1303 | assert!(matches!(handle.data, HandleType::Memory { .. }));
1304 | }
1305 |
1306 | extern "C" fn create_instance(
1307 | _create_info: *const vk::VkInstanceCreateInfo,
1308 | _allocator: *const vk::VkAllocationCallbacks,
1309 | instance_out: *mut vk::VkInstance,
1310 | ) -> vk::VkResult {
1311 | let fake_vulkan = FakeVulkan::current();
1312 |
1313 | let res = fake_vulkan.next_result("vkCreateInstance");
1314 |
1315 | if res != vk::VK_SUCCESS {
1316 | return res;
1317 | }
1318 |
1319 | unsafe {
1320 | *instance_out =
1321 | fake_vulkan.add_dispatchable_handle(HandleType::Instance);
1322 | }
1323 |
1324 | res
1325 | }
1326 |
1327 | extern "C" fn create_device(
1328 | _physical_device: vk::VkPhysicalDevice,
1329 | _create_info: *const vk::VkDeviceCreateInfo,
1330 | _allocator: *const vk::VkAllocationCallbacks,
1331 | device_out: *mut vk::VkDevice,
1332 | ) -> vk::VkResult {
1333 | let fake_vulkan = FakeVulkan::current();
1334 |
1335 | let res = fake_vulkan.next_result("vkCreateDevice");
1336 |
1337 | if res != vk::VK_SUCCESS {
1338 | return res;
1339 | }
1340 |
1341 | unsafe {
1342 | *device_out =
1343 | fake_vulkan.add_dispatchable_handle(HandleType::Device);
1344 | }
1345 |
1346 | res
1347 | }
1348 |
1349 | extern "C" fn destroy_device(
1350 | device: vk::VkDevice,
1351 | _allocator: *const vk::VkAllocationCallbacks
1352 | ) {
1353 | let fake_vulkan = FakeVulkan::current();
1354 |
1355 | let handle = fake_vulkan.get_dispatchable_handle_mut(device);
1356 | assert!(matches!(handle.data, HandleType::Device));
1357 | handle.freed = true;
1358 | }
1359 |
1360 | extern "C" fn destroy_instance(
1361 | instance: vk::VkInstance,
1362 | _allocator: *const vk::VkAllocationCallbacks
1363 | ) {
1364 | let fake_vulkan = FakeVulkan::current();
1365 |
1366 | let handle = fake_vulkan.get_dispatchable_handle_mut(instance);
1367 | assert!(matches!(handle.data, HandleType::Instance));
1368 | handle.freed = true;
1369 | }
1370 |
1371 | extern "C" fn create_command_pool(
1372 | device: vk::VkDevice,
1373 | _create_info: *const vk::VkCommandPoolCreateInfo,
1374 | _allocator: *const vk::VkAllocationCallbacks,
1375 | command_pool_out: *mut vk::VkCommandPool,
1376 | ) -> vk::VkResult {
1377 | let fake_vulkan = FakeVulkan::current();
1378 |
1379 | let res = fake_vulkan.next_result("vkCreateCommandPool");
1380 |
1381 | if res != vk::VK_SUCCESS {
1382 | return res;
1383 | }
1384 |
1385 | fake_vulkan.check_device(device);
1386 |
1387 | unsafe {
1388 | *command_pool_out = fake_vulkan.add_handle(HandleType::CommandPool);
1389 | }
1390 |
1391 | res
1392 | }
1393 |
1394 | extern "C" fn destroy_command_pool(
1395 | device: vk::VkDevice,
1396 | command_pool: vk::VkCommandPool,
1397 | _allocator: *const vk::VkAllocationCallbacks,
1398 | ) {
1399 | let fake_vulkan = FakeVulkan::current();
1400 |
1401 | fake_vulkan.check_device(device);
1402 |
1403 | let handle = fake_vulkan.get_handle_mut(command_pool);
1404 | assert!(matches!(handle.data, HandleType::CommandPool));
1405 | handle.freed = true;
1406 | }
1407 |
1408 | extern "C" fn allocate_command_buffers(
1409 | device: vk::VkDevice,
1410 | allocate_info: *const vk::VkCommandBufferAllocateInfo,
1411 | command_buffers: *mut vk::VkCommandBuffer,
1412 | ) -> vk::VkResult {
1413 | let fake_vulkan = FakeVulkan::current();
1414 |
1415 | let res = fake_vulkan.next_result("vkAllocateCommandBuffers");
1416 |
1417 | if res != vk::VK_SUCCESS {
1418 | return res;
1419 | }
1420 |
1421 | fake_vulkan.check_device(device);
1422 |
1423 | let command_pool_handle = unsafe { (*allocate_info).commandPool };
1424 |
1425 | fake_vulkan.check_command_pool(command_pool_handle);
1426 |
1427 | let n_buffers = unsafe { (*allocate_info).commandBufferCount };
1428 |
1429 | for i in 0..(n_buffers as usize) {
1430 | unsafe {
1431 | *command_buffers.add(i) = fake_vulkan.add_dispatchable_handle(
1432 | HandleType::CommandBuffer {
1433 | command_pool: FakeVulkan::handle_to_index(
1434 | command_pool_handle
1435 | ),
1436 | commands: Vec::new(),
1437 | begun: false,
1438 | },
1439 | );
1440 | }
1441 | }
1442 |
1443 | res
1444 | }
1445 |
1446 | extern "C" fn free_command_buffers(
1447 | device: vk::VkDevice,
1448 | command_pool: vk::VkCommandPool,
1449 | command_buffer_count: u32,
1450 | command_buffers: *const vk::VkCommandBuffer,
1451 | ) {
1452 | let fake_vulkan = FakeVulkan::current();
1453 |
1454 | fake_vulkan.check_device(device);
1455 |
1456 | fake_vulkan.check_command_pool(command_pool);
1457 |
1458 | for i in 0..command_buffer_count as usize {
1459 | let command_buffer = unsafe {
1460 | *command_buffers.add(i)
1461 | };
1462 |
1463 | let command_buffer_handle =
1464 | fake_vulkan.get_dispatchable_handle_mut(command_buffer);
1465 |
1466 | match command_buffer_handle.data {
1467 | HandleType::CommandBuffer { command_pool: handle_pool, .. } => {
1468 | assert_eq!(
1469 | handle_pool,
1470 | FakeVulkan::handle_to_index(command_pool),
1471 | );
1472 | command_buffer_handle.freed = true;
1473 | },
1474 | _ => unreachable!("mismatched handle"),
1475 | }
1476 | }
1477 | }
1478 |
1479 | extern "C" fn create_fence(
1480 | device: vk::VkDevice,
1481 | _create_info: *const vk::VkFenceCreateInfo,
1482 | _allocator: *const vk::VkAllocationCallbacks,
1483 | fence_out: *mut vk::VkFence,
1484 | ) -> vk::VkResult {
1485 | let fake_vulkan = FakeVulkan::current();
1486 |
1487 | let res = fake_vulkan.next_result("vkCreateFence");
1488 |
1489 | if res != vk::VK_SUCCESS {
1490 | return res;
1491 | }
1492 |
1493 | fake_vulkan.check_device(device);
1494 |
1495 | unsafe {
1496 | *fence_out = fake_vulkan.add_handle(HandleType::Fence {
1497 | reset_count: 0,
1498 | wait_count: 0,
1499 | });
1500 | }
1501 |
1502 | res
1503 | }
1504 |
1505 | extern "C" fn destroy_fence(
1506 | device: vk::VkDevice,
1507 | fence: vk::VkFence,
1508 | _allocator: *const vk::VkAllocationCallbacks,
1509 | ) {
1510 | let fake_vulkan = FakeVulkan::current();
1511 |
1512 | fake_vulkan.check_device(device);
1513 |
1514 | let handle = fake_vulkan.get_handle_mut(fence);
1515 | assert!(matches!(handle.data, HandleType::Fence { .. }));
1516 | handle.freed = true;
1517 | }
1518 |
1519 | extern "C" fn create_render_pass(
1520 | device: vk::VkDevice,
1521 | create_info: *const vk::VkRenderPassCreateInfo,
1522 | _allocator: *const vk::VkAllocationCallbacks,
1523 | render_pass_out: *mut vk::VkRenderPass,
1524 | ) -> vk::VkResult {
1525 | let fake_vulkan = FakeVulkan::current();
1526 |
1527 | let res = fake_vulkan.next_result("vkCreateRenderPass");
1528 |
1529 | if res != vk::VK_SUCCESS {
1530 | return res;
1531 | }
1532 |
1533 | fake_vulkan.check_device(device);
1534 |
1535 | unsafe {
1536 | let create_info = &*create_info;
1537 |
1538 | *render_pass_out = fake_vulkan.add_handle(HandleType::RenderPass {
1539 | attachments: vec_from_raw_parts(
1540 | create_info.pAttachments,
1541 | create_info.attachmentCount as usize,
1542 | ),
1543 | });
1544 | }
1545 |
1546 | res
1547 | }
1548 |
1549 | extern "C" fn destroy_render_pass(
1550 | device: vk::VkDevice,
1551 | render_pass: vk::VkRenderPass,
1552 | _allocator: *const vk::VkAllocationCallbacks,
1553 | ) {
1554 | let fake_vulkan = FakeVulkan::current();
1555 |
1556 | fake_vulkan.check_device(device);
1557 |
1558 | let handle = fake_vulkan.get_handle_mut(render_pass);
1559 | assert!(matches!(handle.data, HandleType::RenderPass { .. }));
1560 | handle.freed = true;
1561 | }
1562 |
1563 | extern "C" fn create_image_view(
1564 | device: vk::VkDevice,
1565 | create_info: *const vk::VkImageViewCreateInfo,
1566 | _allocator: *const vk::VkAllocationCallbacks,
1567 | image_view_out: *mut vk::VkImageView,
1568 | ) -> vk::VkResult {
1569 | let fake_vulkan = FakeVulkan::current();
1570 |
1571 | let res = fake_vulkan.next_result("vkCreateImageView");
1572 |
1573 | if res != vk::VK_SUCCESS {
1574 | return res;
1575 | }
1576 |
1577 | fake_vulkan.check_device(device);
1578 |
1579 | fake_vulkan.check_image(unsafe { *create_info }.image);
1580 |
1581 | unsafe {
1582 | *image_view_out = fake_vulkan.add_handle(HandleType::ImageView);
1583 | }
1584 |
1585 | res
1586 | }
1587 |
1588 | extern "C" fn destroy_image_view(
1589 | device: vk::VkDevice,
1590 | image_view: vk::VkImageView,
1591 | _allocator: *const vk::VkAllocationCallbacks,
1592 | ) {
1593 | let fake_vulkan = FakeVulkan::current();
1594 |
1595 | fake_vulkan.check_device(device);
1596 |
1597 | let handle = fake_vulkan.get_handle_mut(image_view);
1598 | assert!(matches!(handle.data, HandleType::ImageView));
1599 | handle.freed = true;
1600 | }
1601 |
1602 | extern "C" fn create_image(
1603 | device: vk::VkDevice,
1604 | _create_info: *const vk::VkImageCreateInfo,
1605 | _allocator: *const vk::VkAllocationCallbacks,
1606 | image_out: *mut vk::VkImage,
1607 | ) -> vk::VkResult {
1608 | let fake_vulkan = FakeVulkan::current();
1609 |
1610 | let res = fake_vulkan.next_result("vkCreateImage");
1611 |
1612 | if res != vk::VK_SUCCESS {
1613 | return res;
1614 | }
1615 |
1616 | fake_vulkan.check_device(device);
1617 |
1618 | unsafe {
1619 | *image_out = fake_vulkan.add_handle(HandleType::Image);
1620 | }
1621 |
1622 | res
1623 | }
1624 |
1625 | extern "C" fn destroy_image(
1626 | device: vk::VkDevice,
1627 | image: vk::VkImage,
1628 | _allocator: *const vk::VkAllocationCallbacks,
1629 | ) {
1630 | let fake_vulkan = FakeVulkan::current();
1631 |
1632 | fake_vulkan.check_device(device);
1633 |
1634 | let handle = fake_vulkan.get_handle_mut(image);
1635 | assert!(matches!(handle.data, HandleType::Image));
1636 | handle.freed = true;
1637 | }
1638 |
1639 | extern "C" fn create_buffer(
1640 | device: vk::VkDevice,
1641 | create_info: *const vk::VkBufferCreateInfo,
1642 | _allocator: *const vk::VkAllocationCallbacks,
1643 | buffer_out: *mut vk::VkBuffer,
1644 | ) -> vk::VkResult {
1645 | let fake_vulkan = FakeVulkan::current();
1646 |
1647 | let res = fake_vulkan.next_result("vkCreateBuffer");
1648 |
1649 | if res != vk::VK_SUCCESS {
1650 | return res;
1651 | }
1652 |
1653 | fake_vulkan.check_device(device);
1654 |
1655 | let create_info = unsafe { &*create_info };
1656 |
1657 | unsafe {
1658 | *buffer_out = fake_vulkan.add_handle(
1659 | HandleType::Buffer {
1660 | create_info: create_info.clone(),
1661 | memory: None,
1662 | }
1663 | );
1664 | }
1665 |
1666 | res
1667 | }
1668 |
1669 | extern "C" fn destroy_buffer(
1670 | device: vk::VkDevice,
1671 | buffer: vk::VkBuffer,
1672 | _allocator: *const vk::VkAllocationCallbacks,
1673 | ) {
1674 | let fake_vulkan = FakeVulkan::current();
1675 |
1676 | fake_vulkan.check_device(device);
1677 |
1678 | let handle = fake_vulkan.get_handle_mut(buffer);
1679 | assert!(matches!(handle.data, HandleType::Buffer { .. }));
1680 | handle.freed = true;
1681 | }
1682 |
1683 | extern "C" fn create_framebuffer(
1684 | device: vk::VkDevice,
1685 | create_info: *const vk::VkFramebufferCreateInfo,
1686 | _allocator: *const vk::VkAllocationCallbacks,
1687 | framebuffer_out: *mut vk::VkFramebuffer,
1688 | ) -> vk::VkResult {
1689 | let fake_vulkan = FakeVulkan::current();
1690 |
1691 | let res = fake_vulkan.next_result("vkCreateFramebuffer");
1692 |
1693 | if res != vk::VK_SUCCESS {
1694 | return res;
1695 | }
1696 |
1697 | fake_vulkan.check_device(device);
1698 |
1699 | let attachments = unsafe {
1700 | let attachment_count = (*create_info).attachmentCount as usize;
1701 | std::slice::from_raw_parts(
1702 | (*create_info).pAttachments,
1703 | attachment_count
1704 | )
1705 | };
1706 |
1707 | for &attachment in attachments {
1708 | fake_vulkan.check_image_view(attachment);
1709 | }
1710 |
1711 | unsafe {
1712 | *framebuffer_out = fake_vulkan.add_handle(HandleType::Framebuffer);
1713 | }
1714 |
1715 | res
1716 | }
1717 |
1718 | extern "C" fn destroy_framebuffer(
1719 | device: vk::VkDevice,
1720 | framebuffer: vk::VkFramebuffer,
1721 | _allocator: *const vk::VkAllocationCallbacks,
1722 | ) {
1723 | let fake_vulkan = FakeVulkan::current();
1724 |
1725 | fake_vulkan.check_device(device);
1726 |
1727 | let handle = fake_vulkan.get_handle_mut(framebuffer);
1728 | assert!(matches!(handle.data, HandleType::Framebuffer));
1729 | handle.freed = true;
1730 | }
1731 |
1732 | extern "C" fn enumerate_instance_version(
1733 | api_version: *mut u32
1734 | ) -> vk::VkResult {
1735 | let fake_vulkan = FakeVulkan::current();
1736 | unsafe { *api_version = requirements::make_version(1, 1, 0) }
1737 | fake_vulkan.next_result("vkEnumerateInstanceVersion")
1738 | }
1739 |
1740 | extern "C" fn get_buffer_memory_requirements(
1741 | device: vk::VkDevice,
1742 | buffer: vk::VkBuffer,
1743 | memory_requirements: *mut vk::VkMemoryRequirements,
1744 | ) {
1745 | let fake_vulkan = FakeVulkan::current();
1746 |
1747 | fake_vulkan.check_device(device);
1748 |
1749 | let size = match fake_vulkan.get_handle(buffer).data {
1750 | HandleType::Buffer { ref create_info, .. } => create_info.size,
1751 | _ => unreachable!("mismatched handle"),
1752 | };
1753 |
1754 | unsafe {
1755 | *memory_requirements = fake_vulkan.memory_requirements.clone();
1756 | (*memory_requirements).size = size;
1757 | }
1758 | }
1759 |
1760 | extern "C" fn get_image_memory_requirements(
1761 | device: vk::VkDevice,
1762 | image: vk::VkImage,
1763 | memory_requirements: *mut vk::VkMemoryRequirements,
1764 | ) {
1765 | let fake_vulkan = FakeVulkan::current();
1766 |
1767 | fake_vulkan.check_device(device);
1768 | fake_vulkan.check_image(image);
1769 |
1770 | unsafe {
1771 | *memory_requirements = fake_vulkan.memory_requirements;
1772 | }
1773 | }
1774 |
1775 | extern "C" fn allocate_memory(
1776 | device: vk::VkDevice,
1777 | allocate_info: *const vk::VkMemoryAllocateInfo,
1778 | _allocator: *const vk::VkAllocationCallbacks,
1779 | memory: *mut vk::VkDeviceMemory,
1780 | ) -> vk::VkResult {
1781 | let fake_vulkan = FakeVulkan::current();
1782 |
1783 | let res = fake_vulkan.next_result("vkAllocateMemory");
1784 |
1785 | if res != vk::VK_SUCCESS {
1786 | return res;
1787 | }
1788 |
1789 | fake_vulkan.check_device(device);
1790 |
1791 | unsafe {
1792 | *memory = fake_vulkan.add_handle(HandleType::Memory {
1793 | contents: vec![
1794 | 0u8;
1795 | (*allocate_info).allocationSize as usize
1796 | ],
1797 | mapped: false,
1798 | });
1799 | }
1800 |
1801 | res
1802 | }
1803 |
1804 | extern "C" fn free_memory(
1805 | device: vk::VkDevice,
1806 | memory: vk::VkDeviceMemory,
1807 | _allocator: *const vk::VkAllocationCallbacks,
1808 | ) {
1809 | let fake_vulkan = FakeVulkan::current();
1810 |
1811 | fake_vulkan.check_device(device);
1812 |
1813 | let handle = fake_vulkan.get_handle_mut(memory);
1814 |
1815 | match handle.data {
1816 | HandleType::Memory { mapped, .. } => assert!(!mapped),
1817 | _ => unreachable!("mismatched handle"),
1818 | }
1819 |
1820 | handle.freed = true;
1821 | }
1822 |
1823 | extern "C" fn bind_buffer_memory(
1824 | device: vk::VkDevice,
1825 | buffer: vk::VkBuffer,
1826 | memory: vk::VkDeviceMemory,
1827 | _memory_offset: vk::VkDeviceSize,
1828 | ) -> vk::VkResult {
1829 | let fake_vulkan = FakeVulkan::current();
1830 |
1831 | let res = fake_vulkan.next_result("vkBindBufferMemory");
1832 |
1833 | if res != vk::VK_SUCCESS {
1834 | return res;
1835 | }
1836 |
1837 | fake_vulkan.check_device(device);
1838 | fake_vulkan.check_memory(memory);
1839 |
1840 | let HandleType::Buffer { memory: ref mut buffer_memory, .. } =
1841 | fake_vulkan.get_handle_mut(buffer).data
1842 | else { unreachable!("mismatched handle"); };
1843 |
1844 | assert!(buffer_memory.is_none());
1845 |
1846 | *buffer_memory = Some(memory);
1847 |
1848 | res
1849 | }
1850 |
1851 | extern "C" fn bind_image_memory(
1852 | _device: vk::VkDevice,
1853 | _image: vk::VkImage,
1854 | _memory: vk::VkDeviceMemory,
1855 | _memory_offset: vk::VkDeviceSize,
1856 | ) -> vk::VkResult {
1857 | let fake_vulkan = FakeVulkan::current();
1858 | fake_vulkan.next_result("vkBindImageMemory")
1859 | }
1860 |
1861 | extern "C" fn map_memory(
1862 | device: vk::VkDevice,
1863 | memory: vk::VkDeviceMemory,
1864 | offset: vk::VkDeviceSize,
1865 | size: vk::VkDeviceSize,
1866 | _flags: vk::VkMemoryMapFlags,
1867 | data_out: *mut *mut c_void,
1868 | ) -> vk::VkResult {
1869 | let fake_vulkan = FakeVulkan::current();
1870 |
1871 | let res = fake_vulkan.next_result("vkMapMemory");
1872 |
1873 | if res != vk::VK_SUCCESS {
1874 | return res;
1875 | }
1876 |
1877 | fake_vulkan.check_device(device);
1878 |
1879 | let HandleType::Memory { ref mut mapped, ref mut contents } =
1880 | fake_vulkan.get_handle_mut(memory).data
1881 | else { unreachable!("mismatched handle"); };
1882 |
1883 | assert!(!*mapped);
1884 | assert!(
1885 | size == vk::VK_WHOLE_SIZE as vk::VkDeviceSize
1886 | || (offset + size) as usize <= contents.len()
1887 | );
1888 |
1889 | unsafe {
1890 | *data_out = contents[offset as usize..].as_mut_ptr().cast();
1891 | }
1892 |
1893 | *mapped = true;
1894 |
1895 | res
1896 | }
1897 |
1898 | extern "C" fn unmap_memory(
1899 | device: vk::VkDevice,
1900 | memory: vk::VkDeviceMemory
1901 | ) {
1902 | let fake_vulkan = FakeVulkan::current();
1903 |
1904 | fake_vulkan.check_device(device);
1905 |
1906 | let HandleType::Memory { ref mut mapped, .. } =
1907 | fake_vulkan.get_handle_mut(memory).data
1908 | else { unreachable!("mismatched handle"); };
1909 |
1910 | assert!(*mapped);
1911 | *mapped = false;
1912 | }
1913 |
1914 | extern "C" fn create_shader_module(
1915 | device: vk::VkDevice,
1916 | create_info: *const vk::VkShaderModuleCreateInfo,
1917 | _allocator: *const vk::VkAllocationCallbacks,
1918 | shader_module_out: *mut vk::VkShaderModule,
1919 | ) -> vk::VkResult {
1920 | let fake_vulkan = FakeVulkan::current();
1921 |
1922 | let res = fake_vulkan.next_result("vkCreateShaderModule");
1923 |
1924 | if res != vk::VK_SUCCESS {
1925 | return res;
1926 | }
1927 |
1928 | fake_vulkan.check_device(device);
1929 |
1930 | unsafe {
1931 | assert_eq!((*create_info).codeSize % (u32::BITS as usize / 8), 0);
1932 |
1933 | let code = vec_from_raw_parts(
1934 | (*create_info).pCode,
1935 | (*create_info).codeSize / (u32::BITS as usize / 8),
1936 | );
1937 |
1938 | *shader_module_out = fake_vulkan.add_handle(
1939 | HandleType::ShaderModule { code }
1940 | );
1941 | }
1942 |
1943 | res
1944 | }
1945 |
1946 | extern "C" fn destroy_shader_module(
1947 | device: vk::VkDevice,
1948 | shader_module: vk::VkShaderModule,
1949 | _allocator: *const vk::VkAllocationCallbacks,
1950 | ) {
1951 | let fake_vulkan = FakeVulkan::current();
1952 |
1953 | fake_vulkan.check_device(device);
1954 |
1955 | let handle = fake_vulkan.get_handle_mut(shader_module);
1956 | assert!(matches!(handle.data, HandleType::ShaderModule { .. }));
1957 | handle.freed = true;
1958 | }
1959 |
1960 | extern "C" fn create_pipeline_cache(
1961 | device: vk::VkDevice,
1962 | _create_info: *const vk::VkPipelineCacheCreateInfo,
1963 | _allocator: *const vk::VkAllocationCallbacks,
1964 | pipeline_cache_out: *mut vk::VkPipelineCache,
1965 | ) -> vk::VkResult {
1966 | let fake_vulkan = FakeVulkan::current();
1967 |
1968 | let res = fake_vulkan.next_result("vkCreatePipelineCache");
1969 |
1970 | if res != vk::VK_SUCCESS {
1971 | return res;
1972 | }
1973 |
1974 | fake_vulkan.check_device(device);
1975 |
1976 | unsafe {
1977 | *pipeline_cache_out = fake_vulkan.add_handle(
1978 | HandleType::PipelineCache
1979 | );
1980 | }
1981 |
1982 | res
1983 | }
1984 |
1985 | extern "C" fn destroy_pipeline_cache(
1986 | device: vk::VkDevice,
1987 | pipeline_cache: vk::VkPipelineCache,
1988 | _allocator: *const vk::VkAllocationCallbacks,
1989 | ) {
1990 | let fake_vulkan = FakeVulkan::current();
1991 |
1992 | fake_vulkan.check_device(device);
1993 |
1994 | let handle = fake_vulkan.get_handle_mut(pipeline_cache);
1995 | assert!(matches!(handle.data, HandleType::PipelineCache));
1996 | handle.freed = true;
1997 | }
1998 |
1999 | extern "C" fn create_descriptor_pool(
2000 | device: vk::VkDevice,
2001 | _create_info: *const vk::VkDescriptorPoolCreateInfo,
2002 | _allocator: *const vk::VkAllocationCallbacks,
2003 | descriptor_pool_out: *mut vk::VkDescriptorPool,
2004 | ) -> vk::VkResult {
2005 | let fake_vulkan = FakeVulkan::current();
2006 |
2007 | let res = fake_vulkan.next_result("vkCreateDescriptorPool");
2008 |
2009 | if res != vk::VK_SUCCESS {
2010 | return res;
2011 | }
2012 |
2013 | fake_vulkan.check_device(device);
2014 |
2015 | unsafe {
2016 | *descriptor_pool_out = fake_vulkan.add_handle(
2017 | HandleType::DescriptorPool
2018 | );
2019 | }
2020 |
2021 | res
2022 | }
2023 |
2024 | extern "C" fn destroy_descriptor_pool(
2025 | device: vk::VkDevice,
2026 | descriptor_pool: vk::VkDescriptorPool,
2027 | _allocator: *const vk::VkAllocationCallbacks,
2028 | ) {
2029 | let fake_vulkan = FakeVulkan::current();
2030 |
2031 | fake_vulkan.check_device(device);
2032 |
2033 | let handle = fake_vulkan.get_handle_mut(descriptor_pool);
2034 | assert!(matches!(handle.data, HandleType::DescriptorPool));
2035 | handle.freed = true;
2036 | }
2037 |
2038 | extern "C" fn create_descriptor_set_layout(
2039 | device: vk::VkDevice,
2040 | create_info: *const vk::VkDescriptorSetLayoutCreateInfo,
2041 | _allocator: *const vk::VkAllocationCallbacks,
2042 | descriptor_set_layout_out: *mut vk::VkDescriptorSetLayout,
2043 | ) -> vk::VkResult {
2044 | let fake_vulkan = FakeVulkan::current();
2045 |
2046 | let res = fake_vulkan.next_result("vkCreateDescriptorSetLayout");
2047 |
2048 | if res != vk::VK_SUCCESS {
2049 | return res;
2050 | }
2051 |
2052 | fake_vulkan.check_device(device);
2053 |
2054 | unsafe {
2055 | let bindings = vec_from_raw_parts(
2056 | (*create_info).pBindings,
2057 | (*create_info).bindingCount as usize,
2058 | );
2059 |
2060 | *descriptor_set_layout_out = fake_vulkan.add_handle(
2061 | HandleType::DescriptorSetLayout { bindings }
2062 | );
2063 | }
2064 |
2065 | res
2066 | }
2067 |
2068 | extern "C" fn destroy_descriptor_set_layout(
2069 | device: vk::VkDevice,
2070 | descriptor_set_layout: vk::VkDescriptorSetLayout,
2071 | _allocator: *const vk::VkAllocationCallbacks,
2072 | ) {
2073 | let fake_vulkan = FakeVulkan::current();
2074 |
2075 | fake_vulkan.check_device(device);
2076 |
2077 | let handle = fake_vulkan.get_handle_mut(descriptor_set_layout);
2078 | assert!(matches!(handle.data, HandleType::DescriptorSetLayout { .. }));
2079 | handle.freed = true;
2080 | }
2081 |
2082 | extern "C" fn create_pipeline_layout(
2083 | device: vk::VkDevice,
2084 | create_info: *const vk::VkPipelineLayoutCreateInfo,
2085 | _allocator: *const vk::VkAllocationCallbacks,
2086 | pipeline_layout_out: *mut vk::VkPipelineLayout,
2087 | ) -> vk::VkResult {
2088 | let fake_vulkan = FakeVulkan::current();
2089 |
2090 | let res = fake_vulkan.next_result("vkCreatePipelineLayout");
2091 |
2092 | if res != vk::VK_SUCCESS {
2093 | return res;
2094 | }
2095 |
2096 | fake_vulkan.check_device(device);
2097 |
2098 | unsafe {
2099 | let push_constant_ranges = vec_from_raw_parts(
2100 | (*create_info).pPushConstantRanges,
2101 | (*create_info).pushConstantRangeCount as usize,
2102 | );
2103 |
2104 | let layouts = vec_from_raw_parts(
2105 | (*create_info).pSetLayouts,
2106 | (*create_info).setLayoutCount as usize,
2107 | );
2108 |
2109 | *pipeline_layout_out = fake_vulkan.add_handle(
2110 | HandleType::PipelineLayout(PipelineLayoutCreateInfo {
2111 | create_info: (*create_info).clone(),
2112 | push_constant_ranges,
2113 | layouts,
2114 | }),
2115 | );
2116 | }
2117 |
2118 | res
2119 | }
2120 |
2121 | extern "C" fn destroy_pipeline_layout(
2122 | device: vk::VkDevice,
2123 | pipeline_layout: vk::VkPipelineLayout,
2124 | _allocator: *const vk::VkAllocationCallbacks,
2125 | ) {
2126 | let fake_vulkan = FakeVulkan::current();
2127 |
2128 | fake_vulkan.check_device(device);
2129 |
2130 | let handle = fake_vulkan.get_handle_mut(pipeline_layout);
2131 | assert!(matches!(handle.data, HandleType::PipelineLayout(_)));
2132 | handle.freed = true;
2133 | }
2134 |
2135 | extern "C" fn create_graphics_pipelines(
2136 | device: vk::VkDevice,
2137 | pipeline_cache: vk::VkPipelineCache,
2138 | create_info_count: u32,
2139 | create_infos: *const vk::VkGraphicsPipelineCreateInfo,
2140 | _allocator: *const vk::VkAllocationCallbacks,
2141 | pipelines_out: *mut vk::VkPipeline,
2142 | ) -> vk::VkResult {
2143 | let fake_vulkan = FakeVulkan::current();
2144 |
2145 | let res = fake_vulkan.next_result("vkCreateGraphicsPipelines");
2146 |
2147 | if res != vk::VK_SUCCESS {
2148 | return res;
2149 | }
2150 |
2151 | fake_vulkan.check_device(device);
2152 | fake_vulkan.check_pipeline_cache(pipeline_cache);
2153 |
2154 | for i in 0..create_info_count as usize {
2155 | unsafe {
2156 | let create_info = &*create_infos.add(i);
2157 |
2158 | *pipelines_out.add(i) = fake_vulkan.add_handle(
2159 | HandleType::Pipeline(
2160 | PipelineCreateInfo::Graphics(
2161 | GraphicsPipelineCreateInfo::new(create_info)
2162 | )
2163 | ),
2164 | );
2165 | }
2166 | }
2167 |
2168 | res
2169 | }
2170 |
2171 | extern "C" fn create_compute_pipelines(
2172 | device: vk::VkDevice,
2173 | pipeline_cache: vk::VkPipelineCache,
2174 | create_info_count: u32,
2175 | create_infos: *const vk::VkComputePipelineCreateInfo,
2176 | _allocator: *const vk::VkAllocationCallbacks,
2177 | pipelines_out: *mut vk::VkPipeline,
2178 | ) -> vk::VkResult {
2179 | let fake_vulkan = FakeVulkan::current();
2180 |
2181 | let res = fake_vulkan.next_result("vkCreateComputePipelines");
2182 |
2183 | if res != vk::VK_SUCCESS {
2184 | return res;
2185 | }
2186 |
2187 | fake_vulkan.check_device(device);
2188 | fake_vulkan.check_pipeline_cache(pipeline_cache);
2189 |
2190 | for i in 0..create_info_count as usize {
2191 | unsafe {
2192 | *pipelines_out.add(i) = fake_vulkan.add_handle(
2193 | HandleType::Pipeline(PipelineCreateInfo::Compute(
2194 | (*create_infos.add(i)).clone()
2195 | )),
2196 | );
2197 | }
2198 | };
2199 |
2200 | res
2201 | }
2202 |
2203 | extern "C" fn destroy_pipeline(
2204 | device: vk::VkDevice,
2205 | pipeline: vk::VkPipeline,
2206 | _allocator: *const vk::VkAllocationCallbacks,
2207 | ) {
2208 | let fake_vulkan = FakeVulkan::current();
2209 |
2210 | fake_vulkan.check_device(device);
2211 |
2212 | let handle = fake_vulkan.get_handle_mut(pipeline);
2213 | assert!(matches!(handle.data, HandleType::Pipeline { .. }));
2214 | handle.freed = true;
2215 | }
2216 |
2217 | extern "C" fn flush_mapped_memory_ranges(
2218 | device: vk::VkDevice,
2219 | memory_range_count: u32,
2220 | memory_ranges: *const vk::VkMappedMemoryRange,
2221 | ) -> vk::VkResult {
2222 | let fake_vulkan = FakeVulkan::current();
2223 |
2224 | let res = fake_vulkan.next_result("vkFlushMappedMemoryRanges");
2225 |
2226 | if res != vk::VK_SUCCESS {
2227 | return res;
2228 | }
2229 |
2230 | fake_vulkan.check_device(device);
2231 |
2232 | let memory_ranges = unsafe {
2233 | std::slice::from_raw_parts(
2234 | memory_ranges,
2235 | memory_range_count as usize,
2236 | )
2237 | };
2238 |
2239 | fake_vulkan.memory_flushes.extend_from_slice(memory_ranges);
2240 |
2241 | res
2242 | }
2243 |
2244 | extern "C" fn invalidate_mapped_memory_ranges(
2245 | device: vk::VkDevice,
2246 | memory_range_count: u32,
2247 | memory_ranges: *const vk::VkMappedMemoryRange,
2248 | ) -> vk::VkResult {
2249 | let fake_vulkan = FakeVulkan::current();
2250 |
2251 | let res = fake_vulkan.next_result("vkInvalidateMappedMemoryRanges");
2252 |
2253 | if res != vk::VK_SUCCESS {
2254 | return res;
2255 | }
2256 |
2257 | fake_vulkan.check_device(device);
2258 |
2259 | let memory_ranges = unsafe {
2260 | std::slice::from_raw_parts(
2261 | memory_ranges,
2262 | memory_range_count as usize,
2263 | )
2264 | };
2265 |
2266 | fake_vulkan.memory_invalidations.extend_from_slice(memory_ranges);
2267 |
2268 | res
2269 | }
2270 |
2271 | extern "C" fn queue_submit(
2272 | _queue: vk::VkQueue,
2273 | submit_count: u32,
2274 | submits: *const vk::VkSubmitInfo,
2275 | fence: vk::VkFence,
2276 | ) -> vk::VkResult {
2277 | let fake_vulkan = FakeVulkan::current();
2278 |
2279 | fake_vulkan.check_fence(fence);
2280 |
2281 | let res = fake_vulkan.next_result("vkQueueSubmit");
2282 |
2283 | if res != vk::VK_SUCCESS {
2284 | return res;
2285 | }
2286 |
2287 | let submits = unsafe {
2288 | std::slice::from_raw_parts(
2289 | submits,
2290 | submit_count as usize,
2291 | )
2292 | };
2293 |
2294 | for submit in submits.iter() {
2295 | let command_buffers = unsafe {
2296 | std::slice::from_raw_parts(
2297 | submit.pCommandBuffers,
2298 | submit.commandBufferCount as usize,
2299 | )
2300 | };
2301 |
2302 | for &command_buffer in command_buffers.iter() {
2303 | let HandleType::CommandBuffer { ref mut commands, begun, .. } =
2304 | fake_vulkan.get_dispatchable_handle_mut(command_buffer).data
2305 | else {
2306 | unreachable!("bad handle type")
2307 | };
2308 |
2309 | assert!(!begun);
2310 |
2311 | let commands = mem::take(commands);
2312 | fake_vulkan.commands.extend(commands);
2313 | }
2314 | }
2315 |
2316 | res
2317 | }
2318 |
2319 | extern "C" fn allocate_descriptor_sets(
2320 | device: vk::VkDevice,
2321 | allocate_info: *const vk::VkDescriptorSetAllocateInfo,
2322 | descriptor_sets: *mut vk::VkDescriptorSet,
2323 | ) -> vk::VkResult {
2324 | let fake_vulkan = FakeVulkan::current();
2325 |
2326 | let res = fake_vulkan.next_result("vkAllocateDescriptorSets");
2327 |
2328 | if res != vk::VK_SUCCESS {
2329 | return res;
2330 | }
2331 |
2332 | fake_vulkan.check_device(device);
2333 |
2334 | let descriptor_pool_handle = unsafe { (*allocate_info).descriptorPool };
2335 |
2336 | fake_vulkan.check_descriptor_pool(descriptor_pool_handle);
2337 |
2338 | let n_buffers = unsafe { (*allocate_info).descriptorSetCount };
2339 |
2340 | for i in 0..(n_buffers as usize) {
2341 | unsafe {
2342 | *descriptor_sets.add(i) = fake_vulkan.add_handle(
2343 | HandleType::DescriptorSet { bindings: HashMap::new() }
2344 | );
2345 | }
2346 | }
2347 |
2348 | res
2349 | }
2350 |
2351 | extern "C" fn free_descriptor_sets(
2352 | device: vk::VkDevice,
2353 | descriptor_pool: vk::VkDescriptorPool,
2354 | descriptor_set_count: u32,
2355 | descriptor_sets: *const vk::VkDescriptorSet,
2356 | ) -> vk::VkResult {
2357 | let fake_vulkan = FakeVulkan::current();
2358 |
2359 | let res = fake_vulkan.next_result("vkAllocateDescriptorSets");
2360 |
2361 | if res != vk::VK_SUCCESS {
2362 | return res;
2363 | }
2364 |
2365 | fake_vulkan.check_device(device);
2366 |
2367 | fake_vulkan.check_descriptor_pool(descriptor_pool);
2368 |
2369 | for i in 0..descriptor_set_count as usize {
2370 | let descriptor_set = unsafe {
2371 | *descriptor_sets.add(i)
2372 | };
2373 |
2374 | let descriptor_set_handle =
2375 | fake_vulkan.get_handle_mut(descriptor_set);
2376 |
2377 | match descriptor_set_handle.data {
2378 | HandleType::DescriptorSet { .. } => {
2379 | descriptor_set_handle.freed = true;
2380 | },
2381 | _ => unreachable!("mismatched handle"),
2382 | }
2383 | }
2384 |
2385 | res
2386 | }
2387 |
2388 | extern "C" fn update_descriptor_sets(
2389 | device: vk::VkDevice,
2390 | descriptor_write_count: u32,
2391 | descriptor_writes: *const vk::VkWriteDescriptorSet,
2392 | _descriptor_copy_count: u32,
2393 | _descriptor_copies: *const vk::VkCopyDescriptorSet,
2394 | ) {
2395 | let fake_vulkan = FakeVulkan::current();
2396 |
2397 | fake_vulkan.check_device(device);
2398 |
2399 | let descriptor_writes = unsafe {
2400 | std::slice::from_raw_parts(
2401 | descriptor_writes,
2402 | descriptor_write_count as usize,
2403 | )
2404 | };
2405 |
2406 | for write in descriptor_writes.iter() {
2407 | assert_eq!(write.sType, vk::VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET);
2408 | assert_eq!(write.descriptorCount, 1);
2409 |
2410 | let HandleType::DescriptorSet { ref mut bindings } =
2411 | fake_vulkan.get_handle_mut(write.dstSet).data
2412 | else { unreachable!("mismatched handle type"); };
2413 |
2414 | bindings.insert(
2415 | write.dstBinding,
2416 | Binding {
2417 | descriptor_type: write.descriptorType,
2418 | info: unsafe { &*write.pBufferInfo }.clone(),
2419 | },
2420 | );
2421 | }
2422 | }
2423 |
2424 | extern "C" fn begin_command_buffer(
2425 | command_buffer: vk::VkCommandBuffer,
2426 | _begin_info: *const vk::VkCommandBufferBeginInfo,
2427 | ) -> vk::VkResult {
2428 | let fake_vulkan = FakeVulkan::current();
2429 |
2430 | let res = fake_vulkan.next_result("vkBeginCommandBuffer");
2431 |
2432 | if res != vk::VK_SUCCESS {
2433 | return res;
2434 | }
2435 |
2436 | let HandleType::CommandBuffer { ref mut begun, .. } =
2437 | fake_vulkan.get_dispatchable_handle_mut(command_buffer).data
2438 | else { unreachable!("mismatched handle"); };
2439 |
2440 | assert!(!*begun);
2441 | *begun = true;
2442 |
2443 | res
2444 | }
2445 |
2446 | extern "C" fn end_command_buffer(
2447 | command_buffer: vk::VkCommandBuffer,
2448 | ) -> vk::VkResult {
2449 | let fake_vulkan = FakeVulkan::current();
2450 |
2451 | let res = fake_vulkan.next_result("vkEndCommandBuffer");
2452 |
2453 | if res != vk::VK_SUCCESS {
2454 | return res;
2455 | }
2456 |
2457 | let HandleType::CommandBuffer { ref mut begun, .. } =
2458 | fake_vulkan.get_dispatchable_handle_mut(command_buffer).data
2459 | else { unreachable!("mismatched handle"); };
2460 |
2461 | assert!(*begun);
2462 | *begun = false;
2463 |
2464 | res
2465 | }
2466 |
2467 | fn add_command(
2468 | &mut self,
2469 | command_buffer: vk::VkCommandBuffer,
2470 | command: Command,
2471 | ) {
2472 | let HandleType::CommandBuffer { ref mut commands, begun, .. } =
2473 | self.get_dispatchable_handle_mut(command_buffer).data
2474 | else { unreachable!("mismatched handle"); };
2475 |
2476 | assert!(begun);
2477 |
2478 | commands.push(command);
2479 | }
2480 |
2481 | extern "C" fn begin_render_pass(
2482 | command_buffer: vk::VkCommandBuffer,
2483 | render_pass_begin: *const vk::VkRenderPassBeginInfo,
2484 | _contents: vk::VkSubpassContents,
2485 | ) {
2486 | let render_pass_begin = unsafe { &*render_pass_begin };
2487 |
2488 | let fake_vulkan = FakeVulkan::current();
2489 |
2490 | fake_vulkan.check_render_pass(render_pass_begin.renderPass);
2491 | fake_vulkan.check_framebuffer(render_pass_begin.framebuffer);
2492 |
2493 | fake_vulkan.add_command(
2494 | command_buffer,
2495 | Command::BeginRenderPass(render_pass_begin.clone()),
2496 | );
2497 | }
2498 |
2499 | extern "C" fn end_render_pass(
2500 | command_buffer: vk::VkCommandBuffer,
2501 | ) {
2502 | let fake_vulkan = FakeVulkan::current();
2503 |
2504 | fake_vulkan.add_command(command_buffer, Command::EndRenderPass);
2505 | }
2506 |
2507 | extern "C" fn bind_pipeline(
2508 | command_buffer: vk::VkCommandBuffer,
2509 | pipeline_bind_point: vk::VkPipelineBindPoint,
2510 | pipeline: vk::VkPipeline,
2511 | ) {
2512 | let fake_vulkan = FakeVulkan::current();
2513 |
2514 | fake_vulkan.check_pipeline(pipeline);
2515 |
2516 | fake_vulkan.add_command(
2517 | command_buffer,
2518 | Command::BindPipeline {
2519 | bind_point: pipeline_bind_point,
2520 | pipeline,
2521 | },
2522 | );
2523 | }
2524 |
2525 | extern "C" fn bind_vertex_buffers(
2526 | command_buffer: vk::VkCommandBuffer,
2527 | first_binding: u32,
2528 | binding_count: u32,
2529 | buffers: *const vk::VkBuffer,
2530 | offsets: *const vk::VkDeviceSize,
2531 | ) {
2532 | let fake_vulkan = FakeVulkan::current();
2533 |
2534 | let buffers = vec_from_raw_parts(
2535 | buffers,
2536 | binding_count as usize,
2537 | );
2538 |
2539 | for &buffer in buffers.iter() {
2540 | fake_vulkan.check_buffer(buffer);
2541 | }
2542 |
2543 | let offsets = vec_from_raw_parts(
2544 | offsets,
2545 | binding_count as usize,
2546 | );
2547 |
2548 | fake_vulkan.add_command(
2549 | command_buffer,
2550 | Command::BindVertexBuffers {
2551 | first_binding,
2552 | buffers,
2553 | offsets,
2554 | },
2555 | );
2556 | }
2557 |
2558 | extern "C" fn bind_index_buffer(
2559 | command_buffer: vk::VkCommandBuffer,
2560 | buffer: vk::VkBuffer,
2561 | offset: vk::VkDeviceSize,
2562 | index_type: vk::VkIndexType,
2563 | ) {
2564 | let fake_vulkan = FakeVulkan::current();
2565 |
2566 | fake_vulkan.add_command(
2567 | command_buffer,
2568 | Command::BindIndexBuffer {
2569 | buffer,
2570 | offset,
2571 | index_type,
2572 | },
2573 | );
2574 | }
2575 |
2576 | extern "C" fn draw(
2577 | command_buffer: vk::VkCommandBuffer,
2578 | vertex_count: u32,
2579 | instance_count: u32,
2580 | first_vertex: u32,
2581 | first_instance: u32,
2582 | ) {
2583 | let fake_vulkan = FakeVulkan::current();
2584 |
2585 | fake_vulkan.add_command(
2586 | command_buffer,
2587 | Command::Draw {
2588 | vertex_count,
2589 | instance_count,
2590 | first_vertex,
2591 | first_instance,
2592 | },
2593 | );
2594 | }
2595 |
2596 | extern "C" fn draw_indexed(
2597 | command_buffer: vk::VkCommandBuffer,
2598 | index_count: u32,
2599 | instance_count: u32,
2600 | first_index: u32,
2601 | vertex_offset: i32,
2602 | first_instance: u32,
2603 | ) {
2604 | let fake_vulkan = FakeVulkan::current();
2605 |
2606 | fake_vulkan.add_command(
2607 | command_buffer,
2608 | Command::DrawIndexed {
2609 | index_count,
2610 | instance_count,
2611 | first_index,
2612 | vertex_offset,
2613 | first_instance,
2614 | },
2615 | );
2616 | }
2617 |
2618 | extern "C" fn dispatch(
2619 | command_buffer: vk::VkCommandBuffer,
2620 | x: u32,
2621 | y: u32,
2622 | z: u32
2623 | ) {
2624 | let fake_vulkan = FakeVulkan::current();
2625 |
2626 | fake_vulkan.add_command(command_buffer, Command::Dispatch { x, y, z });
2627 | }
2628 |
2629 | extern "C" fn clear_attachments(
2630 | command_buffer: vk::VkCommandBuffer,
2631 | attachment_count: u32,
2632 | attachments: *const vk::VkClearAttachment,
2633 | rect_count: u32,
2634 | rects: *const vk::VkClearRect,
2635 | ) {
2636 | let fake_vulkan = FakeVulkan::current();
2637 |
2638 | let attachments = unsafe {
2639 | std::slice::from_raw_parts(
2640 | attachments,
2641 | attachment_count as usize,
2642 | )
2643 | }.iter().map(|attachment| {
2644 | if attachment.aspectMask == vk::VK_IMAGE_ASPECT_COLOR_BIT {
2645 | ClearAttachment::Color {
2646 | attachment: attachment.colorAttachment,
2647 | value: unsafe {
2648 | attachment.clearValue.color.float32.clone()
2649 | },
2650 | }
2651 | } else {
2652 | assert!(
2653 | attachment.aspectMask
2654 | & (vk::VK_IMAGE_ASPECT_DEPTH_BIT
2655 | | vk::VK_IMAGE_ASPECT_STENCIL_BIT)
2656 | != 0
2657 | );
2658 | assert_eq!(
2659 | attachment.aspectMask
2660 | & !(vk::VK_IMAGE_ASPECT_DEPTH_BIT
2661 | | vk::VK_IMAGE_ASPECT_STENCIL_BIT),
2662 | 0,
2663 | );
2664 | ClearAttachment::DepthStencil {
2665 | aspect_mask: attachment.aspectMask,
2666 | value: unsafe {
2667 | attachment.clearValue.depthStencil
2668 | },
2669 | }
2670 | }
2671 | }).collect::<Vec<ClearAttachment>>();
2672 |
2673 | let rects = vec_from_raw_parts(
2674 | rects,
2675 | rect_count as usize,
2676 | );
2677 |
2678 | fake_vulkan.add_command(
2679 | command_buffer,
2680 | Command::ClearAttachments {
2681 | attachments,
2682 | rects,
2683 | }
2684 | );
2685 | }
2686 |
2687 | extern "C" fn pipeline_barrier(
2688 | command_buffer: vk::VkCommandBuffer,
2689 | src_stage_mask: vk::VkPipelineStageFlags,
2690 | dst_stage_mask: vk::VkPipelineStageFlags,
2691 | dependency_flags: vk::VkDependencyFlags,
2692 | memory_barrier_count: u32,
2693 | memory_barriers: *const vk::VkMemoryBarrier,
2694 | buffer_memory_barrier_count: u32,
2695 | buffer_memory_barriers: *const vk::VkBufferMemoryBarrier,
2696 | image_memory_barrier_count: u32,
2697 | image_memory_barriers: *const vk::VkImageMemoryBarrier,
2698 | ) {
2699 | let fake_vulkan = FakeVulkan::current();
2700 |
2701 | let memory_barriers = vec_from_raw_parts(
2702 | memory_barriers,
2703 | memory_barrier_count as usize,
2704 | );
2705 |
2706 | let buffer_memory_barriers = vec_from_raw_parts(
2707 | buffer_memory_barriers,
2708 | buffer_memory_barrier_count as usize,
2709 | );
2710 |
2711 | for barrier in buffer_memory_barriers.iter() {
2712 | fake_vulkan.check_buffer(barrier.buffer);
2713 | }
2714 |
2715 | let image_memory_barriers = vec_from_raw_parts(
2716 | image_memory_barriers,
2717 | image_memory_barrier_count as usize,
2718 | );
2719 |
2720 | for barrier in image_memory_barriers.iter() {
2721 | fake_vulkan.check_image(barrier.image);
2722 | }
2723 |
2724 | fake_vulkan.add_command(
2725 | command_buffer,
2726 | Command::PipelineBarrier {
2727 | src_stage_mask,
2728 | dst_stage_mask,
2729 | dependency_flags,
2730 | memory_barriers,
2731 | buffer_memory_barriers,
2732 | image_memory_barriers,
2733 | },
2734 | );
2735 | }
2736 |
2737 | extern "C" fn copy_image_to_buffer(
2738 | command_buffer: vk::VkCommandBuffer,
2739 | src_image: vk::VkImage,
2740 | src_image_layout: vk::VkImageLayout,
2741 | dst_buffer: vk::VkBuffer,
2742 | region_count: u32,
2743 | regions: *const vk::VkBufferImageCopy,
2744 | ) {
2745 | let fake_vulkan = FakeVulkan::current();
2746 |
2747 | fake_vulkan.check_image(src_image);
2748 | fake_vulkan.check_buffer(dst_buffer);
2749 |
2750 | let regions = vec_from_raw_parts(
2751 | regions,
2752 | region_count as usize,
2753 | );
2754 |
2755 | fake_vulkan.add_command(
2756 | command_buffer,
2757 | Command::CopyImageToBuffer {
2758 | src_image,
2759 | src_image_layout,
2760 | dst_buffer,
2761 | regions,
2762 | },
2763 | );
2764 | }
2765 |
2766 | extern "C" fn push_constants(
2767 | command_buffer: vk::VkCommandBuffer,
2768 | layout: vk::VkPipelineLayout,
2769 | stage_flags: vk::VkShaderStageFlags,
2770 | offset: u32,
2771 | size: u32,
2772 | values: *const c_void,
2773 | ) {
2774 | let fake_vulkan = FakeVulkan::current();
2775 |
2776 | let values = vec_from_raw_parts(
2777 | values as *const u8,
2778 | size as usize,
2779 | );
2780 |
2781 | fake_vulkan.add_command(
2782 | command_buffer,
2783 | Command::PushConstants {
2784 | layout,
2785 | stage_flags,
2786 | offset,
2787 | values,
2788 | },
2789 | );
2790 | }
2791 |
2792 | extern "C" fn bind_descriptor_sets(
2793 | command_buffer: vk::VkCommandBuffer,
2794 | pipeline_bind_point: vk::VkPipelineBindPoint,
2795 | layout: vk::VkPipelineLayout,
2796 | first_set: u32,
2797 | descriptor_set_count: u32,
2798 | descriptor_sets: *const vk::VkDescriptorSet,
2799 | _dynamic_offset_count: u32,
2800 | _dynamic_offsets: *const u32,
2801 | ) {
2802 | let fake_vulkan = FakeVulkan::current();
2803 |
2804 | let descriptor_sets = vec_from_raw_parts(
2805 | descriptor_sets,
2806 | descriptor_set_count as usize,
2807 | );
2808 |
2809 | fake_vulkan.add_command(
2810 | command_buffer,
2811 | Command::BindDescriptorSets {
2812 | pipeline_bind_point,
2813 | layout,
2814 | first_set,
2815 | descriptor_sets,
2816 | },
2817 | );
2818 | }
2819 |
2820 | extern "C" fn reset_fences(
2821 | device: vk::VkDevice,
2822 | fence_count: u32,
2823 | fences: *const vk::VkFence,
2824 | ) -> vk::VkResult {
2825 | let fake_vulkan = FakeVulkan::current();
2826 |
2827 | fake_vulkan.check_device(device);
2828 |
2829 | let res = fake_vulkan.next_result("vkResetFences");
2830 |
2831 | if res != vk::VK_SUCCESS {
2832 | return res;
2833 | }
2834 |
2835 | let fences = unsafe {
2836 | std::slice::from_raw_parts(
2837 | fences,
2838 | fence_count as usize,
2839 | )
2840 | };
2841 |
2842 | for &fence in fences.iter() {
2843 | let HandleType::Fence { ref mut reset_count, .. } =
2844 | fake_vulkan.get_handle_mut(fence).data
2845 | else { unreachable!("bad handle"); };
2846 |
2847 | *reset_count += 1;
2848 | }
2849 |
2850 | res
2851 | }
2852 |
2853 | extern "C" fn wait_for_fences(
2854 | device: vk::VkDevice,
2855 | fence_count: u32,
2856 | fences: *const vk::VkFence,
2857 | _wait_all: vk::VkBool32,
2858 | _timeout: u64,
2859 | ) -> vk::VkResult {
2860 | let fake_vulkan = FakeVulkan::current();
2861 |
2862 | fake_vulkan.check_device(device);
2863 |
2864 | let res = fake_vulkan.next_result("vkWaitForFences");
2865 |
2866 | if res != vk::VK_SUCCESS {
2867 | return res;
2868 | }
2869 |
2870 | let fences = unsafe {
2871 | std::slice::from_raw_parts(
2872 | fences,
2873 | fence_count as usize,
2874 | )
2875 | };
2876 |
2877 | for &fence in fences.iter() {
2878 | let HandleType::Fence { ref mut wait_count, .. } =
2879 | fake_vulkan.get_handle_mut(fence).data
2880 | else { unreachable!("bad handle"); };
2881 |
2882 | *wait_count += 1;
2883 | }
2884 |
2885 | res
2886 | }
2887 | }
2888 |
2889 | impl Drop for FakeVulkan {
2890 | fn drop(&mut self) {
2891 | if !std::thread::panicking() {
2892 | let old_value = CURRENT_FAKE_VULKAN.with(|f| f.replace(None));
2893 | // There should only be one FakeVulkan at a time so the
2894 | // one we just dropped should be the one that was set for
2895 | // the current thread.
2896 | assert_eq!(old_value.unwrap(), self as *mut FakeVulkan);
2897 | }
2898 | }
2899 | }
2900 |
```