#
tokens: 29603/50000 1/78 files (page 7/9)
lines: on (toggle) GitHub
raw markdown copy reset
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 | 
```
Page 7/9FirstPrevNextLast