This is page 3 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/executor.rs: -------------------------------------------------------------------------------- ```rust 1 | // vkrunner 2 | // 3 | // Copyright (C) 2018 Intel Corporation 4 | // Copyright 2023 Neil Roberts 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a 7 | // copy of this software and associated documentation files (the "Software"), 8 | // to deal in the Software without restriction, including without limitation 9 | // the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 | // and/or sell copies of the Software, and to permit persons to whom the 11 | // Software is furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice (including the next 14 | // paragraph) shall be included in all copies or substantial portions of the 15 | // Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 | // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 23 | // DEALINGS IN THE SOFTWARE. 24 | 25 | use crate::vulkan_funcs; 26 | use crate::context::{self, Context}; 27 | use crate::window::{Window, WindowError}; 28 | use crate::config::Config; 29 | use crate::script::Script; 30 | use crate::source::Source; 31 | use crate::result; 32 | use crate::vk; 33 | use crate::requirements::Requirements; 34 | use crate::pipeline_set::{self, PipelineSet}; 35 | use crate::tester; 36 | use crate::requirements; 37 | use std::ffi::c_void; 38 | use std::fmt; 39 | use std::rc::Rc; 40 | use std::cell::RefCell; 41 | 42 | #[derive(Debug)] 43 | pub(crate) enum Error { 44 | Context(context::Error), 45 | Window(WindowError), 46 | PipelineError(pipeline_set::Error), 47 | TestError(tester::Error), 48 | ExternalDeviceRequirementsError(requirements::Error), 49 | } 50 | 51 | impl Error { 52 | pub fn result(&self) -> result::Result { 53 | match self { 54 | Error::Context(e) => e.result(), 55 | Error::Window(e) => e.result(), 56 | Error::ExternalDeviceRequirementsError(e) => e.result(), 57 | Error::PipelineError(_) => result::Result::Fail, 58 | Error::TestError(_) => result::Result::Fail, 59 | } 60 | } 61 | } 62 | 63 | impl From<context::Error> for Error { 64 | fn from(error: context::Error) -> Error { 65 | Error::Context(error) 66 | } 67 | } 68 | 69 | impl From<WindowError> for Error { 70 | fn from(error: WindowError) -> Error { 71 | Error::Window(error) 72 | } 73 | } 74 | 75 | impl From<pipeline_set::Error> for Error { 76 | fn from(error: pipeline_set::Error) -> Error { 77 | Error::PipelineError(error) 78 | } 79 | } 80 | 81 | impl From<tester::Error> for Error { 82 | fn from(error: tester::Error) -> Error { 83 | Error::TestError(error) 84 | } 85 | } 86 | 87 | impl fmt::Display for Error { 88 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 89 | match self { 90 | Error::Context(e) => e.fmt(f), 91 | Error::Window(e) => e.fmt(f), 92 | Error::PipelineError(e) => e.fmt(f), 93 | Error::TestError(e) => e.fmt(f), 94 | Error::ExternalDeviceRequirementsError(e) => e.fmt(f), 95 | } 96 | } 97 | } 98 | 99 | #[derive(Debug)] 100 | struct ExternalData { 101 | get_instance_proc_cb: vulkan_funcs::GetInstanceProcFunc, 102 | user_data: *const c_void, 103 | physical_device: vk::VkPhysicalDevice, 104 | queue_family: u32, 105 | vk_device: vk::VkDevice, 106 | } 107 | 108 | #[derive(Debug)] 109 | pub struct Executor { 110 | config: Rc<RefCell<Config>>, 111 | 112 | window: Option<Rc<Window>>, 113 | context: Option<Rc<Context>>, 114 | // A cache of the requirements that the context was created with. 115 | // Used to detect if the requirements have changed. This won’t be 116 | // used if the context is external. 117 | requirements: Requirements, 118 | 119 | external: Option<ExternalData>, 120 | } 121 | 122 | impl Executor { 123 | fn reset_window(&mut self) { 124 | self.window = None; 125 | } 126 | 127 | fn reset_context(&mut self) { 128 | self.reset_window(); 129 | self.context = None; 130 | } 131 | 132 | fn context_is_compatible(&self, script: &Script) -> bool { 133 | // If the device is created externally then it’s up to the 134 | // caller to ensure the device has all the necessary features 135 | // enabled. 136 | if self.external.is_some() { 137 | return true; 138 | } 139 | 140 | match self.context { 141 | Some(_) => self.requirements.eq(script.requirements()), 142 | None => false, 143 | } 144 | } 145 | 146 | pub fn new(config: Rc<RefCell<Config>>) -> Executor { 147 | Executor { 148 | config, 149 | 150 | window: None, 151 | context: None, 152 | requirements: Requirements::new(), 153 | external: None, 154 | } 155 | } 156 | 157 | pub fn set_device( 158 | &mut self, 159 | get_instance_proc_cb: vulkan_funcs::GetInstanceProcFunc, 160 | user_data: *const c_void, 161 | physical_device: vk::VkPhysicalDevice, 162 | queue_family: u32, 163 | vk_device: vk::VkDevice, 164 | ) { 165 | self.reset_context(); 166 | 167 | self.external = Some(ExternalData { 168 | get_instance_proc_cb, 169 | user_data, 170 | physical_device, 171 | queue_family, 172 | vk_device, 173 | }); 174 | } 175 | 176 | fn create_context( 177 | &self, 178 | requirements: &Requirements, 179 | ) -> Result<Context, Error> { 180 | match &self.external { 181 | Some(e) => { 182 | Ok(Context::new_with_device( 183 | e.get_instance_proc_cb, 184 | e.user_data, 185 | e.physical_device, 186 | e.queue_family, 187 | e.vk_device, 188 | )?) 189 | }, 190 | None => Ok(Context::new( 191 | requirements, 192 | self.config.borrow().device_id() 193 | )?), 194 | } 195 | } 196 | 197 | fn context_for_script( 198 | &mut self, 199 | script: &Script, 200 | ) -> Result<Rc<Context>, Error> { 201 | // Recreate the context if the features or extensions have changed 202 | if !self.context_is_compatible(script) { 203 | self.reset_context(); 204 | } 205 | 206 | match &self.context { 207 | Some(c) => Ok(Rc::clone(c)), 208 | None => { 209 | self.requirements.clone_from(script.requirements()); 210 | let context = self.create_context(&self.requirements)?; 211 | 212 | Ok(Rc::clone(self.context.insert(Rc::new(context)))) 213 | } 214 | } 215 | } 216 | 217 | fn window_for_script( 218 | &mut self, 219 | script: &Script, 220 | context: Rc<Context>, 221 | ) -> Result<Rc<Window>, Error> { 222 | // Recreate the window if the framebuffer format is different 223 | if let Some(window) = &self.window { 224 | if !window.format().eq(script.window_format()) { 225 | self.reset_window(); 226 | } 227 | } 228 | 229 | match &self.window { 230 | Some(w) => Ok(Rc::clone(w)), 231 | None => Ok(Rc::clone(self.window.insert(Rc::new(Window::new( 232 | context, 233 | script.window_format(), 234 | )?)))), 235 | } 236 | } 237 | 238 | fn handle_execute_result( 239 | &self, 240 | result: Result<(), Error> 241 | ) -> result::Result { 242 | match result { 243 | Ok(()) => result::Result::Pass, 244 | Err(e) => { 245 | use std::fmt::Write; 246 | let _ = writeln!( 247 | self.config.borrow_mut().logger().borrow_mut(), 248 | "{}", 249 | e 250 | ); 251 | e.result() 252 | } 253 | } 254 | } 255 | 256 | fn execute_script_or_error( 257 | &mut self, 258 | script: &Script 259 | ) -> Result<(), Error> { 260 | let context = self.context_for_script(script)?; 261 | 262 | if self.external.is_some() { 263 | if let Err(e) = script.requirements().check( 264 | context.instance(), 265 | context.physical_device(), 266 | ) { 267 | return Err(Error::ExternalDeviceRequirementsError(e)); 268 | } 269 | } 270 | 271 | let window = self.window_for_script(script, Rc::clone(&context))?; 272 | 273 | let pipeline_set = PipelineSet::new( 274 | &mut self.config.borrow().logger().borrow_mut(), 275 | Rc::clone(&window), 276 | script, 277 | self.config.borrow().show_disassembly(), 278 | )?; 279 | 280 | tester::run( 281 | window.as_ref(), 282 | &pipeline_set, 283 | script, 284 | self.config.borrow().inspector().clone(), 285 | )?; 286 | 287 | Ok(()) 288 | } 289 | 290 | pub fn execute_script( 291 | &mut self, 292 | script: &Script 293 | ) -> result::Result { 294 | let res = self.execute_script_or_error(script); 295 | self.handle_execute_result(res) 296 | } 297 | 298 | pub fn execute( 299 | &mut self, 300 | source: &Source, 301 | ) -> result::Result { 302 | let load_res = Script::load(&self.config.borrow(), source); 303 | 304 | load_res 305 | .and_then(|script| Some(self.execute_script(&script))) 306 | .unwrap_or(result::Result::Fail) 307 | } 308 | } 309 | 310 | #[cfg(test)] 311 | mod test { 312 | use super::*; 313 | use crate::fake_vulkan::FakeVulkan; 314 | use crate::config::Config; 315 | use std::ffi::c_char; 316 | 317 | fn create_fake_vulkan() -> Box<FakeVulkan> { 318 | let mut fake_vulkan = FakeVulkan::new(); 319 | fake_vulkan.physical_devices.push(Default::default()); 320 | fake_vulkan.physical_devices[0].features.wideLines = vk::VK_TRUE; 321 | fake_vulkan.physical_devices[0].format_properties.insert( 322 | vk::VK_FORMAT_B8G8R8A8_UNORM, 323 | vk::VkFormatProperties { 324 | linearTilingFeatures: 0, 325 | optimalTilingFeatures: 326 | vk::VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT 327 | | vk::VK_FORMAT_FEATURE_BLIT_SRC_BIT, 328 | bufferFeatures: 0, 329 | }, 330 | ); 331 | fake_vulkan.physical_devices[0].format_properties.insert( 332 | vk::VK_FORMAT_R8_UNORM, 333 | vk::VkFormatProperties { 334 | linearTilingFeatures: 0, 335 | optimalTilingFeatures: 336 | vk::VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT 337 | | vk::VK_FORMAT_FEATURE_BLIT_SRC_BIT, 338 | bufferFeatures: 0, 339 | }, 340 | ); 341 | 342 | let memory_properties = 343 | &mut fake_vulkan.physical_devices[0].memory_properties; 344 | memory_properties.memoryTypes[0].propertyFlags = 345 | vk::VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT; 346 | memory_properties.memoryTypeCount = 1; 347 | fake_vulkan.memory_requirements.memoryTypeBits = 1; 348 | 349 | fake_vulkan 350 | } 351 | 352 | #[test] 353 | fn recreate_resources() { 354 | let fake_vulkan = create_fake_vulkan(); 355 | 356 | let config = Rc::new(RefCell::new(Config::new())); 357 | 358 | let mut executor = Executor::new(Rc::clone(&config)); 359 | 360 | fake_vulkan.set_override(); 361 | assert_eq!( 362 | executor.execute(&Source::from_string("".to_string())), 363 | result::Result::Pass, 364 | ); 365 | 366 | let context = Rc::clone(executor.context.as_ref().unwrap()); 367 | let window = Rc::clone(&executor.window.as_ref().unwrap()); 368 | 369 | // Run another script that has the same requirements 370 | assert_eq!( 371 | executor.execute(&Source::from_string( 372 | "[test]\n\ 373 | draw rect -1 -1 2 2".to_string() 374 | )), 375 | result::Result::Pass, 376 | ); 377 | 378 | // The context and window shouldn’t have changed 379 | assert!(Rc::ptr_eq(&context, executor.context.as_ref().unwrap())); 380 | assert!(Rc::ptr_eq(&window, executor.window.as_ref().unwrap())); 381 | 382 | // Run a script with different requirements 383 | fake_vulkan.set_override(); 384 | assert_eq!( 385 | executor.execute(&Source::from_string( 386 | "[require]\n\ 387 | wideLines\n\ 388 | [test]\n\ 389 | draw rect -1 -1 2 2".to_string() 390 | )), 391 | result::Result::Pass, 392 | ); 393 | 394 | // The context and window should have changed 395 | assert!(!Rc::ptr_eq(&context, executor.context.as_ref().unwrap())); 396 | assert!(!Rc::ptr_eq(&window, executor.window.as_ref().unwrap())); 397 | 398 | let context = Rc::clone(executor.context.as_ref().unwrap()); 399 | let window = Rc::clone(&executor.window.as_ref().unwrap()); 400 | 401 | // Run the same script with a different framebuffer format 402 | assert_eq!( 403 | executor.execute(&Source::from_string( 404 | "[require]\n\ 405 | wideLines\n\ 406 | framebuffer R8_UNORM\n\ 407 | [test]\n\ 408 | draw rect -1 -1 2 2".to_string() 409 | )), 410 | result::Result::Pass, 411 | ); 412 | 413 | // The context should stay the same but the framebuffer should 414 | // have changed 415 | assert!(Rc::ptr_eq(&context, executor.context.as_ref().unwrap())); 416 | assert!(!Rc::ptr_eq(&window, executor.window.as_ref().unwrap())); 417 | } 418 | 419 | extern "C" fn get_instance_proc_cb( 420 | func_name: *const c_char, 421 | user_data: *const c_void, 422 | ) -> *const c_void { 423 | unsafe { 424 | let fake_vulkan = &*(user_data as *const FakeVulkan); 425 | 426 | let func = fake_vulkan.get_function(func_name); 427 | 428 | std::mem::transmute(func) 429 | } 430 | } 431 | 432 | #[test] 433 | fn external_device() { 434 | let fake_vulkan = create_fake_vulkan(); 435 | 436 | fake_vulkan.set_override(); 437 | let context = Context::new(&Requirements::new(), None).unwrap(); 438 | 439 | let config = Rc::new(RefCell::new(Config::new())); 440 | 441 | let mut executor = Executor::new(Rc::clone(&config)); 442 | 443 | let (queue_family, _) = FakeVulkan::unmake_queue(context.queue()); 444 | 445 | executor.set_device( 446 | get_instance_proc_cb, 447 | (fake_vulkan.as_ref() as *const FakeVulkan).cast(), 448 | context.physical_device(), 449 | queue_family, 450 | context.vk_device() 451 | ); 452 | 453 | assert_eq!( 454 | executor.execute(&Source::from_string("".to_string())), 455 | result::Result::Pass, 456 | ); 457 | } 458 | 459 | #[test] 460 | fn external_requirements_error() { 461 | let fake_vulkan = create_fake_vulkan(); 462 | 463 | fake_vulkan.set_override(); 464 | let context = Context::new(&Requirements::new(), None).unwrap(); 465 | 466 | let config = Rc::new(RefCell::new(Config::new())); 467 | 468 | let mut executor = Executor::new(Rc::clone(&config)); 469 | 470 | let (queue_family, _) = FakeVulkan::unmake_queue(context.queue()); 471 | 472 | executor.set_device( 473 | get_instance_proc_cb, 474 | (fake_vulkan.as_ref() as *const FakeVulkan).cast(), 475 | context.physical_device(), 476 | queue_family, 477 | context.vk_device() 478 | ); 479 | 480 | let source = Source::from_string( 481 | "[require]\n\ 482 | logicOp".to_string() 483 | ); 484 | let script = Script::load(&executor.config.borrow(), &source).unwrap(); 485 | 486 | let error = executor.execute_script_or_error(&script).unwrap_err(); 487 | 488 | assert_eq!( 489 | &error.to_string(), 490 | "Missing required feature: logicOp", 491 | ); 492 | assert_eq!( 493 | error.result(), 494 | result::Result::Skip, 495 | ); 496 | } 497 | 498 | #[test] 499 | fn context_error() { 500 | let fake_vulkan = create_fake_vulkan(); 501 | 502 | let config = Rc::new(RefCell::new(Config::new())); 503 | config.borrow_mut().set_device_id(Some(12)); 504 | 505 | let mut executor = Executor::new(Rc::clone(&config)); 506 | 507 | let source = Source::from_string("".to_string()); 508 | let script = Script::load(&executor.config.borrow(), &source).unwrap(); 509 | 510 | fake_vulkan.set_override(); 511 | let error = executor.execute_script_or_error(&script).unwrap_err(); 512 | 513 | assert_eq!( 514 | &error.to_string(), 515 | "Device 13 was selected but the Vulkan instance only reported \ 516 | 1 device.", 517 | ); 518 | assert_eq!( 519 | error.result(), 520 | result::Result::Fail, 521 | ); 522 | } 523 | 524 | fn run_script_error(source: &str) -> Error { 525 | let fake_vulkan = create_fake_vulkan(); 526 | 527 | let config = Rc::new(RefCell::new(Config::new())); 528 | 529 | let mut executor = Executor::new(config); 530 | 531 | let source = Source::from_string(source.to_string()); 532 | let script = Script::load(&executor.config.borrow(), &source).unwrap(); 533 | 534 | fake_vulkan.set_override(); 535 | executor.execute_script_or_error(&script).unwrap_err() 536 | } 537 | 538 | #[test] 539 | fn window_error() { 540 | let error = run_script_error( 541 | "[require]\n\ 542 | depthstencil R8_UNORM" 543 | ); 544 | 545 | assert_eq!( 546 | &error.to_string(), 547 | "Format R8_UNORM is not supported as a depth/stencil attachment", 548 | ); 549 | assert_eq!( 550 | error.result(), 551 | result::Result::Skip, 552 | ); 553 | } 554 | 555 | #[test] 556 | fn pipeline_error() { 557 | let error = run_script_error( 558 | "[vertex shader]\n\ 559 | 12" 560 | ); 561 | 562 | assert_eq!( 563 | &error.to_string(), 564 | "The compiler or assembler generated an invalid SPIR-V binary", 565 | ); 566 | assert_eq!( 567 | error.result(), 568 | result::Result::Fail, 569 | ); 570 | } 571 | 572 | #[test] 573 | fn tester_error() { 574 | let error = run_script_error( 575 | "[test]\n\ 576 | probe all rgb 1 2 3" 577 | ); 578 | 579 | assert_eq!( 580 | &error.to_string(), 581 | "line 2: Probe color at (0,0)\n\ 582 | \x20 Expected: 1 2 3\n\ 583 | \x20 Observed: 0 0 0" 584 | ); 585 | assert_eq!( 586 | error.result(), 587 | result::Result::Fail, 588 | ); 589 | } 590 | } 591 | ``` -------------------------------------------------------------------------------- /vkrunner/vkrunner/compiler.rs: -------------------------------------------------------------------------------- ```rust 1 | // vkrunner 2 | // 3 | // Copyright (C) 2018 Intel Corporation 4 | // Copyright 2023 Neil Roberts 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a 7 | // copy of this software and associated documentation files (the "Software"), 8 | // to deal in the Software without restriction, including without limitation 9 | // the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 | // and/or sell copies of the Software, and to permit persons to whom the 11 | // Software is furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice (including the next 14 | // paragraph) shall be included in all copies or substantial portions of the 15 | // Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 | // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 23 | // DEALINGS IN THE SOFTWARE. 24 | 25 | use crate::vk; 26 | use crate::shader_stage; 27 | use crate::logger::Logger; 28 | use crate::context::Context; 29 | use crate::script::{Script, Shader}; 30 | use crate::temp_file; 31 | use crate::requirements::extract_version; 32 | use std::fmt; 33 | use std::mem; 34 | use std::ptr; 35 | use std::io::{self, Write, Read, BufWriter}; 36 | use std::fs::File; 37 | use std::path::Path; 38 | use std::env; 39 | // When testing we’ll divert to a fake command so that we don’t need 40 | // to depend on glslangValidator 41 | #[cfg(test)] 42 | mod fake_process; 43 | #[cfg(test)] 44 | use fake_process::{Command, Output}; 45 | #[cfg(not(test))] 46 | use std::process::{Command, Output}; 47 | use std::process::Stdio; 48 | 49 | /// An error that can be returned by [build_stage]. 50 | #[derive(Debug)] 51 | pub enum Error { 52 | /// There were no shaders for this stage in the script 53 | MissingStageShaders(shader_stage::Stage), 54 | /// vkCreateShaderModule returned an error 55 | CreateShaderModuleFailed, 56 | /// Error creating a temporary file 57 | TempFile(temp_file::Error), 58 | /// Other I/O error 59 | IoError(io::Error), 60 | /// A compiler or assembler command returned a non-zero status 61 | CommandFailed, 62 | /// The generated shader binary didn’t have the right SPIR-V magic 63 | /// number or wasn’t a multiple of 32-bit integers. 64 | InvalidShaderBinary, 65 | } 66 | 67 | impl fmt::Display for Error { 68 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 69 | match self { 70 | Error::MissingStageShaders(stage) => write!( 71 | f, 72 | "No shaders for stage {:?}", 73 | stage, 74 | ), 75 | Error::CreateShaderModuleFailed => write!( 76 | f, 77 | "vkCreateShaderModule failed" 78 | ), 79 | Error::TempFile(e) => e.fmt(f), 80 | Error::IoError(e) => e.fmt(f), 81 | Error::CommandFailed => write!( 82 | f, 83 | "A subprocess failed with a non-zero exit status", 84 | ), 85 | Error::InvalidShaderBinary => write!( 86 | f, 87 | "The compiler or assembler generated an invalid SPIR-V binary", 88 | ), 89 | } 90 | } 91 | } 92 | 93 | impl From<temp_file::Error> for Error { 94 | fn from(e: temp_file::Error) -> Error { 95 | Error::TempFile(e) 96 | } 97 | } 98 | 99 | impl From<io::Error> for Error { 100 | fn from(e: io::Error) -> Error { 101 | Error::IoError(e) 102 | } 103 | } 104 | 105 | fn stage_name(stage: shader_stage::Stage) -> &'static str { 106 | match stage { 107 | shader_stage::Stage::Vertex => "vert", 108 | shader_stage::Stage::TessCtrl => "tesc", 109 | shader_stage::Stage::TessEval => "tese", 110 | shader_stage::Stage::Geometry => "geom", 111 | shader_stage::Stage::Fragment => "frag", 112 | shader_stage::Stage::Compute => "comp", 113 | } 114 | } 115 | 116 | fn handle_command_output( 117 | logger: &mut Logger, 118 | output: Output, 119 | ) -> Result<(), Error> { 120 | logger.write_all(output.stdout.as_slice())?; 121 | logger.write_all(output.stderr.as_slice())?; 122 | 123 | if output.status.success() { 124 | Ok(()) 125 | } else { 126 | Err(Error::CommandFailed) 127 | } 128 | } 129 | 130 | fn show_disassembly_from_file( 131 | logger: &mut Logger, 132 | filename: &Path, 133 | ) -> Result<(), Error> { 134 | let exe = match env::var_os("PIGLIT_SPIRV_DIS_BINARY") { 135 | Some(exe) => exe, 136 | None => "spirv-dis".into(), 137 | }; 138 | 139 | handle_command_output( 140 | logger, 141 | Command::new(exe) 142 | .arg(filename) 143 | .stdout(Stdio::piped()) 144 | .stderr(Stdio::piped()) 145 | .output()? 146 | ) 147 | } 148 | 149 | fn create_shader_from_binary( 150 | context: &Context, 151 | data: &[u32], 152 | ) -> Result<vk::VkShaderModule, Error> { 153 | let shader_module_create_info = vk::VkShaderModuleCreateInfo { 154 | sType: vk::VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO, 155 | pNext: ptr::null(), 156 | flags: 0, 157 | codeSize: data.len() * mem::size_of::<u32>(), 158 | pCode: data.as_ptr(), 159 | }; 160 | 161 | let mut module: vk::VkShaderModule = vk::null_handle(); 162 | 163 | let res = unsafe { 164 | context.device().vkCreateShaderModule.unwrap()( 165 | context.vk_device(), 166 | ptr::addr_of!(shader_module_create_info), 167 | ptr::null(), // allocator 168 | ptr::addr_of_mut!(module), 169 | ) 170 | }; 171 | 172 | if res == vk::VK_SUCCESS { 173 | Ok(module) 174 | } else { 175 | Err(Error::CreateShaderModuleFailed) 176 | } 177 | } 178 | 179 | fn create_shader_from_binary_file( 180 | context: &Context, 181 | file: &mut File, 182 | ) -> Result<vk::VkShaderModule, Error> { 183 | let mut data = Vec::<u32>::new(); 184 | let mut buf = vec![0u8; 512]; 185 | let mut buf_length = 0usize; 186 | let mut big_endian = false; 187 | let mut bytes = [0u8; mem::size_of::<u32>()]; 188 | 189 | loop { 190 | let got = file.read(&mut buf[buf_length..])?; 191 | 192 | if got == 0 { 193 | break; 194 | } 195 | 196 | buf_length += got; 197 | 198 | for i in 0..buf_length / mem::size_of::<u32>() { 199 | let buf_start = i * mem::size_of::<u32>(); 200 | bytes.copy_from_slice(&buf[ 201 | buf_start..buf_start + mem::size_of::<u32>() 202 | ]); 203 | 204 | if data.len() == 0 { 205 | if bytes == [0x07, 0x23, 0x02, 0x03] { 206 | big_endian = true; 207 | } else if bytes == [0x03, 0x02, 0x23, 0x07] { 208 | big_endian = false; 209 | } else { 210 | return Err(Error::InvalidShaderBinary); 211 | } 212 | } 213 | 214 | data.push(if big_endian { 215 | u32::from_be_bytes(bytes) 216 | } else { 217 | u32::from_le_bytes(bytes) 218 | }); 219 | } 220 | 221 | let remainder = buf_length % mem::size_of::<u32>(); 222 | 223 | buf.copy_within(buf_length - remainder.., 0); 224 | buf_length = remainder; 225 | } 226 | 227 | if buf_length != 0 { 228 | Err(Error::InvalidShaderBinary) 229 | } else { 230 | create_shader_from_binary(context, &data) 231 | } 232 | } 233 | 234 | fn create_temp_file_for_source( 235 | source: &str 236 | ) -> Result<temp_file::TempFile, Error> { 237 | let mut temp_file = temp_file::TempFile::new()?; 238 | temp_file.file().unwrap().write_all(source.as_bytes())?; 239 | temp_file.file().unwrap().flush()?; 240 | temp_file.close(); 241 | 242 | Ok(temp_file) 243 | } 244 | 245 | fn version_string(version: u32) -> String { 246 | let (version_major, version_minor, _) = extract_version(version); 247 | format!("vulkan{}.{}", version_major, version_minor) 248 | } 249 | 250 | fn compile_glsl( 251 | logger: &mut Logger, 252 | context: &Context, 253 | script: &Script, 254 | stage: shader_stage::Stage, 255 | show_disassembly: bool, 256 | ) -> Result<vk::VkShaderModule, Error> { 257 | let mut shader_files = Vec::new(); 258 | 259 | for shader in script.shaders(stage) { 260 | let source = match &shader { 261 | Shader::Glsl(s) => s, 262 | _ => unreachable!("Unexpected shader type"), 263 | }; 264 | shader_files.push(create_temp_file_for_source(&source)?); 265 | } 266 | 267 | let version_str = version_string(script.requirements().version()); 268 | 269 | let mut module_file = temp_file::TempFile::new()?; 270 | 271 | let exe = match env::var_os("PIGLIT_GLSLANG_VALIDATOR_BINARY") { 272 | Some(exe) => exe, 273 | None => "glslangValidator".into(), 274 | }; 275 | 276 | handle_command_output( 277 | logger, 278 | Command::new(exe) 279 | .args([ 280 | "--quiet", 281 | "-V", 282 | "--target-env", &version_str, 283 | "-S", stage_name(stage), 284 | ]) 285 | .arg("-o").arg(module_file.filename()) 286 | .args(shader_files.iter().map(|file| file.filename())) 287 | .stdout(Stdio::piped()) 288 | .stderr(Stdio::piped()) 289 | .output()? 290 | )?; 291 | 292 | drop(shader_files); 293 | 294 | if show_disassembly { 295 | show_disassembly_from_file(logger, module_file.filename())?; 296 | } 297 | 298 | create_shader_from_binary_file(context, module_file.file().unwrap()) 299 | } 300 | 301 | fn assemble_spirv( 302 | logger: &mut Logger, 303 | context: &Context, 304 | script: &Script, 305 | source: &str, 306 | show_disassembly: bool, 307 | ) -> Result<vk::VkShaderModule, Error> { 308 | let version_str = version_string(script.requirements().version()); 309 | 310 | let mut module_file = temp_file::TempFile::new()?; 311 | 312 | let source_file = create_temp_file_for_source(source)?; 313 | 314 | let exe = match env::var_os("PIGLIT_SPIRV_AS_BINARY") { 315 | Some(exe) => exe, 316 | None => "spirv-as".into(), 317 | }; 318 | 319 | handle_command_output( 320 | logger, 321 | Command::new(exe) 322 | .args(["--target-env", &version_str]) 323 | .arg("-o").arg(module_file.filename()) 324 | .arg(source_file.filename()) 325 | .stdout(Stdio::piped()) 326 | .stderr(Stdio::piped()) 327 | .output()? 328 | )?; 329 | 330 | drop(source_file); 331 | 332 | if show_disassembly { 333 | show_disassembly_from_file(logger, module_file.filename())?; 334 | } 335 | 336 | create_shader_from_binary_file(context, module_file.file().unwrap()) 337 | } 338 | 339 | fn load_binary_stage( 340 | logger: &mut Logger, 341 | context: &Context, 342 | data: &[u32], 343 | show_disassembly: bool, 344 | ) -> Result<vk::VkShaderModule, Error> { 345 | if show_disassembly { 346 | let mut temp_file = temp_file::TempFile::new()?; 347 | let mut writer = BufWriter::new(temp_file.file().unwrap()); 348 | 349 | for value in data { 350 | writer.write_all(&value.to_ne_bytes())?; 351 | } 352 | 353 | writer.flush()?; 354 | 355 | drop(writer); 356 | 357 | temp_file.close(); 358 | 359 | show_disassembly_from_file(logger, temp_file.filename())?; 360 | } 361 | 362 | create_shader_from_binary(context, data) 363 | } 364 | 365 | pub fn build_stage( 366 | logger: &mut Logger, 367 | context: &Context, 368 | script: &Script, 369 | stage: shader_stage::Stage, 370 | show_disassembly: bool, 371 | ) -> Result<vk::VkShaderModule, Error> { 372 | let shaders = script.shaders(stage); 373 | 374 | match shaders.get(0) { 375 | None => Err(Error::MissingStageShaders(stage)), 376 | Some(Shader::Glsl(_)) => compile_glsl( 377 | logger, 378 | context, 379 | script, 380 | stage, 381 | show_disassembly, 382 | ), 383 | Some(Shader::Spirv(source)) => { 384 | // The script parser should have ensured that there’s 385 | // only one shader 386 | assert_eq!(shaders.len(), 1); 387 | assemble_spirv( 388 | logger, 389 | context, 390 | script, 391 | source, 392 | show_disassembly 393 | ) 394 | }, 395 | Some(Shader::Binary(data)) => { 396 | // The script parser should have ensured that there’s 397 | // only one shader 398 | assert_eq!(shaders.len(), 1); 399 | load_binary_stage( 400 | logger, 401 | context, 402 | data, 403 | show_disassembly 404 | ) 405 | }, 406 | } 407 | } 408 | 409 | #[cfg(test)] 410 | mod test { 411 | use super::*; 412 | use crate::fake_vulkan::{FakeVulkan, HandleType}; 413 | use crate::context::Context; 414 | use crate::requirements::Requirements; 415 | use crate::source::Source; 416 | use crate::config::Config; 417 | use std::ffi::{c_char, c_void, CStr}; 418 | 419 | struct CompileOutput { 420 | log: Vec<String>, 421 | result: Result<Vec<u32>, Error>, 422 | } 423 | 424 | extern "C" fn log_cb(message: *const c_char, user_data: *mut c_void) { 425 | unsafe { 426 | let message = CStr::from_ptr(message).to_str().unwrap().to_owned(); 427 | let log = &mut *(user_data as *mut Vec<String>); 428 | log.push(message); 429 | } 430 | } 431 | 432 | fn compile_script( 433 | source: &str, 434 | stage: shader_stage::Stage, 435 | show_disassembly: bool, 436 | ) -> CompileOutput { 437 | let mut fake_vulkan = FakeVulkan::new(); 438 | fake_vulkan.physical_devices.push(Default::default()); 439 | 440 | compile_script_with_fake_vulkan( 441 | &mut fake_vulkan, 442 | source, 443 | stage, 444 | show_disassembly 445 | ) 446 | } 447 | 448 | fn compile_script_with_fake_vulkan( 449 | fake_vulkan: &mut FakeVulkan, 450 | source: &str, 451 | stage: shader_stage::Stage, 452 | show_disassembly: bool, 453 | ) -> CompileOutput { 454 | fake_vulkan.set_override(); 455 | let context = Context::new(&Requirements::new(), None).unwrap(); 456 | 457 | let source = Source::from_string(source.to_owned()); 458 | let script = Script::load(&Config::new(), &source).unwrap(); 459 | let mut log = Vec::new(); 460 | let mut logger = Logger::new( 461 | Some(log_cb), 462 | ptr::addr_of_mut!(log).cast(), 463 | ); 464 | 465 | let result = build_stage( 466 | &mut logger, 467 | &context, 468 | &script, 469 | stage, 470 | show_disassembly, 471 | ).map(|module| { 472 | let code = match &fake_vulkan.get_handle(module).data { 473 | HandleType::ShaderModule { code } => code.clone(), 474 | _ => unreachable!("Unexpected Vulkan handle type"), 475 | }; 476 | unsafe { 477 | context.device().vkDestroyShaderModule.unwrap()( 478 | context.vk_device(), 479 | module, 480 | ptr::null(), // allocator 481 | ); 482 | } 483 | code 484 | }); 485 | 486 | CompileOutput { log, result } 487 | } 488 | 489 | #[test] 490 | fn glsl_le() { 491 | let CompileOutput { log, result } = compile_script( 492 | "[fragment shader]\n\ 493 | 03 02 23 07\n\ 494 | fe ca fe ca\n", 495 | shader_stage::Stage::Fragment, 496 | false, // show_disassembly 497 | ); 498 | 499 | assert_eq!( 500 | &log, 501 | &[ 502 | "quiet", 503 | "vulkan_spirv", 504 | "target_env: vulkan1.0", 505 | "stage: frag", 506 | ], 507 | ); 508 | 509 | assert_eq!(result.unwrap(), &[0x07230203, 0xcafecafe]); 510 | } 511 | 512 | #[test] 513 | fn glsl_be() { 514 | let CompileOutput { log, result } = compile_script( 515 | "[vertex shader]\n\ 516 | 07 23 02 03\n\ 517 | ca fe ca fe\n", 518 | shader_stage::Stage::Vertex, 519 | false, // show_disassembly 520 | ); 521 | 522 | assert_eq!( 523 | &log, 524 | &[ 525 | "quiet", 526 | "vulkan_spirv", 527 | "target_env: vulkan1.0", 528 | "stage: vert", 529 | ], 530 | ); 531 | 532 | assert_eq!(result.unwrap(), &[0x07230203, 0xcafecafe]); 533 | } 534 | 535 | #[test] 536 | fn spirv() { 537 | let CompileOutput { log, result } = compile_script( 538 | "[vertex shader spirv]\n\ 539 | 07 23 02 03\n\ 540 | f0 0d fe ed\n", 541 | shader_stage::Stage::Vertex, 542 | false, // show_disassembly 543 | ); 544 | 545 | assert_eq!(&log, &["target_env: vulkan1.0"]); 546 | 547 | assert_eq!(result.unwrap(), &[0x07230203, 0xf00dfeed]); 548 | } 549 | 550 | #[test] 551 | fn binary() { 552 | let CompileOutput { log, result } = compile_script( 553 | "[vertex shader binary]\n\ 554 | 07230203\n\ 555 | f00dfeed\n", 556 | shader_stage::Stage::Vertex, 557 | false, // show_disassembly 558 | ); 559 | 560 | assert!(log.is_empty()); 561 | 562 | assert_eq!(result.unwrap(), &[0x07230203, 0xf00dfeed]); 563 | } 564 | 565 | fn test_stage( 566 | stage: shader_stage::Stage, 567 | section_name: &str, 568 | compiler_argument: &str 569 | ) { 570 | let CompileOutput { log, result } = compile_script( 571 | &format!( 572 | "[{}]\n\ 573 | 07 23 02 03\n", 574 | section_name, 575 | ), 576 | stage, 577 | false, // show_disassembly 578 | ); 579 | 580 | assert_eq!( 581 | &log, 582 | &[ 583 | "quiet", 584 | "vulkan_spirv", 585 | "target_env: vulkan1.0", 586 | &format!("stage: {}", compiler_argument) 587 | ] 588 | ); 589 | 590 | assert!(result.is_ok()); 591 | } 592 | 593 | #[test] 594 | fn all_stages() { 595 | test_stage( 596 | shader_stage::Stage::Vertex, 597 | "vertex shader", 598 | "vert" 599 | ); 600 | test_stage( 601 | shader_stage::Stage::TessCtrl, 602 | "tessellation control shader", 603 | "tesc" 604 | ); 605 | test_stage( 606 | shader_stage::Stage::TessEval, 607 | "tessellation evaluation shader", 608 | "tese" 609 | ); 610 | test_stage( 611 | shader_stage::Stage::Geometry, 612 | "geometry shader", 613 | "geom" 614 | ); 615 | test_stage( 616 | shader_stage::Stage::Fragment, 617 | "fragment shader", 618 | "frag" 619 | ); 620 | test_stage( 621 | shader_stage::Stage::Compute, 622 | "compute shader", 623 | "comp" 624 | ); 625 | } 626 | 627 | #[test] 628 | fn no_shaders() { 629 | let CompileOutput { result, .. } = compile_script( 630 | "[vertex shader]\n\ 631 | 07 23 02 03\n", 632 | shader_stage::Stage::Fragment, 633 | false, // show_disassembly 634 | ); 635 | assert_eq!( 636 | &result.unwrap_err().to_string(), 637 | "No shaders for stage Fragment", 638 | ); 639 | } 640 | 641 | #[test] 642 | fn create_shader_module_error() { 643 | let mut fake_vulkan = FakeVulkan::new(); 644 | fake_vulkan.physical_devices.push(Default::default()); 645 | fake_vulkan.queue_result( 646 | "vkCreateShaderModule".to_string(), 647 | vk::VK_ERROR_UNKNOWN 648 | ); 649 | 650 | let CompileOutput { result, .. } = compile_script_with_fake_vulkan( 651 | &mut fake_vulkan, 652 | "[vertex shader]\n\ 653 | 07 23 02 03\n", 654 | shader_stage::Stage::Vertex, 655 | false, // show_disassembly 656 | ); 657 | assert_eq!( 658 | &result.unwrap_err().to_string(), 659 | "vkCreateShaderModule failed", 660 | ); 661 | } 662 | 663 | #[test] 664 | fn invalid_magic() { 665 | let CompileOutput { result, .. } = compile_script( 666 | "[vertex shader]\n\ 667 | 12 34 56 78\n", 668 | shader_stage::Stage::Vertex, 669 | false, // show_disassembly 670 | ); 671 | assert_eq!( 672 | &result.unwrap_err().to_string(), 673 | "The compiler or assembler generated an invalid SPIR-V binary", 674 | ); 675 | } 676 | 677 | #[test] 678 | fn not_multiple_of_u32() { 679 | let CompileOutput { result, .. } = compile_script( 680 | "[vertex shader]\n\ 681 | 07 23 02 03 9a\n", 682 | shader_stage::Stage::Vertex, 683 | false, // show_disassembly 684 | ); 685 | assert_eq!( 686 | &result.unwrap_err().to_string(), 687 | "The compiler or assembler generated an invalid SPIR-V binary", 688 | ); 689 | } 690 | 691 | #[test] 692 | fn compiler_failed() { 693 | let CompileOutput { result, .. } = compile_script( 694 | "[vertex shader]\n\ 695 | invalid hex values\n", 696 | shader_stage::Stage::Vertex, 697 | false, // show_disassembly 698 | ); 699 | assert_eq!( 700 | &result.unwrap_err().to_string(), 701 | "A subprocess failed with a non-zero exit status", 702 | ); 703 | } 704 | 705 | fn test_show_disassembly(section_suffix: &str) { 706 | let CompileOutput { log, result } = compile_script( 707 | &format!( 708 | "[fragment shader{}]\n\ 709 | 03 02 23 07\n\ 710 | fe ca fe ca\n", 711 | section_suffix, 712 | ), 713 | shader_stage::Stage::Fragment, 714 | true, // show_disassembly 715 | ); 716 | 717 | assert!(log.iter().find(|&line| line == "disassembly").is_some()); 718 | 719 | assert!(result.is_ok()); 720 | } 721 | 722 | #[test] 723 | fn show_glsl_disassembly() { 724 | test_show_disassembly(""); 725 | } 726 | 727 | #[test] 728 | fn show_spirv_disassembly() { 729 | test_show_disassembly(" spirv"); 730 | } 731 | 732 | #[test] 733 | fn show_binary_disassembly() { 734 | test_show_disassembly(" binary"); 735 | } 736 | } 737 | ``` -------------------------------------------------------------------------------- /vkrunner/vkrunner/format.rs: -------------------------------------------------------------------------------- ```rust 1 | // vkrunner 2 | // 3 | // Copyright (C) 2018 Intel Corporation 4 | // Copyright 2023 Neil Roberts 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a 7 | // copy of this software and associated documentation files (the "Software"), 8 | // to deal in the Software without restriction, including without limitation 9 | // on the rights to use, copy, modify, merge, publish, distribute, sub 10 | // license, and/or sell copies of the Software, and to permit persons to whom 11 | // the Software is furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice (including the next 14 | // paragraph) shall be included in all copies or substantial portions of the 15 | // Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | // FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 20 | // VA LINUX SYSTEM, IBM AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, 21 | // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 22 | // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 23 | // USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | 25 | use crate::small_float; 26 | use crate::half_float; 27 | use crate::vk; 28 | use std::convert::TryInto; 29 | use std::num::NonZeroUsize; 30 | 31 | #[derive(Debug)] 32 | pub struct Format { 33 | pub(crate) vk_format: vk::VkFormat, 34 | pub(crate) name: &'static str, 35 | pub(crate) packed_size: Option<NonZeroUsize>, 36 | n_parts: usize, 37 | parts: [Part; 4], 38 | } 39 | 40 | #[derive(Debug, Eq, PartialEq, Copy, Clone)] 41 | pub(crate) enum Component { 42 | R, 43 | G, 44 | B, 45 | A, 46 | D, 47 | S, 48 | X, 49 | } 50 | 51 | #[derive(Debug, Eq, PartialEq, Copy, Clone)] 52 | pub(crate) enum Mode { 53 | UNORM, 54 | SNORM, 55 | USCALED, 56 | SSCALED, 57 | UINT, 58 | SINT, 59 | UFLOAT, 60 | SFLOAT, 61 | SRGB, 62 | } 63 | 64 | #[derive(Debug, PartialEq, Eq)] 65 | pub(crate) struct Part { 66 | pub bits: usize, 67 | pub component: Component, 68 | pub mode: Mode, 69 | } 70 | 71 | include!{"format_table.rs"} 72 | 73 | impl PartialEq for Format { 74 | #[inline] 75 | fn eq(&self, other: &Format) -> bool { 76 | // If the Vulkan format enum is the same then everything else 77 | // about the format should be the same too 78 | self.vk_format == other.vk_format 79 | } 80 | } 81 | 82 | impl PartialEq<vk::VkFormat> for Format { 83 | #[inline] 84 | fn eq(&self, other: &vk::VkFormat) -> bool { 85 | self.vk_format == *other 86 | } 87 | } 88 | 89 | impl PartialEq<Format> for vk::VkFormat { 90 | #[inline] 91 | fn eq(&self, other: &Format) -> bool { 92 | *self == other.vk_format 93 | } 94 | } 95 | 96 | impl Format { 97 | pub(crate) fn lookup_by_name(name: &str) -> Option<&'static Format> { 98 | match FORMATS.binary_search_by(|format| format.name.cmp(name)) { 99 | Ok(pos) => Some(&FORMATS[pos]), 100 | Err(_) => None, 101 | } 102 | } 103 | 104 | pub(crate) fn lookup_by_vk_format( 105 | vk_format: vk::VkFormat 106 | ) -> &'static Format { 107 | for format in FORMATS.iter() { 108 | if format.vk_format == vk_format { 109 | return format; 110 | } 111 | } 112 | 113 | unreachable!("lookup failed for format {:?}", vk_format); 114 | } 115 | 116 | pub(crate) fn lookup_by_details( 117 | bit_size: usize, 118 | mode: Mode, 119 | n_components: usize 120 | ) -> Option<&'static Format> { 121 | static COMP_ORDER: [Component; 4] = [ 122 | Component::R, 123 | Component::G, 124 | Component::B, 125 | Component::A, 126 | ]; 127 | 128 | 'format_loop: for format in FORMATS.iter() { 129 | if format.n_parts != n_components { 130 | continue; 131 | } 132 | 133 | if let Some(_) = format.packed_size { 134 | continue; 135 | } 136 | 137 | for (i, part) in format.parts().iter().enumerate() { 138 | if part.bits != bit_size 139 | || part.component != COMP_ORDER[i] 140 | || part.mode != mode 141 | { 142 | continue 'format_loop; 143 | } 144 | } 145 | 146 | return Some(format); 147 | } 148 | 149 | None 150 | } 151 | 152 | pub(crate) fn parts(&self) -> &[Part] { 153 | &self.parts[0..self.n_parts] 154 | } 155 | 156 | pub fn size(&self) -> usize { 157 | match self.packed_size { 158 | Some(size) => usize::from(size) / 8, 159 | None => self.parts().iter().map(|p| p.bits).sum::<usize>() / 8, 160 | } 161 | } 162 | 163 | pub(crate) fn packed_size(&self) -> Option<usize> { 164 | self.packed_size.map(|s| usize::from(s)) 165 | } 166 | 167 | pub(crate) fn alignment(&self) -> usize { 168 | match self.packed_size { 169 | Some(size) => usize::from(size) / 8, 170 | None => self.parts().iter().map(|p| p.bits).max().unwrap() / 8, 171 | } 172 | } 173 | 174 | pub(crate) fn depth_stencil_aspect_flags(&self) -> vk::VkImageAspectFlags { 175 | self.parts().iter().map(|part| match part.component { 176 | Component::D => vk::VK_IMAGE_ASPECT_DEPTH_BIT, 177 | Component::S => vk::VK_IMAGE_ASPECT_STENCIL_BIT, 178 | _ => 0, 179 | }).fold(0, |a, b| a | b) 180 | } 181 | } 182 | 183 | impl Mode { 184 | fn load_packed_part(&self, part: u32, bits: usize) -> f64 { 185 | assert!(bits < 32); 186 | 187 | match self { 188 | Mode::SRGB | Mode::UNORM => part as f64 / ((1 << bits) - 1) as f64, 189 | Mode::SNORM => { 190 | sign_extend(part, bits) as f64 / ((1 << (bits - 1)) - 1) as f64 191 | }, 192 | Mode::UINT | Mode::USCALED => part as f64, 193 | Mode::SSCALED | Mode::SINT => sign_extend(part, bits) as f64, 194 | Mode::UFLOAT => { 195 | match bits { 196 | 10 => small_float::load_unsigned(part, 5, 5), 197 | 11 => small_float::load_unsigned(part, 5, 6), 198 | _ => { 199 | unreachable!( 200 | "unknown bit size {} in packed UFLOAT \ 201 | format", 202 | bits 203 | ) 204 | }, 205 | } 206 | }, 207 | Mode::SFLOAT => unreachable!("Unexpected packed SFLOAT format"), 208 | } 209 | } 210 | 211 | fn load_part(&self, bits: usize, fb: &[u8]) -> f64 { 212 | match self { 213 | Mode::SRGB | Mode::UNORM => { 214 | match bits { 215 | 8 => fb[0] as f64 / u8::MAX as f64, 216 | 16 => { 217 | u16::from_ne_bytes(fb[0..2].try_into().unwrap()) as f64 218 | / u16::MAX as f64 219 | }, 220 | 24 => extract_u24(fb) as f64 / 16777215.0, 221 | 32 => { 222 | u32::from_ne_bytes(fb[0..4].try_into().unwrap()) as f64 223 | / u32::MAX as f64 224 | }, 225 | 64 => { 226 | u64::from_ne_bytes(fb[0..8].try_into().unwrap()) as f64 227 | / u64::MAX as f64 228 | }, 229 | _=> unreachable!("unsupported component bit size {}", bits), 230 | } 231 | }, 232 | Mode::SNORM => { 233 | match bits { 234 | 8 => fb[0] as i8 as f64 / i8::MAX as f64, 235 | 16 => { 236 | i16::from_ne_bytes(fb[0..2].try_into().unwrap()) as f64 237 | / i16::MAX as f64 238 | }, 239 | 32 => { 240 | i32::from_ne_bytes(fb[0..4].try_into().unwrap()) as f64 241 | / i32::MAX as f64 242 | }, 243 | 64 => { 244 | i64::from_ne_bytes(fb[0..8].try_into().unwrap()) as f64 245 | / i64::MAX as f64 246 | }, 247 | _=> unreachable!("unsupported component bit size {}", bits), 248 | } 249 | }, 250 | Mode::UINT | Mode::USCALED => { 251 | match bits { 252 | 8 => fb[0] as f64, 253 | 16 => { 254 | u16::from_ne_bytes(fb[0..2].try_into().unwrap()) as f64 255 | }, 256 | 32 => { 257 | u32::from_ne_bytes(fb[0..4].try_into().unwrap()) as f64 258 | }, 259 | 64 => { 260 | u64::from_ne_bytes(fb[0..8].try_into().unwrap()) as f64 261 | }, 262 | _=> unreachable!("unsupported component bit size {}", bits), 263 | } 264 | }, 265 | Mode::SINT | Mode::SSCALED => { 266 | match bits { 267 | 8 => fb[0] as i8 as f64, 268 | 16 => { 269 | i16::from_ne_bytes(fb[0..2].try_into().unwrap()) as f64 270 | }, 271 | 32 => { 272 | i32::from_ne_bytes(fb[0..4].try_into().unwrap()) as f64 273 | }, 274 | 64 => { 275 | i64::from_ne_bytes(fb[0..8].try_into().unwrap()) as f64 276 | }, 277 | _=> unreachable!("unsupported component bit size {}", bits), 278 | } 279 | }, 280 | Mode::UFLOAT => unreachable!("unexpected unpacked UFLOAT part"), 281 | Mode::SFLOAT => { 282 | match bits { 283 | 16 => { 284 | let bits = 285 | u16::from_ne_bytes(fb[0..2].try_into().unwrap()); 286 | half_float::to_f64(bits) 287 | }, 288 | 32 => { 289 | f32::from_ne_bytes(fb[0..4].try_into().unwrap()) as f64 290 | }, 291 | 64 => f64::from_ne_bytes(fb[0..8].try_into().unwrap()), 292 | _ => { 293 | unreachable!( 294 | "unsupported unpacked SFLOAT size {}", 295 | bits 296 | ); 297 | }, 298 | } 299 | }, 300 | } 301 | } 302 | } 303 | 304 | impl Format { 305 | fn load_packed_parts(&self, source: &[u8], parts: &mut [f64]) { 306 | let mut packed_parts = match self.packed_size().unwrap() { 307 | 8 => source[0] as u32, 308 | 16 => u16::from_ne_bytes(source[0..2].try_into().unwrap()) as u32, 309 | 32 => u32::from_ne_bytes(source[0..4].try_into().unwrap()), 310 | _ => { 311 | unreachable!( 312 | "unsupported packed bit size {}", 313 | self.packed_size.unwrap() 314 | ); 315 | }, 316 | }; 317 | 318 | for (i, part) in self.parts().iter().enumerate().rev() { 319 | let part_bits = 320 | packed_parts 321 | & (u32::MAX >> (u32::BITS - part.bits as u32)); 322 | parts[i] = part.mode.load_packed_part(part_bits, part.bits); 323 | packed_parts >>= part.bits; 324 | } 325 | } 326 | 327 | pub fn load_pixel(&self, source: &[u8]) -> [f64; 4] { 328 | assert!(source.len() >= self.size()); 329 | assert!(self.n_parts <= 4); 330 | 331 | let mut parts = [0.0; 4]; 332 | 333 | match self.packed_size { 334 | Some(_) => self.load_packed_parts(source, &mut parts), 335 | None => { 336 | let mut source = source; 337 | 338 | for (i, part) in self.parts().iter().enumerate() { 339 | parts[i] = part.mode.load_part(part.bits, source); 340 | source = &source[part.bits / 8..]; 341 | } 342 | }, 343 | } 344 | 345 | // Set all the colour components to zero in case they aren’t 346 | // contained in the format. The alpha component default to 1.0 347 | // if it’s not in the format. 348 | let mut pixel = [0.0, 0.0, 0.0, 1.0]; 349 | 350 | for (i, part) in self.parts().iter().enumerate() { 351 | match part.component { 352 | Component::R => pixel[0] = parts[i], 353 | Component::G => pixel[1] = parts[i], 354 | Component::B => pixel[2] = parts[i], 355 | Component::A => pixel[3] = parts[i], 356 | Component::D | Component::S | Component:: X => (), 357 | } 358 | } 359 | 360 | pixel 361 | } 362 | } 363 | 364 | fn sign_extend(part: u32, bits: usize) -> i32 365 | { 366 | let uresult = if part & (1 << (bits - 1)) != 0 { 367 | ((u32::MAX) << bits) | part 368 | } else { 369 | part 370 | }; 371 | 372 | uresult as i32 373 | } 374 | 375 | fn extract_u24(bytes: &[u8]) -> u32 { 376 | let mut value = 0; 377 | 378 | for i in 0..3 { 379 | let byte_pos; 380 | 381 | #[cfg(target_endian = "little")] 382 | { 383 | byte_pos = 2 - i; 384 | } 385 | #[cfg(not(target_endian = "little"))] 386 | { 387 | byte_pos = i; 388 | } 389 | 390 | value = ((value) << 8) | bytes[byte_pos] as u32; 391 | } 392 | 393 | value 394 | } 395 | 396 | #[cfg(test)] 397 | mod test { 398 | use super::*; 399 | 400 | #[test] 401 | fn test_lookup_by_name() { 402 | // Test that we can find every name 403 | for format in FORMATS.iter() { 404 | let other_format = match Format::lookup_by_name(format.name) { 405 | Some(f) => f, 406 | None => unreachable!("lookup for {} failed", format.name), 407 | }; 408 | 409 | // Assert that it returns a reference to the same object 410 | assert!(std::ptr::eq(format, other_format)); 411 | } 412 | 413 | // Test that a similar name fails 414 | assert!(matches!(Format::lookup_by_name("B8G8R8_SRGBC"), None)); 415 | } 416 | 417 | #[test] 418 | fn test_lookup_by_vk_format() { 419 | // Test that we can find every format 420 | for format in FORMATS.iter() { 421 | let other_format = Format::lookup_by_vk_format(format.vk_format); 422 | // Assert that it returns a reference to the same object 423 | assert!(std::ptr::eq(format, other_format)); 424 | } 425 | } 426 | 427 | #[test] 428 | fn test_lookup_by_details() { 429 | let expected_format = 430 | Format::lookup_by_vk_format(vk::VK_FORMAT_R8G8B8_UNORM); 431 | assert_eq!( 432 | Format::lookup_by_details(8, Mode::UNORM, 3), 433 | Some(expected_format), 434 | ); 435 | let expected_format = 436 | Format::lookup_by_vk_format(vk::VK_FORMAT_R64G64B64A64_SFLOAT); 437 | assert_eq!( 438 | Format::lookup_by_details(64, Mode::SFLOAT, 4), 439 | Some(expected_format), 440 | ); 441 | assert_eq!( 442 | Format::lookup_by_details(64, Mode::UFLOAT, 4), 443 | None 444 | ); 445 | } 446 | 447 | #[test] 448 | fn test_parts() { 449 | // Check that parts returns the right size slice for each type 450 | for format in FORMATS.iter() { 451 | assert_eq!(format.parts().len(), format.n_parts); 452 | } 453 | 454 | // Check some types 455 | assert_eq!( 456 | Format::lookup_by_vk_format(vk::VK_FORMAT_R8_UINT).parts(), 457 | &[Part { bits: 8, component: Component::R, mode: Mode::UINT }] 458 | ); 459 | assert_eq!( 460 | Format::lookup_by_vk_format(vk::VK_FORMAT_B5G6R5_UNORM_PACK16) 461 | .parts(), 462 | &[ 463 | Part { bits: 5, component: Component::B, mode: Mode::UNORM }, 464 | Part { bits: 6, component: Component::G, mode: Mode::UNORM }, 465 | Part { bits: 5, component: Component::R, mode: Mode::UNORM }, 466 | ] 467 | ); 468 | } 469 | 470 | #[test] 471 | fn test_size() { 472 | assert_eq!( 473 | Format::lookup_by_vk_format(vk::VK_FORMAT_B8G8R8_UINT).size(), 474 | 3 475 | ); 476 | assert_eq!( 477 | Format::lookup_by_vk_format(vk::VK_FORMAT_R16G16_SINT).size(), 478 | 4 479 | ); 480 | assert_eq!( 481 | Format::lookup_by_vk_format(vk::VK_FORMAT_B5G6R5_UNORM_PACK16) 482 | .size(), 483 | 2 484 | ); 485 | } 486 | 487 | #[test] 488 | fn test_sign_extend() { 489 | assert_eq!(sign_extend(0xff, 8), -1); 490 | assert_eq!(sign_extend(1, 8), 1); 491 | } 492 | 493 | fn assert_float_equal(a: f64, b: f64) { 494 | assert!((a - b).abs() < 0.01, "a={}, b={}", a, b); 495 | } 496 | 497 | #[test] 498 | fn test_load_packed_part() { 499 | // Test that there are no formats with unsupported packed modes 500 | for format in FORMATS.iter() { 501 | if let Some(_) = format.packed_size { 502 | for part in format.parts().iter() { 503 | part.mode.load_packed_part(0, part.bits); 504 | } 505 | } 506 | } 507 | 508 | assert_float_equal(Mode::SRGB.load_packed_part(0x80, 8), 0.5); 509 | assert_float_equal(Mode::SNORM.load_packed_part(0x80, 8), -1.0); 510 | assert_float_equal(Mode::SNORM.load_packed_part(0x7f, 8), 1.0); 511 | assert_float_equal(Mode::UINT.load_packed_part(42, 8), 42.0); 512 | assert_float_equal(Mode::SINT.load_packed_part(0xff, 8), -1.0); 513 | assert_float_equal(Mode::UFLOAT.load_packed_part(0x1e0, 10), 1.0); 514 | assert_float_equal(Mode::UFLOAT.load_packed_part(0x3c0, 11), 1.0); 515 | } 516 | 517 | fn load_part(mode: Mode, bits: usize, fb_bytes: u64) -> f64 { 518 | let mut fb = Vec::new(); 519 | let n_bytes = bits / 8; 520 | 521 | for i in 0..n_bytes { 522 | let byte_pos; 523 | 524 | #[cfg(target_endian = "little")] 525 | { 526 | byte_pos = i 527 | } 528 | #[cfg(not(target_endian = "little"))] 529 | { 530 | byte_pos = n_bytes - 1 - i 531 | } 532 | 533 | fb.push(((fb_bytes >> (byte_pos * 8)) & 0xff) as u8); 534 | } 535 | 536 | mode.load_part(bits, &fb) 537 | } 538 | 539 | #[test] 540 | fn test_load_part() { 541 | let dummy_array = [0u8; 8]; 542 | 543 | // Test that there are no formats with unsupported unpacked modes 544 | for format in FORMATS.iter() { 545 | if let None = format.packed_size { 546 | for part in format.parts().iter() { 547 | assert!(part.bits <= dummy_array.len() * 8); 548 | part.mode.load_part(part.bits, &dummy_array); 549 | } 550 | } 551 | } 552 | 553 | assert_float_equal(load_part(Mode::UNORM, 8, 0x80), 0.5); 554 | assert_float_equal(load_part(Mode::UNORM, 16, 0x8000), 0.5); 555 | assert_float_equal(load_part(Mode::UNORM, 24, 0x800000), 0.5); 556 | assert_float_equal(load_part(Mode::UNORM, 32, 0x80000000), 0.5); 557 | assert_float_equal(load_part(Mode::UNORM, 64, 0x8000000000000000), 0.5); 558 | assert_float_equal(load_part(Mode::SNORM, 8, 0x81), -1.0); 559 | assert_float_equal(load_part(Mode::SNORM, 16, 0x8001), -1.0); 560 | assert_float_equal(load_part(Mode::SNORM, 32, 0x80000001), -1.0); 561 | assert_float_equal( 562 | load_part(Mode::SNORM, 64, 0x8000000000000001), 563 | -1.0 564 | ); 565 | assert_float_equal(load_part(Mode::UINT, 8, 0x80), 128.0); 566 | assert_float_equal(load_part(Mode::UINT, 16, 0x8000), 32768.0); 567 | assert_float_equal(load_part(Mode::UINT, 32, 0x80000000), 2147483648.0); 568 | assert_float_equal( 569 | load_part(Mode::UINT, 64, 0x200000000), 570 | 8589934592.0, 571 | ); 572 | assert_float_equal(load_part(Mode::SINT, 8, 0x80), -128.0); 573 | assert_float_equal(load_part(Mode::SINT, 16, 0x8000), -32768.0); 574 | assert_float_equal( 575 | load_part(Mode::SINT, 32, 0x80000000), 576 | -2147483648.0 577 | ); 578 | assert_float_equal( 579 | load_part(Mode::SINT, 64, u64::MAX), 580 | -1.0, 581 | ); 582 | assert_float_equal(load_part(Mode::SFLOAT, 16, 0x3c00), 1.0); 583 | assert_float_equal(load_part(Mode::SFLOAT, 32, 0x3f800000), 1.0); 584 | assert_float_equal( 585 | load_part(Mode::SFLOAT, 64, 0xbfe0000000000000), 586 | -0.5 587 | ); 588 | } 589 | 590 | #[test] 591 | fn test_load_pixel() { 592 | let dummy_source = [0u8; 32]; 593 | 594 | // Test that the code handles every format 595 | for format in FORMATS.iter() { 596 | format.load_pixel(&dummy_source); 597 | } 598 | 599 | let source_data = [5.0f64, 4.0f64, -3.0f64, 0.5f64]; 600 | let pixel: Vec<u8> = source_data 601 | .iter() 602 | .map(|v| v.to_ne_bytes()) 603 | .flatten() 604 | .collect(); 605 | let format = 606 | Format::lookup_by_vk_format(vk::VK_FORMAT_R64G64B64A64_SFLOAT); 607 | assert_eq!(format.load_pixel(&pixel), source_data); 608 | 609 | // Try a depth-stencil format. This should just return the 610 | // default rgb values. 611 | let format = 612 | Format::lookup_by_vk_format(vk::VK_FORMAT_D24_UNORM_S8_UINT); 613 | assert_eq!(format.load_pixel(&[0xff; 4]), [0.0, 0.0, 0.0, 1.0]); 614 | 615 | // Packed format 616 | let format = 617 | Format::lookup_by_vk_format(vk::VK_FORMAT_R5G6B5_UNORM_PACK16); 618 | let pixel = format.load_pixel(&0xae27u16.to_ne_bytes()); 619 | let expected = [ 620 | 0b10101 as f64 / 0b11111 as f64, 621 | 0b110001 as f64 / 0b111111 as f64, 622 | 0b00111 as f64 / 0b11111 as f64, 623 | 1.0, 624 | ]; 625 | for (i, &pixel_comp) in pixel.iter().enumerate() { 626 | assert_float_equal(pixel_comp, expected[i]); 627 | } 628 | } 629 | 630 | #[test] 631 | fn test_alignment() { 632 | let format = 633 | Format::lookup_by_vk_format(vk::VK_FORMAT_R5G6B5_UNORM_PACK16); 634 | assert_eq!(format.alignment(), 2); 635 | 636 | let format = 637 | Format::lookup_by_vk_format(vk::VK_FORMAT_D24_UNORM_S8_UINT); 638 | assert_eq!(format.alignment(), 3); 639 | 640 | let format = 641 | Format::lookup_by_vk_format(vk::VK_FORMAT_R8G8B8_UNORM); 642 | assert_eq!(format.alignment(), 1); 643 | } 644 | } 645 | ``` -------------------------------------------------------------------------------- /vkrunner/vkrunner/enum_table.rs: -------------------------------------------------------------------------------- ```rust 1 | // Automatically generated by make-enums.py 2 | static ENUM_VALUES: [EnumValue; 174] = [ 3 | EnumValue { 4 | name: "VK_BLEND_FACTOR_CONSTANT_ALPHA", 5 | value: vk::VK_BLEND_FACTOR_CONSTANT_ALPHA as i32 6 | }, 7 | EnumValue { 8 | name: "VK_BLEND_FACTOR_CONSTANT_COLOR", 9 | value: vk::VK_BLEND_FACTOR_CONSTANT_COLOR as i32 10 | }, 11 | EnumValue { 12 | name: "VK_BLEND_FACTOR_DST_ALPHA", 13 | value: vk::VK_BLEND_FACTOR_DST_ALPHA as i32 14 | }, 15 | EnumValue { 16 | name: "VK_BLEND_FACTOR_DST_COLOR", 17 | value: vk::VK_BLEND_FACTOR_DST_COLOR as i32 18 | }, 19 | EnumValue { 20 | name: "VK_BLEND_FACTOR_MAX_ENUM", 21 | value: vk::VK_BLEND_FACTOR_MAX_ENUM as i32 22 | }, 23 | EnumValue { 24 | name: "VK_BLEND_FACTOR_ONE", 25 | value: vk::VK_BLEND_FACTOR_ONE as i32 26 | }, 27 | EnumValue { 28 | name: "VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA", 29 | value: vk::VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA as i32 30 | }, 31 | EnumValue { 32 | name: "VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR", 33 | value: vk::VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR as i32 34 | }, 35 | EnumValue { 36 | name: "VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA", 37 | value: vk::VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA as i32 38 | }, 39 | EnumValue { 40 | name: "VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR", 41 | value: vk::VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR as i32 42 | }, 43 | EnumValue { 44 | name: "VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA", 45 | value: vk::VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA as i32 46 | }, 47 | EnumValue { 48 | name: "VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR", 49 | value: vk::VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR as i32 50 | }, 51 | EnumValue { 52 | name: "VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA", 53 | value: vk::VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA as i32 54 | }, 55 | EnumValue { 56 | name: "VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR", 57 | value: vk::VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR as i32 58 | }, 59 | EnumValue { 60 | name: "VK_BLEND_FACTOR_SRC1_ALPHA", 61 | value: vk::VK_BLEND_FACTOR_SRC1_ALPHA as i32 62 | }, 63 | EnumValue { 64 | name: "VK_BLEND_FACTOR_SRC1_COLOR", 65 | value: vk::VK_BLEND_FACTOR_SRC1_COLOR as i32 66 | }, 67 | EnumValue { 68 | name: "VK_BLEND_FACTOR_SRC_ALPHA", 69 | value: vk::VK_BLEND_FACTOR_SRC_ALPHA as i32 70 | }, 71 | EnumValue { 72 | name: "VK_BLEND_FACTOR_SRC_ALPHA_SATURATE", 73 | value: vk::VK_BLEND_FACTOR_SRC_ALPHA_SATURATE as i32 74 | }, 75 | EnumValue { 76 | name: "VK_BLEND_FACTOR_SRC_COLOR", 77 | value: vk::VK_BLEND_FACTOR_SRC_COLOR as i32 78 | }, 79 | EnumValue { 80 | name: "VK_BLEND_FACTOR_ZERO", 81 | value: vk::VK_BLEND_FACTOR_ZERO as i32 82 | }, 83 | EnumValue { 84 | name: "VK_BLEND_OP_ADD", 85 | value: vk::VK_BLEND_OP_ADD as i32 86 | }, 87 | EnumValue { 88 | name: "VK_BLEND_OP_BLUE_EXT", 89 | value: vk::VK_BLEND_OP_BLUE_EXT as i32 90 | }, 91 | EnumValue { 92 | name: "VK_BLEND_OP_COLORBURN_EXT", 93 | value: vk::VK_BLEND_OP_COLORBURN_EXT as i32 94 | }, 95 | EnumValue { 96 | name: "VK_BLEND_OP_COLORDODGE_EXT", 97 | value: vk::VK_BLEND_OP_COLORDODGE_EXT as i32 98 | }, 99 | EnumValue { 100 | name: "VK_BLEND_OP_CONTRAST_EXT", 101 | value: vk::VK_BLEND_OP_CONTRAST_EXT as i32 102 | }, 103 | EnumValue { 104 | name: "VK_BLEND_OP_DARKEN_EXT", 105 | value: vk::VK_BLEND_OP_DARKEN_EXT as i32 106 | }, 107 | EnumValue { 108 | name: "VK_BLEND_OP_DIFFERENCE_EXT", 109 | value: vk::VK_BLEND_OP_DIFFERENCE_EXT as i32 110 | }, 111 | EnumValue { 112 | name: "VK_BLEND_OP_DST_ATOP_EXT", 113 | value: vk::VK_BLEND_OP_DST_ATOP_EXT as i32 114 | }, 115 | EnumValue { 116 | name: "VK_BLEND_OP_DST_EXT", 117 | value: vk::VK_BLEND_OP_DST_EXT as i32 118 | }, 119 | EnumValue { 120 | name: "VK_BLEND_OP_DST_IN_EXT", 121 | value: vk::VK_BLEND_OP_DST_IN_EXT as i32 122 | }, 123 | EnumValue { 124 | name: "VK_BLEND_OP_DST_OUT_EXT", 125 | value: vk::VK_BLEND_OP_DST_OUT_EXT as i32 126 | }, 127 | EnumValue { 128 | name: "VK_BLEND_OP_DST_OVER_EXT", 129 | value: vk::VK_BLEND_OP_DST_OVER_EXT as i32 130 | }, 131 | EnumValue { 132 | name: "VK_BLEND_OP_EXCLUSION_EXT", 133 | value: vk::VK_BLEND_OP_EXCLUSION_EXT as i32 134 | }, 135 | EnumValue { 136 | name: "VK_BLEND_OP_GREEN_EXT", 137 | value: vk::VK_BLEND_OP_GREEN_EXT as i32 138 | }, 139 | EnumValue { 140 | name: "VK_BLEND_OP_HARDLIGHT_EXT", 141 | value: vk::VK_BLEND_OP_HARDLIGHT_EXT as i32 142 | }, 143 | EnumValue { 144 | name: "VK_BLEND_OP_HARDMIX_EXT", 145 | value: vk::VK_BLEND_OP_HARDMIX_EXT as i32 146 | }, 147 | EnumValue { 148 | name: "VK_BLEND_OP_HSL_COLOR_EXT", 149 | value: vk::VK_BLEND_OP_HSL_COLOR_EXT as i32 150 | }, 151 | EnumValue { 152 | name: "VK_BLEND_OP_HSL_HUE_EXT", 153 | value: vk::VK_BLEND_OP_HSL_HUE_EXT as i32 154 | }, 155 | EnumValue { 156 | name: "VK_BLEND_OP_HSL_LUMINOSITY_EXT", 157 | value: vk::VK_BLEND_OP_HSL_LUMINOSITY_EXT as i32 158 | }, 159 | EnumValue { 160 | name: "VK_BLEND_OP_HSL_SATURATION_EXT", 161 | value: vk::VK_BLEND_OP_HSL_SATURATION_EXT as i32 162 | }, 163 | EnumValue { 164 | name: "VK_BLEND_OP_INVERT_EXT", 165 | value: vk::VK_BLEND_OP_INVERT_EXT as i32 166 | }, 167 | EnumValue { 168 | name: "VK_BLEND_OP_INVERT_OVG_EXT", 169 | value: vk::VK_BLEND_OP_INVERT_OVG_EXT as i32 170 | }, 171 | EnumValue { 172 | name: "VK_BLEND_OP_INVERT_RGB_EXT", 173 | value: vk::VK_BLEND_OP_INVERT_RGB_EXT as i32 174 | }, 175 | EnumValue { 176 | name: "VK_BLEND_OP_LIGHTEN_EXT", 177 | value: vk::VK_BLEND_OP_LIGHTEN_EXT as i32 178 | }, 179 | EnumValue { 180 | name: "VK_BLEND_OP_LINEARBURN_EXT", 181 | value: vk::VK_BLEND_OP_LINEARBURN_EXT as i32 182 | }, 183 | EnumValue { 184 | name: "VK_BLEND_OP_LINEARDODGE_EXT", 185 | value: vk::VK_BLEND_OP_LINEARDODGE_EXT as i32 186 | }, 187 | EnumValue { 188 | name: "VK_BLEND_OP_LINEARLIGHT_EXT", 189 | value: vk::VK_BLEND_OP_LINEARLIGHT_EXT as i32 190 | }, 191 | EnumValue { 192 | name: "VK_BLEND_OP_MAX", 193 | value: vk::VK_BLEND_OP_MAX as i32 194 | }, 195 | EnumValue { 196 | name: "VK_BLEND_OP_MAX_ENUM", 197 | value: vk::VK_BLEND_OP_MAX_ENUM as i32 198 | }, 199 | EnumValue { 200 | name: "VK_BLEND_OP_MIN", 201 | value: vk::VK_BLEND_OP_MIN as i32 202 | }, 203 | EnumValue { 204 | name: "VK_BLEND_OP_MINUS_CLAMPED_EXT", 205 | value: vk::VK_BLEND_OP_MINUS_CLAMPED_EXT as i32 206 | }, 207 | EnumValue { 208 | name: "VK_BLEND_OP_MINUS_EXT", 209 | value: vk::VK_BLEND_OP_MINUS_EXT as i32 210 | }, 211 | EnumValue { 212 | name: "VK_BLEND_OP_MULTIPLY_EXT", 213 | value: vk::VK_BLEND_OP_MULTIPLY_EXT as i32 214 | }, 215 | EnumValue { 216 | name: "VK_BLEND_OP_OVERLAY_EXT", 217 | value: vk::VK_BLEND_OP_OVERLAY_EXT as i32 218 | }, 219 | EnumValue { 220 | name: "VK_BLEND_OP_PINLIGHT_EXT", 221 | value: vk::VK_BLEND_OP_PINLIGHT_EXT as i32 222 | }, 223 | EnumValue { 224 | name: "VK_BLEND_OP_PLUS_CLAMPED_ALPHA_EXT", 225 | value: vk::VK_BLEND_OP_PLUS_CLAMPED_ALPHA_EXT as i32 226 | }, 227 | EnumValue { 228 | name: "VK_BLEND_OP_PLUS_CLAMPED_EXT", 229 | value: vk::VK_BLEND_OP_PLUS_CLAMPED_EXT as i32 230 | }, 231 | EnumValue { 232 | name: "VK_BLEND_OP_PLUS_DARKER_EXT", 233 | value: vk::VK_BLEND_OP_PLUS_DARKER_EXT as i32 234 | }, 235 | EnumValue { 236 | name: "VK_BLEND_OP_PLUS_EXT", 237 | value: vk::VK_BLEND_OP_PLUS_EXT as i32 238 | }, 239 | EnumValue { 240 | name: "VK_BLEND_OP_RED_EXT", 241 | value: vk::VK_BLEND_OP_RED_EXT as i32 242 | }, 243 | EnumValue { 244 | name: "VK_BLEND_OP_REVERSE_SUBTRACT", 245 | value: vk::VK_BLEND_OP_REVERSE_SUBTRACT as i32 246 | }, 247 | EnumValue { 248 | name: "VK_BLEND_OP_SCREEN_EXT", 249 | value: vk::VK_BLEND_OP_SCREEN_EXT as i32 250 | }, 251 | EnumValue { 252 | name: "VK_BLEND_OP_SOFTLIGHT_EXT", 253 | value: vk::VK_BLEND_OP_SOFTLIGHT_EXT as i32 254 | }, 255 | EnumValue { 256 | name: "VK_BLEND_OP_SRC_ATOP_EXT", 257 | value: vk::VK_BLEND_OP_SRC_ATOP_EXT as i32 258 | }, 259 | EnumValue { 260 | name: "VK_BLEND_OP_SRC_EXT", 261 | value: vk::VK_BLEND_OP_SRC_EXT as i32 262 | }, 263 | EnumValue { 264 | name: "VK_BLEND_OP_SRC_IN_EXT", 265 | value: vk::VK_BLEND_OP_SRC_IN_EXT as i32 266 | }, 267 | EnumValue { 268 | name: "VK_BLEND_OP_SRC_OUT_EXT", 269 | value: vk::VK_BLEND_OP_SRC_OUT_EXT as i32 270 | }, 271 | EnumValue { 272 | name: "VK_BLEND_OP_SRC_OVER_EXT", 273 | value: vk::VK_BLEND_OP_SRC_OVER_EXT as i32 274 | }, 275 | EnumValue { 276 | name: "VK_BLEND_OP_SUBTRACT", 277 | value: vk::VK_BLEND_OP_SUBTRACT as i32 278 | }, 279 | EnumValue { 280 | name: "VK_BLEND_OP_VIVIDLIGHT_EXT", 281 | value: vk::VK_BLEND_OP_VIVIDLIGHT_EXT as i32 282 | }, 283 | EnumValue { 284 | name: "VK_BLEND_OP_XOR_EXT", 285 | value: vk::VK_BLEND_OP_XOR_EXT as i32 286 | }, 287 | EnumValue { 288 | name: "VK_BLEND_OP_ZERO_EXT", 289 | value: vk::VK_BLEND_OP_ZERO_EXT as i32 290 | }, 291 | EnumValue { 292 | name: "VK_COLOR_COMPONENT_A_BIT", 293 | value: vk::VK_COLOR_COMPONENT_A_BIT as i32 294 | }, 295 | EnumValue { 296 | name: "VK_COLOR_COMPONENT_B_BIT", 297 | value: vk::VK_COLOR_COMPONENT_B_BIT as i32 298 | }, 299 | EnumValue { 300 | name: "VK_COLOR_COMPONENT_FLAG_BITS_MAX_ENUM", 301 | value: vk::VK_COLOR_COMPONENT_FLAG_BITS_MAX_ENUM as i32 302 | }, 303 | EnumValue { 304 | name: "VK_COLOR_COMPONENT_G_BIT", 305 | value: vk::VK_COLOR_COMPONENT_G_BIT as i32 306 | }, 307 | EnumValue { 308 | name: "VK_COLOR_COMPONENT_R_BIT", 309 | value: vk::VK_COLOR_COMPONENT_R_BIT as i32 310 | }, 311 | EnumValue { 312 | name: "VK_COMPARE_OP_ALWAYS", 313 | value: vk::VK_COMPARE_OP_ALWAYS as i32 314 | }, 315 | EnumValue { 316 | name: "VK_COMPARE_OP_EQUAL", 317 | value: vk::VK_COMPARE_OP_EQUAL as i32 318 | }, 319 | EnumValue { 320 | name: "VK_COMPARE_OP_GREATER", 321 | value: vk::VK_COMPARE_OP_GREATER as i32 322 | }, 323 | EnumValue { 324 | name: "VK_COMPARE_OP_GREATER_OR_EQUAL", 325 | value: vk::VK_COMPARE_OP_GREATER_OR_EQUAL as i32 326 | }, 327 | EnumValue { 328 | name: "VK_COMPARE_OP_LESS", 329 | value: vk::VK_COMPARE_OP_LESS as i32 330 | }, 331 | EnumValue { 332 | name: "VK_COMPARE_OP_LESS_OR_EQUAL", 333 | value: vk::VK_COMPARE_OP_LESS_OR_EQUAL as i32 334 | }, 335 | EnumValue { 336 | name: "VK_COMPARE_OP_MAX_ENUM", 337 | value: vk::VK_COMPARE_OP_MAX_ENUM as i32 338 | }, 339 | EnumValue { 340 | name: "VK_COMPARE_OP_NEVER", 341 | value: vk::VK_COMPARE_OP_NEVER as i32 342 | }, 343 | EnumValue { 344 | name: "VK_COMPARE_OP_NOT_EQUAL", 345 | value: vk::VK_COMPARE_OP_NOT_EQUAL as i32 346 | }, 347 | EnumValue { 348 | name: "VK_COMPONENT_TYPE_BFLOAT16_KHR", 349 | value: vk::VK_COMPONENT_TYPE_BFLOAT16_KHR as i32 350 | }, 351 | EnumValue { 352 | name: "VK_COMPONENT_TYPE_FLOAT16_KHR", 353 | value: vk::VK_COMPONENT_TYPE_FLOAT16_KHR as i32 354 | }, 355 | EnumValue { 356 | name: "VK_COMPONENT_TYPE_FLOAT16_NV", 357 | value: vk::VK_COMPONENT_TYPE_FLOAT16_NV as i32 358 | }, 359 | EnumValue { 360 | name: "VK_COMPONENT_TYPE_FLOAT32_KHR", 361 | value: vk::VK_COMPONENT_TYPE_FLOAT32_KHR as i32 362 | }, 363 | EnumValue { 364 | name: "VK_COMPONENT_TYPE_FLOAT32_NV", 365 | value: vk::VK_COMPONENT_TYPE_FLOAT32_NV as i32 366 | }, 367 | EnumValue { 368 | name: "VK_COMPONENT_TYPE_FLOAT64_KHR", 369 | value: vk::VK_COMPONENT_TYPE_FLOAT64_KHR as i32 370 | }, 371 | EnumValue { 372 | name: "VK_COMPONENT_TYPE_FLOAT64_NV", 373 | value: vk::VK_COMPONENT_TYPE_FLOAT64_NV as i32 374 | }, 375 | EnumValue { 376 | name: "VK_COMPONENT_TYPE_FLOAT_E4M3_NV", 377 | value: vk::VK_COMPONENT_TYPE_FLOAT_E4M3_NV as i32 378 | }, 379 | EnumValue { 380 | name: "VK_COMPONENT_TYPE_FLOAT_E5M2_NV", 381 | value: vk::VK_COMPONENT_TYPE_FLOAT_E5M2_NV as i32 382 | }, 383 | EnumValue { 384 | name: "VK_COMPONENT_TYPE_MAX_ENUM_KHR", 385 | value: vk::VK_COMPONENT_TYPE_MAX_ENUM_KHR as i32 386 | }, 387 | EnumValue { 388 | name: "VK_COMPONENT_TYPE_SINT16_KHR", 389 | value: vk::VK_COMPONENT_TYPE_SINT16_KHR as i32 390 | }, 391 | EnumValue { 392 | name: "VK_COMPONENT_TYPE_SINT16_NV", 393 | value: vk::VK_COMPONENT_TYPE_SINT16_NV as i32 394 | }, 395 | EnumValue { 396 | name: "VK_COMPONENT_TYPE_SINT32_KHR", 397 | value: vk::VK_COMPONENT_TYPE_SINT32_KHR as i32 398 | }, 399 | EnumValue { 400 | name: "VK_COMPONENT_TYPE_SINT32_NV", 401 | value: vk::VK_COMPONENT_TYPE_SINT32_NV as i32 402 | }, 403 | EnumValue { 404 | name: "VK_COMPONENT_TYPE_SINT64_KHR", 405 | value: vk::VK_COMPONENT_TYPE_SINT64_KHR as i32 406 | }, 407 | EnumValue { 408 | name: "VK_COMPONENT_TYPE_SINT64_NV", 409 | value: vk::VK_COMPONENT_TYPE_SINT64_NV as i32 410 | }, 411 | EnumValue { 412 | name: "VK_COMPONENT_TYPE_SINT8_KHR", 413 | value: vk::VK_COMPONENT_TYPE_SINT8_KHR as i32 414 | }, 415 | EnumValue { 416 | name: "VK_COMPONENT_TYPE_SINT8_NV", 417 | value: vk::VK_COMPONENT_TYPE_SINT8_NV as i32 418 | }, 419 | EnumValue { 420 | name: "VK_COMPONENT_TYPE_SINT8_PACKED_NV", 421 | value: vk::VK_COMPONENT_TYPE_SINT8_PACKED_NV as i32 422 | }, 423 | EnumValue { 424 | name: "VK_COMPONENT_TYPE_UINT16_KHR", 425 | value: vk::VK_COMPONENT_TYPE_UINT16_KHR as i32 426 | }, 427 | EnumValue { 428 | name: "VK_COMPONENT_TYPE_UINT16_NV", 429 | value: vk::VK_COMPONENT_TYPE_UINT16_NV as i32 430 | }, 431 | EnumValue { 432 | name: "VK_COMPONENT_TYPE_UINT32_KHR", 433 | value: vk::VK_COMPONENT_TYPE_UINT32_KHR as i32 434 | }, 435 | EnumValue { 436 | name: "VK_COMPONENT_TYPE_UINT32_NV", 437 | value: vk::VK_COMPONENT_TYPE_UINT32_NV as i32 438 | }, 439 | EnumValue { 440 | name: "VK_COMPONENT_TYPE_UINT64_KHR", 441 | value: vk::VK_COMPONENT_TYPE_UINT64_KHR as i32 442 | }, 443 | EnumValue { 444 | name: "VK_COMPONENT_TYPE_UINT64_NV", 445 | value: vk::VK_COMPONENT_TYPE_UINT64_NV as i32 446 | }, 447 | EnumValue { 448 | name: "VK_COMPONENT_TYPE_UINT8_KHR", 449 | value: vk::VK_COMPONENT_TYPE_UINT8_KHR as i32 450 | }, 451 | EnumValue { 452 | name: "VK_COMPONENT_TYPE_UINT8_NV", 453 | value: vk::VK_COMPONENT_TYPE_UINT8_NV as i32 454 | }, 455 | EnumValue { 456 | name: "VK_COMPONENT_TYPE_UINT8_PACKED_NV", 457 | value: vk::VK_COMPONENT_TYPE_UINT8_PACKED_NV as i32 458 | }, 459 | EnumValue { 460 | name: "VK_CULL_MODE_BACK_BIT", 461 | value: vk::VK_CULL_MODE_BACK_BIT as i32 462 | }, 463 | EnumValue { 464 | name: "VK_CULL_MODE_FLAG_BITS_MAX_ENUM", 465 | value: vk::VK_CULL_MODE_FLAG_BITS_MAX_ENUM as i32 466 | }, 467 | EnumValue { 468 | name: "VK_CULL_MODE_FRONT_AND_BACK", 469 | value: vk::VK_CULL_MODE_FRONT_AND_BACK as i32 470 | }, 471 | EnumValue { 472 | name: "VK_CULL_MODE_FRONT_BIT", 473 | value: vk::VK_CULL_MODE_FRONT_BIT as i32 474 | }, 475 | EnumValue { 476 | name: "VK_CULL_MODE_NONE", 477 | value: vk::VK_CULL_MODE_NONE as i32 478 | }, 479 | EnumValue { 480 | name: "VK_FRONT_FACE_CLOCKWISE", 481 | value: vk::VK_FRONT_FACE_CLOCKWISE as i32 482 | }, 483 | EnumValue { 484 | name: "VK_FRONT_FACE_COUNTER_CLOCKWISE", 485 | value: vk::VK_FRONT_FACE_COUNTER_CLOCKWISE as i32 486 | }, 487 | EnumValue { 488 | name: "VK_FRONT_FACE_MAX_ENUM", 489 | value: vk::VK_FRONT_FACE_MAX_ENUM as i32 490 | }, 491 | EnumValue { 492 | name: "VK_LOGIC_OP_AND", 493 | value: vk::VK_LOGIC_OP_AND as i32 494 | }, 495 | EnumValue { 496 | name: "VK_LOGIC_OP_AND_INVERTED", 497 | value: vk::VK_LOGIC_OP_AND_INVERTED as i32 498 | }, 499 | EnumValue { 500 | name: "VK_LOGIC_OP_AND_REVERSE", 501 | value: vk::VK_LOGIC_OP_AND_REVERSE as i32 502 | }, 503 | EnumValue { 504 | name: "VK_LOGIC_OP_CLEAR", 505 | value: vk::VK_LOGIC_OP_CLEAR as i32 506 | }, 507 | EnumValue { 508 | name: "VK_LOGIC_OP_COPY", 509 | value: vk::VK_LOGIC_OP_COPY as i32 510 | }, 511 | EnumValue { 512 | name: "VK_LOGIC_OP_COPY_INVERTED", 513 | value: vk::VK_LOGIC_OP_COPY_INVERTED as i32 514 | }, 515 | EnumValue { 516 | name: "VK_LOGIC_OP_EQUIVALENT", 517 | value: vk::VK_LOGIC_OP_EQUIVALENT as i32 518 | }, 519 | EnumValue { 520 | name: "VK_LOGIC_OP_INVERT", 521 | value: vk::VK_LOGIC_OP_INVERT as i32 522 | }, 523 | EnumValue { 524 | name: "VK_LOGIC_OP_MAX_ENUM", 525 | value: vk::VK_LOGIC_OP_MAX_ENUM as i32 526 | }, 527 | EnumValue { 528 | name: "VK_LOGIC_OP_NAND", 529 | value: vk::VK_LOGIC_OP_NAND as i32 530 | }, 531 | EnumValue { 532 | name: "VK_LOGIC_OP_NOR", 533 | value: vk::VK_LOGIC_OP_NOR as i32 534 | }, 535 | EnumValue { 536 | name: "VK_LOGIC_OP_NO_OP", 537 | value: vk::VK_LOGIC_OP_NO_OP as i32 538 | }, 539 | EnumValue { 540 | name: "VK_LOGIC_OP_OR", 541 | value: vk::VK_LOGIC_OP_OR as i32 542 | }, 543 | EnumValue { 544 | name: "VK_LOGIC_OP_OR_INVERTED", 545 | value: vk::VK_LOGIC_OP_OR_INVERTED as i32 546 | }, 547 | EnumValue { 548 | name: "VK_LOGIC_OP_OR_REVERSE", 549 | value: vk::VK_LOGIC_OP_OR_REVERSE as i32 550 | }, 551 | EnumValue { 552 | name: "VK_LOGIC_OP_SET", 553 | value: vk::VK_LOGIC_OP_SET as i32 554 | }, 555 | EnumValue { 556 | name: "VK_LOGIC_OP_XOR", 557 | value: vk::VK_LOGIC_OP_XOR as i32 558 | }, 559 | EnumValue { 560 | name: "VK_POLYGON_MODE_FILL", 561 | value: vk::VK_POLYGON_MODE_FILL as i32 562 | }, 563 | EnumValue { 564 | name: "VK_POLYGON_MODE_FILL_RECTANGLE_NV", 565 | value: vk::VK_POLYGON_MODE_FILL_RECTANGLE_NV as i32 566 | }, 567 | EnumValue { 568 | name: "VK_POLYGON_MODE_LINE", 569 | value: vk::VK_POLYGON_MODE_LINE as i32 570 | }, 571 | EnumValue { 572 | name: "VK_POLYGON_MODE_MAX_ENUM", 573 | value: vk::VK_POLYGON_MODE_MAX_ENUM as i32 574 | }, 575 | EnumValue { 576 | name: "VK_POLYGON_MODE_POINT", 577 | value: vk::VK_POLYGON_MODE_POINT as i32 578 | }, 579 | EnumValue { 580 | name: "VK_PRIMITIVE_TOPOLOGY_LINE_LIST", 581 | value: vk::VK_PRIMITIVE_TOPOLOGY_LINE_LIST as i32 582 | }, 583 | EnumValue { 584 | name: "VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY", 585 | value: vk::VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY as i32 586 | }, 587 | EnumValue { 588 | name: "VK_PRIMITIVE_TOPOLOGY_LINE_STRIP", 589 | value: vk::VK_PRIMITIVE_TOPOLOGY_LINE_STRIP as i32 590 | }, 591 | EnumValue { 592 | name: "VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY", 593 | value: vk::VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY as i32 594 | }, 595 | EnumValue { 596 | name: "VK_PRIMITIVE_TOPOLOGY_MAX_ENUM", 597 | value: vk::VK_PRIMITIVE_TOPOLOGY_MAX_ENUM as i32 598 | }, 599 | EnumValue { 600 | name: "VK_PRIMITIVE_TOPOLOGY_PATCH_LIST", 601 | value: vk::VK_PRIMITIVE_TOPOLOGY_PATCH_LIST as i32 602 | }, 603 | EnumValue { 604 | name: "VK_PRIMITIVE_TOPOLOGY_POINT_LIST", 605 | value: vk::VK_PRIMITIVE_TOPOLOGY_POINT_LIST as i32 606 | }, 607 | EnumValue { 608 | name: "VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN", 609 | value: vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN as i32 610 | }, 611 | EnumValue { 612 | name: "VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST", 613 | value: vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST as i32 614 | }, 615 | EnumValue { 616 | name: "VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY", 617 | value: vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY as i32 618 | }, 619 | EnumValue { 620 | name: "VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP", 621 | value: vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP as i32 622 | }, 623 | EnumValue { 624 | name: "VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY", 625 | value: vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY as i32 626 | }, 627 | EnumValue { 628 | name: "VK_SCOPE_DEVICE_KHR", 629 | value: vk::VK_SCOPE_DEVICE_KHR as i32 630 | }, 631 | EnumValue { 632 | name: "VK_SCOPE_DEVICE_NV", 633 | value: vk::VK_SCOPE_DEVICE_NV as i32 634 | }, 635 | EnumValue { 636 | name: "VK_SCOPE_MAX_ENUM_KHR", 637 | value: vk::VK_SCOPE_MAX_ENUM_KHR as i32 638 | }, 639 | EnumValue { 640 | name: "VK_SCOPE_QUEUE_FAMILY_KHR", 641 | value: vk::VK_SCOPE_QUEUE_FAMILY_KHR as i32 642 | }, 643 | EnumValue { 644 | name: "VK_SCOPE_QUEUE_FAMILY_NV", 645 | value: vk::VK_SCOPE_QUEUE_FAMILY_NV as i32 646 | }, 647 | EnumValue { 648 | name: "VK_SCOPE_SUBGROUP_KHR", 649 | value: vk::VK_SCOPE_SUBGROUP_KHR as i32 650 | }, 651 | EnumValue { 652 | name: "VK_SCOPE_SUBGROUP_NV", 653 | value: vk::VK_SCOPE_SUBGROUP_NV as i32 654 | }, 655 | EnumValue { 656 | name: "VK_SCOPE_WORKGROUP_KHR", 657 | value: vk::VK_SCOPE_WORKGROUP_KHR as i32 658 | }, 659 | EnumValue { 660 | name: "VK_SCOPE_WORKGROUP_NV", 661 | value: vk::VK_SCOPE_WORKGROUP_NV as i32 662 | }, 663 | EnumValue { 664 | name: "VK_STENCIL_OP_DECREMENT_AND_CLAMP", 665 | value: vk::VK_STENCIL_OP_DECREMENT_AND_CLAMP as i32 666 | }, 667 | EnumValue { 668 | name: "VK_STENCIL_OP_DECREMENT_AND_WRAP", 669 | value: vk::VK_STENCIL_OP_DECREMENT_AND_WRAP as i32 670 | }, 671 | EnumValue { 672 | name: "VK_STENCIL_OP_INCREMENT_AND_CLAMP", 673 | value: vk::VK_STENCIL_OP_INCREMENT_AND_CLAMP as i32 674 | }, 675 | EnumValue { 676 | name: "VK_STENCIL_OP_INCREMENT_AND_WRAP", 677 | value: vk::VK_STENCIL_OP_INCREMENT_AND_WRAP as i32 678 | }, 679 | EnumValue { 680 | name: "VK_STENCIL_OP_INVERT", 681 | value: vk::VK_STENCIL_OP_INVERT as i32 682 | }, 683 | EnumValue { 684 | name: "VK_STENCIL_OP_KEEP", 685 | value: vk::VK_STENCIL_OP_KEEP as i32 686 | }, 687 | EnumValue { 688 | name: "VK_STENCIL_OP_MAX_ENUM", 689 | value: vk::VK_STENCIL_OP_MAX_ENUM as i32 690 | }, 691 | EnumValue { 692 | name: "VK_STENCIL_OP_REPLACE", 693 | value: vk::VK_STENCIL_OP_REPLACE as i32 694 | }, 695 | EnumValue { 696 | name: "VK_STENCIL_OP_ZERO", 697 | value: vk::VK_STENCIL_OP_ZERO as i32 698 | }, 699 | ]; 700 | ``` -------------------------------------------------------------------------------- /vkrunner/include/vk_video/vulkan_video_codec_h265std.h: -------------------------------------------------------------------------------- ``` 1 | #ifndef VULKAN_VIDEO_CODEC_H265STD_H_ 2 | #define VULKAN_VIDEO_CODEC_H265STD_H_ 1 3 | 4 | /* 5 | ** Copyright 2015-2025 The Khronos Group Inc. 6 | ** 7 | ** SPDX-License-Identifier: Apache-2.0 8 | */ 9 | 10 | /* 11 | ** This header is generated from the Khronos Vulkan XML API Registry. 12 | ** 13 | */ 14 | 15 | 16 | #ifdef __cplusplus 17 | extern "C" { 18 | #endif 19 | 20 | 21 | 22 | // vulkan_video_codec_h265std is a preprocessor guard. Do not pass it to API calls. 23 | #define vulkan_video_codec_h265std 1 24 | #include "vulkan_video_codecs_common.h" 25 | #define STD_VIDEO_H265_CPB_CNT_LIST_SIZE 32 26 | #define STD_VIDEO_H265_SUBLAYERS_LIST_SIZE 7 27 | #define STD_VIDEO_H265_SCALING_LIST_4X4_NUM_LISTS 6 28 | #define STD_VIDEO_H265_SCALING_LIST_4X4_NUM_ELEMENTS 16 29 | #define STD_VIDEO_H265_SCALING_LIST_8X8_NUM_LISTS 6 30 | #define STD_VIDEO_H265_SCALING_LIST_8X8_NUM_ELEMENTS 64 31 | #define STD_VIDEO_H265_SCALING_LIST_16X16_NUM_LISTS 6 32 | #define STD_VIDEO_H265_SCALING_LIST_16X16_NUM_ELEMENTS 64 33 | #define STD_VIDEO_H265_SCALING_LIST_32X32_NUM_LISTS 2 34 | #define STD_VIDEO_H265_SCALING_LIST_32X32_NUM_ELEMENTS 64 35 | #define STD_VIDEO_H265_CHROMA_QP_OFFSET_LIST_SIZE 6 36 | #define STD_VIDEO_H265_CHROMA_QP_OFFSET_TILE_COLS_LIST_SIZE 19 37 | #define STD_VIDEO_H265_CHROMA_QP_OFFSET_TILE_ROWS_LIST_SIZE 21 38 | #define STD_VIDEO_H265_PREDICTOR_PALETTE_COMPONENTS_LIST_SIZE 3 39 | #define STD_VIDEO_H265_PREDICTOR_PALETTE_COMP_ENTRIES_LIST_SIZE 128 40 | #define STD_VIDEO_H265_MAX_NUM_LIST_REF 15 41 | #define STD_VIDEO_H265_MAX_CHROMA_PLANES 2 42 | #define STD_VIDEO_H265_MAX_SHORT_TERM_REF_PIC_SETS 64 43 | #define STD_VIDEO_H265_MAX_DPB_SIZE 16 44 | #define STD_VIDEO_H265_MAX_LONG_TERM_REF_PICS_SPS 32 45 | #define STD_VIDEO_H265_MAX_LONG_TERM_PICS 16 46 | #define STD_VIDEO_H265_MAX_DELTA_POC 48 47 | #define STD_VIDEO_H265_NO_REFERENCE_PICTURE 0xFF 48 | 49 | typedef enum StdVideoH265ChromaFormatIdc { 50 | STD_VIDEO_H265_CHROMA_FORMAT_IDC_MONOCHROME = 0, 51 | STD_VIDEO_H265_CHROMA_FORMAT_IDC_420 = 1, 52 | STD_VIDEO_H265_CHROMA_FORMAT_IDC_422 = 2, 53 | STD_VIDEO_H265_CHROMA_FORMAT_IDC_444 = 3, 54 | STD_VIDEO_H265_CHROMA_FORMAT_IDC_INVALID = 0x7FFFFFFF, 55 | STD_VIDEO_H265_CHROMA_FORMAT_IDC_MAX_ENUM = 0x7FFFFFFF 56 | } StdVideoH265ChromaFormatIdc; 57 | 58 | typedef enum StdVideoH265ProfileIdc { 59 | STD_VIDEO_H265_PROFILE_IDC_MAIN = 1, 60 | STD_VIDEO_H265_PROFILE_IDC_MAIN_10 = 2, 61 | STD_VIDEO_H265_PROFILE_IDC_MAIN_STILL_PICTURE = 3, 62 | STD_VIDEO_H265_PROFILE_IDC_FORMAT_RANGE_EXTENSIONS = 4, 63 | STD_VIDEO_H265_PROFILE_IDC_SCC_EXTENSIONS = 9, 64 | STD_VIDEO_H265_PROFILE_IDC_INVALID = 0x7FFFFFFF, 65 | STD_VIDEO_H265_PROFILE_IDC_MAX_ENUM = 0x7FFFFFFF 66 | } StdVideoH265ProfileIdc; 67 | 68 | typedef enum StdVideoH265LevelIdc { 69 | STD_VIDEO_H265_LEVEL_IDC_1_0 = 0, 70 | STD_VIDEO_H265_LEVEL_IDC_2_0 = 1, 71 | STD_VIDEO_H265_LEVEL_IDC_2_1 = 2, 72 | STD_VIDEO_H265_LEVEL_IDC_3_0 = 3, 73 | STD_VIDEO_H265_LEVEL_IDC_3_1 = 4, 74 | STD_VIDEO_H265_LEVEL_IDC_4_0 = 5, 75 | STD_VIDEO_H265_LEVEL_IDC_4_1 = 6, 76 | STD_VIDEO_H265_LEVEL_IDC_5_0 = 7, 77 | STD_VIDEO_H265_LEVEL_IDC_5_1 = 8, 78 | STD_VIDEO_H265_LEVEL_IDC_5_2 = 9, 79 | STD_VIDEO_H265_LEVEL_IDC_6_0 = 10, 80 | STD_VIDEO_H265_LEVEL_IDC_6_1 = 11, 81 | STD_VIDEO_H265_LEVEL_IDC_6_2 = 12, 82 | STD_VIDEO_H265_LEVEL_IDC_INVALID = 0x7FFFFFFF, 83 | STD_VIDEO_H265_LEVEL_IDC_MAX_ENUM = 0x7FFFFFFF 84 | } StdVideoH265LevelIdc; 85 | 86 | typedef enum StdVideoH265SliceType { 87 | STD_VIDEO_H265_SLICE_TYPE_B = 0, 88 | STD_VIDEO_H265_SLICE_TYPE_P = 1, 89 | STD_VIDEO_H265_SLICE_TYPE_I = 2, 90 | STD_VIDEO_H265_SLICE_TYPE_INVALID = 0x7FFFFFFF, 91 | STD_VIDEO_H265_SLICE_TYPE_MAX_ENUM = 0x7FFFFFFF 92 | } StdVideoH265SliceType; 93 | 94 | typedef enum StdVideoH265PictureType { 95 | STD_VIDEO_H265_PICTURE_TYPE_P = 0, 96 | STD_VIDEO_H265_PICTURE_TYPE_B = 1, 97 | STD_VIDEO_H265_PICTURE_TYPE_I = 2, 98 | STD_VIDEO_H265_PICTURE_TYPE_IDR = 3, 99 | STD_VIDEO_H265_PICTURE_TYPE_INVALID = 0x7FFFFFFF, 100 | STD_VIDEO_H265_PICTURE_TYPE_MAX_ENUM = 0x7FFFFFFF 101 | } StdVideoH265PictureType; 102 | 103 | typedef enum StdVideoH265AspectRatioIdc { 104 | STD_VIDEO_H265_ASPECT_RATIO_IDC_UNSPECIFIED = 0, 105 | STD_VIDEO_H265_ASPECT_RATIO_IDC_SQUARE = 1, 106 | STD_VIDEO_H265_ASPECT_RATIO_IDC_12_11 = 2, 107 | STD_VIDEO_H265_ASPECT_RATIO_IDC_10_11 = 3, 108 | STD_VIDEO_H265_ASPECT_RATIO_IDC_16_11 = 4, 109 | STD_VIDEO_H265_ASPECT_RATIO_IDC_40_33 = 5, 110 | STD_VIDEO_H265_ASPECT_RATIO_IDC_24_11 = 6, 111 | STD_VIDEO_H265_ASPECT_RATIO_IDC_20_11 = 7, 112 | STD_VIDEO_H265_ASPECT_RATIO_IDC_32_11 = 8, 113 | STD_VIDEO_H265_ASPECT_RATIO_IDC_80_33 = 9, 114 | STD_VIDEO_H265_ASPECT_RATIO_IDC_18_11 = 10, 115 | STD_VIDEO_H265_ASPECT_RATIO_IDC_15_11 = 11, 116 | STD_VIDEO_H265_ASPECT_RATIO_IDC_64_33 = 12, 117 | STD_VIDEO_H265_ASPECT_RATIO_IDC_160_99 = 13, 118 | STD_VIDEO_H265_ASPECT_RATIO_IDC_4_3 = 14, 119 | STD_VIDEO_H265_ASPECT_RATIO_IDC_3_2 = 15, 120 | STD_VIDEO_H265_ASPECT_RATIO_IDC_2_1 = 16, 121 | STD_VIDEO_H265_ASPECT_RATIO_IDC_EXTENDED_SAR = 255, 122 | STD_VIDEO_H265_ASPECT_RATIO_IDC_INVALID = 0x7FFFFFFF, 123 | STD_VIDEO_H265_ASPECT_RATIO_IDC_MAX_ENUM = 0x7FFFFFFF 124 | } StdVideoH265AspectRatioIdc; 125 | typedef struct StdVideoH265DecPicBufMgr { 126 | uint32_t max_latency_increase_plus1[STD_VIDEO_H265_SUBLAYERS_LIST_SIZE]; 127 | uint8_t max_dec_pic_buffering_minus1[STD_VIDEO_H265_SUBLAYERS_LIST_SIZE]; 128 | uint8_t max_num_reorder_pics[STD_VIDEO_H265_SUBLAYERS_LIST_SIZE]; 129 | } StdVideoH265DecPicBufMgr; 130 | 131 | typedef struct StdVideoH265SubLayerHrdParameters { 132 | uint32_t bit_rate_value_minus1[STD_VIDEO_H265_CPB_CNT_LIST_SIZE]; 133 | uint32_t cpb_size_value_minus1[STD_VIDEO_H265_CPB_CNT_LIST_SIZE]; 134 | uint32_t cpb_size_du_value_minus1[STD_VIDEO_H265_CPB_CNT_LIST_SIZE]; 135 | uint32_t bit_rate_du_value_minus1[STD_VIDEO_H265_CPB_CNT_LIST_SIZE]; 136 | uint32_t cbr_flag; 137 | } StdVideoH265SubLayerHrdParameters; 138 | 139 | typedef struct StdVideoH265HrdFlags { 140 | uint32_t nal_hrd_parameters_present_flag : 1; 141 | uint32_t vcl_hrd_parameters_present_flag : 1; 142 | uint32_t sub_pic_hrd_params_present_flag : 1; 143 | uint32_t sub_pic_cpb_params_in_pic_timing_sei_flag : 1; 144 | uint32_t fixed_pic_rate_general_flag : 8; 145 | uint32_t fixed_pic_rate_within_cvs_flag : 8; 146 | uint32_t low_delay_hrd_flag : 8; 147 | } StdVideoH265HrdFlags; 148 | 149 | typedef struct StdVideoH265HrdParameters { 150 | StdVideoH265HrdFlags flags; 151 | uint8_t tick_divisor_minus2; 152 | uint8_t du_cpb_removal_delay_increment_length_minus1; 153 | uint8_t dpb_output_delay_du_length_minus1; 154 | uint8_t bit_rate_scale; 155 | uint8_t cpb_size_scale; 156 | uint8_t cpb_size_du_scale; 157 | uint8_t initial_cpb_removal_delay_length_minus1; 158 | uint8_t au_cpb_removal_delay_length_minus1; 159 | uint8_t dpb_output_delay_length_minus1; 160 | uint8_t cpb_cnt_minus1[STD_VIDEO_H265_SUBLAYERS_LIST_SIZE]; 161 | uint16_t elemental_duration_in_tc_minus1[STD_VIDEO_H265_SUBLAYERS_LIST_SIZE]; 162 | uint16_t reserved[3]; 163 | const StdVideoH265SubLayerHrdParameters* pSubLayerHrdParametersNal; 164 | const StdVideoH265SubLayerHrdParameters* pSubLayerHrdParametersVcl; 165 | } StdVideoH265HrdParameters; 166 | 167 | typedef struct StdVideoH265VpsFlags { 168 | uint32_t vps_temporal_id_nesting_flag : 1; 169 | uint32_t vps_sub_layer_ordering_info_present_flag : 1; 170 | uint32_t vps_timing_info_present_flag : 1; 171 | uint32_t vps_poc_proportional_to_timing_flag : 1; 172 | } StdVideoH265VpsFlags; 173 | 174 | typedef struct StdVideoH265ProfileTierLevelFlags { 175 | uint32_t general_tier_flag : 1; 176 | uint32_t general_progressive_source_flag : 1; 177 | uint32_t general_interlaced_source_flag : 1; 178 | uint32_t general_non_packed_constraint_flag : 1; 179 | uint32_t general_frame_only_constraint_flag : 1; 180 | } StdVideoH265ProfileTierLevelFlags; 181 | 182 | typedef struct StdVideoH265ProfileTierLevel { 183 | StdVideoH265ProfileTierLevelFlags flags; 184 | StdVideoH265ProfileIdc general_profile_idc; 185 | StdVideoH265LevelIdc general_level_idc; 186 | } StdVideoH265ProfileTierLevel; 187 | 188 | typedef struct StdVideoH265VideoParameterSet { 189 | StdVideoH265VpsFlags flags; 190 | uint8_t vps_video_parameter_set_id; 191 | uint8_t vps_max_sub_layers_minus1; 192 | uint8_t reserved1; 193 | uint8_t reserved2; 194 | uint32_t vps_num_units_in_tick; 195 | uint32_t vps_time_scale; 196 | uint32_t vps_num_ticks_poc_diff_one_minus1; 197 | uint32_t reserved3; 198 | const StdVideoH265DecPicBufMgr* pDecPicBufMgr; 199 | const StdVideoH265HrdParameters* pHrdParameters; 200 | const StdVideoH265ProfileTierLevel* pProfileTierLevel; 201 | } StdVideoH265VideoParameterSet; 202 | 203 | typedef struct StdVideoH265ScalingLists { 204 | uint8_t ScalingList4x4[STD_VIDEO_H265_SCALING_LIST_4X4_NUM_LISTS][STD_VIDEO_H265_SCALING_LIST_4X4_NUM_ELEMENTS]; 205 | uint8_t ScalingList8x8[STD_VIDEO_H265_SCALING_LIST_8X8_NUM_LISTS][STD_VIDEO_H265_SCALING_LIST_8X8_NUM_ELEMENTS]; 206 | uint8_t ScalingList16x16[STD_VIDEO_H265_SCALING_LIST_16X16_NUM_LISTS][STD_VIDEO_H265_SCALING_LIST_16X16_NUM_ELEMENTS]; 207 | uint8_t ScalingList32x32[STD_VIDEO_H265_SCALING_LIST_32X32_NUM_LISTS][STD_VIDEO_H265_SCALING_LIST_32X32_NUM_ELEMENTS]; 208 | uint8_t ScalingListDCCoef16x16[STD_VIDEO_H265_SCALING_LIST_16X16_NUM_LISTS]; 209 | uint8_t ScalingListDCCoef32x32[STD_VIDEO_H265_SCALING_LIST_32X32_NUM_LISTS]; 210 | } StdVideoH265ScalingLists; 211 | 212 | typedef struct StdVideoH265SpsVuiFlags { 213 | uint32_t aspect_ratio_info_present_flag : 1; 214 | uint32_t overscan_info_present_flag : 1; 215 | uint32_t overscan_appropriate_flag : 1; 216 | uint32_t video_signal_type_present_flag : 1; 217 | uint32_t video_full_range_flag : 1; 218 | uint32_t colour_description_present_flag : 1; 219 | uint32_t chroma_loc_info_present_flag : 1; 220 | uint32_t neutral_chroma_indication_flag : 1; 221 | uint32_t field_seq_flag : 1; 222 | uint32_t frame_field_info_present_flag : 1; 223 | uint32_t default_display_window_flag : 1; 224 | uint32_t vui_timing_info_present_flag : 1; 225 | uint32_t vui_poc_proportional_to_timing_flag : 1; 226 | uint32_t vui_hrd_parameters_present_flag : 1; 227 | uint32_t bitstream_restriction_flag : 1; 228 | uint32_t tiles_fixed_structure_flag : 1; 229 | uint32_t motion_vectors_over_pic_boundaries_flag : 1; 230 | uint32_t restricted_ref_pic_lists_flag : 1; 231 | } StdVideoH265SpsVuiFlags; 232 | 233 | typedef struct StdVideoH265SequenceParameterSetVui { 234 | StdVideoH265SpsVuiFlags flags; 235 | StdVideoH265AspectRatioIdc aspect_ratio_idc; 236 | uint16_t sar_width; 237 | uint16_t sar_height; 238 | uint8_t video_format; 239 | uint8_t colour_primaries; 240 | uint8_t transfer_characteristics; 241 | uint8_t matrix_coeffs; 242 | uint8_t chroma_sample_loc_type_top_field; 243 | uint8_t chroma_sample_loc_type_bottom_field; 244 | uint8_t reserved1; 245 | uint8_t reserved2; 246 | uint16_t def_disp_win_left_offset; 247 | uint16_t def_disp_win_right_offset; 248 | uint16_t def_disp_win_top_offset; 249 | uint16_t def_disp_win_bottom_offset; 250 | uint32_t vui_num_units_in_tick; 251 | uint32_t vui_time_scale; 252 | uint32_t vui_num_ticks_poc_diff_one_minus1; 253 | uint16_t min_spatial_segmentation_idc; 254 | uint16_t reserved3; 255 | uint8_t max_bytes_per_pic_denom; 256 | uint8_t max_bits_per_min_cu_denom; 257 | uint8_t log2_max_mv_length_horizontal; 258 | uint8_t log2_max_mv_length_vertical; 259 | const StdVideoH265HrdParameters* pHrdParameters; 260 | } StdVideoH265SequenceParameterSetVui; 261 | 262 | typedef struct StdVideoH265PredictorPaletteEntries { 263 | uint16_t PredictorPaletteEntries[STD_VIDEO_H265_PREDICTOR_PALETTE_COMPONENTS_LIST_SIZE][STD_VIDEO_H265_PREDICTOR_PALETTE_COMP_ENTRIES_LIST_SIZE]; 264 | } StdVideoH265PredictorPaletteEntries; 265 | 266 | typedef struct StdVideoH265SpsFlags { 267 | uint32_t sps_temporal_id_nesting_flag : 1; 268 | uint32_t separate_colour_plane_flag : 1; 269 | uint32_t conformance_window_flag : 1; 270 | uint32_t sps_sub_layer_ordering_info_present_flag : 1; 271 | uint32_t scaling_list_enabled_flag : 1; 272 | uint32_t sps_scaling_list_data_present_flag : 1; 273 | uint32_t amp_enabled_flag : 1; 274 | uint32_t sample_adaptive_offset_enabled_flag : 1; 275 | uint32_t pcm_enabled_flag : 1; 276 | uint32_t pcm_loop_filter_disabled_flag : 1; 277 | uint32_t long_term_ref_pics_present_flag : 1; 278 | uint32_t sps_temporal_mvp_enabled_flag : 1; 279 | uint32_t strong_intra_smoothing_enabled_flag : 1; 280 | uint32_t vui_parameters_present_flag : 1; 281 | uint32_t sps_extension_present_flag : 1; 282 | uint32_t sps_range_extension_flag : 1; 283 | uint32_t transform_skip_rotation_enabled_flag : 1; 284 | uint32_t transform_skip_context_enabled_flag : 1; 285 | uint32_t implicit_rdpcm_enabled_flag : 1; 286 | uint32_t explicit_rdpcm_enabled_flag : 1; 287 | uint32_t extended_precision_processing_flag : 1; 288 | uint32_t intra_smoothing_disabled_flag : 1; 289 | uint32_t high_precision_offsets_enabled_flag : 1; 290 | uint32_t persistent_rice_adaptation_enabled_flag : 1; 291 | uint32_t cabac_bypass_alignment_enabled_flag : 1; 292 | uint32_t sps_scc_extension_flag : 1; 293 | uint32_t sps_curr_pic_ref_enabled_flag : 1; 294 | uint32_t palette_mode_enabled_flag : 1; 295 | uint32_t sps_palette_predictor_initializers_present_flag : 1; 296 | uint32_t intra_boundary_filtering_disabled_flag : 1; 297 | } StdVideoH265SpsFlags; 298 | 299 | typedef struct StdVideoH265ShortTermRefPicSetFlags { 300 | uint32_t inter_ref_pic_set_prediction_flag : 1; 301 | uint32_t delta_rps_sign : 1; 302 | } StdVideoH265ShortTermRefPicSetFlags; 303 | 304 | typedef struct StdVideoH265ShortTermRefPicSet { 305 | StdVideoH265ShortTermRefPicSetFlags flags; 306 | uint32_t delta_idx_minus1; 307 | uint16_t use_delta_flag; 308 | uint16_t abs_delta_rps_minus1; 309 | uint16_t used_by_curr_pic_flag; 310 | uint16_t used_by_curr_pic_s0_flag; 311 | uint16_t used_by_curr_pic_s1_flag; 312 | uint16_t reserved1; 313 | uint8_t reserved2; 314 | uint8_t reserved3; 315 | uint8_t num_negative_pics; 316 | uint8_t num_positive_pics; 317 | uint16_t delta_poc_s0_minus1[STD_VIDEO_H265_MAX_DPB_SIZE]; 318 | uint16_t delta_poc_s1_minus1[STD_VIDEO_H265_MAX_DPB_SIZE]; 319 | } StdVideoH265ShortTermRefPicSet; 320 | 321 | typedef struct StdVideoH265LongTermRefPicsSps { 322 | uint32_t used_by_curr_pic_lt_sps_flag; 323 | uint32_t lt_ref_pic_poc_lsb_sps[STD_VIDEO_H265_MAX_LONG_TERM_REF_PICS_SPS]; 324 | } StdVideoH265LongTermRefPicsSps; 325 | 326 | typedef struct StdVideoH265SequenceParameterSet { 327 | StdVideoH265SpsFlags flags; 328 | StdVideoH265ChromaFormatIdc chroma_format_idc; 329 | uint32_t pic_width_in_luma_samples; 330 | uint32_t pic_height_in_luma_samples; 331 | uint8_t sps_video_parameter_set_id; 332 | uint8_t sps_max_sub_layers_minus1; 333 | uint8_t sps_seq_parameter_set_id; 334 | uint8_t bit_depth_luma_minus8; 335 | uint8_t bit_depth_chroma_minus8; 336 | uint8_t log2_max_pic_order_cnt_lsb_minus4; 337 | uint8_t log2_min_luma_coding_block_size_minus3; 338 | uint8_t log2_diff_max_min_luma_coding_block_size; 339 | uint8_t log2_min_luma_transform_block_size_minus2; 340 | uint8_t log2_diff_max_min_luma_transform_block_size; 341 | uint8_t max_transform_hierarchy_depth_inter; 342 | uint8_t max_transform_hierarchy_depth_intra; 343 | uint8_t num_short_term_ref_pic_sets; 344 | uint8_t num_long_term_ref_pics_sps; 345 | uint8_t pcm_sample_bit_depth_luma_minus1; 346 | uint8_t pcm_sample_bit_depth_chroma_minus1; 347 | uint8_t log2_min_pcm_luma_coding_block_size_minus3; 348 | uint8_t log2_diff_max_min_pcm_luma_coding_block_size; 349 | uint8_t reserved1; 350 | uint8_t reserved2; 351 | uint8_t palette_max_size; 352 | uint8_t delta_palette_max_predictor_size; 353 | uint8_t motion_vector_resolution_control_idc; 354 | uint8_t sps_num_palette_predictor_initializers_minus1; 355 | uint32_t conf_win_left_offset; 356 | uint32_t conf_win_right_offset; 357 | uint32_t conf_win_top_offset; 358 | uint32_t conf_win_bottom_offset; 359 | const StdVideoH265ProfileTierLevel* pProfileTierLevel; 360 | const StdVideoH265DecPicBufMgr* pDecPicBufMgr; 361 | const StdVideoH265ScalingLists* pScalingLists; 362 | const StdVideoH265ShortTermRefPicSet* pShortTermRefPicSet; 363 | const StdVideoH265LongTermRefPicsSps* pLongTermRefPicsSps; 364 | const StdVideoH265SequenceParameterSetVui* pSequenceParameterSetVui; 365 | const StdVideoH265PredictorPaletteEntries* pPredictorPaletteEntries; 366 | } StdVideoH265SequenceParameterSet; 367 | 368 | typedef struct StdVideoH265PpsFlags { 369 | uint32_t dependent_slice_segments_enabled_flag : 1; 370 | uint32_t output_flag_present_flag : 1; 371 | uint32_t sign_data_hiding_enabled_flag : 1; 372 | uint32_t cabac_init_present_flag : 1; 373 | uint32_t constrained_intra_pred_flag : 1; 374 | uint32_t transform_skip_enabled_flag : 1; 375 | uint32_t cu_qp_delta_enabled_flag : 1; 376 | uint32_t pps_slice_chroma_qp_offsets_present_flag : 1; 377 | uint32_t weighted_pred_flag : 1; 378 | uint32_t weighted_bipred_flag : 1; 379 | uint32_t transquant_bypass_enabled_flag : 1; 380 | uint32_t tiles_enabled_flag : 1; 381 | uint32_t entropy_coding_sync_enabled_flag : 1; 382 | uint32_t uniform_spacing_flag : 1; 383 | uint32_t loop_filter_across_tiles_enabled_flag : 1; 384 | uint32_t pps_loop_filter_across_slices_enabled_flag : 1; 385 | uint32_t deblocking_filter_control_present_flag : 1; 386 | uint32_t deblocking_filter_override_enabled_flag : 1; 387 | uint32_t pps_deblocking_filter_disabled_flag : 1; 388 | uint32_t pps_scaling_list_data_present_flag : 1; 389 | uint32_t lists_modification_present_flag : 1; 390 | uint32_t slice_segment_header_extension_present_flag : 1; 391 | uint32_t pps_extension_present_flag : 1; 392 | uint32_t cross_component_prediction_enabled_flag : 1; 393 | uint32_t chroma_qp_offset_list_enabled_flag : 1; 394 | uint32_t pps_curr_pic_ref_enabled_flag : 1; 395 | uint32_t residual_adaptive_colour_transform_enabled_flag : 1; 396 | uint32_t pps_slice_act_qp_offsets_present_flag : 1; 397 | uint32_t pps_palette_predictor_initializers_present_flag : 1; 398 | uint32_t monochrome_palette_flag : 1; 399 | uint32_t pps_range_extension_flag : 1; 400 | } StdVideoH265PpsFlags; 401 | 402 | typedef struct StdVideoH265PictureParameterSet { 403 | StdVideoH265PpsFlags flags; 404 | uint8_t pps_pic_parameter_set_id; 405 | uint8_t pps_seq_parameter_set_id; 406 | uint8_t sps_video_parameter_set_id; 407 | uint8_t num_extra_slice_header_bits; 408 | uint8_t num_ref_idx_l0_default_active_minus1; 409 | uint8_t num_ref_idx_l1_default_active_minus1; 410 | int8_t init_qp_minus26; 411 | uint8_t diff_cu_qp_delta_depth; 412 | int8_t pps_cb_qp_offset; 413 | int8_t pps_cr_qp_offset; 414 | int8_t pps_beta_offset_div2; 415 | int8_t pps_tc_offset_div2; 416 | uint8_t log2_parallel_merge_level_minus2; 417 | uint8_t log2_max_transform_skip_block_size_minus2; 418 | uint8_t diff_cu_chroma_qp_offset_depth; 419 | uint8_t chroma_qp_offset_list_len_minus1; 420 | int8_t cb_qp_offset_list[STD_VIDEO_H265_CHROMA_QP_OFFSET_LIST_SIZE]; 421 | int8_t cr_qp_offset_list[STD_VIDEO_H265_CHROMA_QP_OFFSET_LIST_SIZE]; 422 | uint8_t log2_sao_offset_scale_luma; 423 | uint8_t log2_sao_offset_scale_chroma; 424 | int8_t pps_act_y_qp_offset_plus5; 425 | int8_t pps_act_cb_qp_offset_plus5; 426 | int8_t pps_act_cr_qp_offset_plus3; 427 | uint8_t pps_num_palette_predictor_initializers; 428 | uint8_t luma_bit_depth_entry_minus8; 429 | uint8_t chroma_bit_depth_entry_minus8; 430 | uint8_t num_tile_columns_minus1; 431 | uint8_t num_tile_rows_minus1; 432 | uint8_t reserved1; 433 | uint8_t reserved2; 434 | uint16_t column_width_minus1[STD_VIDEO_H265_CHROMA_QP_OFFSET_TILE_COLS_LIST_SIZE]; 435 | uint16_t row_height_minus1[STD_VIDEO_H265_CHROMA_QP_OFFSET_TILE_ROWS_LIST_SIZE]; 436 | uint32_t reserved3; 437 | const StdVideoH265ScalingLists* pScalingLists; 438 | const StdVideoH265PredictorPaletteEntries* pPredictorPaletteEntries; 439 | } StdVideoH265PictureParameterSet; 440 | 441 | 442 | #ifdef __cplusplus 443 | } 444 | #endif 445 | 446 | #endif 447 | ``` -------------------------------------------------------------------------------- /vkrunner/src/main.rs: -------------------------------------------------------------------------------- ```rust 1 | // vkrunner 2 | // 3 | // Copyright (C) 2018 Intel Corporation 4 | // Copyright 2023 Neil Roberts 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a 7 | // copy of this software and associated documentation files (the "Software"), 8 | // to deal in the Software without restriction, including without limitation 9 | // the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 | // and/or sell copies of the Software, and to permit persons to whom the 11 | // Software is furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice (including the next 14 | // paragraph) shall be included in all copies or substantial portions of the 15 | // Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 | // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 23 | // DEALINGS IN THE SOFTWARE. 24 | 25 | use std::ffi::{OsString, OsStr}; 26 | use std::collections::HashMap; 27 | use std::fmt; 28 | use std::process::ExitCode; 29 | use std::ptr; 30 | use std::rc::Rc; 31 | use std::cell::RefCell; 32 | use std::ffi::c_void; 33 | use std::io::{self, BufWriter}; 34 | use std::fs::File; 35 | extern crate vkrunner; 36 | use vkrunner::{Config, Executor, Source, inspect, result}; 37 | 38 | #[derive(Debug)] 39 | struct Opt { 40 | short: Option<char>, 41 | long: &'static str, 42 | help: &'static str, 43 | argument_name: Option<&'static str>, 44 | argument_type: ArgumentType, 45 | } 46 | 47 | #[derive(Debug)] 48 | enum OptError { 49 | UnknownOption(String), 50 | MissingArgument(&'static Opt), 51 | InvalidUtf8(&'static Opt), 52 | InvalidInteger(String), 53 | ArgumentForFlag(&'static Opt), 54 | } 55 | 56 | #[derive(Debug)] 57 | enum Error { 58 | OptError(OptError), 59 | InvalidTokenReplacement(String), 60 | ShowHelp, 61 | TestFailed, 62 | IoError(io::Error), 63 | BufferNotFound(u32), 64 | NoBuffers, 65 | ZeroDeviceId, 66 | } 67 | 68 | #[derive(Debug)] 69 | enum ArgumentType { 70 | Flag, 71 | Filename, 72 | StringArray, 73 | Integer, 74 | } 75 | 76 | #[derive(Debug)] 77 | enum ArgumentValue { 78 | Flag, 79 | Filename(OsString), 80 | StringArray(Vec<String>), 81 | Integer(u32), 82 | } 83 | 84 | type OptValues = HashMap<&'static str, ArgumentValue>; 85 | 86 | #[derive(Debug)] 87 | struct Options { 88 | values: OptValues, 89 | scripts: Vec<OsString>, 90 | } 91 | 92 | #[derive(Debug)] 93 | struct TokenReplacement<'a> { 94 | token: &'a str, 95 | replacement: &'a str, 96 | } 97 | 98 | impl fmt::Display for OptError { 99 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 100 | match self { 101 | OptError::UnknownOption(s) => write!(f, "Unknown option: {}", s), 102 | OptError::MissingArgument(o) => { 103 | write!(f, "Option --{} requires an argument", o.long) 104 | }, 105 | OptError::InvalidUtf8(o) => { 106 | write!(f, "Invalid UTF-8 in argument to --{}", o.long) 107 | }, 108 | OptError::InvalidInteger(s) => { 109 | write!(f, "Invalid integer: {}", s) 110 | }, 111 | OptError::ArgumentForFlag(o) => { 112 | write!( 113 | f, 114 | "Option --{} is a flag and can not take an argument", 115 | o.long, 116 | ) 117 | }, 118 | } 119 | } 120 | } 121 | 122 | impl fmt::Display for Error { 123 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 124 | match self { 125 | Error::OptError(e) => e.fmt(f), 126 | Error::InvalidTokenReplacement(s) => { 127 | write!(f, "Invalid token replacement: {}", s) 128 | }, 129 | Error::ShowHelp => format_help(f), 130 | Error::TestFailed => { 131 | write!(f, "{}", format_result(result::Result::Fail)) 132 | }, 133 | Error::IoError(e) => e.fmt(f), 134 | Error::BufferNotFound(binding) => { 135 | write!(f, "No buffer with binding {} was found", binding) 136 | }, 137 | Error::NoBuffers => { 138 | write!( 139 | f, 140 | "Buffer dump requested but the script has no buffers" 141 | ) 142 | }, 143 | Error::ZeroDeviceId => { 144 | write!( 145 | f, 146 | "Device IDs start from 1 but 0 was specified", 147 | ) 148 | }, 149 | } 150 | } 151 | } 152 | 153 | impl From<OptError> for Error { 154 | fn from(e: OptError) -> Error { 155 | Error::OptError(e) 156 | } 157 | } 158 | 159 | impl From<io::Error> for Error { 160 | fn from(e: io::Error) -> Error { 161 | Error::IoError(e) 162 | } 163 | } 164 | 165 | static HELP_OPTION: &'static str = "help"; 166 | static IMAGE_OPTION: &'static str = "image"; 167 | static BUFFER_OPTION: &'static str = "buffer"; 168 | static BINDING_OPTION: &'static str = "binding"; 169 | static DISASM_OPTION: &'static str = "disasm"; 170 | static REPLACE_OPTION: &'static str = "replace"; 171 | static QUIET_OPTION: &'static str = "quiet"; 172 | static DEVICE_ID_OPTION: &'static str = "device-id"; 173 | 174 | static OPTIONS: [Opt; 8] = [ 175 | Opt { 176 | short: Some('h'), 177 | long: HELP_OPTION, 178 | help: "Show this help message", 179 | argument_name: None, 180 | argument_type: ArgumentType::Flag, 181 | }, 182 | Opt { 183 | short: Some('i'), 184 | long: IMAGE_OPTION, 185 | help: "Write the final rendering to IMG as a PPM image", 186 | argument_name: Some("IMG"), 187 | argument_type: ArgumentType::Filename, 188 | }, 189 | Opt { 190 | short: Some('b'), 191 | long: BUFFER_OPTION, 192 | help: "Dump contents of a UBO or SSBO to BUF", 193 | argument_name: Some("BUF"), 194 | argument_type: ArgumentType::Filename, 195 | }, 196 | Opt { 197 | short: Some('B'), 198 | long: BINDING_OPTION, 199 | help: "Select which buffer to dump using the -b option. Defaults to \ 200 | first buffer", 201 | argument_name: Some("BINDING"), 202 | argument_type: ArgumentType::Integer, 203 | }, 204 | Opt { 205 | short: Some('d'), 206 | long: DISASM_OPTION, 207 | help: "Show the SPIR-V disassembly", 208 | argument_name: None, 209 | argument_type: ArgumentType::Flag, 210 | }, 211 | Opt { 212 | short: Some('D'), 213 | long: REPLACE_OPTION, 214 | help: "Replace occurences of TOK with REPL in the scripts", 215 | argument_name: Some("TOK=REPL"), 216 | argument_type: ArgumentType::StringArray, 217 | }, 218 | Opt { 219 | short: Some('q'), 220 | long: QUIET_OPTION, 221 | help: "Don’t print any non-error information to stdout", 222 | argument_name: None, 223 | argument_type: ArgumentType::Flag, 224 | }, 225 | Opt { 226 | short: None, 227 | long: DEVICE_ID_OPTION, 228 | help: "Select the Vulkan device", 229 | argument_name: Some("DEVID"), 230 | argument_type: ArgumentType::Integer, 231 | }, 232 | ]; 233 | 234 | fn format_help(f: &mut fmt::Formatter) -> fmt::Result { 235 | writeln!( 236 | f, 237 | "usage: vkrunner [OPTION]… SCRIPT…\n\ 238 | Runs the shader test script SCRIPT\n\ 239 | \n\ 240 | Options:" 241 | )?; 242 | 243 | let longest_long = OPTIONS 244 | .iter() 245 | .map(|o| o.long.chars().count()) 246 | .max() 247 | .unwrap(); 248 | let longest_arg = OPTIONS 249 | .iter() 250 | .map(|o| o.argument_name.map(|n| n.chars().count()).unwrap_or(0)) 251 | .max() 252 | .unwrap(); 253 | 254 | for (i, option) in OPTIONS.iter().enumerate() { 255 | if i > 0 { 256 | writeln!(f)?; 257 | } 258 | 259 | write!(f, " ")?; 260 | 261 | match option.short { 262 | Some(c) => write!(f, "-{},", c)?, 263 | None => write!(f, " ")?, 264 | } 265 | 266 | write!( 267 | f, 268 | "--{:long_width$} {:arg_width$} {}", 269 | option.long, 270 | option.argument_name.unwrap_or(""), 271 | option.help, 272 | long_width = longest_long, 273 | arg_width = longest_arg, 274 | )?; 275 | } 276 | 277 | Ok(()) 278 | } 279 | 280 | fn next_arg<I>( 281 | opt: &'static Opt, 282 | args: &mut I, 283 | opt_arg: Option<&str> 284 | ) -> Result<OsString, OptError> 285 | where I: Iterator<Item = OsString> 286 | { 287 | // Use opt_arg if it’s available or else get the next arg from the iterator 288 | opt_arg 289 | .map(|arg| arg.into()) 290 | .or_else(|| args.next()) 291 | .ok_or_else(|| OptError::MissingArgument(opt)) 292 | } 293 | 294 | fn process_argument<I>( 295 | values: &mut OptValues, 296 | args: &mut I, 297 | opt: &'static Opt, 298 | opt_arg: Option<&str>, 299 | ) -> Result<(), OptError> 300 | where I: Iterator<Item = OsString> 301 | { 302 | match opt.argument_type { 303 | ArgumentType::Flag => { 304 | if opt_arg.is_some() { 305 | return Err(OptError::ArgumentForFlag(opt)); 306 | } 307 | 308 | values.insert(opt.long, ArgumentValue::Flag); 309 | }, 310 | ArgumentType::Filename => { 311 | values.insert( 312 | opt.long, 313 | ArgumentValue::Filename(next_arg(opt, args, opt_arg)?), 314 | ); 315 | }, 316 | ArgumentType::StringArray => { 317 | let arg = next_arg(opt, args, opt_arg)?; 318 | 319 | match arg.to_str() { 320 | Some(s) => { 321 | values.entry(opt.long) 322 | .and_modify(|value| match value { 323 | ArgumentValue::StringArray(values) => 324 | values.push(s.to_string()), 325 | _ => unreachable!(), 326 | }) 327 | .or_insert_with(|| ArgumentValue::StringArray( 328 | vec![s.to_string()] 329 | )); 330 | }, 331 | None => return Err(OptError::InvalidUtf8(opt)), 332 | } 333 | }, 334 | ArgumentType::Integer => { 335 | let arg = next_arg(opt, args, opt_arg)?; 336 | 337 | match arg.to_str() { 338 | Some(s) => match s.parse::<u32>() { 339 | Ok(value) => { 340 | values.insert( 341 | opt.long, 342 | ArgumentValue::Integer(value), 343 | ); 344 | }, 345 | Err(_) => { 346 | return Err(OptError::InvalidInteger( 347 | s.to_owned() 348 | )); 349 | }, 350 | }, 351 | None => return Err(OptError::InvalidUtf8(opt)), 352 | } 353 | }, 354 | } 355 | 356 | Ok(()) 357 | } 358 | 359 | fn process_long_arg<I>( 360 | values: &mut OptValues, 361 | args: &mut I, 362 | arg: &str 363 | ) -> Result<(), OptError> 364 | where I: Iterator<Item = OsString> 365 | { 366 | let (arg, opt_arg) = match arg.split_once('=') { 367 | Some((arg, opt_arg)) => (arg, Some(opt_arg)), 368 | None => (arg, None), 369 | }; 370 | 371 | for opt in OPTIONS.iter() { 372 | if opt.long.eq(arg) { 373 | return process_argument(values, args, opt, opt_arg); 374 | } 375 | } 376 | 377 | Err(OptError::UnknownOption(format!("--{}", arg))) 378 | } 379 | 380 | fn process_short_args<I>( 381 | values: &mut OptValues, 382 | args: &mut I, 383 | arg: &str 384 | ) -> Result<(), OptError> 385 | where I: Iterator<Item = OsString> 386 | { 387 | if arg.len() == 0 { 388 | return Err(OptError::UnknownOption("-".to_string())); 389 | } 390 | 391 | 'arg_loop: for ch in arg.chars() { 392 | for opt in OPTIONS.iter() { 393 | if let Some(opt_ch) = opt.short { 394 | if opt_ch == ch { 395 | process_argument(values, args, opt, None)?; 396 | continue 'arg_loop; 397 | } 398 | } 399 | } 400 | 401 | return Err(OptError::UnknownOption(format!("{}", ch))); 402 | } 403 | 404 | Ok(()) 405 | } 406 | 407 | fn parse_options<I>( 408 | mut args: I 409 | ) -> Result<Options, OptError> 410 | where I: Iterator<Item = OsString> 411 | { 412 | let mut values = HashMap::new(); 413 | let mut scripts = Vec::new(); 414 | 415 | // Skip the first arg 416 | if args.next().is_none() { 417 | return Ok(Options { values, scripts }); 418 | } 419 | 420 | while let Some(arg) = args.next() { 421 | match arg.to_str() { 422 | Some(arg_str) => { 423 | if arg_str == "--" { 424 | scripts.extend(args); 425 | break; 426 | } else if arg_str.starts_with("--") { 427 | process_long_arg(&mut values, &mut args, &arg_str[2..])?; 428 | } else if arg_str.starts_with("-") { 429 | process_short_args(&mut values, &mut args, &arg_str[1..])?; 430 | } else { 431 | scripts.push(arg); 432 | } 433 | }, 434 | None => scripts.push(arg), 435 | } 436 | } 437 | 438 | Ok(Options { values, scripts }) 439 | } 440 | 441 | impl<'a> InspectData<'a> { 442 | fn new(options: &'a Options) -> InspectData<'a> { 443 | InspectData { 444 | image_filename: match options.values.get(IMAGE_OPTION) { 445 | Some(ArgumentValue::Filename(filename)) => { 446 | Some(filename) 447 | }, 448 | _ => None, 449 | }, 450 | buffer_filename: match options.values.get(BUFFER_OPTION) { 451 | Some(ArgumentValue::Filename(filename)) => { 452 | Some(filename) 453 | }, 454 | _ => None, 455 | }, 456 | buffer_binding: match options.values.get(BINDING_OPTION) { 457 | Some(&ArgumentValue::Integer(binding)) => { 458 | Some(binding) 459 | }, 460 | _ => None, 461 | }, 462 | failed: false, 463 | } 464 | } 465 | } 466 | 467 | fn get_token_replacements<'a>( 468 | values: &'a OptValues 469 | ) -> Result<Vec<TokenReplacement<'a>>, Error> { 470 | let mut res = Vec::new(); 471 | 472 | if let Some(ArgumentValue::StringArray(replacements)) = 473 | values.get(REPLACE_OPTION) 474 | { 475 | for replacement in replacements { 476 | match replacement.split_once('=') { 477 | None => { 478 | return Err(Error::InvalidTokenReplacement( 479 | replacement.to_owned() 480 | )); 481 | }, 482 | Some((token, replacement)) => res.push(TokenReplacement { 483 | token, 484 | replacement, 485 | }), 486 | } 487 | } 488 | } 489 | 490 | Ok(res) 491 | } 492 | 493 | struct InspectData<'a> { 494 | image_filename: Option<&'a OsStr>, 495 | buffer_filename: Option<&'a OsStr>, 496 | buffer_binding: Option<u32>, 497 | failed: bool, 498 | } 499 | 500 | fn write_ppm( 501 | image: &inspect::Image, 502 | filename: &OsStr, 503 | ) -> Result<(), Error> { 504 | let mut file = BufWriter::new(File::create(filename)?); 505 | 506 | use std::io::Write; 507 | 508 | write!( 509 | &mut file, 510 | "P6\n\ 511 | {} {}\n\ 512 | 255\n", 513 | image.width, 514 | image.height, 515 | )?; 516 | 517 | let format_size = image.format.size(); 518 | 519 | for y in 0..image.height { 520 | let mut line = unsafe { 521 | std::slice::from_raw_parts( 522 | (image.data as *const u8).add(y as usize * image.stride), 523 | image.width as usize * format_size, 524 | ) 525 | }; 526 | 527 | for _ in 0..image.width { 528 | let pixel = image.format.load_pixel(&line[0..format_size]); 529 | let mut bytes = [0u8; 3]; 530 | 531 | for (i, component) in pixel[0..3].iter().enumerate() { 532 | bytes[i] = (component.clamp(0.0, 1.0) * 255.0).round() as u8; 533 | } 534 | 535 | file.write_all(&bytes)?; 536 | 537 | line = &line[format_size..]; 538 | } 539 | } 540 | 541 | Ok(()) 542 | } 543 | 544 | fn write_buffer( 545 | data: &inspect::Data, 546 | filename: &OsStr, 547 | binding: Option<u32>, 548 | ) -> Result<(), Error> { 549 | let buffers = unsafe { 550 | std::slice::from_raw_parts(data.buffers, data.n_buffers) 551 | }; 552 | 553 | let buffer = match binding { 554 | None => match buffers.get(0) { 555 | Some(buffer) => buffer, 556 | None => return Err(Error::NoBuffers), 557 | }, 558 | Some(binding) => match buffers.iter().find( 559 | |b| b.binding as u32 == binding 560 | ) { 561 | Some(buffer) => buffer, 562 | None => return Err(Error::BufferNotFound(binding)), 563 | }, 564 | }; 565 | 566 | let mut file = File::create(filename)?; 567 | 568 | let data = unsafe { 569 | std::slice::from_raw_parts( 570 | buffer.data as *const u8, 571 | buffer.size, 572 | ) 573 | }; 574 | 575 | use std::io::Write; 576 | 577 | file.write_all(data)?; 578 | 579 | Ok(()) 580 | } 581 | 582 | extern "C" fn inspect_cb(data: &inspect::Data, user_data: *mut c_void) { 583 | let inspect_data = unsafe { &mut *(user_data as *mut InspectData) }; 584 | 585 | if let Some(filename) = inspect_data.image_filename { 586 | match write_ppm(&data.color_buffer, filename) { 587 | Err(e) => { 588 | eprintln!("{}", e); 589 | inspect_data.failed = true; 590 | }, 591 | Ok(()) => (), 592 | } 593 | } 594 | 595 | if let Some(filename) = inspect_data.buffer_filename { 596 | match write_buffer(&data, filename, inspect_data.buffer_binding) { 597 | Err(e) => { 598 | eprintln!("{}", e); 599 | inspect_data.failed = true; 600 | }, 601 | Ok(()) => (), 602 | } 603 | } 604 | } 605 | 606 | fn set_up_config( 607 | config: &Rc<RefCell<Config>>, 608 | options: &Options, 609 | inspect_data: &mut InspectData, 610 | ) -> Result<(), Error> { 611 | let mut config = config.borrow_mut(); 612 | 613 | config.set_inspect_cb(Some(inspect_cb)); 614 | config.set_user_data(ptr::addr_of_mut!(*inspect_data).cast()); 615 | 616 | if let Some(&ArgumentValue::Integer(device_id)) 617 | = options.values.get(DEVICE_ID_OPTION) 618 | { 619 | match device_id.checked_sub(1) { 620 | None => return Err(Error::ZeroDeviceId), 621 | Some(device_id) => config.set_device_id(Some(device_id as usize)), 622 | } 623 | } 624 | 625 | if let Some(ArgumentValue::Flag) = options.values.get(DISASM_OPTION) { 626 | config.set_show_disassembly(true); 627 | } 628 | 629 | Ok(()) 630 | } 631 | 632 | fn format_result(result: result::Result) -> String { 633 | format!("PIGLIT: {{\"result\": \"{}\" }}", result.name()) 634 | } 635 | 636 | fn add_token_replacements( 637 | token_replacements: &[TokenReplacement<'_>], 638 | source: &mut Source, 639 | ) { 640 | for token_replacement in token_replacements.iter() { 641 | source.add_token_replacement( 642 | token_replacement.token.to_owned(), 643 | token_replacement.replacement.to_owned(), 644 | ); 645 | } 646 | } 647 | 648 | fn run() -> Result<(), Error> { 649 | let options = parse_options(std::env::args_os())?; 650 | 651 | if options.values.contains_key(HELP_OPTION) || options.scripts.is_empty() { 652 | return Err(Error::ShowHelp); 653 | } 654 | 655 | let config = Rc::new(RefCell::new(Config::new())); 656 | 657 | let mut inspect_data = InspectData::new(&options); 658 | 659 | set_up_config(&config, &options, &mut inspect_data)?; 660 | 661 | let token_replacements = get_token_replacements(&options.values)?; 662 | 663 | let mut executor = Executor::new(Rc::clone(&config)); 664 | 665 | let mut overall_result = result::Result::Skip; 666 | 667 | for script_filename in options.scripts.iter() { 668 | if options.scripts.len() > 1 669 | && !options.values.contains_key(QUIET_OPTION) 670 | { 671 | println!("{}", script_filename.to_string_lossy()); 672 | } 673 | 674 | let mut source = Source::from_file(script_filename.into()); 675 | 676 | add_token_replacements(&token_replacements, &mut source); 677 | 678 | let result = executor.execute(&source); 679 | 680 | overall_result = overall_result.merge(result); 681 | } 682 | 683 | if inspect_data.failed { 684 | overall_result = overall_result.merge(result::Result::Fail); 685 | } 686 | 687 | match overall_result { 688 | result::Result::Fail => Err(Error::TestFailed), 689 | result::Result::Pass if options.values.contains_key(QUIET_OPTION) => { 690 | Ok(()) 691 | }, 692 | _ => { 693 | println!("{}", format_result(overall_result)); 694 | Ok(()) 695 | }, 696 | } 697 | } 698 | 699 | fn main() -> ExitCode { 700 | match run() { 701 | Ok(()) => ExitCode::SUCCESS, 702 | Err(e) => { 703 | eprintln!("{}", e); 704 | ExitCode::FAILURE 705 | }, 706 | } 707 | } 708 | 709 | #[cfg(test)] 710 | mod test { 711 | use super::*; 712 | 713 | #[test] 714 | fn all_arg_types() { 715 | let args: Vec<OsString> = vec![ 716 | "vkrunner".into(), 717 | "-dB".into(), "12".into(), 718 | "--image".into(), "screenshot.png".into(), 719 | "--replace".into(), "bad=aĉa".into(), 720 | "--replace=good=bona".into(), 721 | "script.shader_test".into(), 722 | ]; 723 | 724 | let options = parse_options(args.into_iter()).unwrap(); 725 | 726 | assert!(matches!(&options.values[DISASM_OPTION], ArgumentValue::Flag)); 727 | 728 | let ArgumentValue::Integer(binding) = &options.values[BINDING_OPTION] 729 | else { unreachable!(); }; 730 | assert_eq!(*binding, 12); 731 | 732 | let ArgumentValue::Filename(image) = &options.values[IMAGE_OPTION] 733 | else { unreachable!(); }; 734 | assert_eq!(image.to_str().unwrap(), "screenshot.png"); 735 | 736 | let ArgumentValue::StringArray(values) = &options.values[REPLACE_OPTION] 737 | else { unreachable!(); }; 738 | assert_eq!( 739 | values, 740 | &vec!["bad=aĉa".to_string(), "good=bona".to_string()] 741 | ); 742 | 743 | assert_eq!(options.scripts.len(), 1); 744 | assert_eq!(options.scripts[0].to_str().unwrap(), "script.shader_test"); 745 | } 746 | 747 | #[test] 748 | fn multi_arguments() { 749 | let args = vec![ 750 | "vkrunner".into(), 751 | "-ib".into(), "image.png".into(), "buffer.raw".into(), 752 | ]; 753 | 754 | let options = parse_options(args.into_iter()).unwrap(); 755 | 756 | let ArgumentValue::Filename(image) = &options.values[IMAGE_OPTION] 757 | else { unreachable!(); }; 758 | assert_eq!(image.to_str().unwrap(), "image.png"); 759 | 760 | let ArgumentValue::Filename(image) = &options.values[BUFFER_OPTION] 761 | else { unreachable!(); }; 762 | assert_eq!(image.to_str().unwrap(), "buffer.raw"); 763 | } 764 | 765 | #[test] 766 | fn unknown_option() { 767 | let args = vec!["vkrunner".into(), "--bad-option".into()].into_iter(); 768 | let error = parse_options(args).unwrap_err(); 769 | assert_eq!(&error.to_string(), "Unknown option: --bad-option"); 770 | 771 | let args = vec!["vkrunner".into(), "-d?".into()].into_iter(); 772 | let error = parse_options(args).unwrap_err(); 773 | assert_eq!(&error.to_string(), "Unknown option: ?"); 774 | 775 | let args = vec!["vkrunner".into(), "-".into()].into_iter(); 776 | let error = parse_options(args).unwrap_err(); 777 | assert_eq!(&error.to_string(), "Unknown option: -"); 778 | } 779 | 780 | #[test] 781 | fn trailing_arguments() { 782 | let args = vec![ 783 | "vkrunner".into(), 784 | "-i".into(), "image.png".into(), 785 | "--".into(), 786 | "-i.shader_test".into(), 787 | ]; 788 | 789 | let options = parse_options(args.into_iter()).unwrap(); 790 | 791 | assert_eq!(options.scripts.len(), 1); 792 | assert_eq!(options.scripts[0].to_str().unwrap(), "-i.shader_test"); 793 | } 794 | 795 | #[test] 796 | fn missing_argument() { 797 | let args = vec!["vkrunner".into(), "--buffer".into()].into_iter(); 798 | let error = parse_options(args).unwrap_err(); 799 | assert_eq!(&error.to_string(), "Option --buffer requires an argument"); 800 | 801 | let args = vec!["vkrunner".into(), "-D".into()].into_iter(); 802 | let error = parse_options(args).unwrap_err(); 803 | assert_eq!(&error.to_string(), "Option --replace requires an argument"); 804 | 805 | let args = vec!["vkrunner".into(), "-B".into()].into_iter(); 806 | let error = parse_options(args).unwrap_err(); 807 | assert_eq!(&error.to_string(), "Option --binding requires an argument"); 808 | } 809 | 810 | #[test] 811 | #[cfg(unix)] 812 | fn invalid_utf8() { 813 | use std::os::unix::ffi::OsStrExt; 814 | use std::ffi::OsStr; 815 | 816 | let args = vec![ 817 | "vkrunner".into(), 818 | "-D".into(), 819 | OsStr::from_bytes(b"buffer-\x80.raw").into(), 820 | ].into_iter(); 821 | 822 | let error = parse_options(args).unwrap_err(); 823 | assert_eq!( 824 | &error.to_string(), 825 | "Invalid UTF-8 in argument to --replace", 826 | ); 827 | 828 | let args = vec![ 829 | "vkrunner".into(), 830 | "-B".into(), 831 | OsStr::from_bytes(b"TWELVE-\x80").into(), 832 | ].into_iter(); 833 | 834 | let error = parse_options(args).unwrap_err(); 835 | assert_eq!( 836 | &error.to_string(), 837 | "Invalid UTF-8 in argument to --binding", 838 | ); 839 | } 840 | 841 | #[test] 842 | fn invalid_integer() { 843 | let args = vec![ 844 | "vkrunner".into(), 845 | "-B".into(), "twelve".into(), 846 | ].into_iter(); 847 | 848 | let error = parse_options(args).unwrap_err(); 849 | assert_eq!( 850 | &error.to_string(), 851 | "Invalid integer: twelve", 852 | ); 853 | } 854 | 855 | #[test] 856 | fn argument_for_flag() { 857 | let args = vec!["vkrunner".into(), "--quiet=yes".into()].into_iter(); 858 | let error = parse_options(args).unwrap_err(); 859 | assert_eq!( 860 | &error.to_string(), 861 | "Option --quiet is a flag and can not take an argument", 862 | ); 863 | } 864 | } 865 | ``` -------------------------------------------------------------------------------- /vkrunner/vkrunner/vulkan_funcs_data.rs: -------------------------------------------------------------------------------- ```rust 1 | // Automatically generated by make-vulkan-funcs-data.py 2 | 3 | #[derive(Debug, Clone)] 4 | #[allow(non_snake_case)] 5 | pub struct Library { 6 | lib_vulkan: *const c_void, 7 | lib_vulkan_is_fake: bool, 8 | 9 | pub vkGetInstanceProcAddr: vk::PFN_vkGetInstanceProcAddr, 10 | pub vkCreateInstance: vk::PFN_vkCreateInstance, 11 | pub vkEnumerateInstanceExtensionProperties: vk::PFN_vkEnumerateInstanceExtensionProperties, 12 | } 13 | 14 | #[derive(Debug, Clone)] 15 | #[allow(non_snake_case)] 16 | pub struct Instance { 17 | pub vkCreateDevice: vk::PFN_vkCreateDevice, 18 | pub vkDestroyInstance: vk::PFN_vkDestroyInstance, 19 | pub vkEnumerateDeviceExtensionProperties: vk::PFN_vkEnumerateDeviceExtensionProperties, 20 | pub vkEnumeratePhysicalDevices: vk::PFN_vkEnumeratePhysicalDevices, 21 | pub vkGetDeviceProcAddr: vk::PFN_vkGetDeviceProcAddr, 22 | pub vkGetPhysicalDeviceFeatures: vk::PFN_vkGetPhysicalDeviceFeatures, 23 | pub vkGetPhysicalDeviceFeatures2KHR: vk::PFN_vkGetPhysicalDeviceFeatures2KHR, 24 | pub vkGetPhysicalDeviceFormatProperties: vk::PFN_vkGetPhysicalDeviceFormatProperties, 25 | pub vkGetPhysicalDeviceMemoryProperties: vk::PFN_vkGetPhysicalDeviceMemoryProperties, 26 | pub vkGetPhysicalDeviceProperties: vk::PFN_vkGetPhysicalDeviceProperties, 27 | pub vkGetPhysicalDeviceProperties2: vk::PFN_vkGetPhysicalDeviceProperties2, 28 | pub vkGetPhysicalDeviceQueueFamilyProperties: vk::PFN_vkGetPhysicalDeviceQueueFamilyProperties, 29 | pub vkGetPhysicalDeviceCooperativeMatrixPropertiesKHR: vk::PFN_vkGetPhysicalDeviceCooperativeMatrixPropertiesKHR, 30 | } 31 | 32 | #[derive(Debug, Clone)] 33 | #[allow(non_snake_case)] 34 | #[allow(dead_code)] 35 | pub struct Device { 36 | pub vkAllocateCommandBuffers: vk::PFN_vkAllocateCommandBuffers, 37 | pub vkAllocateDescriptorSets: vk::PFN_vkAllocateDescriptorSets, 38 | pub vkAllocateMemory: vk::PFN_vkAllocateMemory, 39 | pub vkBeginCommandBuffer: vk::PFN_vkBeginCommandBuffer, 40 | pub vkBindBufferMemory: vk::PFN_vkBindBufferMemory, 41 | pub vkBindImageMemory: vk::PFN_vkBindImageMemory, 42 | pub vkCmdBeginRenderPass: vk::PFN_vkCmdBeginRenderPass, 43 | pub vkCmdBindDescriptorSets: vk::PFN_vkCmdBindDescriptorSets, 44 | pub vkCmdBindIndexBuffer: vk::PFN_vkCmdBindIndexBuffer, 45 | pub vkCmdBindPipeline: vk::PFN_vkCmdBindPipeline, 46 | pub vkCmdBindVertexBuffers: vk::PFN_vkCmdBindVertexBuffers, 47 | pub vkCmdClearAttachments: vk::PFN_vkCmdClearAttachments, 48 | pub vkCmdCopyBufferToImage: vk::PFN_vkCmdCopyBufferToImage, 49 | pub vkCmdCopyImageToBuffer: vk::PFN_vkCmdCopyImageToBuffer, 50 | pub vkCmdDispatch: vk::PFN_vkCmdDispatch, 51 | pub vkCmdDraw: vk::PFN_vkCmdDraw, 52 | pub vkCmdDrawIndexed: vk::PFN_vkCmdDrawIndexed, 53 | pub vkCmdDrawIndexedIndirect: vk::PFN_vkCmdDrawIndexedIndirect, 54 | pub vkCmdEndRenderPass: vk::PFN_vkCmdEndRenderPass, 55 | pub vkCmdPipelineBarrier: vk::PFN_vkCmdPipelineBarrier, 56 | pub vkCmdPushConstants: vk::PFN_vkCmdPushConstants, 57 | pub vkCmdSetScissor: vk::PFN_vkCmdSetScissor, 58 | pub vkCmdSetViewport: vk::PFN_vkCmdSetViewport, 59 | pub vkCreateBuffer: vk::PFN_vkCreateBuffer, 60 | pub vkCreateCommandPool: vk::PFN_vkCreateCommandPool, 61 | pub vkCreateComputePipelines: vk::PFN_vkCreateComputePipelines, 62 | pub vkCreateDescriptorPool: vk::PFN_vkCreateDescriptorPool, 63 | pub vkCreateDescriptorSetLayout: vk::PFN_vkCreateDescriptorSetLayout, 64 | pub vkCreateFence: vk::PFN_vkCreateFence, 65 | pub vkCreateFramebuffer: vk::PFN_vkCreateFramebuffer, 66 | pub vkCreateGraphicsPipelines: vk::PFN_vkCreateGraphicsPipelines, 67 | pub vkCreateImage: vk::PFN_vkCreateImage, 68 | pub vkCreateImageView: vk::PFN_vkCreateImageView, 69 | pub vkCreatePipelineCache: vk::PFN_vkCreatePipelineCache, 70 | pub vkCreatePipelineLayout: vk::PFN_vkCreatePipelineLayout, 71 | pub vkCreateRenderPass: vk::PFN_vkCreateRenderPass, 72 | pub vkCreateSampler: vk::PFN_vkCreateSampler, 73 | pub vkCreateSemaphore: vk::PFN_vkCreateSemaphore, 74 | pub vkCreateShaderModule: vk::PFN_vkCreateShaderModule, 75 | pub vkDestroyBuffer: vk::PFN_vkDestroyBuffer, 76 | pub vkDestroyCommandPool: vk::PFN_vkDestroyCommandPool, 77 | pub vkDestroyDescriptorPool: vk::PFN_vkDestroyDescriptorPool, 78 | pub vkDestroyDescriptorSetLayout: vk::PFN_vkDestroyDescriptorSetLayout, 79 | pub vkDestroyDevice: vk::PFN_vkDestroyDevice, 80 | pub vkDestroyFence: vk::PFN_vkDestroyFence, 81 | pub vkDestroyFramebuffer: vk::PFN_vkDestroyFramebuffer, 82 | pub vkDestroyImage: vk::PFN_vkDestroyImage, 83 | pub vkDestroyImageView: vk::PFN_vkDestroyImageView, 84 | pub vkDestroyPipeline: vk::PFN_vkDestroyPipeline, 85 | pub vkDestroyPipelineCache: vk::PFN_vkDestroyPipelineCache, 86 | pub vkDestroyPipelineLayout: vk::PFN_vkDestroyPipelineLayout, 87 | pub vkDestroyRenderPass: vk::PFN_vkDestroyRenderPass, 88 | pub vkDestroySampler: vk::PFN_vkDestroySampler, 89 | pub vkDestroySemaphore: vk::PFN_vkDestroySemaphore, 90 | pub vkDestroyShaderModule: vk::PFN_vkDestroyShaderModule, 91 | pub vkEndCommandBuffer: vk::PFN_vkEndCommandBuffer, 92 | pub vkFlushMappedMemoryRanges: vk::PFN_vkFlushMappedMemoryRanges, 93 | pub vkFreeCommandBuffers: vk::PFN_vkFreeCommandBuffers, 94 | pub vkFreeDescriptorSets: vk::PFN_vkFreeDescriptorSets, 95 | pub vkFreeMemory: vk::PFN_vkFreeMemory, 96 | pub vkGetBufferMemoryRequirements: vk::PFN_vkGetBufferMemoryRequirements, 97 | pub vkGetDeviceQueue: vk::PFN_vkGetDeviceQueue, 98 | pub vkGetImageMemoryRequirements: vk::PFN_vkGetImageMemoryRequirements, 99 | pub vkGetImageSubresourceLayout: vk::PFN_vkGetImageSubresourceLayout, 100 | pub vkInvalidateMappedMemoryRanges: vk::PFN_vkInvalidateMappedMemoryRanges, 101 | pub vkMapMemory: vk::PFN_vkMapMemory, 102 | pub vkQueueSubmit: vk::PFN_vkQueueSubmit, 103 | pub vkQueueWaitIdle: vk::PFN_vkQueueWaitIdle, 104 | pub vkResetFences: vk::PFN_vkResetFences, 105 | pub vkUnmapMemory: vk::PFN_vkUnmapMemory, 106 | pub vkUpdateDescriptorSets: vk::PFN_vkUpdateDescriptorSets, 107 | pub vkWaitForFences: vk::PFN_vkWaitForFences, 108 | } 109 | 110 | impl Instance { 111 | pub unsafe fn new( 112 | get_instance_proc_cb: GetInstanceProcFunc, 113 | user_data: *const c_void, 114 | ) -> Instance { 115 | Instance { 116 | vkCreateDevice: std::mem::transmute(get_instance_proc_cb( 117 | "vkCreateDevice\0".as_ptr().cast(), 118 | user_data, 119 | )), 120 | vkDestroyInstance: std::mem::transmute(get_instance_proc_cb( 121 | "vkDestroyInstance\0".as_ptr().cast(), 122 | user_data, 123 | )), 124 | vkEnumerateDeviceExtensionProperties: std::mem::transmute(get_instance_proc_cb( 125 | "vkEnumerateDeviceExtensionProperties\0".as_ptr().cast(), 126 | user_data, 127 | )), 128 | vkEnumeratePhysicalDevices: std::mem::transmute(get_instance_proc_cb( 129 | "vkEnumeratePhysicalDevices\0".as_ptr().cast(), 130 | user_data, 131 | )), 132 | vkGetDeviceProcAddr: std::mem::transmute(get_instance_proc_cb( 133 | "vkGetDeviceProcAddr\0".as_ptr().cast(), 134 | user_data, 135 | )), 136 | vkGetPhysicalDeviceFeatures: std::mem::transmute(get_instance_proc_cb( 137 | "vkGetPhysicalDeviceFeatures\0".as_ptr().cast(), 138 | user_data, 139 | )), 140 | vkGetPhysicalDeviceFeatures2KHR: std::mem::transmute(get_instance_proc_cb( 141 | "vkGetPhysicalDeviceFeatures2KHR\0".as_ptr().cast(), 142 | user_data, 143 | )), 144 | vkGetPhysicalDeviceFormatProperties: std::mem::transmute(get_instance_proc_cb( 145 | "vkGetPhysicalDeviceFormatProperties\0".as_ptr().cast(), 146 | user_data, 147 | )), 148 | vkGetPhysicalDeviceMemoryProperties: std::mem::transmute(get_instance_proc_cb( 149 | "vkGetPhysicalDeviceMemoryProperties\0".as_ptr().cast(), 150 | user_data, 151 | )), 152 | vkGetPhysicalDeviceProperties: std::mem::transmute(get_instance_proc_cb( 153 | "vkGetPhysicalDeviceProperties\0".as_ptr().cast(), 154 | user_data, 155 | )), 156 | vkGetPhysicalDeviceProperties2: std::mem::transmute(get_instance_proc_cb( 157 | "vkGetPhysicalDeviceProperties2\0".as_ptr().cast(), 158 | user_data, 159 | )), 160 | vkGetPhysicalDeviceQueueFamilyProperties: std::mem::transmute(get_instance_proc_cb( 161 | "vkGetPhysicalDeviceQueueFamilyProperties\0".as_ptr().cast(), 162 | user_data, 163 | )), 164 | vkGetPhysicalDeviceCooperativeMatrixPropertiesKHR: std::mem::transmute(get_instance_proc_cb( 165 | "vkGetPhysicalDeviceCooperativeMatrixPropertiesKHR\0".as_ptr().cast(), 166 | user_data, 167 | )), 168 | } 169 | } 170 | } 171 | 172 | #[allow(dead_code)] 173 | impl Device { 174 | pub fn new(instance: &Instance, device: vk::VkDevice) -> Device { 175 | Device { 176 | vkAllocateCommandBuffers: unsafe { 177 | std::mem::transmute(instance.vkGetDeviceProcAddr.unwrap()( 178 | device, 179 | "vkAllocateCommandBuffers\0".as_ptr().cast(), 180 | )) 181 | }, 182 | vkAllocateDescriptorSets: unsafe { 183 | std::mem::transmute(instance.vkGetDeviceProcAddr.unwrap()( 184 | device, 185 | "vkAllocateDescriptorSets\0".as_ptr().cast(), 186 | )) 187 | }, 188 | vkAllocateMemory: unsafe { 189 | std::mem::transmute(instance.vkGetDeviceProcAddr.unwrap()( 190 | device, 191 | "vkAllocateMemory\0".as_ptr().cast(), 192 | )) 193 | }, 194 | vkBeginCommandBuffer: unsafe { 195 | std::mem::transmute(instance.vkGetDeviceProcAddr.unwrap()( 196 | device, 197 | "vkBeginCommandBuffer\0".as_ptr().cast(), 198 | )) 199 | }, 200 | vkBindBufferMemory: unsafe { 201 | std::mem::transmute(instance.vkGetDeviceProcAddr.unwrap()( 202 | device, 203 | "vkBindBufferMemory\0".as_ptr().cast(), 204 | )) 205 | }, 206 | vkBindImageMemory: unsafe { 207 | std::mem::transmute(instance.vkGetDeviceProcAddr.unwrap()( 208 | device, 209 | "vkBindImageMemory\0".as_ptr().cast(), 210 | )) 211 | }, 212 | vkCmdBeginRenderPass: unsafe { 213 | std::mem::transmute(instance.vkGetDeviceProcAddr.unwrap()( 214 | device, 215 | "vkCmdBeginRenderPass\0".as_ptr().cast(), 216 | )) 217 | }, 218 | vkCmdBindDescriptorSets: unsafe { 219 | std::mem::transmute(instance.vkGetDeviceProcAddr.unwrap()( 220 | device, 221 | "vkCmdBindDescriptorSets\0".as_ptr().cast(), 222 | )) 223 | }, 224 | vkCmdBindIndexBuffer: unsafe { 225 | std::mem::transmute(instance.vkGetDeviceProcAddr.unwrap()( 226 | device, 227 | "vkCmdBindIndexBuffer\0".as_ptr().cast(), 228 | )) 229 | }, 230 | vkCmdBindPipeline: unsafe { 231 | std::mem::transmute(instance.vkGetDeviceProcAddr.unwrap()( 232 | device, 233 | "vkCmdBindPipeline\0".as_ptr().cast(), 234 | )) 235 | }, 236 | vkCmdBindVertexBuffers: unsafe { 237 | std::mem::transmute(instance.vkGetDeviceProcAddr.unwrap()( 238 | device, 239 | "vkCmdBindVertexBuffers\0".as_ptr().cast(), 240 | )) 241 | }, 242 | vkCmdClearAttachments: unsafe { 243 | std::mem::transmute(instance.vkGetDeviceProcAddr.unwrap()( 244 | device, 245 | "vkCmdClearAttachments\0".as_ptr().cast(), 246 | )) 247 | }, 248 | vkCmdCopyBufferToImage: unsafe { 249 | std::mem::transmute(instance.vkGetDeviceProcAddr.unwrap()( 250 | device, 251 | "vkCmdCopyBufferToImage\0".as_ptr().cast(), 252 | )) 253 | }, 254 | vkCmdCopyImageToBuffer: unsafe { 255 | std::mem::transmute(instance.vkGetDeviceProcAddr.unwrap()( 256 | device, 257 | "vkCmdCopyImageToBuffer\0".as_ptr().cast(), 258 | )) 259 | }, 260 | vkCmdDispatch: unsafe { 261 | std::mem::transmute(instance.vkGetDeviceProcAddr.unwrap()( 262 | device, 263 | "vkCmdDispatch\0".as_ptr().cast(), 264 | )) 265 | }, 266 | vkCmdDraw: unsafe { 267 | std::mem::transmute(instance.vkGetDeviceProcAddr.unwrap()( 268 | device, 269 | "vkCmdDraw\0".as_ptr().cast(), 270 | )) 271 | }, 272 | vkCmdDrawIndexed: unsafe { 273 | std::mem::transmute(instance.vkGetDeviceProcAddr.unwrap()( 274 | device, 275 | "vkCmdDrawIndexed\0".as_ptr().cast(), 276 | )) 277 | }, 278 | vkCmdDrawIndexedIndirect: unsafe { 279 | std::mem::transmute(instance.vkGetDeviceProcAddr.unwrap()( 280 | device, 281 | "vkCmdDrawIndexedIndirect\0".as_ptr().cast(), 282 | )) 283 | }, 284 | vkCmdEndRenderPass: unsafe { 285 | std::mem::transmute(instance.vkGetDeviceProcAddr.unwrap()( 286 | device, 287 | "vkCmdEndRenderPass\0".as_ptr().cast(), 288 | )) 289 | }, 290 | vkCmdPipelineBarrier: unsafe { 291 | std::mem::transmute(instance.vkGetDeviceProcAddr.unwrap()( 292 | device, 293 | "vkCmdPipelineBarrier\0".as_ptr().cast(), 294 | )) 295 | }, 296 | vkCmdPushConstants: unsafe { 297 | std::mem::transmute(instance.vkGetDeviceProcAddr.unwrap()( 298 | device, 299 | "vkCmdPushConstants\0".as_ptr().cast(), 300 | )) 301 | }, 302 | vkCmdSetScissor: unsafe { 303 | std::mem::transmute(instance.vkGetDeviceProcAddr.unwrap()( 304 | device, 305 | "vkCmdSetScissor\0".as_ptr().cast(), 306 | )) 307 | }, 308 | vkCmdSetViewport: unsafe { 309 | std::mem::transmute(instance.vkGetDeviceProcAddr.unwrap()( 310 | device, 311 | "vkCmdSetViewport\0".as_ptr().cast(), 312 | )) 313 | }, 314 | vkCreateBuffer: unsafe { 315 | std::mem::transmute(instance.vkGetDeviceProcAddr.unwrap()( 316 | device, 317 | "vkCreateBuffer\0".as_ptr().cast(), 318 | )) 319 | }, 320 | vkCreateCommandPool: unsafe { 321 | std::mem::transmute(instance.vkGetDeviceProcAddr.unwrap()( 322 | device, 323 | "vkCreateCommandPool\0".as_ptr().cast(), 324 | )) 325 | }, 326 | vkCreateComputePipelines: unsafe { 327 | std::mem::transmute(instance.vkGetDeviceProcAddr.unwrap()( 328 | device, 329 | "vkCreateComputePipelines\0".as_ptr().cast(), 330 | )) 331 | }, 332 | vkCreateDescriptorPool: unsafe { 333 | std::mem::transmute(instance.vkGetDeviceProcAddr.unwrap()( 334 | device, 335 | "vkCreateDescriptorPool\0".as_ptr().cast(), 336 | )) 337 | }, 338 | vkCreateDescriptorSetLayout: unsafe { 339 | std::mem::transmute(instance.vkGetDeviceProcAddr.unwrap()( 340 | device, 341 | "vkCreateDescriptorSetLayout\0".as_ptr().cast(), 342 | )) 343 | }, 344 | vkCreateFence: unsafe { 345 | std::mem::transmute(instance.vkGetDeviceProcAddr.unwrap()( 346 | device, 347 | "vkCreateFence\0".as_ptr().cast(), 348 | )) 349 | }, 350 | vkCreateFramebuffer: unsafe { 351 | std::mem::transmute(instance.vkGetDeviceProcAddr.unwrap()( 352 | device, 353 | "vkCreateFramebuffer\0".as_ptr().cast(), 354 | )) 355 | }, 356 | vkCreateGraphicsPipelines: unsafe { 357 | std::mem::transmute(instance.vkGetDeviceProcAddr.unwrap()( 358 | device, 359 | "vkCreateGraphicsPipelines\0".as_ptr().cast(), 360 | )) 361 | }, 362 | vkCreateImage: unsafe { 363 | std::mem::transmute(instance.vkGetDeviceProcAddr.unwrap()( 364 | device, 365 | "vkCreateImage\0".as_ptr().cast(), 366 | )) 367 | }, 368 | vkCreateImageView: unsafe { 369 | std::mem::transmute(instance.vkGetDeviceProcAddr.unwrap()( 370 | device, 371 | "vkCreateImageView\0".as_ptr().cast(), 372 | )) 373 | }, 374 | vkCreatePipelineCache: unsafe { 375 | std::mem::transmute(instance.vkGetDeviceProcAddr.unwrap()( 376 | device, 377 | "vkCreatePipelineCache\0".as_ptr().cast(), 378 | )) 379 | }, 380 | vkCreatePipelineLayout: unsafe { 381 | std::mem::transmute(instance.vkGetDeviceProcAddr.unwrap()( 382 | device, 383 | "vkCreatePipelineLayout\0".as_ptr().cast(), 384 | )) 385 | }, 386 | vkCreateRenderPass: unsafe { 387 | std::mem::transmute(instance.vkGetDeviceProcAddr.unwrap()( 388 | device, 389 | "vkCreateRenderPass\0".as_ptr().cast(), 390 | )) 391 | }, 392 | vkCreateSampler: unsafe { 393 | std::mem::transmute(instance.vkGetDeviceProcAddr.unwrap()( 394 | device, 395 | "vkCreateSampler\0".as_ptr().cast(), 396 | )) 397 | }, 398 | vkCreateSemaphore: unsafe { 399 | std::mem::transmute(instance.vkGetDeviceProcAddr.unwrap()( 400 | device, 401 | "vkCreateSemaphore\0".as_ptr().cast(), 402 | )) 403 | }, 404 | vkCreateShaderModule: unsafe { 405 | std::mem::transmute(instance.vkGetDeviceProcAddr.unwrap()( 406 | device, 407 | "vkCreateShaderModule\0".as_ptr().cast(), 408 | )) 409 | }, 410 | vkDestroyBuffer: unsafe { 411 | std::mem::transmute(instance.vkGetDeviceProcAddr.unwrap()( 412 | device, 413 | "vkDestroyBuffer\0".as_ptr().cast(), 414 | )) 415 | }, 416 | vkDestroyCommandPool: unsafe { 417 | std::mem::transmute(instance.vkGetDeviceProcAddr.unwrap()( 418 | device, 419 | "vkDestroyCommandPool\0".as_ptr().cast(), 420 | )) 421 | }, 422 | vkDestroyDescriptorPool: unsafe { 423 | std::mem::transmute(instance.vkGetDeviceProcAddr.unwrap()( 424 | device, 425 | "vkDestroyDescriptorPool\0".as_ptr().cast(), 426 | )) 427 | }, 428 | vkDestroyDescriptorSetLayout: unsafe { 429 | std::mem::transmute(instance.vkGetDeviceProcAddr.unwrap()( 430 | device, 431 | "vkDestroyDescriptorSetLayout\0".as_ptr().cast(), 432 | )) 433 | }, 434 | vkDestroyDevice: unsafe { 435 | std::mem::transmute(instance.vkGetDeviceProcAddr.unwrap()( 436 | device, 437 | "vkDestroyDevice\0".as_ptr().cast(), 438 | )) 439 | }, 440 | vkDestroyFence: unsafe { 441 | std::mem::transmute(instance.vkGetDeviceProcAddr.unwrap()( 442 | device, 443 | "vkDestroyFence\0".as_ptr().cast(), 444 | )) 445 | }, 446 | vkDestroyFramebuffer: unsafe { 447 | std::mem::transmute(instance.vkGetDeviceProcAddr.unwrap()( 448 | device, 449 | "vkDestroyFramebuffer\0".as_ptr().cast(), 450 | )) 451 | }, 452 | vkDestroyImage: unsafe { 453 | std::mem::transmute(instance.vkGetDeviceProcAddr.unwrap()( 454 | device, 455 | "vkDestroyImage\0".as_ptr().cast(), 456 | )) 457 | }, 458 | vkDestroyImageView: unsafe { 459 | std::mem::transmute(instance.vkGetDeviceProcAddr.unwrap()( 460 | device, 461 | "vkDestroyImageView\0".as_ptr().cast(), 462 | )) 463 | }, 464 | vkDestroyPipeline: unsafe { 465 | std::mem::transmute(instance.vkGetDeviceProcAddr.unwrap()( 466 | device, 467 | "vkDestroyPipeline\0".as_ptr().cast(), 468 | )) 469 | }, 470 | vkDestroyPipelineCache: unsafe { 471 | std::mem::transmute(instance.vkGetDeviceProcAddr.unwrap()( 472 | device, 473 | "vkDestroyPipelineCache\0".as_ptr().cast(), 474 | )) 475 | }, 476 | vkDestroyPipelineLayout: unsafe { 477 | std::mem::transmute(instance.vkGetDeviceProcAddr.unwrap()( 478 | device, 479 | "vkDestroyPipelineLayout\0".as_ptr().cast(), 480 | )) 481 | }, 482 | vkDestroyRenderPass: unsafe { 483 | std::mem::transmute(instance.vkGetDeviceProcAddr.unwrap()( 484 | device, 485 | "vkDestroyRenderPass\0".as_ptr().cast(), 486 | )) 487 | }, 488 | vkDestroySampler: unsafe { 489 | std::mem::transmute(instance.vkGetDeviceProcAddr.unwrap()( 490 | device, 491 | "vkDestroySampler\0".as_ptr().cast(), 492 | )) 493 | }, 494 | vkDestroySemaphore: unsafe { 495 | std::mem::transmute(instance.vkGetDeviceProcAddr.unwrap()( 496 | device, 497 | "vkDestroySemaphore\0".as_ptr().cast(), 498 | )) 499 | }, 500 | vkDestroyShaderModule: unsafe { 501 | std::mem::transmute(instance.vkGetDeviceProcAddr.unwrap()( 502 | device, 503 | "vkDestroyShaderModule\0".as_ptr().cast(), 504 | )) 505 | }, 506 | vkEndCommandBuffer: unsafe { 507 | std::mem::transmute(instance.vkGetDeviceProcAddr.unwrap()( 508 | device, 509 | "vkEndCommandBuffer\0".as_ptr().cast(), 510 | )) 511 | }, 512 | vkFlushMappedMemoryRanges: unsafe { 513 | std::mem::transmute(instance.vkGetDeviceProcAddr.unwrap()( 514 | device, 515 | "vkFlushMappedMemoryRanges\0".as_ptr().cast(), 516 | )) 517 | }, 518 | vkFreeCommandBuffers: unsafe { 519 | std::mem::transmute(instance.vkGetDeviceProcAddr.unwrap()( 520 | device, 521 | "vkFreeCommandBuffers\0".as_ptr().cast(), 522 | )) 523 | }, 524 | vkFreeDescriptorSets: unsafe { 525 | std::mem::transmute(instance.vkGetDeviceProcAddr.unwrap()( 526 | device, 527 | "vkFreeDescriptorSets\0".as_ptr().cast(), 528 | )) 529 | }, 530 | vkFreeMemory: unsafe { 531 | std::mem::transmute(instance.vkGetDeviceProcAddr.unwrap()( 532 | device, 533 | "vkFreeMemory\0".as_ptr().cast(), 534 | )) 535 | }, 536 | vkGetBufferMemoryRequirements: unsafe { 537 | std::mem::transmute(instance.vkGetDeviceProcAddr.unwrap()( 538 | device, 539 | "vkGetBufferMemoryRequirements\0".as_ptr().cast(), 540 | )) 541 | }, 542 | vkGetDeviceQueue: unsafe { 543 | std::mem::transmute(instance.vkGetDeviceProcAddr.unwrap()( 544 | device, 545 | "vkGetDeviceQueue\0".as_ptr().cast(), 546 | )) 547 | }, 548 | vkGetImageMemoryRequirements: unsafe { 549 | std::mem::transmute(instance.vkGetDeviceProcAddr.unwrap()( 550 | device, 551 | "vkGetImageMemoryRequirements\0".as_ptr().cast(), 552 | )) 553 | }, 554 | vkGetImageSubresourceLayout: unsafe { 555 | std::mem::transmute(instance.vkGetDeviceProcAddr.unwrap()( 556 | device, 557 | "vkGetImageSubresourceLayout\0".as_ptr().cast(), 558 | )) 559 | }, 560 | vkInvalidateMappedMemoryRanges: unsafe { 561 | std::mem::transmute(instance.vkGetDeviceProcAddr.unwrap()( 562 | device, 563 | "vkInvalidateMappedMemoryRanges\0".as_ptr().cast(), 564 | )) 565 | }, 566 | vkMapMemory: unsafe { 567 | std::mem::transmute(instance.vkGetDeviceProcAddr.unwrap()( 568 | device, 569 | "vkMapMemory\0".as_ptr().cast(), 570 | )) 571 | }, 572 | vkQueueSubmit: unsafe { 573 | std::mem::transmute(instance.vkGetDeviceProcAddr.unwrap()( 574 | device, 575 | "vkQueueSubmit\0".as_ptr().cast(), 576 | )) 577 | }, 578 | vkQueueWaitIdle: unsafe { 579 | std::mem::transmute(instance.vkGetDeviceProcAddr.unwrap()( 580 | device, 581 | "vkQueueWaitIdle\0".as_ptr().cast(), 582 | )) 583 | }, 584 | vkResetFences: unsafe { 585 | std::mem::transmute(instance.vkGetDeviceProcAddr.unwrap()( 586 | device, 587 | "vkResetFences\0".as_ptr().cast(), 588 | )) 589 | }, 590 | vkUnmapMemory: unsafe { 591 | std::mem::transmute(instance.vkGetDeviceProcAddr.unwrap()( 592 | device, 593 | "vkUnmapMemory\0".as_ptr().cast(), 594 | )) 595 | }, 596 | vkUpdateDescriptorSets: unsafe { 597 | std::mem::transmute(instance.vkGetDeviceProcAddr.unwrap()( 598 | device, 599 | "vkUpdateDescriptorSets\0".as_ptr().cast(), 600 | )) 601 | }, 602 | vkWaitForFences: unsafe { 603 | std::mem::transmute(instance.vkGetDeviceProcAddr.unwrap()( 604 | device, 605 | "vkWaitForFences\0".as_ptr().cast(), 606 | )) 607 | }, 608 | } 609 | } 610 | } 611 | ```