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