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 | ```