#
tokens: 49481/50000 14/78 files (page 2/9)
lines: on (toggle) GitHub
raw markdown copy reset
This is page 2 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/include/vk_video/vulkan_video_codec_h265std_encode.h:
--------------------------------------------------------------------------------

```
  1 | #ifndef VULKAN_VIDEO_CODEC_H265STD_ENCODE_H_
  2 | #define VULKAN_VIDEO_CODEC_H265STD_ENCODE_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_encode is a preprocessor guard. Do not pass it to API calls.
 23 | #define vulkan_video_codec_h265std_encode 1
 24 | #include "vulkan_video_codec_h265std.h"
 25 | 
 26 | #define VK_STD_VULKAN_VIDEO_CODEC_H265_ENCODE_API_VERSION_1_0_0 VK_MAKE_VIDEO_STD_VERSION(1, 0, 0)
 27 | 
 28 | #define VK_STD_VULKAN_VIDEO_CODEC_H265_ENCODE_SPEC_VERSION VK_STD_VULKAN_VIDEO_CODEC_H265_ENCODE_API_VERSION_1_0_0
 29 | #define VK_STD_VULKAN_VIDEO_CODEC_H265_ENCODE_EXTENSION_NAME "VK_STD_vulkan_video_codec_h265_encode"
 30 | typedef struct StdVideoEncodeH265WeightTableFlags {
 31 |     uint16_t    luma_weight_l0_flag;
 32 |     uint16_t    chroma_weight_l0_flag;
 33 |     uint16_t    luma_weight_l1_flag;
 34 |     uint16_t    chroma_weight_l1_flag;
 35 | } StdVideoEncodeH265WeightTableFlags;
 36 | 
 37 | typedef struct StdVideoEncodeH265WeightTable {
 38 |     StdVideoEncodeH265WeightTableFlags    flags;
 39 |     uint8_t                               luma_log2_weight_denom;
 40 |     int8_t                                delta_chroma_log2_weight_denom;
 41 |     int8_t                                delta_luma_weight_l0[STD_VIDEO_H265_MAX_NUM_LIST_REF];
 42 |     int8_t                                luma_offset_l0[STD_VIDEO_H265_MAX_NUM_LIST_REF];
 43 |     int8_t                                delta_chroma_weight_l0[STD_VIDEO_H265_MAX_NUM_LIST_REF][STD_VIDEO_H265_MAX_CHROMA_PLANES];
 44 |     int8_t                                delta_chroma_offset_l0[STD_VIDEO_H265_MAX_NUM_LIST_REF][STD_VIDEO_H265_MAX_CHROMA_PLANES];
 45 |     int8_t                                delta_luma_weight_l1[STD_VIDEO_H265_MAX_NUM_LIST_REF];
 46 |     int8_t                                luma_offset_l1[STD_VIDEO_H265_MAX_NUM_LIST_REF];
 47 |     int8_t                                delta_chroma_weight_l1[STD_VIDEO_H265_MAX_NUM_LIST_REF][STD_VIDEO_H265_MAX_CHROMA_PLANES];
 48 |     int8_t                                delta_chroma_offset_l1[STD_VIDEO_H265_MAX_NUM_LIST_REF][STD_VIDEO_H265_MAX_CHROMA_PLANES];
 49 | } StdVideoEncodeH265WeightTable;
 50 | 
 51 | typedef struct StdVideoEncodeH265SliceSegmentHeaderFlags {
 52 |     uint32_t    first_slice_segment_in_pic_flag : 1;
 53 |     uint32_t    dependent_slice_segment_flag : 1;
 54 |     uint32_t    slice_sao_luma_flag : 1;
 55 |     uint32_t    slice_sao_chroma_flag : 1;
 56 |     uint32_t    num_ref_idx_active_override_flag : 1;
 57 |     uint32_t    mvd_l1_zero_flag : 1;
 58 |     uint32_t    cabac_init_flag : 1;
 59 |     uint32_t    cu_chroma_qp_offset_enabled_flag : 1;
 60 |     uint32_t    deblocking_filter_override_flag : 1;
 61 |     uint32_t    slice_deblocking_filter_disabled_flag : 1;
 62 |     uint32_t    collocated_from_l0_flag : 1;
 63 |     uint32_t    slice_loop_filter_across_slices_enabled_flag : 1;
 64 |     uint32_t    reserved : 20;
 65 | } StdVideoEncodeH265SliceSegmentHeaderFlags;
 66 | 
 67 | typedef struct StdVideoEncodeH265SliceSegmentHeader {
 68 |     StdVideoEncodeH265SliceSegmentHeaderFlags    flags;
 69 |     StdVideoH265SliceType                        slice_type;
 70 |     uint32_t                                     slice_segment_address;
 71 |     uint8_t                                      collocated_ref_idx;
 72 |     uint8_t                                      MaxNumMergeCand;
 73 |     int8_t                                       slice_cb_qp_offset;
 74 |     int8_t                                       slice_cr_qp_offset;
 75 |     int8_t                                       slice_beta_offset_div2;
 76 |     int8_t                                       slice_tc_offset_div2;
 77 |     int8_t                                       slice_act_y_qp_offset;
 78 |     int8_t                                       slice_act_cb_qp_offset;
 79 |     int8_t                                       slice_act_cr_qp_offset;
 80 |     int8_t                                       slice_qp_delta;
 81 |     uint16_t                                     reserved1;
 82 |     const StdVideoEncodeH265WeightTable*         pWeightTable;
 83 | } StdVideoEncodeH265SliceSegmentHeader;
 84 | 
 85 | typedef struct StdVideoEncodeH265ReferenceListsInfoFlags {
 86 |     uint32_t    ref_pic_list_modification_flag_l0 : 1;
 87 |     uint32_t    ref_pic_list_modification_flag_l1 : 1;
 88 |     uint32_t    reserved : 30;
 89 | } StdVideoEncodeH265ReferenceListsInfoFlags;
 90 | 
 91 | typedef struct StdVideoEncodeH265ReferenceListsInfo {
 92 |     StdVideoEncodeH265ReferenceListsInfoFlags    flags;
 93 |     uint8_t                                      num_ref_idx_l0_active_minus1;
 94 |     uint8_t                                      num_ref_idx_l1_active_minus1;
 95 |     uint8_t                                      RefPicList0[STD_VIDEO_H265_MAX_NUM_LIST_REF];
 96 |     uint8_t                                      RefPicList1[STD_VIDEO_H265_MAX_NUM_LIST_REF];
 97 |     uint8_t                                      list_entry_l0[STD_VIDEO_H265_MAX_NUM_LIST_REF];
 98 |     uint8_t                                      list_entry_l1[STD_VIDEO_H265_MAX_NUM_LIST_REF];
 99 | } StdVideoEncodeH265ReferenceListsInfo;
100 | 
101 | typedef struct StdVideoEncodeH265PictureInfoFlags {
102 |     uint32_t    is_reference : 1;
103 |     uint32_t    IrapPicFlag : 1;
104 |     uint32_t    used_for_long_term_reference : 1;
105 |     uint32_t    discardable_flag : 1;
106 |     uint32_t    cross_layer_bla_flag : 1;
107 |     uint32_t    pic_output_flag : 1;
108 |     uint32_t    no_output_of_prior_pics_flag : 1;
109 |     uint32_t    short_term_ref_pic_set_sps_flag : 1;
110 |     uint32_t    slice_temporal_mvp_enabled_flag : 1;
111 |     uint32_t    reserved : 23;
112 | } StdVideoEncodeH265PictureInfoFlags;
113 | 
114 | typedef struct StdVideoEncodeH265LongTermRefPics {
115 |     uint8_t     num_long_term_sps;
116 |     uint8_t     num_long_term_pics;
117 |     uint8_t     lt_idx_sps[STD_VIDEO_H265_MAX_LONG_TERM_REF_PICS_SPS];
118 |     uint8_t     poc_lsb_lt[STD_VIDEO_H265_MAX_LONG_TERM_PICS];
119 |     uint16_t    used_by_curr_pic_lt_flag;
120 |     uint8_t     delta_poc_msb_present_flag[STD_VIDEO_H265_MAX_DELTA_POC];
121 |     uint8_t     delta_poc_msb_cycle_lt[STD_VIDEO_H265_MAX_DELTA_POC];
122 | } StdVideoEncodeH265LongTermRefPics;
123 | 
124 | typedef struct StdVideoEncodeH265PictureInfo {
125 |     StdVideoEncodeH265PictureInfoFlags             flags;
126 |     StdVideoH265PictureType                        pic_type;
127 |     uint8_t                                        sps_video_parameter_set_id;
128 |     uint8_t                                        pps_seq_parameter_set_id;
129 |     uint8_t                                        pps_pic_parameter_set_id;
130 |     uint8_t                                        short_term_ref_pic_set_idx;
131 |     int32_t                                        PicOrderCntVal;
132 |     uint8_t                                        TemporalId;
133 |     uint8_t                                        reserved1[7];
134 |     const StdVideoEncodeH265ReferenceListsInfo*    pRefLists;
135 |     const StdVideoH265ShortTermRefPicSet*          pShortTermRefPicSet;
136 |     const StdVideoEncodeH265LongTermRefPics*       pLongTermRefPics;
137 | } StdVideoEncodeH265PictureInfo;
138 | 
139 | typedef struct StdVideoEncodeH265ReferenceInfoFlags {
140 |     uint32_t    used_for_long_term_reference : 1;
141 |     uint32_t    unused_for_reference : 1;
142 |     uint32_t    reserved : 30;
143 | } StdVideoEncodeH265ReferenceInfoFlags;
144 | 
145 | typedef struct StdVideoEncodeH265ReferenceInfo {
146 |     StdVideoEncodeH265ReferenceInfoFlags    flags;
147 |     StdVideoH265PictureType                 pic_type;
148 |     int32_t                                 PicOrderCntVal;
149 |     uint8_t                                 TemporalId;
150 | } StdVideoEncodeH265ReferenceInfo;
151 | 
152 | 
153 | #ifdef __cplusplus
154 | }
155 | #endif
156 | 
157 | #endif
158 | 
```

--------------------------------------------------------------------------------
/vkrunner/vkrunner/flush_memory.rs:
--------------------------------------------------------------------------------

```rust
  1 | // vkrunner
  2 | //
  3 | // Copyright (C) 2017, 2023 Neil Roberts
  4 | //
  5 | // Permission is hereby granted, free of charge, to any person obtaining a
  6 | // copy of this software and associated documentation files (the "Software"),
  7 | // to deal in the Software without restriction, including without limitation
  8 | // the rights to use, copy, modify, merge, publish, distribute, sublicense,
  9 | // and/or sell copies of the Software, and to permit persons to whom the
 10 | // Software is furnished to do so, subject to the following conditions:
 11 | //
 12 | // The above copyright notice and this permission notice (including the next
 13 | // paragraph) shall be included in all copies or substantial portions of the
 14 | // Software.
 15 | //
 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 19 | // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 21 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 22 | // DEALINGS IN THE SOFTWARE.
 23 | 
 24 | use crate::context::Context;
 25 | use crate::vk;
 26 | use std::ptr;
 27 | use std::fmt;
 28 | 
 29 | #[derive(Debug)]
 30 | pub struct Error(vk::VkResult);
 31 | 
 32 | impl fmt::Display for Error {
 33 |     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
 34 |         write!(f, "vkFlushMappedMemoryRanges failed: {:?}", self.0)
 35 |     }
 36 | }
 37 | 
 38 | /// Calls `vkFlushMappedMemoryRanges` with the range specified in
 39 | /// `offset` and `size` unless the specified memory type has the
 40 | /// `VK_MEMORY_PROPERTY_HOST_COHERENT_BIT` property set.
 41 | ///
 42 | /// For testing, the environment variable
 43 | /// `VKRUNNER_ALWAYS_FLUSH_MEMORY` can be set to `true` to make it
 44 | /// always flush the memory regardless of memory type properties.
 45 | pub fn flush_memory(
 46 |     context: &Context,
 47 |     memory_type_index: usize,
 48 |     memory: vk::VkDeviceMemory,
 49 |     offset: vk::VkDeviceSize,
 50 |     size: vk::VkDeviceSize,
 51 | ) -> Result<(), Error> {
 52 |     let memory_properties = context.memory_properties();
 53 |     let memory_type =
 54 |         &memory_properties.memoryTypes[memory_type_index as usize];
 55 | 
 56 |     // We don’t need to do anything if the memory is already coherent
 57 |     if !context.always_flush_memory()
 58 |         && (memory_type.propertyFlags
 59 |             & vk::VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) != 0
 60 |     {
 61 |         return Ok(());
 62 |     }
 63 | 
 64 |     let mapped_memory_range = vk::VkMappedMemoryRange {
 65 |         sType: vk::VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
 66 |         pNext: ptr::null(),
 67 |         memory,
 68 |         offset,
 69 |         size,
 70 |     };
 71 | 
 72 |     let res = unsafe {
 73 |         context.device().vkFlushMappedMemoryRanges.unwrap()(
 74 |             context.vk_device(),
 75 |             1, // memoryRangeCount
 76 |             ptr::addr_of!(mapped_memory_range),
 77 |         )
 78 |     };
 79 | 
 80 |     if res == vk::VK_SUCCESS {
 81 |         Ok(())
 82 |     } else {
 83 |         Err(Error(res))
 84 |     }
 85 | }
 86 | 
 87 | #[cfg(test)]
 88 | mod test {
 89 |     use super::*;
 90 |     use std::rc::Rc;
 91 |     use crate::requirements::Requirements;
 92 |     use crate::fake_vulkan::FakeVulkan;
 93 |     use crate::env_var_test::EnvVarLock;
 94 | 
 95 |     struct Memory {
 96 |         handle: vk::VkDeviceMemory,
 97 |         context: Rc<Context>,
 98 |     }
 99 | 
100 |     impl Memory {
101 |         fn new(context: Rc<Context>) -> Memory {
102 |             let mut handle = vk::null_handle();
103 | 
104 |             let allocate_info = vk::VkMemoryAllocateInfo {
105 |                 sType: vk::VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
106 |                 pNext: ptr::null(),
107 |                 allocationSize: 1024,
108 |                 memoryTypeIndex: 0,
109 |             };
110 | 
111 |             unsafe {
112 |                 let res = context.device().vkAllocateMemory.unwrap()(
113 |                     context.vk_device(),
114 |                     ptr::addr_of!(allocate_info),
115 |                     ptr::null(), // allocator
116 |                     ptr::addr_of_mut!(handle),
117 |                 );
118 | 
119 |                 assert_eq!(res, vk::VK_SUCCESS);
120 |             }
121 | 
122 |             Memory { handle, context }
123 |         }
124 |     }
125 | 
126 |     impl Drop for Memory {
127 |         fn drop(&mut self) {
128 |             unsafe {
129 |                 self.context.device().vkFreeMemory.unwrap()(
130 |                     self.context.vk_device(),
131 |                     self.handle,
132 |                     ptr::null_mut(), // allocator
133 |                 );
134 |             }
135 |         }
136 |     }
137 | 
138 |     struct TestData {
139 |         context: Rc<Context>,
140 |         fake_vulkan: Box<FakeVulkan>,
141 |     }
142 | 
143 |     impl TestData {
144 |         fn new(coherent_memory: bool) -> TestData {
145 |             let mut fake_vulkan = FakeVulkan::new();
146 |             fake_vulkan.physical_devices.push(Default::default());
147 |             let memory_properties =
148 |                 &mut fake_vulkan.physical_devices[0].memory_properties;
149 |             memory_properties.memoryTypeCount = 1;
150 | 
151 |             memory_properties.memoryTypes[0].propertyFlags =
152 |                 if coherent_memory {
153 |                     vk::VK_MEMORY_PROPERTY_HOST_COHERENT_BIT
154 |                 } else {
155 |                     0
156 |                 };
157 | 
158 |             fake_vulkan.set_override();
159 |             let context = Rc::new(
160 |                 Context::new(&Requirements::new(), None).unwrap()
161 |             );
162 | 
163 |             TestData { context, fake_vulkan }
164 |         }
165 |     }
166 | 
167 |     fn test_flag_combination(
168 |         memory_is_coherent: bool,
169 |         always_flush: bool,
170 |         flush_expected: bool,
171 |     ) {
172 |         let _env_var_lock = EnvVarLock::new(&[
173 |             (
174 |                 "VKRUNNER_ALWAYS_FLUSH_MEMORY",
175 |                 if always_flush { "true" } else { "false" },
176 |             )
177 |         ]);
178 | 
179 |         let test_data = TestData::new(memory_is_coherent);
180 | 
181 |         let memory = Memory::new(Rc::clone(&test_data.context));
182 | 
183 |         flush_memory(
184 |             &test_data.context,
185 |             0, // memory_type_index
186 |             memory.handle,
187 |             16, // offset
188 |             24, // size
189 |         ).unwrap();
190 | 
191 |         if flush_expected {
192 |             assert_eq!(test_data.fake_vulkan.memory_flushes.len(), 1);
193 |             assert_eq!(
194 |                 test_data.fake_vulkan.memory_flushes[0].memory,
195 |                 memory.handle,
196 |             );
197 |             assert_eq!(test_data.fake_vulkan.memory_flushes[0].offset, 16);
198 |             assert_eq!(test_data.fake_vulkan.memory_flushes[0].size, 24);
199 |         } else {
200 |             assert_eq!(test_data.fake_vulkan.memory_flushes.len(), 0);
201 |         }
202 |     }
203 | 
204 |     #[test]
205 |     fn should_flush() {
206 |         test_flag_combination(
207 |             false, // memory_is_coherent
208 |             false, // always_flush
209 |             true, // flush_expected
210 |         );
211 |         test_flag_combination(
212 |             false, // memory_is_coherent
213 |             true, // always_flush
214 |             true, // flush_expected
215 |         );
216 |         test_flag_combination(
217 |             true, // memory_is_coherent
218 |             false, // always_flush
219 |             false, // flush_expected
220 |         );
221 |         test_flag_combination(
222 |             true, // memory_is_coherent
223 |             true, // always_flush
224 |             true, // flush_expected
225 |         );
226 |     }
227 | 
228 |     #[test]
229 |     fn error() {
230 |         let _env_var_lock = EnvVarLock::new(&[
231 |             ("VKRUNNER_ALWAYS_FLUSH_MEMORY", "false")
232 |         ]);
233 | 
234 |         let mut test_data = TestData::new(
235 |             false, // memory_is_coherent
236 |         );
237 | 
238 |         let memory = Memory::new(Rc::clone(&test_data.context));
239 | 
240 |         test_data.fake_vulkan.queue_result(
241 |             "vkFlushMappedMemoryRanges".to_string(),
242 |             vk::VK_ERROR_UNKNOWN,
243 |         );
244 | 
245 |         let error = flush_memory(
246 |             &test_data.context,
247 |             0, // memory_type_index
248 |             memory.handle,
249 |             16, // offset
250 |             24, // size
251 |         ).unwrap_err();
252 | 
253 |         assert!(error.to_string().starts_with("vkFlushMappedMemoryRanges failed"));
254 |         assert_eq!(error.0, vk::VK_ERROR_UNKNOWN);
255 |     }
256 | }
257 | 
```

--------------------------------------------------------------------------------
/vkrunner/vkrunner/vulkan_funcs.rs:
--------------------------------------------------------------------------------

```rust
  1 | // vkrunner
  2 | //
  3 | // Copyright (C) 2016, 2023 Neil Roberts
  4 | // Copyright (C) 2018 Intel Corporation
  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::util;
 27 | use std::ffi::{c_void, c_int, c_char, CString};
 28 | use std::mem;
 29 | use std::fmt;
 30 | 
 31 | /// Offset of the pNext member of the structs that can be chained.
 32 | /// There doesn’t seem to be a nice equivalent to offsetof in Rust so
 33 | /// this is just trying to replicate the C struct alignment rules.
 34 | pub const NEXT_PTR_OFFSET: usize = util::align(
 35 |     mem::size_of::<vk::VkStructureType>(),
 36 |     mem::align_of::<*mut std::os::raw::c_void>(),
 37 | );
 38 | /// Offset of the first VkBool32 field in the features structs.
 39 | pub const FIRST_FEATURE_OFFSET: usize = util::align(
 40 |     NEXT_PTR_OFFSET + mem::size_of::<*mut std::os::raw::c_void>(),
 41 |     mem::align_of::<vk::VkBool32>(),
 42 | );
 43 | 
 44 | pub type GetInstanceProcFunc = unsafe extern "C" fn(
 45 |     func_name: *const c_char,
 46 |     user_data: *const c_void,
 47 | ) -> *const c_void;
 48 | 
 49 | #[derive(Debug)]
 50 | pub enum Error {
 51 |     OpenLibraryFailed(&'static str),
 52 | }
 53 | 
 54 | impl fmt::Display for Error {
 55 |     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
 56 |         match self {
 57 |             Error::OpenLibraryFailed(lib) => write!(f, "Error opening {}", lib)
 58 |         }
 59 |     }
 60 | }
 61 | 
 62 | include!{"vulkan_funcs_data.rs"}
 63 | 
 64 | struct LoaderFunc {
 65 |     lib_vulkan: *const c_void,
 66 |     lib_vulkan_is_fake: bool,
 67 |     get_instance_proc_addr: vk::PFN_vkGetInstanceProcAddr,
 68 | }
 69 | 
 70 | // Per-thread override for the get_instance_proc_address function.
 71 | // This is only used in unit tests to implement a fake Vulkan driver.
 72 | #[cfg(test)]
 73 | thread_local! {
 74 |     static LOADER_FUNC_OVERRIDE:
 75 |     std::cell::Cell<Option<LoaderFunc>> = std::cell::Cell::new(None);
 76 | }
 77 | 
 78 | impl Library {
 79 |     fn get_loader_func(
 80 |     ) -> Result<LoaderFunc, Error> {
 81 |         // Override for unit tests. If an override function is set
 82 |         // then we will return that instead. `take` is called on it so
 83 |         // that it will only be used once and subsequent calls will
 84 |         // revert back to the normal mechanism.
 85 |         #[cfg(test)]
 86 |         if let Some(loader_func) = LOADER_FUNC_OVERRIDE.with(|f| f.take()) {
 87 |             return Ok(loader_func);
 88 |         }
 89 | 
 90 |         #[cfg(unix)]
 91 |         {
 92 |             extern "C" {
 93 |                 fn dlopen(name: *const c_char, flags: c_int) -> *const c_void;
 94 |                 fn dlsym(
 95 |                     lib: *const c_void,
 96 |                     name: *const c_char
 97 |                 ) -> *const c_void;
 98 |             }
 99 | 
100 |             let lib_name;
101 | 
102 |             #[cfg(target_os = "android")]
103 |             {
104 |                 lib_name = "libvulkan.so";
105 |             }
106 |             #[cfg(not(target_os = "android"))]
107 |             {
108 |                 lib_name = "libvulkan.so.1";
109 |             }
110 | 
111 |             let lib_name_c = CString::new(lib_name).unwrap();
112 | 
113 |             let lib = unsafe {
114 |                 dlopen(lib_name_c.as_ptr(), 1)
115 |             };
116 | 
117 |             if lib.is_null() {
118 |                 return Err(Error::OpenLibraryFailed(lib_name));
119 |             }
120 | 
121 |             let get_instance_proc_addr = unsafe {
122 |                 std::mem::transmute(dlsym(
123 |                     lib,
124 |                     "vkGetInstanceProcAddr\0".as_ptr().cast()
125 |                 ))
126 |             };
127 | 
128 |             return Ok(LoaderFunc {
129 |                 lib_vulkan: lib,
130 |                 lib_vulkan_is_fake: false,
131 |                 get_instance_proc_addr
132 |             });
133 |         }
134 | 
135 |         #[cfg(windows)]
136 |         {
137 |             extern "system" {
138 |                 fn LoadLibraryA(
139 |                     filename: *const c_char,
140 |                 ) -> *mut c_void;
141 |                 fn GetProcAddress(
142 |                     handle: *mut c_void,
143 |                     func_name: *const c_char,
144 |                 ) -> *const c_void;
145 |             }
146 | 
147 |             let lib_name = "vulkan-1.dll";
148 | 
149 |             let lib = unsafe {
150 |                 let c_lib_name = CString::new(lib_name).unwrap();
151 |                 LoadLibraryA(c_lib_name.as_ptr())
152 |             };
153 | 
154 |             if lib.is_null() {
155 |                 return Err(Error::OpenLibraryFailed(lib_name));
156 |             }
157 | 
158 |             let get_instance_proc_addr = unsafe {
159 |                 std::mem::transmute(GetProcAddress(
160 |                     lib,
161 |                     "vkGetInstanceProcAddr\0".as_ptr().cast()
162 |                 ))
163 |             };
164 | 
165 |             return Ok(LoaderFunc {
166 |                 lib_vulkan: lib,
167 |                 lib_vulkan_is_fake: false,
168 |                 get_instance_proc_addr
169 |             });
170 |         }
171 | 
172 |         #[cfg(not(any(unix,windows)))]
173 |         todo!(
174 |             "library opening on platforms other than Unix and Windows is \
175 |              not yet implemented"
176 |         );
177 |     }
178 | 
179 |     pub fn new() -> Result<Library, Error> {
180 |         let LoaderFunc {
181 |             lib_vulkan,
182 |             lib_vulkan_is_fake,
183 |             get_instance_proc_addr,
184 |         } = Library::get_loader_func()?;
185 | 
186 |         Ok(Library {
187 |             lib_vulkan,
188 |             lib_vulkan_is_fake,
189 |             vkGetInstanceProcAddr: get_instance_proc_addr,
190 |             vkCreateInstance: unsafe {
191 |                 std::mem::transmute(get_instance_proc_addr.unwrap()(
192 |                     std::ptr::null_mut(),
193 |                     "vkCreateInstance\0".as_ptr().cast()
194 |                 ))
195 |             },
196 |             vkEnumerateInstanceExtensionProperties: unsafe {
197 |                 std::mem::transmute(get_instance_proc_addr.unwrap()(
198 |                     std::ptr::null_mut(),
199 |                     "vkEnumerateInstanceExtensionProperties\0".as_ptr().cast()
200 |                 ))
201 |             }
202 |         })
203 |     }
204 | }
205 | 
206 | impl Drop for Library {
207 |     fn drop(&mut self) {
208 |         #[cfg(unix)]
209 |         {
210 |             extern "C" {
211 |                 fn dlclose(lib: *const c_void) -> *const c_void;
212 |             }
213 | 
214 |             if !self.lib_vulkan_is_fake {
215 |                 unsafe { dlclose(self.lib_vulkan) };
216 |             }
217 |         }
218 | 
219 |         #[cfg(windows)]
220 |         {
221 |             extern "system" {
222 |                 fn FreeLibrary(handle: *const c_void) -> c_int;
223 |             }
224 | 
225 |             if !self.lib_vulkan_is_fake {
226 |                 unsafe { FreeLibrary(self.lib_vulkan) };
227 |             }
228 |         }
229 | 
230 |         #[cfg(not(any(unix,windows)))]
231 |         todo!(
232 |             "library closing on platforms other than Windows and Unix is not \
233 |              yet implemented"
234 |         );
235 |     }
236 | }
237 | 
238 | /// Helper function to temporarily replace the `vkGetInstanceProcAddr`
239 | /// function that will be used for the next call to [Library::new].
240 | /// The override will only be used once and subsequent calls to
241 | /// [Library::new] will revert back to trying to open the Vulkan
242 | /// library. The override is per-thread so it is safe to use in a
243 | /// multi-threaded testing environment. This function is only
244 | /// available in test build configs and it is intended to help make a
245 | /// fake Vulkan driver for unit tests.
246 | #[cfg(test)]
247 | pub fn override_get_instance_proc_addr(
248 |     lib: *const c_void,
249 |     proc: vk::PFN_vkGetInstanceProcAddr,
250 | ) {
251 |     LOADER_FUNC_OVERRIDE.with(|f| f.replace(Some(LoaderFunc {
252 |         lib_vulkan: lib,
253 |         lib_vulkan_is_fake: true,
254 |         get_instance_proc_addr: proc,
255 |     })));
256 | }
257 | 
```

--------------------------------------------------------------------------------
/vkrunner/vkrunner/logger.rs:
--------------------------------------------------------------------------------

```rust
  1 | // vkrunner
  2 | //
  3 | // Copyright 2023 Neil Roberts
  4 | //
  5 | // Permission is hereby granted, free of charge, to any person obtaining a
  6 | // copy of this software and associated documentation files (the "Software"),
  7 | // to deal in the Software without restriction, including without limitation
  8 | // the rights to use, copy, modify, merge, publish, distribute, sublicense,
  9 | // and/or sell copies of the Software, and to permit persons to whom the
 10 | // Software is furnished to do so, subject to the following conditions:
 11 | //
 12 | // The above copyright notice and this permission notice (including the next
 13 | // paragraph) shall be included in all copies or substantial portions of the
 14 | // Software.
 15 | //
 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 19 | // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 21 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 22 | // DEALINGS IN THE SOFTWARE.
 23 | 
 24 | use std::ffi::{c_char, c_void};
 25 | use std::fmt;
 26 | use std::io;
 27 | use std::str;
 28 | 
 29 | /// An object that log messages can be written to. Normally this will
 30 | /// just write the messages to standard out, but an application can
 31 | /// configure a C callback to receive the messages by tweaking the
 32 | /// [Config](crate::config::Config). The struct implements `Write` so
 33 | /// it can be used with macros like [write!](std::write).
 34 | #[derive(Debug)]
 35 | pub struct Logger {
 36 |     callback: Option<WriteCallback>,
 37 |     user_data: *mut c_void,
 38 | 
 39 |     // The data is collected into this buffer until we have a complete
 40 |     // line to send to the callback.
 41 |     buf: Vec<u8>,
 42 | 
 43 |     // True if the any data was added from a u8 slice so it might not
 44 |     // be valid UTF-8.
 45 |     maybe_invalid_utf8: bool,
 46 | }
 47 | 
 48 | /// A callback to use to write the data to instead of writing to
 49 | /// stdout. This will be called one line at a time. Each line will be
 50 | /// terminated the C null terminator but no newlines. It will always
 51 | /// be valid UTF-8.
 52 | pub type WriteCallback = extern "C" fn(
 53 |     message: *const c_char,
 54 |     user_data: *mut c_void,
 55 | );
 56 | 
 57 | impl Logger {
 58 |     /// Construct a new logger that will write to the given callback.
 59 |     /// If the callback is `None` then the log will go to the stdout
 60 |     /// instead. `user_data` will be passed to the callback. You can
 61 |     /// pass [`ptr::null_mut()`](std::ptr::null_mut) if there is no
 62 |     /// callback.
 63 |     pub fn new(
 64 |         callback: Option<WriteCallback>,
 65 |         user_data: *mut c_void
 66 |     ) -> Logger {
 67 |         Logger {
 68 |             callback,
 69 |             user_data,
 70 |             maybe_invalid_utf8: false,
 71 | 
 72 |             buf: Vec::new(),
 73 |         }
 74 |     }
 75 | 
 76 |     fn send_range(&mut self, start: usize, end: usize) {
 77 |         if self.maybe_invalid_utf8 {
 78 |             let mut pos = start;
 79 | 
 80 |             loop {
 81 |                 match str::from_utf8(&self.buf[pos..end]) {
 82 |                     Ok(_) => break,
 83 |                     Err(e) => {
 84 |                         // Replace the offending byte with a question
 85 |                         // mark. This should result in valid UTF-8
 86 |                         // without having to move the bytes around.
 87 |                         self.buf[pos + e.valid_up_to()] = b'?';
 88 |                         pos += e.valid_up_to() + 1;
 89 |                     },
 90 |                 }
 91 |             }
 92 |         }
 93 | 
 94 |         match self.callback {
 95 |             Some(callback) => {
 96 |                 // Add the C null terminator. This method should be
 97 |                 // called knowing that the zero will be set at `end`
 98 |                 // so it should have ensured the buffer is large
 99 |                 // enough.
100 |                 self.buf[end] = 0;
101 | 
102 |                 callback(
103 |                     self.buf[start..end + 1].as_ptr().cast(),
104 |                     self.user_data
105 |                 );
106 |             },
107 |             None => {
108 |                 // SAFETY: We just ensured that the range is valid
109 |                 // UTF-8 above.
110 |                 let s = unsafe {
111 |                     str::from_utf8_unchecked(&self.buf[start..end])
112 |                 };
113 |                 println!("{}", s);
114 |             },
115 |         }
116 |     }
117 | 
118 |     fn flush_lines(&mut self) {
119 |         let mut pos = 0;
120 | 
121 |         while let Some(line_len) = self.buf[pos..]
122 |             .into_iter()
123 |             .position(|&c| c == b'\n')
124 |         {
125 |             self.send_range(pos, pos + line_len);
126 |             pos += line_len + 1;
127 |         }
128 | 
129 |         // Remove the lines that we successfully processed
130 |         self.buf.drain(0..pos);
131 | 
132 |         if self.buf.is_empty() {
133 |             self.maybe_invalid_utf8 = false;
134 |         }
135 |     }
136 | }
137 | 
138 | impl io::Write for Logger {
139 |     fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
140 |         if !buf.is_empty() {
141 |             self.maybe_invalid_utf8 = true;
142 |             self.buf.extend_from_slice(buf);
143 |             self.flush_lines();
144 |         }
145 | 
146 |         Ok(buf.len())
147 |     }
148 | 
149 |     fn flush(&mut self) -> io::Result<()> {
150 |         if !self.buf.is_empty() {
151 |             let old_len = self.buf.len();
152 | 
153 |             // Make sure there is enough space for the null terminator
154 |             // to be added
155 |             self.buf.push(0);
156 | 
157 |             self.send_range(0, old_len);
158 |             self.buf.clear();
159 |         }
160 | 
161 |         Ok(())
162 |     }
163 | }
164 | 
165 | impl fmt::Write for Logger {
166 |     fn write_str(&mut self, s: &str) -> Result<(), fmt::Error> {
167 |         self.buf.extend_from_slice(s.as_bytes());
168 |         self.flush_lines();
169 |         Ok(())
170 |     }
171 | }
172 | 
173 | #[cfg(test)]
174 | mod test {
175 |     use super::*;
176 |     use std::ffi::CStr;
177 | 
178 |     struct TestLogger {
179 |         logger: Logger,
180 |         items: Vec<String>,
181 |     }
182 | 
183 |     extern "C" fn log_item_cb(message: *const c_char, user_data: *mut c_void) {
184 |         let logger = unsafe {
185 |             &mut *(user_data as *mut TestLogger)
186 |         };
187 | 
188 |         let message = unsafe { CStr::from_ptr(message.cast()) };
189 |         logger.items.push(message.to_str().unwrap().to_string());
190 |     }
191 | 
192 |     fn test_logger() -> Box<TestLogger> {
193 |         // Need to box the logger so we can pass a pointer to it in
194 |         // the logging callback
195 |         let mut logger = Box::new(TestLogger {
196 |             logger: Logger::new(None, std::ptr::null_mut()),
197 |             items: Vec::new(),
198 |         });
199 | 
200 |         logger.logger = Logger::new(
201 |             Some(log_item_cb),
202 |             logger.as_mut() as *mut TestLogger as *mut c_void,
203 |         );
204 | 
205 |         logger
206 |     }
207 | 
208 |     #[test]
209 |     fn multiple_lines() {
210 |         let mut logger = test_logger();
211 | 
212 |         use std::fmt::Write;
213 | 
214 |         writeln!(
215 |             &mut logger.logger,
216 |             "This is a line\n\
217 |              This is another line.\n\
218 |              This is followed by a number: {}",
219 |             42,
220 |         ).unwrap();
221 | 
222 |         assert_eq!(logger.items.len(), 3);
223 |         assert_eq!(logger.items[0], "This is a line");
224 |         assert_eq!(logger.items[1], "This is another line.");
225 |         assert_eq!(logger.items[2], "This is followed by a number: 42");
226 |     }
227 | 
228 |     #[test]
229 |     fn split_line() {
230 |         let mut logger = test_logger();
231 | 
232 |         use std::fmt::Write;
233 | 
234 |         write!(&mut logger.logger, "Part of first line ").unwrap();
235 |         assert_eq!(logger.items.len(), 0);
236 |         write!(
237 |             &mut logger.logger,
238 |             "next part of first line\nSecond line\n"
239 |         ).unwrap();
240 |         assert_eq!(logger.items.len(), 2);
241 |         assert_eq!(
242 |             logger.items[0],
243 |             "Part of first line next part of first line",
244 |         );
245 |         assert_eq!(logger.items[1], "Second line");
246 |     }
247 | 
248 |     #[test]
249 |     fn bad_utf8() {
250 |         let mut logger = test_logger();
251 | 
252 |         use std::io::Write;
253 | 
254 |         logger.logger.write(
255 |             b"\xc4u ne mankas bajtoj \xc4\x89i tie \xe2\n"
256 |         ).unwrap();
257 |         assert_eq!(logger.items.len(), 1);
258 |         assert_eq!(logger.items[0], "?u ne mankas bajtoj ĉi tie ?");
259 |     }
260 | 
261 |     #[test]
262 |     fn flush() {
263 |         let mut logger = test_logger();
264 | 
265 |         use std::fmt::Write;
266 | 
267 |         write!(&mut logger.logger, "One line\nUnterminated line").unwrap();
268 |         assert_eq!(logger.items.len(), 1);
269 |         assert_eq!(logger.items[0], "One line");
270 | 
271 |         io::Write::flush(&mut logger.logger).unwrap();
272 | 
273 |         assert_eq!(logger.items.len(), 2);
274 |         assert_eq!(logger.items[1], "Unterminated line");
275 | 
276 |         assert!(logger.logger.buf.is_empty());
277 | 
278 |         io::Write::flush(&mut logger.logger).unwrap();
279 | 
280 |         assert_eq!(logger.items.len(), 2);
281 |     }
282 | }
283 | 
```

--------------------------------------------------------------------------------
/vkrunner/vkrunner/parse_num.rs:
--------------------------------------------------------------------------------

```rust
  1 | // Copyright 2023 Neil Roberts
  2 | //
  3 | // Permission is hereby granted, free of charge, to any person obtaining a
  4 | // copy of this software and associated documentation files (the "Software"),
  5 | // to deal in the Software without restriction, including without limitation
  6 | // on the rights to use, copy, modify, merge, publish, distribute, sub
  7 | // license, and/or sell copies of the Software, and to permit persons to whom
  8 | // the Software is furnished to do so, subject to the following conditions:
  9 | //
 10 | // The above copyright notice and this permission notice (including the next
 11 | // paragraph) shall be included in all copies or substantial portions of the
 12 | // Software.
 13 | //
 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.  IN NO EVENT SHALL
 17 | // VA LINUX SYSTEM, IBM AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
 18 | // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
 19 | // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
 20 | // USE OR OTHER DEALINGS IN THE SOFTWARE.
 21 | 
 22 | use std::num::ParseIntError;
 23 | use std::fmt;
 24 | 
 25 | #[derive(Debug, PartialEq)]
 26 | pub enum ParseError {
 27 |     // The negative sign was used in an unsigned number type
 28 |     NegativeError,
 29 |     // A number that would be valid in an unsigned type overflows the
 30 |     // signed type
 31 |     SignedOverflow,
 32 |     // Any other error returned by the from_str_radix function
 33 |     Other(ParseIntError),
 34 | }
 35 | 
 36 | impl fmt::Display for ParseError {
 37 |     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
 38 |         match self {
 39 |             ParseError::NegativeError => write!(f, "Number can’t be negated"),
 40 |             ParseError::SignedOverflow => {
 41 |                 write!(f, "Number out of range for type")
 42 |             },
 43 |             ParseError::Other(e) => e.fmt(f),
 44 |         }
 45 |     }
 46 | }
 47 | 
 48 | impl From<ParseIntError> for ParseError {
 49 |     fn from(e: ParseIntError) -> ParseError {
 50 |         ParseError::Other(e)
 51 |     }
 52 | }
 53 | 
 54 | struct NumAnalysis<'a> {
 55 |     negative: bool,
 56 |     radix: u32,
 57 |     num_part: &'a str,
 58 |     tail: &'a str,
 59 | }
 60 | 
 61 | fn is_octal_prefix(prefix: &str) -> bool {
 62 |     prefix.starts_with("0")
 63 |         && prefix.len() > 1
 64 |         && prefix.as_bytes()[1].is_ascii_digit()
 65 | }
 66 | 
 67 | fn analyse_num(mut s: &str) -> NumAnalysis {
 68 |     // skip only ASCII spaces and tabs
 69 |     while !s.is_empty() &&
 70 |         (s.as_bytes()[0] == b' ' || s.as_bytes()[0] == b'\t')
 71 |     {
 72 |         s = &s[1..];
 73 |     }
 74 | 
 75 |     // Optional sign
 76 |     let (prefix_start, negative) = match s.chars().next() {
 77 |         Some('-') => (1, true),
 78 |         Some('+') => (1, false),
 79 |         _ => (0, false),
 80 |     };
 81 | 
 82 |     let prefix = &s[prefix_start..];
 83 | 
 84 |     let (radix, num_start) = if prefix.starts_with("0x") {
 85 |         (16, 2)
 86 |     } else if is_octal_prefix(prefix) {
 87 |         (8, 1)
 88 |     } else {
 89 |         (10, 0)
 90 |     };
 91 | 
 92 |     let num_start = &prefix[num_start..];
 93 | 
 94 |     let split_point = num_start
 95 |         .chars()
 96 |         .take_while(|c| c.is_ascii_hexdigit())
 97 |         .count();
 98 | 
 99 |     NumAnalysis {
100 |         negative,
101 |         radix,
102 |         num_part: &num_start[0..split_point],
103 |         tail: &num_start[split_point..],
104 |     }
105 | }
106 | 
107 | // Macro to create a function to parse an unsigned int type. These are
108 | // needed because there doesn’t seem to be an equivalent to strtoul in
109 | // rust where the radix can be zero. The regular parse function also
110 | // doesn’t return a tail pointer.
111 | macro_rules! parse_unsigned {
112 |     ($func:ident, $t:ident) => {
113 |         pub fn $func(s: &str) -> Result<($t, &str), ParseError> {
114 |             let analysis = analyse_num(s);
115 | 
116 |             let num = $t::from_str_radix(analysis.num_part, analysis.radix)?;
117 | 
118 |             if analysis.negative {
119 |                 Err(ParseError::NegativeError)
120 |             } else {
121 |                 Ok((num, analysis.tail))
122 |             }
123 |         }
124 |     }
125 | }
126 | 
127 | // Macro to create a function to parse a signed int type. These are
128 | // needed because there doesn’t seem to be an equivalent to strtol in
129 | // rust where the radix can be zero. The regular parse function also
130 | // doesn’t return a tail pointer.
131 | macro_rules! parse_signed {
132 |     ($func:ident, $st:ident, $ut:ident) => {
133 |         pub fn $func(s: &str) -> Result<($st, &str), ParseError> {
134 |             let analysis = analyse_num(s);
135 | 
136 |             let num = $ut::from_str_radix(analysis.num_part, analysis.radix)?;
137 | 
138 |             if analysis.negative {
139 |                 if num > $st::MAX as $ut + 1 {
140 |                     Err(ParseError::SignedOverflow)
141 |                 } else {
142 |                     // We have an unsigned value that we need to
143 |                     // negate. We can’t just cast it to signed and
144 |                     // then negate it because the MIN value is not
145 |                     // representable as a positive value in the signed
146 |                     // type. Instead we do the trick of !x+1 to
147 |                     // negate while staying in the unsigned type.
148 |                     Ok(((!num).wrapping_add(1) as $st, analysis.tail))
149 |                 }
150 |             } else {
151 |                 if num > $st::MAX as $ut {
152 |                     Err(ParseError::SignedOverflow)
153 |                 } else {
154 |                     Ok((num as $st, analysis.tail))
155 |                 }
156 |             }
157 |         }
158 |     }
159 | }
160 | 
161 | parse_unsigned!(parse_u64, u64);
162 | parse_unsigned!(parse_u32, u32);
163 | parse_unsigned!(parse_u16, u16);
164 | parse_unsigned!(parse_u8, u8);
165 | parse_signed!(parse_i64, i64, u64);
166 | parse_signed!(parse_i32, i32, u32);
167 | parse_signed!(parse_i16, i16, u16);
168 | parse_signed!(parse_i8, i8, u8);
169 | 
170 | #[cfg(test)]
171 | mod test {
172 |     use super::*;
173 | 
174 |     #[test]
175 |     fn test_unsigned() {
176 |         assert_eq!(
177 |             parse_u64(&u64::MAX.to_string()).unwrap(),
178 |             (u64::MAX, ""),
179 |         );
180 |         assert_eq!(
181 |             parse_u32(&u32::MAX.to_string()).unwrap(),
182 |             (u32::MAX, ""),
183 |         );
184 |         assert_eq!(
185 |             parse_u16(&u16::MAX.to_string()).unwrap(),
186 |             (u16::MAX, ""),
187 |         );
188 |         assert_eq!(
189 |             parse_u8(&u8::MAX.to_string()).unwrap(),
190 |             (u8::MAX, ""),
191 |         );
192 | 
193 |         assert!(matches!(parse_u8("-1"), Err(ParseError::NegativeError)));
194 |         assert!(matches!(parse_u8("-0"), Err(ParseError::NegativeError)));
195 | 
196 |         assert!(matches!(
197 |             parse_u8("256"),
198 |             Err(ParseError::Other(ParseIntError { .. })),
199 |         ));
200 | 
201 |         assert_eq!(
202 |             parse_i8("  0 12"),
203 |             Ok((0, " 12")),
204 |         );
205 | 
206 |         assert_eq!(
207 |             parse_u8("   0x42  after"),
208 |             Ok((66, "  after")),
209 |         );
210 |         assert_eq!(
211 |             parse_u32("   0xaBCdef01  after"),
212 |             Ok((0xabcdef01, "  after")),
213 |         );
214 |         assert_eq!(
215 |             parse_u32("   0xffgoat"),
216 |             Ok((255, "goat")),
217 |         );
218 |         assert_eq!(
219 |             parse_u32(" \t  0100  after"),
220 |             Ok((64, "  after")),
221 |         );
222 |     }
223 | 
224 |     #[test]
225 |     fn test_signed() {
226 |         assert_eq!(
227 |             parse_i64(&i64::MAX.to_string()).unwrap(),
228 |             (i64::MAX, ""),
229 |         );
230 |         assert_eq!(
231 |             parse_i32(&i32::MAX.to_string()).unwrap(),
232 |             (i32::MAX, ""),
233 |         );
234 |         assert_eq!(
235 |             parse_i16(&i16::MAX.to_string()).unwrap(),
236 |             (i16::MAX, ""),
237 |         );
238 |         assert_eq!(
239 |             parse_i8(&i8::MAX.to_string()).unwrap(),
240 |             (i8::MAX, ""),
241 |         );
242 |         assert_eq!(
243 |             parse_i64(&i64::MIN.to_string()).unwrap(),
244 |             (i64::MIN, ""),
245 |         );
246 |         assert_eq!(
247 |             parse_i32(&i32::MIN.to_string()).unwrap(),
248 |             (i32::MIN, ""),
249 |         );
250 |         assert_eq!(
251 |             parse_i16(&i16::MIN.to_string()).unwrap(),
252 |             (i16::MIN, ""),
253 |         );
254 |         assert_eq!(
255 |             parse_i8(&i8::MIN.to_string()).unwrap(),
256 |             (i8::MIN, ""),
257 |         );
258 | 
259 |         assert_eq!(
260 |             parse_i8("-0"),
261 |             Ok((0, "")),
262 |         );
263 | 
264 |         assert_eq!(
265 |             parse_i8("  -0 0"),
266 |             Ok((0, " 0")),
267 |         );
268 | 
269 |         assert!(matches!(
270 |             parse_i8("128"),
271 |             Err(ParseError::SignedOverflow),
272 |         ));
273 |         assert!(matches!(
274 |             parse_i8("-129"),
275 |             Err(ParseError::SignedOverflow),
276 |         ));
277 | 
278 |         assert_eq!(
279 |             parse_i8("   0x42  after"),
280 |             Ok((66, "  after")),
281 |         );
282 |         assert_eq!(
283 |             parse_i32(" \t  0100  after"),
284 |             Ok((64, "  after")),
285 |         );
286 |         assert_eq!(
287 |             parse_i8("   -0x42  after"),
288 |             Ok((-66, "  after")),
289 |         );
290 |         assert_eq!(
291 |             parse_i32(" \t  -0100  after"),
292 |             Ok((-64, "  after")),
293 |         );
294 |     }
295 | }
296 | 
```

--------------------------------------------------------------------------------
/.github/workflows/build-push-image.yml:
--------------------------------------------------------------------------------

```yaml
  1 | name: Build and Push Image
  2 | 
  3 | on:
  4 |   push:
  5 |     branches: [main]
  6 |   workflow_dispatch:
  7 | 
  8 | jobs:
  9 |   prepare:
 10 |     name: Prepare Build Environment
 11 |     runs-on: ubuntu-latest
 12 |     outputs:
 13 |       repo_name: ${{ steps.meta.outputs.repo_name }}
 14 |       short_sha: ${{ steps.meta.outputs.short_sha }}
 15 |     steps:
 16 |       - name: Extract metadata
 17 |         id: meta
 18 |         run: |
 19 |           echo "repo_name=$(echo ${{ github.repository }} | tr '[:upper:]' '[:lower:]')" >> $GITHUB_OUTPUT
 20 |           echo "short_sha=$(echo ${{ github.sha }} | cut -c1-7)" >> $GITHUB_OUTPUT
 21 | 
 22 |   build-amd64:
 23 |     name: Build for amd64
 24 |     needs: prepare
 25 |     runs-on: ubuntu-24.04
 26 |     permissions:
 27 |       contents: read
 28 |       packages: write
 29 |     steps:
 30 |       - name: Checkout repository
 31 |         uses: actions/checkout@v4
 32 | 
 33 |       - name: Set up Docker Buildx
 34 |         uses: docker/setup-buildx-action@v3
 35 | 
 36 |       - name: Login to GitHub Container Registry
 37 |         if: github.event_name != 'pull_request'
 38 |         uses: docker/login-action@v3
 39 |         with:
 40 |           registry: ghcr.io
 41 |           username: ${{ github.actor }}
 42 |           password: ${{ secrets.GITHUB_TOKEN }}
 43 | 
 44 |       - name: Build and push amd64 image
 45 |         uses: docker/build-push-action@v5
 46 |         with:
 47 |           context: .
 48 |           push: ${{ github.event_name != 'pull_request' }}
 49 |           platforms: linux/amd64
 50 |           tags: |
 51 |             ghcr.io/${{ needs.prepare.outputs.repo_name }}:amd64-latest
 52 |             ghcr.io/${{ needs.prepare.outputs.repo_name }}:amd64-${{ needs.prepare.outputs.short_sha }}
 53 |           labels: |
 54 |             org.opencontainers.image.source=https://github.com/${{ github.repository }}
 55 |             org.opencontainers.image.revision=${{ github.sha }}
 56 |             org.opencontainers.image.description=Docker image for amd64
 57 |           cache-from: type=gha
 58 |           cache-to: type=gha,mode=max
 59 | 
 60 |   build-arm64:
 61 |     name: Build for arm64
 62 |     needs: prepare
 63 |     runs-on: ubuntu-24.04-arm
 64 |     permissions:
 65 |       contents: read
 66 |       packages: write
 67 |     steps:
 68 |       - name: Checkout repository
 69 |         uses: actions/checkout@v4
 70 | 
 71 |       - name: Set up Docker Buildx
 72 |         uses: docker/setup-buildx-action@v3
 73 | 
 74 |       - name: Login to GitHub Container Registry
 75 |         if: github.event_name != 'pull_request'
 76 |         uses: docker/login-action@v3
 77 |         with:
 78 |           registry: ghcr.io
 79 |           username: ${{ github.actor }}
 80 |           password: ${{ secrets.GITHUB_TOKEN }}
 81 | 
 82 |       - name: Build and push arm64 image
 83 |         uses: docker/build-push-action@v5
 84 |         with:
 85 |           context: .
 86 |           push: ${{ github.event_name != 'pull_request' }}
 87 |           platforms: linux/arm64
 88 |           tags: |
 89 |             ghcr.io/${{ needs.prepare.outputs.repo_name }}:arm64-latest
 90 |             ghcr.io/${{ needs.prepare.outputs.repo_name }}:arm64-${{ needs.prepare.outputs.short_sha }}
 91 |           labels: |
 92 |             org.opencontainers.image.source=https://github.com/${{ github.repository }}
 93 |             org.opencontainers.image.revision=${{ github.sha }}
 94 |             org.opencontainers.image.description=Docker image for arm64
 95 |           cache-from: type=gha
 96 |           cache-to: type=gha,mode=max
 97 | 
 98 |   build-riscv64:
 99 |     if: false # Needs hosted runner
100 |     name: Build for riscv64
101 |     needs: prepare
102 |     runs-on: ubuntu-latest
103 |     permissions:
104 |       contents: read
105 |       packages: write
106 |     steps:
107 |       - name: Checkout repository
108 |         uses: actions/checkout@v4
109 | 
110 |       - name: Set up QEMU
111 |         uses: docker/setup-qemu-action@v3
112 | 
113 |       - name: Set up Docker Buildx
114 |         uses: docker/setup-buildx-action@v3
115 | 
116 |       - name: Login to GitHub Container Registry
117 |         if: github.event_name != 'pull_request'
118 |         uses: docker/login-action@v3
119 |         with:
120 |           registry: ghcr.io
121 |           username: ${{ github.actor }}
122 |           password: ${{ secrets.GITHUB_TOKEN }}
123 | 
124 |       - name: Build and push riscv64 image
125 |         id: build_riscv64
126 |         continue-on-error: true
127 |         uses: docker/build-push-action@v5
128 |         with:
129 |           context: .
130 |           push: ${{ github.event_name != 'pull_request' }}
131 |           platforms: linux/riscv64
132 |           tags: |
133 |             ghcr.io/${{ needs.prepare.outputs.repo_name }}:riscv64-latest
134 |             ghcr.io/${{ needs.prepare.outputs.repo_name }}:riscv64-${{ needs.prepare.outputs.short_sha }}
135 |           labels: |
136 |             org.opencontainers.image.source=https://github.com/${{ github.repository }}
137 |             org.opencontainers.image.revision=${{ github.sha }}
138 |             org.opencontainers.image.description=Docker image for riscv64
139 |           cache-from: type=gha
140 |           cache-to: type=gha,mode=max
141 | 
142 |       - name: Set build status
143 |         id: status
144 |         run: echo "success=${{ steps.build_riscv64.outcome == 'success' }}" >> $GITHUB_OUTPUT
145 | 
146 |     outputs:
147 |       success: ${{ steps.status.outputs.success }}
148 | 
149 |   build-ppc64le:
150 |     if: false # Needs hosted runner
151 |     name: Build for ppc64le
152 |     needs: prepare
153 |     runs-on: ubuntu-latest
154 |     permissions:
155 |       contents: read
156 |       packages: write
157 |     steps:
158 |       - name: Checkout repository
159 |         uses: actions/checkout@v4
160 | 
161 |       - name: Set up QEMU
162 |         uses: docker/setup-qemu-action@v3
163 | 
164 |       - name: Set up Docker Buildx
165 |         uses: docker/setup-buildx-action@v3
166 | 
167 |       - name: Login to GitHub Container Registry
168 |         if: github.event_name != 'pull_request'
169 |         uses: docker/login-action@v3
170 |         with:
171 |           registry: ghcr.io
172 |           username: ${{ github.actor }}
173 |           password: ${{ secrets.GITHUB_TOKEN }}
174 | 
175 |       - name: Build and push ppc64le image
176 |         id: build_ppc64le
177 |         continue-on-error: true
178 |         uses: docker/build-push-action@v5
179 |         with:
180 |           context: .
181 |           push: ${{ github.event_name != 'pull_request' }}
182 |           platforms: linux/ppc64le
183 |           tags: |
184 |             ghcr.io/${{ needs.prepare.outputs.repo_name }}:ppc64le-latest
185 |             ghcr.io/${{ needs.prepare.outputs.repo_name }}:ppc64le-${{ needs.prepare.outputs.short_sha }}
186 |           labels: |
187 |             org.opencontainers.image.source=https://github.com/${{ github.repository }}
188 |             org.opencontainers.image.revision=${{ github.sha }}
189 |             org.opencontainers.image.description=Docker image for ppc64le
190 |           cache-from: type=gha
191 |           cache-to: type=gha,mode=max
192 | 
193 |       - name: Set build status
194 |         id: status
195 |         run: echo "success=${{ steps.build_ppc64le.outcome == 'success' }}" >> $GITHUB_OUTPUT
196 | 
197 |     outputs:
198 |       success: ${{ steps.status.outputs.success }}
199 | 
200 |   create-manifest:
201 |     name: Create Multi-Arch Manifest
202 |     needs: [prepare, build-amd64, build-arm64] # [build-riscv64, build-ppc64le]
203 |     runs-on: ubuntu-latest
204 |     permissions:
205 |       contents: read
206 |       packages: write
207 |     if: github.event_name != 'pull_request'
208 |     steps:
209 |       - name: Login to GitHub Container Registry
210 |         uses: docker/login-action@v3
211 |         with:
212 |           registry: ghcr.io
213 |           username: ${{ github.actor }}
214 |           password: ${{ secrets.GITHUB_TOKEN }}
215 | 
216 |       - name: Set up Docker Buildx
217 |         uses: docker/setup-buildx-action@v3
218 | 
219 |       - name: Create and push multi-arch manifests
220 |         run: |
221 | 
222 |           LATEST_SOURCES="ghcr.io/${{ needs.prepare.outputs.repo_name }}:amd64-latest"
223 |           SHA_SOURCES="ghcr.io/${{ needs.prepare.outputs.repo_name }}:amd64-${{ needs.prepare.outputs.short_sha }}"
224 | 
225 | 
226 |           # if [ "${{ needs.build-arm64.outputs.success }}" == "true" ]; then
227 |           #   LATEST_SOURCES="${LATEST_SOURCES} ghcr.io/${{ needs.prepare.outputs.repo_name }}:arm64-latest"
228 |           #   SHA_SOURCES="${SHA_SOURCES} ghcr.io/${{ needs.prepare.outputs.repo_name }}:arm64-${{ needs.prepare.outputs.short_sha }}"
229 |           # fi
230 | 
231 | 
232 |           # if [ "${{ needs.build-riscv64.outputs.success }}" == "true" ]; then
233 |           #   LATEST_SOURCES="${LATEST_SOURCES} ghcr.io/${{ needs.prepare.outputs.repo_name }}:riscv64-latest"
234 |           #   SHA_SOURCES="${SHA_SOURCES} ghcr.io/${{ needs.prepare.outputs.repo_name }}:riscv64-${{ needs.prepare.outputs.short_sha }}"
235 |           # fi
236 | 
237 |           # if [ "${{ needs.build-ppc64le.outputs.success }}" == "true" ]; then
238 |           #   LATEST_SOURCES="${LATEST_SOURCES} ghcr.io/${{ needs.prepare.outputs.repo_name }}:ppc64le-latest"
239 |           #   SHA_SOURCES="${SHA_SOURCES} ghcr.io/${{ needs.prepare.outputs.repo_name }}:ppc64le-${{ needs.prepare.outputs.short_sha }}"
240 |           # fi
241 | 
242 | 
243 |           echo "Creating latest manifest from: ${LATEST_SOURCES}"
244 |           docker buildx imagetools create --tag ghcr.io/${{ needs.prepare.outputs.repo_name }}:latest ${LATEST_SOURCES}
245 | 
246 | 
247 |           echo "Creating SHA manifest from: ${SHA_SOURCES}"
248 |           docker buildx imagetools create --tag ghcr.io/${{ needs.prepare.outputs.repo_name }}:${{ needs.prepare.outputs.short_sha }} ${SHA_SOURCES}
249 | 
```

--------------------------------------------------------------------------------
/vkrunner/vkrunner/allocate_store.rs:
--------------------------------------------------------------------------------

```rust
  1 | // vkrunner
  2 | //
  3 | // Copyright (C) 2016, 2017, 2023 Neil Roberts
  4 | //
  5 | // Permission is hereby granted, free of charge, to any person obtaining a
  6 | // copy of this software and associated documentation files (the "Software"),
  7 | // to deal in the Software without restriction, including without limitation
  8 | // the rights to use, copy, modify, merge, publish, distribute, sublicense,
  9 | // and/or sell copies of the Software, and to permit persons to whom the
 10 | // Software is furnished to do so, subject to the following conditions:
 11 | //
 12 | // The above copyright notice and this permission notice (including the next
 13 | // paragraph) shall be included in all copies or substantial portions of the
 14 | // Software.
 15 | //
 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 19 | // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 21 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 22 | // DEALINGS IN THE SOFTWARE.
 23 | 
 24 | //! Helper functions for allocating Vulkan device memory for a buffer
 25 | //! or an image.
 26 | 
 27 | use crate::context::Context;
 28 | use crate::vk;
 29 | use std::ptr;
 30 | 
 31 | fn find_memory_type(
 32 |     context: &Context,
 33 |     mut usable_memory_types: u32,
 34 |     memory_type_flags: vk::VkMemoryPropertyFlags,
 35 | ) -> Result<u32, String> {
 36 |     let memory_properties = context.memory_properties();
 37 | 
 38 |     while usable_memory_types != 0 {
 39 |         let memory_type = usable_memory_types.trailing_zeros();
 40 | 
 41 |         if memory_properties.memoryTypes[memory_type as usize].propertyFlags
 42 |             & memory_type_flags
 43 |             == memory_type_flags
 44 |         {
 45 |             return Ok(memory_type);
 46 |         }
 47 | 
 48 |         usable_memory_types &= !(1 << memory_type);
 49 |     }
 50 | 
 51 |     Err("Couldn’t find suitable memory type to allocate buffer".to_string())
 52 | }
 53 | 
 54 | fn allocate_memory(
 55 |     context: &Context,
 56 |     reqs: &vk::VkMemoryRequirements,
 57 |     memory_type_flags: vk::VkMemoryPropertyFlags,
 58 | ) -> Result<(vk::VkDeviceMemory, u32), String> {
 59 |     let memory_type_index = find_memory_type(
 60 |         context,
 61 |         reqs.memoryTypeBits,
 62 |         memory_type_flags,
 63 |     )?;
 64 | 
 65 |     let mut memory = vk::null_handle();
 66 | 
 67 |     let allocate_info = vk::VkMemoryAllocateInfo {
 68 |         sType: vk::VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
 69 |         pNext: ptr::null(),
 70 |         allocationSize: reqs.size,
 71 |         memoryTypeIndex: memory_type_index,
 72 |     };
 73 |     let res = unsafe {
 74 |         context.device().vkAllocateMemory.unwrap()(
 75 |             context.vk_device(),
 76 |             ptr::addr_of!(allocate_info),
 77 |             ptr::null(), // allocator
 78 |             ptr::addr_of_mut!(memory),
 79 |         )
 80 |     };
 81 |     if res == vk::VK_SUCCESS {
 82 |         Ok((memory, memory_type_index))
 83 |     } else {
 84 |         Err("vkAllocateMemory failed".to_string())
 85 |     }
 86 | }
 87 | 
 88 | /// Allocate Vulkan device memory for the given buffer. It will pick
 89 | /// the right memory type by querying the device for the memory
 90 | /// requirements of the buffer. You can also limit the memory types
 91 | /// further by specifying extra flags in `memory_type_flags`. A handle
 92 | /// to the newly allocate device memory will be returned along with an
 93 | /// index representing the chosen memory type.
 94 | ///
 95 | /// If the allocation fails a `String` will be returned describing the
 96 | /// error.
 97 | pub fn allocate_buffer(
 98 |     context: &Context,
 99 |     memory_type_flags: vk::VkMemoryPropertyFlags,
100 |     buffer: vk::VkBuffer,
101 | ) -> Result<(vk::VkDeviceMemory, u32), String> {
102 |     let vkdev = context.device();
103 | 
104 |     let mut reqs = vk::VkMemoryRequirements::default();
105 | 
106 |     unsafe {
107 |         vkdev.vkGetBufferMemoryRequirements.unwrap()(
108 |             context.vk_device(),
109 |             buffer,
110 |             ptr::addr_of_mut!(reqs),
111 |         );
112 |     }
113 | 
114 |     let (memory, memory_type_index) =
115 |         allocate_memory(context, &reqs, memory_type_flags)?;
116 | 
117 |     unsafe {
118 |         vkdev.vkBindBufferMemory.unwrap()(
119 |             context.vk_device(),
120 |             buffer,
121 |             memory,
122 |             0, // memoryOffset
123 |         );
124 |     }
125 | 
126 |     Ok((memory, memory_type_index))
127 | }
128 | 
129 | /// Allocate Vulkan device memory for the given image. It will pick
130 | /// the right memory type by querying the device for the memory
131 | /// requirements of the image. You can also limit the memory types
132 | /// further by specifying extra flags in `memory_type_flags`. A handle
133 | /// to the newly allocate device memory will be returned along with an
134 | /// index representing the chosen memory type.
135 | ///
136 | /// If the allocation fails a `String` will be returned describing the
137 | /// error.
138 | pub fn allocate_image(
139 |     context: &Context,
140 |     memory_type_flags: vk::VkMemoryPropertyFlags,
141 |     image: vk::VkImage,
142 | ) -> Result<(vk::VkDeviceMemory, u32), String> {
143 |     let vkdev = context.device();
144 | 
145 |     let mut reqs = vk::VkMemoryRequirements::default();
146 | 
147 |     unsafe {
148 |         vkdev.vkGetImageMemoryRequirements.unwrap()(
149 |             context.vk_device(),
150 |             image,
151 |             ptr::addr_of_mut!(reqs),
152 |         );
153 |     }
154 | 
155 |     let (memory, memory_type_index) =
156 |         allocate_memory(context, &reqs, memory_type_flags)?;
157 | 
158 |     unsafe {
159 |         vkdev.vkBindImageMemory.unwrap()(
160 |             context.vk_device(),
161 |             image,
162 |             memory,
163 |             0, // memoryOffset
164 |         );
165 |     }
166 | 
167 |     Ok((memory, memory_type_index))
168 | }
169 | 
170 | #[cfg(test)]
171 | mod test {
172 |     use super::*;
173 |     use crate::fake_vulkan::{FakeVulkan, HandleType};
174 |     use crate::requirements::Requirements;
175 | 
176 |     fn call_with_temp_buffer(
177 |         fake_vulkan: &mut FakeVulkan,
178 |         context: &Context,
179 |         memory_type_flags: vk::VkMemoryPropertyFlags,
180 |     ) -> Result<(vk::VkDeviceMemory, u32), String> {
181 |         let buffer = fake_vulkan.add_handle(
182 |             HandleType::Buffer {
183 |                 create_info: Default::default(),
184 |                 memory: None,
185 |             }
186 |         );
187 | 
188 |         let res = allocate_buffer(context, memory_type_flags, buffer);
189 | 
190 |         fake_vulkan.get_handle_mut(buffer).freed = true;
191 | 
192 |         res
193 |     }
194 | 
195 |     fn call_with_temp_image(
196 |         fake_vulkan: &mut FakeVulkan,
197 |         context: &Context,
198 |         memory_type_flags: vk::VkMemoryPropertyFlags,
199 |     ) -> Result<(vk::VkDeviceMemory, u32), String> {
200 |         let image = fake_vulkan.add_handle(HandleType::Image);
201 | 
202 |         let res = allocate_image(context, memory_type_flags, image);
203 | 
204 |         fake_vulkan.get_handle_mut(image).freed = true;
205 | 
206 |         res
207 |     }
208 | 
209 |     fn do_allocate_buffer(
210 |         memory_property_flags: &[u32],
211 |         memory_type_bits: u32,
212 |         memory_type_flags: vk::VkMemoryPropertyFlags,
213 |     ) -> Result<(vk::VkDeviceMemory, u32, Context, Box<FakeVulkan>), String> {
214 |         let mut fake_vulkan = FakeVulkan::new();
215 |         fake_vulkan.physical_devices.push(Default::default());
216 | 
217 |         let memory_properties =
218 |             &mut fake_vulkan.physical_devices[0].memory_properties;
219 | 
220 |         for (i, &flags) in memory_property_flags.iter().enumerate() {
221 |             memory_properties.memoryTypes[i].propertyFlags = flags;
222 |         }
223 |         memory_properties.memoryTypeCount = memory_property_flags.len() as u32;
224 | 
225 |         fake_vulkan.memory_requirements.memoryTypeBits = memory_type_bits;
226 | 
227 |         fake_vulkan.set_override();
228 |         let context = Context::new(&mut Requirements::new(), None).unwrap();
229 |         call_with_temp_buffer(
230 |             &mut fake_vulkan,
231 |             &context,
232 |             memory_type_flags,
233 |         ).map(|(memory, memory_type)| (
234 |             memory,
235 |             memory_type,
236 |             context,
237 |             fake_vulkan,
238 |         ))
239 |     }
240 | 
241 |     #[test]
242 |     fn find_memory() {
243 |         let (device_memory, memory_type, context, fake_vulkan) =
244 |             do_allocate_buffer(
245 |             // Made-up set of memory properties
246 |             &[
247 |                 vk::VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT
248 |                     | vk::VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT,
249 |                 vk::VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT
250 |                     | vk::VK_MEMORY_PROPERTY_PROTECTED_BIT,
251 |                 vk::VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT
252 |                     | vk::VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT
253 |                     | vk::VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT,
254 |                 vk::VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT
255 |                     | vk::VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT
256 |                     | vk::VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT
257 |             ],
258 |             // Pretend that the buffer can use types 0, 1 or 3
259 |             0b1011,
260 |             // Pretend we need host visible and lazily allocated. This
261 |             // means either of the last two
262 |             vk::VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT
263 |                 | vk::VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT,
264 |         ).unwrap();
265 | 
266 |         // Only 2 or 3 have the properties we need, but only 3 is
267 |         // allowed for the buffer requirements.
268 |         assert_eq!(memory_type, 3);
269 | 
270 |         unsafe {
271 |             context.device().vkFreeMemory.unwrap()(
272 |                 context.vk_device(),
273 |                 device_memory,
274 |                 ptr::null(), // allocator
275 |             );
276 |         }
277 | 
278 |         drop(context);
279 |         drop(fake_vulkan);
280 | 
281 |         // Try with an impossible combination
282 |         let err = do_allocate_buffer(
283 |             &[
284 |                 vk::VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT
285 |                     | vk::VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT,
286 |             ],
287 |             0b1,
288 |             vk::VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT
289 |                 | vk::VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT,
290 |         ).unwrap_err();
291 | 
292 |         assert_eq!(
293 |             err,
294 |             "Couldn’t find suitable memory type to allocate buffer"
295 |         );
296 |     }
297 | 
298 |     fn make_error_context() -> (Box<FakeVulkan>, Context) {
299 |         let mut fake_vulkan = FakeVulkan::new();
300 |         fake_vulkan.physical_devices.push(Default::default());
301 | 
302 |         fake_vulkan.physical_devices[0].memory_properties.memoryTypeCount = 1;
303 |         fake_vulkan.memory_requirements.memoryTypeBits = 1;
304 | 
305 |         fake_vulkan.queue_result(
306 |             "vkAllocateMemory".to_string(),
307 |             vk::VK_ERROR_UNKNOWN
308 |         );
309 | 
310 |         fake_vulkan.set_override();
311 |         let context = Context::new(&mut Requirements::new(), None).unwrap();
312 | 
313 |         (fake_vulkan, context)
314 |     }
315 | 
316 |     #[test]
317 |     fn buffer_error() {
318 |         let (mut fake_vulkan, context) = make_error_context();
319 | 
320 |         let err = call_with_temp_buffer(
321 |             &mut fake_vulkan,
322 |             &context,
323 |             0, // memory_type_flags
324 |         ).unwrap_err();
325 | 
326 |         assert_eq!(err, "vkAllocateMemory failed");
327 |     }
328 | 
329 |     #[test]
330 |     fn image_error() {
331 |         let (mut fake_vulkan, context) = make_error_context();
332 | 
333 |         let err = call_with_temp_image(
334 |             &mut fake_vulkan,
335 |             &context,
336 |             0, // memory_type_flags
337 |         ).unwrap_err();
338 | 
339 |         assert_eq!(err, "vkAllocateMemory failed");
340 |     }
341 | 
342 |     #[test]
343 |     fn image() {
344 |         let mut fake_vulkan = FakeVulkan::new();
345 |         fake_vulkan.physical_devices.push(Default::default());
346 | 
347 |         fake_vulkan.physical_devices[0].memory_properties.memoryTypeCount = 1;
348 |         fake_vulkan.memory_requirements.memoryTypeBits = 1;
349 | 
350 |         fake_vulkan.set_override();
351 |         let context = Context::new(&mut Requirements::new(), None).unwrap();
352 | 
353 |         let (device_memory, memory_type) = call_with_temp_image(
354 |             &mut fake_vulkan,
355 |             &context,
356 |             0, // memory_type_flags
357 |         ).unwrap();
358 | 
359 |         assert!(device_memory != vk::null_handle());
360 |         assert_eq!(memory_type, 0);
361 | 
362 |         unsafe {
363 |             context.device().vkFreeMemory.unwrap()(
364 |                 context.vk_device(),
365 |                 device_memory,
366 |                 ptr::null(), // allocator
367 |             );
368 |         }
369 |     }
370 | }
371 | 
```

--------------------------------------------------------------------------------
/vkrunner/vkrunner/pipeline_key_data.rs:
--------------------------------------------------------------------------------

```rust
  1 | // Automatically generated by make-pipeline-key-data.py
  2 | 
  3 | const N_BOOL_PROPERTIES: usize = 10;
  4 | const N_INT_PROPERTIES: usize = 28;
  5 | const N_FLOAT_PROPERTIES: usize = 6;
  6 | 
  7 | const TOPOLOGY_PROP_NUM: usize = 0;
  8 | const PATCH_CONTROL_POINTS_PROP_NUM: usize = 1;
  9 | 
 10 | static PROPERTIES: [Property; 44] = [
 11 |     Property {
 12 |         prop_type: PropertyType::Int,
 13 |         num: 11,
 14 |         name: "alphaBlendOp",
 15 |     },
 16 |     Property {
 17 |         prop_type: PropertyType::Int,
 18 |         num: 25,
 19 |         name: "back.compareMask",
 20 |     },
 21 |     Property {
 22 |         prop_type: PropertyType::Int,
 23 |         num: 24,
 24 |         name: "back.compareOp",
 25 |     },
 26 |     Property {
 27 |         prop_type: PropertyType::Int,
 28 |         num: 23,
 29 |         name: "back.depthFailOp",
 30 |     },
 31 |     Property {
 32 |         prop_type: PropertyType::Int,
 33 |         num: 21,
 34 |         name: "back.failOp",
 35 |     },
 36 |     Property {
 37 |         prop_type: PropertyType::Int,
 38 |         num: 22,
 39 |         name: "back.passOp",
 40 |     },
 41 |     Property {
 42 |         prop_type: PropertyType::Int,
 43 |         num: 27,
 44 |         name: "back.reference",
 45 |     },
 46 |     Property {
 47 |         prop_type: PropertyType::Int,
 48 |         num: 26,
 49 |         name: "back.writeMask",
 50 |     },
 51 |     Property {
 52 |         prop_type: PropertyType::Bool,
 53 |         num: 5,
 54 |         name: "blendEnable",
 55 |     },
 56 |     Property {
 57 |         prop_type: PropertyType::Int,
 58 |         num: 8,
 59 |         name: "colorBlendOp",
 60 |     },
 61 |     Property {
 62 |         prop_type: PropertyType::Int,
 63 |         num: 12,
 64 |         name: "colorWriteMask",
 65 |     },
 66 |     Property {
 67 |         prop_type: PropertyType::Int,
 68 |         num: 3,
 69 |         name: "cullMode",
 70 |     },
 71 |     Property {
 72 |         prop_type: PropertyType::Float,
 73 |         num: 1,
 74 |         name: "depthBiasClamp",
 75 |     },
 76 |     Property {
 77 |         prop_type: PropertyType::Float,
 78 |         num: 0,
 79 |         name: "depthBiasConstantFactor",
 80 |     },
 81 |     Property {
 82 |         prop_type: PropertyType::Bool,
 83 |         num: 3,
 84 |         name: "depthBiasEnable",
 85 |     },
 86 |     Property {
 87 |         prop_type: PropertyType::Float,
 88 |         num: 2,
 89 |         name: "depthBiasSlopeFactor",
 90 |     },
 91 |     Property {
 92 |         prop_type: PropertyType::Bool,
 93 |         num: 8,
 94 |         name: "depthBoundsTestEnable",
 95 |     },
 96 |     Property {
 97 |         prop_type: PropertyType::Bool,
 98 |         num: 1,
 99 |         name: "depthClampEnable",
100 |     },
101 |     Property {
102 |         prop_type: PropertyType::Int,
103 |         num: 13,
104 |         name: "depthCompareOp",
105 |     },
106 |     Property {
107 |         prop_type: PropertyType::Bool,
108 |         num: 6,
109 |         name: "depthTestEnable",
110 |     },
111 |     Property {
112 |         prop_type: PropertyType::Bool,
113 |         num: 7,
114 |         name: "depthWriteEnable",
115 |     },
116 |     Property {
117 |         prop_type: PropertyType::Int,
118 |         num: 10,
119 |         name: "dstAlphaBlendFactor",
120 |     },
121 |     Property {
122 |         prop_type: PropertyType::Int,
123 |         num: 7,
124 |         name: "dstColorBlendFactor",
125 |     },
126 |     Property {
127 |         prop_type: PropertyType::Int,
128 |         num: 18,
129 |         name: "front.compareMask",
130 |     },
131 |     Property {
132 |         prop_type: PropertyType::Int,
133 |         num: 17,
134 |         name: "front.compareOp",
135 |     },
136 |     Property {
137 |         prop_type: PropertyType::Int,
138 |         num: 16,
139 |         name: "front.depthFailOp",
140 |     },
141 |     Property {
142 |         prop_type: PropertyType::Int,
143 |         num: 14,
144 |         name: "front.failOp",
145 |     },
146 |     Property {
147 |         prop_type: PropertyType::Int,
148 |         num: 15,
149 |         name: "front.passOp",
150 |     },
151 |     Property {
152 |         prop_type: PropertyType::Int,
153 |         num: 20,
154 |         name: "front.reference",
155 |     },
156 |     Property {
157 |         prop_type: PropertyType::Int,
158 |         num: 19,
159 |         name: "front.writeMask",
160 |     },
161 |     Property {
162 |         prop_type: PropertyType::Int,
163 |         num: 4,
164 |         name: "frontFace",
165 |     },
166 |     Property {
167 |         prop_type: PropertyType::Float,
168 |         num: 3,
169 |         name: "lineWidth",
170 |     },
171 |     Property {
172 |         prop_type: PropertyType::Int,
173 |         num: 5,
174 |         name: "logicOp",
175 |     },
176 |     Property {
177 |         prop_type: PropertyType::Bool,
178 |         num: 4,
179 |         name: "logicOpEnable",
180 |     },
181 |     Property {
182 |         prop_type: PropertyType::Float,
183 |         num: 5,
184 |         name: "maxDepthBounds",
185 |     },
186 |     Property {
187 |         prop_type: PropertyType::Float,
188 |         num: 4,
189 |         name: "minDepthBounds",
190 |     },
191 |     Property {
192 |         prop_type: PropertyType::Int,
193 |         num: 1,
194 |         name: "patchControlPoints",
195 |     },
196 |     Property {
197 |         prop_type: PropertyType::Int,
198 |         num: 2,
199 |         name: "polygonMode",
200 |     },
201 |     Property {
202 |         prop_type: PropertyType::Bool,
203 |         num: 0,
204 |         name: "primitiveRestartEnable",
205 |     },
206 |     Property {
207 |         prop_type: PropertyType::Bool,
208 |         num: 2,
209 |         name: "rasterizerDiscardEnable",
210 |     },
211 |     Property {
212 |         prop_type: PropertyType::Int,
213 |         num: 9,
214 |         name: "srcAlphaBlendFactor",
215 |     },
216 |     Property {
217 |         prop_type: PropertyType::Int,
218 |         num: 6,
219 |         name: "srcColorBlendFactor",
220 |     },
221 |     Property {
222 |         prop_type: PropertyType::Bool,
223 |         num: 9,
224 |         name: "stencilTestEnable",
225 |     },
226 |     Property {
227 |         prop_type: PropertyType::Int,
228 |         num: 0,
229 |         name: "topology",
230 |     },
231 | ];
232 | 
233 | fn copy_properties_to_create_info(
234 |     key: &Key,
235 |     s: &mut vk::VkGraphicsPipelineCreateInfo
236 | ) {
237 |     {
238 |         let s = unsafe { std::mem::transmute::<_, &mut vk::VkPipelineInputAssemblyStateCreateInfo>(s.pInputAssemblyState) };
239 |         s.topology = key.int_properties[0] as vk::VkPrimitiveTopology;
240 |         s.primitiveRestartEnable = key.bool_properties[0] as vk::VkBool32;
241 |     }
242 |     {
243 |         let s = unsafe { std::mem::transmute::<_, &mut vk::VkPipelineTessellationStateCreateInfo>(s.pTessellationState) };
244 |         s.patchControlPoints = key.int_properties[1] as u32;
245 |     }
246 |     {
247 |         let s = unsafe { std::mem::transmute::<_, &mut vk::VkPipelineRasterizationStateCreateInfo>(s.pRasterizationState) };
248 |         s.depthClampEnable = key.bool_properties[1] as vk::VkBool32;
249 |         s.rasterizerDiscardEnable = key.bool_properties[2] as vk::VkBool32;
250 |         s.polygonMode = key.int_properties[2] as vk::VkPolygonMode;
251 |         s.cullMode = key.int_properties[3] as vk::VkCullModeFlags;
252 |         s.frontFace = key.int_properties[4] as vk::VkFrontFace;
253 |         s.depthBiasEnable = key.bool_properties[3] as vk::VkBool32;
254 |         s.depthBiasConstantFactor = key.float_properties[0] as f32;
255 |         s.depthBiasClamp = key.float_properties[1] as f32;
256 |         s.depthBiasSlopeFactor = key.float_properties[2] as f32;
257 |         s.lineWidth = key.float_properties[3] as f32;
258 |     }
259 |     {
260 |         let s = unsafe { std::mem::transmute::<_, &mut vk::VkPipelineColorBlendStateCreateInfo>(s.pColorBlendState) };
261 |         s.logicOpEnable = key.bool_properties[4] as vk::VkBool32;
262 |         s.logicOp = key.int_properties[5] as vk::VkLogicOp;
263 |         {
264 |             let s = unsafe { std::mem::transmute::<_, &mut vk::VkPipelineColorBlendAttachmentState>(s.pAttachments) };
265 |             s.blendEnable = key.bool_properties[5] as vk::VkBool32;
266 |             s.srcColorBlendFactor = key.int_properties[6] as vk::VkBlendFactor;
267 |             s.dstColorBlendFactor = key.int_properties[7] as vk::VkBlendFactor;
268 |             s.colorBlendOp = key.int_properties[8] as vk::VkBlendOp;
269 |             s.srcAlphaBlendFactor = key.int_properties[9] as vk::VkBlendFactor;
270 |             s.dstAlphaBlendFactor = key.int_properties[10] as vk::VkBlendFactor;
271 |             s.alphaBlendOp = key.int_properties[11] as vk::VkBlendOp;
272 |             s.colorWriteMask = key.int_properties[12] as vk::VkColorComponentFlags;
273 |         }
274 |     }
275 |     {
276 |         let s = unsafe { std::mem::transmute::<_, &mut vk::VkPipelineDepthStencilStateCreateInfo>(s.pDepthStencilState) };
277 |         s.depthTestEnable = key.bool_properties[6] as vk::VkBool32;
278 |         s.depthWriteEnable = key.bool_properties[7] as vk::VkBool32;
279 |         s.depthCompareOp = key.int_properties[13] as vk::VkCompareOp;
280 |         s.depthBoundsTestEnable = key.bool_properties[8] as vk::VkBool32;
281 |         s.stencilTestEnable = key.bool_properties[9] as vk::VkBool32;
282 |         s.front.failOp = key.int_properties[14] as vk::VkStencilOp;
283 |         s.front.passOp = key.int_properties[15] as vk::VkStencilOp;
284 |         s.front.depthFailOp = key.int_properties[16] as vk::VkStencilOp;
285 |         s.front.compareOp = key.int_properties[17] as vk::VkCompareOp;
286 |         s.front.compareMask = key.int_properties[18] as u32;
287 |         s.front.writeMask = key.int_properties[19] as u32;
288 |         s.front.reference = key.int_properties[20] as u32;
289 |         s.back.failOp = key.int_properties[21] as vk::VkStencilOp;
290 |         s.back.passOp = key.int_properties[22] as vk::VkStencilOp;
291 |         s.back.depthFailOp = key.int_properties[23] as vk::VkStencilOp;
292 |         s.back.compareOp = key.int_properties[24] as vk::VkCompareOp;
293 |         s.back.compareMask = key.int_properties[25] as u32;
294 |         s.back.writeMask = key.int_properties[26] as u32;
295 |         s.back.reference = key.int_properties[27] as u32;
296 |         s.minDepthBounds = key.float_properties[4] as f32;
297 |         s.maxDepthBounds = key.float_properties[5] as f32;
298 |     }
299 | }
300 | 
301 | impl Default for Key {
302 |     fn default() -> Key {
303 |         Key {
304 |             pipeline_type: Type::Graphics,
305 |             source: Source::Rectangle,
306 |             entrypoints: Default::default(),
307 | 
308 |             bool_properties: [
309 |                 false, // primitiveRestartEnable
310 |                 false, // depthClampEnable
311 |                 false, // rasterizerDiscardEnable
312 |                 false, // depthBiasEnable
313 |                 false, // logicOpEnable
314 |                 false, // blendEnable
315 |                 false, // depthTestEnable
316 |                 false, // depthWriteEnable
317 |                 false, // depthBoundsTestEnable
318 |                 false, // stencilTestEnable
319 |             ],
320 |             int_properties: [
321 |                 vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP as i32, // topology
322 |                 0 as i32, // patchControlPoints
323 |                 vk::VK_POLYGON_MODE_FILL as i32, // polygonMode
324 |                 vk::VK_CULL_MODE_NONE as i32, // cullMode
325 |                 vk::VK_FRONT_FACE_COUNTER_CLOCKWISE as i32, // frontFace
326 |                 vk::VK_LOGIC_OP_SET as i32, // logicOp
327 |                 vk::VK_BLEND_FACTOR_SRC_ALPHA as i32, // srcColorBlendFactor
328 |                 vk::VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA as i32, // dstColorBlendFactor
329 |                 vk::VK_BLEND_OP_ADD as i32, // colorBlendOp
330 |                 vk::VK_BLEND_FACTOR_SRC_ALPHA as i32, // srcAlphaBlendFactor
331 |                 vk::VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA as i32, // dstAlphaBlendFactor
332 |                 vk::VK_BLEND_OP_ADD as i32, // alphaBlendOp
333 |                 (vk::VK_COLOR_COMPONENT_R_BIT | vk::VK_COLOR_COMPONENT_G_BIT | vk::VK_COLOR_COMPONENT_B_BIT | vk::VK_COLOR_COMPONENT_A_BIT) as i32, // colorWriteMask
334 |                 vk::VK_COMPARE_OP_LESS as i32, // depthCompareOp
335 |                 vk::VK_STENCIL_OP_KEEP as i32, // front.failOp
336 |                 vk::VK_STENCIL_OP_KEEP as i32, // front.passOp
337 |                 vk::VK_STENCIL_OP_KEEP as i32, // front.depthFailOp
338 |                 vk::VK_COMPARE_OP_ALWAYS as i32, // front.compareOp
339 |                 u32::MAX as i32, // front.compareMask
340 |                 u32::MAX as i32, // front.writeMask
341 |                 0 as i32, // front.reference
342 |                 vk::VK_STENCIL_OP_KEEP as i32, // back.failOp
343 |                 vk::VK_STENCIL_OP_KEEP as i32, // back.passOp
344 |                 vk::VK_STENCIL_OP_KEEP as i32, // back.depthFailOp
345 |                 vk::VK_COMPARE_OP_ALWAYS as i32, // back.compareOp
346 |                 u32::MAX as i32, // back.compareMask
347 |                 u32::MAX as i32, // back.writeMask
348 |                 0 as i32, // back.reference
349 |             ],
350 |             float_properties: [
351 |                 0.0, // depthBiasConstantFactor
352 |                 0.0, // depthBiasClamp
353 |                 0.0, // depthBiasSlopeFactor
354 |                 1.0, // lineWidth
355 |                 0.0, // minDepthBounds
356 |                 0.0, // maxDepthBounds
357 |             ],
358 |         }
359 |     }
360 | }
361 | 
362 | 
```

--------------------------------------------------------------------------------
/vkrunner/vkrunner/hex.rs:
--------------------------------------------------------------------------------

```rust
  1 | // Copyright (c) The Piglit project 2007
  2 | // Copyright 2023 Neil Roberts
  3 | //
  4 | // Permission is hereby granted, free of charge, to any person obtaining a
  5 | // copy of this software and associated documentation files (the "Software"),
  6 | // to deal in the Software without restriction, including without limitation
  7 | // on the rights to use, copy, modify, merge, publish, distribute, sub
  8 | // license, and/or sell copies of the Software, and to permit persons to whom
  9 | // the Software is furnished to do so, subject to the following conditions:
 10 | //
 11 | // The above copyright notice and this permission notice (including the next
 12 | // paragraph) shall be included in all copies or substantial portions of the
 13 | // Software.
 14 | //
 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.  IN NO EVENT SHALL
 18 | // VA LINUX SYSTEM, IBM AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
 19 | // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
 20 | // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
 21 | // USE OR OTHER DEALINGS IN THE SOFTWARE.
 22 | 
 23 | use crate::half_float;
 24 | use std::num::{ParseFloatError, ParseIntError};
 25 | use std::fmt;
 26 | use std::convert::From;
 27 | 
 28 | // Based on functions from piglit-util.c
 29 | 
 30 | #[derive(Debug)]
 31 | pub enum ParseError {
 32 |     Float(ParseFloatError),
 33 |     Int(ParseIntError),
 34 | }
 35 | 
 36 | impl fmt::Display for ParseError {
 37 |     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
 38 |         match self {
 39 |             ParseError::Float(e) => e.fmt(f),
 40 |             ParseError::Int(e) => e.fmt(f),
 41 |         }
 42 |     }
 43 | }
 44 | 
 45 | impl From<ParseFloatError> for ParseError {
 46 |     fn from(e: ParseFloatError) -> ParseError {
 47 |         ParseError::Float(e)
 48 |     }
 49 | }
 50 | 
 51 | impl From<ParseIntError> for ParseError {
 52 |     fn from(e: ParseIntError) -> ParseError {
 53 |         ParseError::Int(e)
 54 |     }
 55 | }
 56 | 
 57 | // Similar to haystack.starts_with(needle) but the ASCII characters of
 58 | // haystack are converted to lower case before comparing. The needle
 59 | // value should already be in lowercase for this to work.
 60 | fn starts_with_ignore_case(haystack: &str, needle: &str) -> bool {
 61 |     let mut haystack_chars = haystack.chars();
 62 | 
 63 |     for needle_c in needle.chars() {
 64 |         match haystack_chars.next() {
 65 |             None => return false,
 66 |             Some(haystack_c) => if haystack_c.to_ascii_lowercase() != needle_c {
 67 |                 return false;
 68 |             },
 69 |         }
 70 |     }
 71 | 
 72 |     true
 73 | }
 74 | 
 75 | // Checks whether the string slice starts with one of the special
 76 | // words allowed in a float string. If so it returns the length of the
 77 | // word, otherwise it returns None.
 78 | fn starts_with_float_special_word(s: &str) -> Option<usize> {
 79 |     for word in ["infinity", "inf", "nan"] {
 80 |         if starts_with_ignore_case(s, word) {
 81 |             return Some(word.len());
 82 |         }
 83 |     }
 84 | 
 85 |    None
 86 | }
 87 | 
 88 | // Checks whether the string starts with a valid Number part of a
 89 | // float. If so it returns the byte length, otherwise it returns None.
 90 | fn count_number(s: &str) -> Option<usize> {
 91 |     // Optional units
 92 |     let before_digits = count_digits(s);
 93 | 
 94 |     let num_end = &s[before_digits..];
 95 | 
 96 |     // Optional decimal
 97 |     let after_digits;
 98 |     let n_points;
 99 | 
100 |     if let Some('.') = num_end.chars().next() {
101 |         n_points = 1;
102 |         let digits = &num_end[1..];
103 |         after_digits = count_digits(digits);
104 |     } else {
105 |         n_points = 0;
106 |         after_digits = 0;
107 |     }
108 | 
109 |     // Either the units or the decimal must be present
110 |     if before_digits > 0 || after_digits > 0 {
111 |         Some(before_digits + n_points + after_digits)
112 |     } else {
113 |         None
114 |     }
115 | }
116 | 
117 | // Returns how many ASCII digits are at the start of the string
118 | fn count_digits(s: &str) -> usize {
119 |     s.chars().take_while(char::is_ascii_digit).count()
120 | }
121 | 
122 | // Checks whether the strings starts with a valid Exp part of a float.
123 | // If so it returns the byte length, otherwise it returns None.
124 | fn count_exp(s: &str) -> Option<usize> {
125 |     if let Some('E' | 'e') = s.chars().next() {
126 |         let mut count = 1;
127 | 
128 |         if let Some('+' | '-') = s[count..].chars().next() {
129 |             count += 1;
130 |         }
131 | 
132 |         let digits = count_digits(&s[count..]);
133 | 
134 |         if digits > 0 {
135 |             Some(count + digits)
136 |         } else {
137 |             None
138 |         }
139 |     } else {
140 |         None
141 |     }
142 | }
143 | 
144 | // It looks like the rust float parsing functions don’t have an
145 | // equivalent of the `endptr` argument to `strtod`. This function
146 | // tries to work around that by extracting the float part and the rest
147 | // of the string and returning the two string slices as a tuple. It also
148 | // skips leading spaces.
149 | fn split_parts(mut s: &str) -> (&str, &str) {
150 |     // skip only ASCII spaces and tabs
151 |     while !s.is_empty() &&
152 |         (s.as_bytes()[0] == b' ' || s.as_bytes()[0] == b'\t')
153 |     {
154 |         s = &s[1..];
155 |     }
156 | 
157 |     let mut split_point = 0;
158 | 
159 |     if s.starts_with("0x") {
160 |         split_point =
161 |             2
162 |             + s[2..]
163 |             .chars()
164 |             .take_while(char::is_ascii_hexdigit)
165 |             .count();
166 |     } else {
167 |         // Optional sign
168 |         if let Some('-' | '+') = s[split_point..].chars().next() {
169 |             split_point += 1;
170 |         }
171 | 
172 |         if let Some(len) = starts_with_float_special_word(&s[split_point..]) {
173 |             split_point += len;
174 |         } else if let Some(len) = count_number(&s[split_point..]) {
175 |             split_point += len;
176 | 
177 |             if let Some(len) = count_exp(&s[split_point..]) {
178 |                 split_point += len;
179 |             }
180 |         }
181 |     }
182 | 
183 |     (&s[0..split_point], &s[split_point..])
184 | }
185 | 
186 | // Wrapper for str.parse<f32> which allows using an exact hex bit
187 | // pattern to generate a float value and ignores trailing data.
188 | //
189 | // If the parsing works, it will return a tuple with the floating
190 | // point value and a string slice pointing to the rest of the string.
191 | pub fn parse_f32(s: &str) -> Result<(f32, &str), ParseError> {
192 |     let (s, tail) = split_parts(s);
193 | 
194 |     if s.starts_with("0x") {
195 |         Ok((f32::from_bits(u32::from_str_radix(&s[2..], 16)?), tail))
196 |     } else {
197 |         Ok((s.parse::<f32>()?, tail))
198 |     }
199 | }
200 | 
201 | // Wrapper for str.parse<f64> which allows using an exact hex bit
202 | // pattern to generate a float value and ignores trailing data.
203 | //
204 | // If the parsing works, it will return a tuple with the floating
205 | // point value and a string slice pointing to the rest of the string.
206 | pub fn parse_f64(s: &str) -> Result<(f64, &str), ParseError> {
207 |     let (s, tail) = split_parts(s);
208 | 
209 |     if s.starts_with("0x") {
210 |         Ok((f64::from_bits(u64::from_str_radix(&s[2..], 16)?), tail))
211 |     } else {
212 |         Ok((s.parse::<f64>()?, tail))
213 |     }
214 | }
215 | 
216 | // Wrapper for calling half_float::from_f32 on the result of parsing to the
217 | // string to a float but that also allows specifying the value exactly
218 | // as a hexadecimal number.
219 | //
220 | // If the parsing works, it will return a tuple with the half float
221 | // value and a string slice pointing to the rest of the string.
222 | pub fn parse_half_float(s: &str) -> Result<(u16, &str), ParseError> {
223 |     let (s, tail) = split_parts(s);
224 | 
225 |     if s.starts_with("0x") {
226 |         Ok((u16::from_str_radix(&s[2..], 16)?, tail))
227 |     } else {
228 |         Ok((half_float::from_f32(s.parse::<f32>()?), tail))
229 |     }
230 | }
231 | 
232 | #[cfg(test)]
233 | mod test {
234 |     use super::*;
235 | 
236 |     #[test]
237 |     fn test_split_parts() {
238 |         // Skip spaces and tabs
239 |         assert_eq!(split_parts("    0"), ("0", ""));
240 |         assert_eq!(split_parts("  \t  0"), ("0", ""));
241 |         // Don’t skip other whitespace characters
242 |         assert_eq!(split_parts("  \n  0"), ("", "\n  0"));
243 | 
244 |         // Hex digits
245 |         assert_eq!(split_parts("0xCafeCafeTEA"), ("0xCafeCafe", "TEA"));
246 | 
247 |         // Signs
248 |         assert_eq!(split_parts("+42 cupcakes"), ("+42", " cupcakes"));
249 |         assert_eq!(split_parts("-42 gerbils"), ("-42", " gerbils"));
250 | 
251 |         // Special words
252 |         assert_eq!(split_parts("+infinity forever"), ("+infinity", " forever"));
253 |         assert_eq!(split_parts("INf forever"), ("INf", " forever"));
254 |         assert_eq!(split_parts("   -NaN fornever"), ("-NaN", " fornever"));
255 |         assert_eq!(split_parts("infin"), ("inf", "in"));
256 |         assert_eq!(split_parts("NaN12"), ("NaN", "12"));
257 | 
258 |         // Normal numbers
259 |         assert_eq!(split_parts("12.2"), ("12.2", ""));
260 |         assert_eq!(split_parts("-12.2"), ("-12.2", ""));
261 |         assert_eq!(split_parts("12.2e6"), ("12.2e6", ""));
262 |         assert_eq!(split_parts("12.2E6"), ("12.2E6", ""));
263 |         assert_eq!(split_parts("12.E6"), ("12.E6", ""));
264 |         assert_eq!(split_parts("12.E-6"), ("12.E-6", ""));
265 |         assert_eq!(split_parts("12.E+6"), ("12.E+6", ""));
266 |         assert_eq!(split_parts(".0"), (".0", ""));
267 |         assert_eq!(split_parts("5."), ("5.", ""));
268 |         assert_eq!(split_parts(".5e6"), (".5e6", ""));
269 |         assert_eq!(split_parts("5.e6"), ("5.e6", ""));
270 | 
271 |         // At least one side of the decimal point must be specified
272 |         assert_eq!(split_parts("+."), ("+", "."));
273 | 
274 |         // The exponent must have some digits
275 |         assert_eq!(split_parts("12e"), ("12", "e"));
276 |         assert_eq!(split_parts("12e-"), ("12", "e-"));
277 | 
278 |         // Can’t have the exponent on its own
279 |         assert_eq!(split_parts("e12"), ("", "e12"));
280 |     }
281 | 
282 |     fn float_matches<T: Into<f64>>(
283 |         res: Result<(T, &str), ParseError>,
284 |         expected_value: T,
285 |         expected_tail: &str
286 |     ) {
287 |         let (value, tail) = res.unwrap();
288 |         let value = value.into();
289 |         let expected_value = expected_value.into();
290 | 
291 |         assert!((value - expected_value).abs() < 0.0001,
292 |                 "value={}, expected_value={}",
293 |                 value,
294 |                 expected_value);
295 |         assert_eq!(expected_tail, tail);
296 |     }
297 | 
298 |     #[test]
299 |     fn test_parse_f32() {
300 |         float_matches(parse_f32("1.0"), 1.0, "");
301 |         float_matches(parse_f32("  \t 1.0"), 1.0, "");
302 |         float_matches(parse_f32("-1.0"), -1.0, "");
303 |         float_matches(parse_f32("+1.0"), 1.0, "");
304 |         float_matches(parse_f32("42 monkies"), 42.0, " monkies");
305 | 
306 |         float_matches(parse_f32("0x0"), 0.0, "");
307 |         assert_eq!(parse_f32("0x7f800000").unwrap().0, f32::INFINITY);
308 | 
309 |         assert_eq!(parse_f32("-inf").unwrap(), (-f32::INFINITY, ""));
310 |         assert_eq!(parse_f32("infinity 12").unwrap(), (f32::INFINITY, " 12"));
311 |         assert!(parse_f32("NaN").unwrap().0.is_nan());
312 | 
313 |         assert!(matches!(
314 |             parse_f32(""),
315 |             Err(ParseError::Float(ParseFloatError { .. }))
316 |         ));
317 | 
318 |         assert!(matches!(
319 |             parse_f32("0xaaaaaaaaa"),
320 |             Err(ParseError::Int(ParseIntError { .. }))
321 |         ));
322 |     }
323 | 
324 |     #[test]
325 |     fn test_parse_f64() {
326 |         float_matches(parse_f64("1.0"), 1.0, "");
327 |         float_matches(parse_f64("42 monkies"), 42.0, " monkies");
328 | 
329 |         float_matches(parse_f64("0x0"), 0.0, "");
330 |         assert_eq!(parse_f64("0xfff0000000000000").unwrap().0, -f64::INFINITY);
331 | 
332 |         assert_eq!(parse_f64("-inf").unwrap(), (-f64::INFINITY, ""));
333 |         assert_eq!(parse_f64("infinity 12").unwrap(), (f64::INFINITY, " 12"));
334 |         assert!(parse_f64("NaN").unwrap().0.is_nan());
335 | 
336 |         assert!(matches!(
337 |             parse_f64(""),
338 |             Err(ParseError::Float(ParseFloatError { .. }))
339 |         ));
340 | 
341 |         assert!(matches!(
342 |             parse_f64("0xaaaaaaaaaaaaaaaaa"),
343 |             Err(ParseError::Int(ParseIntError { .. }))
344 |         ));
345 |     }
346 | 
347 |     #[test]
348 |     fn test_parse_half_float() {
349 |         assert_eq!(parse_half_float("1.0").unwrap(), (0x3c00, ""));
350 | 
351 |         assert_eq!(parse_half_float("0x7bff").unwrap(), (0x7bff, ""));
352 |         assert_eq!(parse_half_float("0x7c00").unwrap(), (0x7c00, ""));
353 | 
354 |         assert_eq!(
355 |             parse_half_float("infinity 12").unwrap(),
356 |             (0x7c00, " 12")
357 |         );
358 | 
359 |         assert!(matches!(
360 |             parse_half_float(""),
361 |             Err(ParseError::Float(ParseFloatError { .. }))
362 |         ));
363 | 
364 |         assert!(matches!(
365 |             parse_half_float("0xffff1"),
366 |             Err(ParseError::Int(ParseIntError { .. }))
367 |         ));
368 |     }
369 | }
370 | 
```

--------------------------------------------------------------------------------
/vkrunner/vkrunner/make-pipeline-key-data.py:
--------------------------------------------------------------------------------

```python
  1 | #!/usr/bin/python3
  2 | 
  3 | # Copyright 2023 Neil Roberts
  4 | 
  5 | # Permission is hereby granted, free of charge, to any person obtaining a
  6 | # copy of this software and associated documentation files (the "Software"),
  7 | # to deal in the Software without restriction, including without limitation
  8 | # the rights to use, copy, modify, merge, publish, distribute, sublicense,
  9 | # and/or sell copies of the Software, and to permit persons to whom the
 10 | # Software is furnished to do so, subject to the following conditions:
 11 | 
 12 | # The above copyright notice and this permission notice (including the next
 13 | # paragraph) shall be included in all copies or substantial portions of the
 14 | # Software.
 15 | 
 16 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 17 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 18 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 19 | # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 20 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 21 | # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 22 | # DEALINGS IN THE SOFTWARE.
 23 | 
 24 | # This script is used to generate pipeline_key_data.rs. It is not run
 25 | # automatically as part of the build process but if need be it can be
 26 | # used to update the file as follows:
 27 | #
 28 | # ./make-pipeline-key-data.py > pipeline_key_data.rs
 29 | 
 30 | from mako.template import Template
 31 | 
 32 | TEMPLATE="""\
 33 | // Automatically generated by make-pipeline-key-data.py
 34 | 
 35 | const N_BOOL_PROPERTIES: usize = ${sum(1 for p in props
 36 |                                        if p.base_type == "bool")};
 37 | const N_INT_PROPERTIES: usize = ${sum(1 for p in props
 38 |                                       if p.base_type == "int")};
 39 | const N_FLOAT_PROPERTIES: usize = ${sum(1 for p in props
 40 |                                         if p.base_type == "float")};
 41 | 
 42 | const TOPOLOGY_PROP_NUM: usize = ${next(p for p in props
 43 |                                         if p.name == "topology").num};
 44 | const PATCH_CONTROL_POINTS_PROP_NUM: usize = ${
 45 |     next(p for p in props if p.name == "patchControlPoints").num};
 46 | 
 47 | static PROPERTIES: [Property; ${len(props)}] = [
 48 | % for prop in sorted(props, key=lambda p: p.name):
 49 |     Property {
 50 |         prop_type: PropertyType::${prop.base_type.capitalize()},
 51 |         num: ${prop.num},
 52 |         name: "${prop.name}",
 53 |     },
 54 | % endfor
 55 | ];
 56 | 
 57 | fn copy_properties_to_create_info(
 58 |     key: &Key,
 59 |     s: &mut vk::VkGraphicsPipelineCreateInfo
 60 | ) {
 61 | ${setters}
 62 | }
 63 | 
 64 | impl Default for Key {
 65 |     fn default() -> Key {
 66 |         Key {
 67 |             pipeline_type: Type::Graphics,
 68 |             source: Source::Rectangle,
 69 |             entrypoints: Default::default(),
 70 | 
 71 |             bool_properties: [
 72 | % for prop in sorted(props, key=lambda p: p.num):
 73 | %   if prop.base_type == "bool":
 74 |                 ${prop.default}, // ${prop.name}
 75 | %   endif
 76 | % endfor
 77 |             ],
 78 |             int_properties: [
 79 | % for prop in sorted(props, key=lambda p: p.num):
 80 | %   if prop.base_type == "int":
 81 |                 ${prop.default} as i32, // ${prop.name}
 82 | %   endif
 83 | % endfor
 84 |             ],
 85 |             float_properties: [
 86 | % for prop in sorted(props, key=lambda p: p.num):
 87 | %   if prop.base_type == "float":
 88 |                 ${prop.default}, // ${prop.name}
 89 | %   endif
 90 | % endfor
 91 |             ],
 92 |         }
 93 |     }
 94 | }
 95 | """
 96 | 
 97 | 
 98 | class Structure:
 99 |     def __init__(self, name, variable, children):
100 |         self.name = name
101 |         self.variable = variable
102 |         self.children = children
103 | 
104 | 
105 | class Property:
106 |     def __init__(self, vk_type, name, default):
107 |         self.vk_type = vk_type
108 |         self.base_type = vk_type_as_base_type(vk_type)
109 |         self.name = name
110 |         self.default = default
111 | 
112 | 
113 | class Properties:
114 |     def __init__(self):
115 |         self.values = []
116 |         self.counts = {}
117 | 
118 |     def add(self, prop):
119 |         base_type = prop.base_type
120 |         try:
121 |             self.counts[base_type] += 1
122 |         except KeyError:
123 |             self.counts[base_type] = 1
124 | 
125 |         prop.num = self.counts[base_type] - 1
126 | 
127 |         self.values.append(prop)
128 | 
129 | 
130 | def vk_type_as_base_type(vk_type):
131 |     if vk_type == "vk::VkBool32":
132 |         return "bool"
133 |     elif vk_type == "f32":
134 |         return "float"
135 |     elif vk_type == "u32":
136 |         return "int"
137 |     elif vk_type.startswith("vk::Vk"):
138 |         return "int"
139 | 
140 |     raise ValueError("Unsupported Vulkan type: {}".format(vk_type))
141 | 
142 | 
143 | STRUCTURES = [
144 |     Structure("VkPipelineInputAssemblyStateCreateInfo",
145 |               "pInputAssemblyState",
146 |               [
147 |                   Property("vk::VkPrimitiveTopology",
148 |                            "topology",
149 |                            "vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP"),
150 |                   Property("vk::VkBool32",
151 |                            "primitiveRestartEnable",
152 |                            "false"),
153 |               ]),
154 | 
155 |     Structure("VkPipelineTessellationStateCreateInfo",
156 |               "pTessellationState",
157 |               [
158 |                   Property("u32", "patchControlPoints", "0"),
159 |               ]),
160 | 
161 |     Structure("VkPipelineRasterizationStateCreateInfo",
162 |               "pRasterizationState",
163 |               [
164 |                   Property("vk::VkBool32", "depthClampEnable", "false"),
165 |                   Property("vk::VkBool32", "rasterizerDiscardEnable", "false"),
166 |                   Property("vk::VkPolygonMode",
167 |                            "polygonMode",
168 |                            "vk::VK_POLYGON_MODE_FILL"),
169 |                   Property("vk::VkCullModeFlags",
170 |                            "cullMode",
171 |                            "vk::VK_CULL_MODE_NONE"),
172 |                   Property("vk::VkFrontFace",
173 |                            "frontFace",
174 |                            "vk::VK_FRONT_FACE_COUNTER_CLOCKWISE"),
175 |                   Property("vk::VkBool32", "depthBiasEnable", "false"),
176 |                   Property("f32", "depthBiasConstantFactor", "0.0"),
177 |                   Property("f32", "depthBiasClamp", "0.0"),
178 |                   Property("f32", "depthBiasSlopeFactor", "0.0"),
179 |                   Property("f32", "lineWidth", "1.0"),
180 |               ]),
181 | 
182 |     Structure("VkPipelineColorBlendStateCreateInfo",
183 |               "pColorBlendState",
184 |               [
185 |                   Property("vk::VkBool32", "logicOpEnable", "false"),
186 |                   Property("vk::VkLogicOp", "logicOp", "vk::VK_LOGIC_OP_SET"),
187 | 
188 |                   Structure("VkPipelineColorBlendAttachmentState",
189 |                             "pAttachments",
190 |                             [
191 |                                 Property("vk::VkBool32",
192 |                                          "blendEnable",
193 |                                          "false"),
194 |                                 Property("vk::VkBlendFactor",
195 |                                          "srcColorBlendFactor",
196 |                                          "vk::VK_BLEND_FACTOR_SRC_ALPHA"),
197 |                                 Property("vk::VkBlendFactor",
198 |                                          "dstColorBlendFactor",
199 |                                          "vk::VK_BLEND_FACTOR_"
200 |                                          "ONE_MINUS_SRC_ALPHA"),
201 |                                 Property("vk::VkBlendOp",
202 |                                          "colorBlendOp",
203 |                                          "vk::VK_BLEND_OP_ADD"),
204 |                                 Property("vk::VkBlendFactor",
205 |                                          "srcAlphaBlendFactor",
206 |                                          "vk::VK_BLEND_FACTOR_SRC_ALPHA"),
207 |                                 Property("vk::VkBlendFactor",
208 |                                          "dstAlphaBlendFactor",
209 |                                          "vk::VK_BLEND_FACTOR_"
210 |                                          "ONE_MINUS_SRC_ALPHA"),
211 |                                 Property("vk::VkBlendOp",
212 |                                          "alphaBlendOp",
213 |                                          "vk::VK_BLEND_OP_ADD"),
214 |                                 Property("vk::VkColorComponentFlags",
215 |                                          "colorWriteMask",
216 |                                          "(vk::VK_COLOR_COMPONENT_R_BIT | "
217 |                                          "vk::VK_COLOR_COMPONENT_G_BIT | "
218 |                                          "vk::VK_COLOR_COMPONENT_B_BIT | "
219 |                                          "vk::VK_COLOR_COMPONENT_A_BIT)"),
220 |                             ]),
221 |               ]),
222 | 
223 |     Structure("VkPipelineDepthStencilStateCreateInfo",
224 |               "pDepthStencilState",
225 |               [
226 |                   Property("vk::VkBool32", "depthTestEnable", "false"),
227 |                   Property("vk::VkBool32", "depthWriteEnable", "false"),
228 |                   Property("vk::VkCompareOp",
229 |                            "depthCompareOp",
230 |                            "vk::VK_COMPARE_OP_LESS"),
231 |                   Property("vk::VkBool32",
232 |                            "depthBoundsTestEnable",
233 |                            "false"),
234 |                   Property("vk::VkBool32",
235 |                            "stencilTestEnable",
236 |                            "false"),
237 |                   Property("vk::VkStencilOp",
238 |                            "front.failOp",
239 |                            "vk::VK_STENCIL_OP_KEEP"),
240 |                   Property("vk::VkStencilOp",
241 |                            "front.passOp",
242 |                            "vk::VK_STENCIL_OP_KEEP"),
243 |                   Property("vk::VkStencilOp",
244 |                            "front.depthFailOp",
245 |                            "vk::VK_STENCIL_OP_KEEP"),
246 |                   Property("vk::VkCompareOp",
247 |                            "front.compareOp",
248 |                            "vk::VK_COMPARE_OP_ALWAYS"),
249 |                   Property("u32",
250 |                            "front.compareMask",
251 |                            "u32::MAX"),
252 |                   Property("u32",
253 |                            "front.writeMask",
254 |                            "u32::MAX"),
255 |                   Property("u32",
256 |                            "front.reference",
257 |                            "0"),
258 |                   Property("vk::VkStencilOp",
259 |                            "back.failOp",
260 |                            "vk::VK_STENCIL_OP_KEEP"),
261 |                   Property("vk::VkStencilOp",
262 |                            "back.passOp",
263 |                            "vk::VK_STENCIL_OP_KEEP"),
264 |                   Property("vk::VkStencilOp",
265 |                            "back.depthFailOp",
266 |                            "vk::VK_STENCIL_OP_KEEP"),
267 |                   Property("vk::VkCompareOp",
268 |                            "back.compareOp",
269 |                            "vk::VK_COMPARE_OP_ALWAYS"),
270 |                   Property("u32",
271 |                            "back.compareMask",
272 |                            "u32::MAX"),
273 |                   Property("u32",
274 |                            "back.writeMask",
275 |                            "u32::MAX"),
276 |                   Property("u32",
277 |                            "back.reference",
278 |                            "0"),
279 |                   Property("f32", "minDepthBounds", "0.0"),
280 |                   Property("f32", "maxDepthBounds", "0.0"),
281 |               ])
282 | ]
283 | 
284 | 
285 | def get_props(structure, props):
286 |     for child in structure.children:
287 |         if isinstance(child, Property):
288 |             props.add(child)
289 |         elif isinstance(child, Structure):
290 |             get_props(child, props)
291 |         else:
292 |             raise Exception("STRUCTURES array is broken")
293 | 
294 | 
295 | def make_setters(structure):
296 |     parts = []
297 | 
298 |     parts.append("    {")
299 |     parts.append("        let s = unsafe {{ "
300 |                  "std::mem::transmute::<_, &mut vk::{}>(s.{}) }};".format(
301 |                      structure.name,
302 |                      structure.variable))
303 | 
304 |     for child in structure.children:
305 |         if isinstance(child, Structure):
306 |             parts.extend(map(lambda line: "    " + line,
307 |                              make_setters(child)))
308 |         elif isinstance(child, Property):
309 |             parts.append("        s.{} = key.{}_properties[{}] as {};".format(
310 |                 child.name,
311 |                 child.base_type,
312 |                 child.num,
313 |                 child.vk_type))
314 | 
315 |     parts.append("    }")
316 | 
317 |     return parts
318 | 
319 | 
320 | def main():
321 |     template = Template(TEMPLATE)
322 | 
323 |     props = Properties()
324 |     for structure in STRUCTURES:
325 |         get_props(structure, props)
326 | 
327 |     setters = "\n".join(sum(map(make_setters, STRUCTURES), start=[]))
328 | 
329 |     print(template.render(props = props.values, setters = setters))
330 | 
331 | 
332 | if __name__ == '__main__':
333 |     main()
334 | 
```

--------------------------------------------------------------------------------
/vkrunner/vkrunner/stream.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::source;
 26 | use std::io;
 27 | use std::io::BufRead;
 28 | use std::fmt;
 29 | use std::fs;
 30 | 
 31 | // Encapsulates the two possible buf readers (either from a file or
 32 | // from a string) that the stream will use. I don’t think we can put
 33 | // this behind a boxed trait object because we can’t tell Rust that
 34 | // the box won’t outlive the Stream object.
 35 | #[derive(Debug)]
 36 | enum Reader<'a> {
 37 |     File(io::BufReader<fs::File>),
 38 |     String(io::BufReader<&'a [u8]>),
 39 | }
 40 | 
 41 | /// A struct used to read lines from a [Source](source::Source). This
 42 | /// will handle concatening lines that end with the line continuation
 43 | /// character (`\`) and the token replacements.
 44 | #[derive(Debug)]
 45 | pub struct Stream<'a> {
 46 |     source: &'a source::Source,
 47 |     reader: Reader<'a>,
 48 | 
 49 |     line_num: usize,
 50 |     next_line_num: usize,
 51 |     reached_eof: bool,
 52 | }
 53 | 
 54 | /// An error that can be returned from [Stream::read_line] or [Stream::new].
 55 | #[derive(Debug)]
 56 | pub enum StreamError {
 57 |     IoError(io::Error),
 58 |     /// A token replacement causes an infinite loop of replacements to
 59 |     /// occur.
 60 |     TokenReplacementLoop,
 61 | }
 62 | 
 63 | impl fmt::Display for StreamError {
 64 |     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
 65 |         match self {
 66 |             StreamError::IoError(e) => e.fmt(f),
 67 |             StreamError::TokenReplacementLoop => {
 68 |                 write!(f, "The token replacements cause an infinite loop")
 69 |             },
 70 |         }
 71 |     }
 72 | }
 73 | 
 74 | impl std::convert::From<io::Error> for StreamError {
 75 |     fn from(value: io::Error) -> StreamError {
 76 |         StreamError::IoError(value)
 77 |     }
 78 | }
 79 | 
 80 | impl<'a> Stream<'a> {
 81 |     /// Constructs a new [Stream] that will read lines from the given
 82 |     /// [Source](source::Source). The construction can fail if the
 83 |     /// stream is a file source and opening the file fails. In that
 84 |     /// case the returned [StreamError] will contain an
 85 |     /// [io::Error](std::io::Error).
 86 |     pub fn new(source: &source::Source) -> Result<Stream, StreamError> {
 87 |         let reader = match source.data() {
 88 |             source::Data::File { filename } => {
 89 |                 let file = fs::File::open(filename)?;
 90 |                 Reader::File(io::BufReader::new(file))
 91 |             },
 92 |             source::Data::String { source } => {
 93 |                 Reader::String(io::BufReader::new(source.as_bytes()))
 94 |             },
 95 |         };
 96 | 
 97 |         Ok(Stream {
 98 |             source,
 99 |             reader,
100 |             line_num: 0,
101 |             next_line_num: 1,
102 |             reached_eof: false,
103 |         })
104 |     }
105 | 
106 |     /// Read a line from the stream and append it to the given String.
107 |     /// This will handle the line continuation characters (`\`) and
108 |     /// the token replacements set on the [Source](source::Source).
109 |     ///
110 |     /// The length of the data appended to the string is returned. If
111 |     /// the end of the source is reached then it will return 0.
112 |     pub fn read_line(
113 |         &mut self,
114 |         line: &mut String
115 |     ) -> Result<usize, StreamError> {
116 |         let start_length = line.len();
117 | 
118 |         self.line_num = self.next_line_num;
119 | 
120 |         while !self.reached_eof {
121 |             let length = match &mut self.reader {
122 |                 Reader::File(r) => r.read_line(line)?,
123 |                 Reader::String(r) => r.read_line(line)?,
124 |             };
125 | 
126 |             if length == 0 {
127 |                 self.reached_eof = true;
128 |                 break;
129 |             }
130 | 
131 |             self.next_line_num += 1;
132 | 
133 |             if length >= 2 {
134 |                 if line.ends_with("\\\n") {
135 |                     line.truncate(line.len() - 2);
136 |                     continue;
137 |                 } else if length >= 3 && line.ends_with("\\\r\n") {
138 |                     line.truncate(line.len() - 3);
139 |                     continue;
140 |                 }
141 |             }
142 | 
143 |             break;
144 |         }
145 | 
146 |         self.process_token_replacements(line, start_length)?;
147 | 
148 |         Ok(line.len() - start_length)
149 |     }
150 | 
151 |     /// Returns the line number in the source data of the start of the
152 |     /// last line that was returned by [read_line](Stream::read_line).
153 |     /// For example, if the source file is like this:
154 |     ///
155 |     /// ```text
156 |     /// line one \
157 |     /// continuation of line one.
158 |     /// line two \
159 |     /// continuation of line two.
160 |     /// ```
161 |     ///
162 |     /// then the second time `read_line` is called it will append
163 |     /// “line two continuation of line two” and
164 |     /// [line_num](Stream::line_num) will report 3 because the line
165 |     /// starts on the third line of the source data.
166 |     pub fn line_num(&self) -> usize {
167 |         self.line_num
168 |     }
169 | 
170 |     fn process_token_replacements(
171 |         &self,
172 |         line: &mut String,
173 |         start_pos: usize
174 |     ) -> Result<(), StreamError> {
175 |         let mut count = 0usize;
176 | 
177 |         // Loop through each valid position in the line string. We
178 |         // can’t safely use an iterator because we’re going to modify
179 |         // the string as we iterate
180 |         let mut pos = start_pos;
181 | 
182 |         while pos < line.len() {
183 |             'token_loop: loop {
184 |                 for token_replacement in self.source.token_replacements() {
185 |                     if line[pos..].starts_with(&token_replacement.token) {
186 |                         count += 1;
187 | 
188 |                         // If we’ve replaced at least 1000 tokens then
189 |                         // something has probably gone wrong and this
190 |                         // is never going to finish.
191 |                         if count >= 1000 {
192 |                             return Err(StreamError::TokenReplacementLoop);
193 |                         }
194 | 
195 |                         line.replace_range(
196 |                             pos..pos + token_replacement.token.len(),
197 |                             &token_replacement.replacement,
198 |                         );
199 | 
200 |                         // Start looking for tokens from the start of
201 |                         // the list in case the replacement contains
202 |                         // one of the earlier tokens
203 |                         continue 'token_loop;
204 |                     }
205 |                 }
206 | 
207 |                 break 'token_loop;
208 |             }
209 | 
210 |             // Move to the next character. It would be nice if we
211 |             // could do this by just looking at the first byte of the
212 |             // UTF-8 sequence but there doesn’t seem to be a handy
213 |             // Rust API for that.
214 |             pos += line[pos..].chars().next().unwrap().len_utf8();
215 |         }
216 | 
217 |         Ok(())
218 |     }
219 | }
220 | 
221 | #[cfg(test)]
222 | mod test {
223 |     use super::*;
224 | 
225 |     #[test]
226 |     fn test_line_continuation() {
227 |         let source = source::Source::from_string(
228 |             "line one \\\n\
229 |              more line one\n\
230 |              line three \\\n\
231 |              is really long \\\n\
232 |              \\\n\
233 |              and even has blank lines".to_string()
234 |         );
235 |         let mut stream = Stream::new(&source).unwrap();
236 | 
237 |         let mut line = String::new();
238 |         assert_eq!(stream.read_line(&mut line).unwrap(), 23);
239 |         assert_eq!(line, "line one more line one\n");
240 |         assert_eq!(stream.line_num(), 1);
241 | 
242 |         assert_eq!(stream.read_line(&mut line).unwrap(), 50);
243 |         assert_eq!(
244 |             &line[23..],
245 |             "line three is really long and even has blank lines",
246 |         );
247 |         assert_eq!(stream.line_num(), 3);
248 | 
249 |         // The line can also be continued if it has Windows-style line endings
250 |         let source = source::Source::from_string(
251 |             "line one \\\r\n\
252 |              more line one\n\
253 |              line three \r what".to_string()
254 |         );
255 |         let mut stream = Stream::new(&source).unwrap();
256 |         let mut line = String::new();
257 | 
258 |         assert_eq!(stream.read_line(&mut line).unwrap(), 23);
259 |         assert_eq!(line, "line one more line one\n");
260 |         assert_eq!(stream.line_num(), 1);
261 | 
262 |         line.clear();
263 |         assert_eq!(stream.read_line(&mut line).unwrap(), 17);
264 |         assert_eq!(line, "line three \r what");
265 |         assert_eq!(stream.line_num(), 3);
266 | 
267 |         // Backslashes in the middle of the string should just be left alone
268 |         let source = source::Source::from_string(
269 |             "I am happy \\o//".to_string()
270 |         );
271 |         let mut stream = Stream::new(&source).unwrap();
272 |         let mut line = String::new();
273 |         assert_eq!(stream.read_line(&mut line).unwrap(), 15);
274 |         assert_eq!(line, "I am happy \\o//");
275 |     }
276 | 
277 |     #[test]
278 |     fn test_missing_file() {
279 |         let source = source::Source::from_file(
280 |             "this-file-does-not-exist".to_string().into()
281 |         );
282 |         let e = Stream::new(&source).unwrap_err();
283 |         match e {
284 |             StreamError::IoError(e) => {
285 |                 assert_eq!(e.kind(), io::ErrorKind::NotFound);
286 |             },
287 |             _ => unreachable!("expected StreamError::IoError, got: {}", e),
288 |         }
289 |     }
290 | 
291 |     fn run_test_file_source(filename: String) {
292 |         fs::write(&filename, "my source code").unwrap();
293 | 
294 |         let source = source::Source::from_file(filename.into());
295 |         let mut stream = Stream::new(&source).unwrap();
296 |         let mut line = String::new();
297 |         assert_eq!(stream.read_line(&mut line).unwrap(), 14);
298 |         assert_eq!(line, "my source code");
299 | 
300 |         // EOF should return 0
301 |         assert_eq!(stream.read_line(&mut line).unwrap(), 0);
302 |         // It should also work a second time
303 |         assert_eq!(stream.read_line(&mut line).unwrap(), 0);
304 |     }
305 | 
306 |     #[test]
307 |     fn test_file_source() {
308 |         let mut filename = std::env::temp_dir();
309 |         filename.push("vkrunner-test-file-source");
310 |         let filename_str = filename.to_str().unwrap().to_owned();
311 | 
312 |         // Catch the unwind to try to remove the file that we created
313 |         // if the test fails
314 |         let r = std::panic::catch_unwind(
315 |             move || run_test_file_source(filename_str)
316 |         );
317 | 
318 |         if let Err(e) = fs::remove_file(filename) {
319 |             assert_eq!(e.kind(), io::ErrorKind::NotFound);
320 |         }
321 | 
322 |         if let Err(e) = r {
323 |             std::panic::resume_unwind(e);
324 |         }
325 |     }
326 | 
327 |     macro_rules! replace_tokens {
328 |         ($source:expr, $expected:expr, $($token:expr, $replacement:expr),*) => {
329 |             let mut source = source::Source::from_string($source.to_owned());
330 | 
331 |             $(
332 |                 {
333 |                     source.add_token_replacement(
334 |                         $token.to_owned(),
335 |                         $replacement.to_owned()
336 |                     );
337 |                 }
338 |             )*;
339 | 
340 |             let mut stream = Stream::new(&source).unwrap();
341 |             let mut line = String::new();
342 | 
343 |             assert_eq!(stream.read_line(&mut line).unwrap(), $expected.len());
344 |             assert_eq!(line, $expected);
345 |         };
346 |     }
347 | 
348 |     #[test]
349 |     fn test_token_replacements() {
350 |         // Simple replacement
351 |         replace_tokens!(
352 |             "one two",
353 |             "1 2",
354 |             "one", "1",
355 |             "two", "2"
356 |         );
357 |         // Line continuation within a replacement
358 |         replace_tokens!(
359 |             "tok\\\n\
360 |              ens are neat",
361 |             "replacements are neat",
362 |             "token",
363 |             "replacement"
364 |         );
365 |         // Chain of replacements
366 |         replace_tokens!(
367 |             "I like this",
368 |             "I like tomatoes",
369 |             "this", "thatthing",
370 |             "that", "t",
371 |             "thing", "omatoes"
372 |         );
373 | 
374 |         let mut source = source::Source::from_string(
375 |             "Infinite recursion!".to_string()
376 |         );
377 |         source.add_token_replacement(
378 |             "recursion".to_string(),
379 |             "deeper".to_string(),
380 |         );
381 |         source.add_token_replacement(
382 |             "deeper".to_string(),
383 |             "keep-going".to_string(),
384 |         );
385 |         source.add_token_replacement(
386 |             "keep-going".to_string(),
387 |             "recursion".to_string(),
388 |         );
389 |         let mut stream = Stream::new(&source).unwrap();
390 |         let mut line = String::new();
391 |         let e = stream.read_line(&mut line).unwrap_err();
392 |         assert!(matches!(e, StreamError::TokenReplacementLoop));
393 |         assert_eq!(
394 |             e.to_string(),
395 |             "The token replacements cause an infinite loop"
396 |         );
397 | 
398 |         // Try an empty token
399 |         let mut source = source::Source::from_string(
400 |             "Infinite recursion!".to_string()
401 |         );
402 |         source.add_token_replacement(
403 |             "".to_string(),
404 |             "ever longer".to_string(),
405 |         );
406 |         let mut stream = Stream::new(&source).unwrap();
407 |         let mut line = String::new();
408 |         let e = stream.read_line(&mut line).unwrap_err();
409 |         assert!(matches!(e, StreamError::TokenReplacementLoop));
410 |     }
411 | }
412 | 
```

--------------------------------------------------------------------------------
/vkrunner/vkrunner/features.rs:
--------------------------------------------------------------------------------

```rust
  1 | // Automatically generated by make-features.py
  2 | 
  3 | static EXTENSIONS: [Extension; 29] = [
  4 |     Extension {
  5 |         name_bytes: vk::VK_KHR_16BIT_STORAGE_EXTENSION_NAME,
  6 |         struct_size: mem::size_of::<vk::VkPhysicalDevice16BitStorageFeaturesKHR>(),
  7 |         struct_type: vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES_KHR,
  8 |         features: &[
  9 |             "storageBuffer16BitAccess",
 10 |             "uniformAndStorageBuffer16BitAccess",
 11 |             "storagePushConstant16",
 12 |             "storageInputOutput16",
 13 |         ],
 14 |     },
 15 |     Extension {
 16 |         name_bytes: vk::VK_KHR_8BIT_STORAGE_EXTENSION_NAME,
 17 |         struct_size: mem::size_of::<vk::VkPhysicalDevice8BitStorageFeaturesKHR>(),
 18 |         struct_type: vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_8BIT_STORAGE_FEATURES_KHR,
 19 |         features: &[
 20 |             "storageBuffer8BitAccess",
 21 |             "uniformAndStorageBuffer8BitAccess",
 22 |             "storagePushConstant8",
 23 |         ],
 24 |     },
 25 |     Extension {
 26 |         name_bytes: vk::VK_EXT_ASTC_DECODE_MODE_EXTENSION_NAME,
 27 |         struct_size: mem::size_of::<vk::VkPhysicalDeviceASTCDecodeFeaturesEXT>(),
 28 |         struct_type: vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ASTC_DECODE_FEATURES_EXT,
 29 |         features: &[
 30 |             "decodeModeSharedExponent",
 31 |         ],
 32 |     },
 33 |     Extension {
 34 |         name_bytes: vk::VK_EXT_BLEND_OPERATION_ADVANCED_EXTENSION_NAME,
 35 |         struct_size: mem::size_of::<vk::VkPhysicalDeviceBlendOperationAdvancedFeaturesEXT>(),
 36 |         struct_type: vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BLEND_OPERATION_ADVANCED_FEATURES_EXT,
 37 |         features: &[
 38 |             "advancedBlendCoherentOperations",
 39 |         ],
 40 |     },
 41 |     Extension {
 42 |         name_bytes: vk::VK_EXT_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME,
 43 |         struct_size: mem::size_of::<vk::VkPhysicalDeviceBufferDeviceAddressFeaturesEXT>(),
 44 |         struct_type: vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES_EXT,
 45 |         features: &[
 46 |             "bufferDeviceAddress",
 47 |             "bufferDeviceAddressCaptureReplay",
 48 |             "bufferDeviceAddressMultiDevice",
 49 |         ],
 50 |     },
 51 |     Extension {
 52 |         name_bytes: vk::VK_KHR_COMPUTE_SHADER_DERIVATIVES_EXTENSION_NAME,
 53 |         struct_size: mem::size_of::<vk::VkPhysicalDeviceComputeShaderDerivativesFeaturesKHR>(),
 54 |         struct_type: vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COMPUTE_SHADER_DERIVATIVES_FEATURES_KHR,
 55 |         features: &[
 56 |             "computeDerivativeGroupQuads",
 57 |             "computeDerivativeGroupLinear",
 58 |         ],
 59 |     },
 60 |     Extension {
 61 |         name_bytes: vk::VK_EXT_CONDITIONAL_RENDERING_EXTENSION_NAME,
 62 |         struct_size: mem::size_of::<vk::VkPhysicalDeviceConditionalRenderingFeaturesEXT>(),
 63 |         struct_type: vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CONDITIONAL_RENDERING_FEATURES_EXT,
 64 |         features: &[
 65 |             "conditionalRendering",
 66 |             "inheritedConditionalRendering",
 67 |         ],
 68 |     },
 69 |     Extension {
 70 |         name_bytes: vk::VK_NV_CORNER_SAMPLED_IMAGE_EXTENSION_NAME,
 71 |         struct_size: mem::size_of::<vk::VkPhysicalDeviceCornerSampledImageFeaturesNV>(),
 72 |         struct_type: vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CORNER_SAMPLED_IMAGE_FEATURES_NV,
 73 |         features: &[
 74 |             "cornerSampledImage",
 75 |         ],
 76 |     },
 77 |     Extension {
 78 |         name_bytes: vk::VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME,
 79 |         struct_size: mem::size_of::<vk::VkPhysicalDeviceDescriptorIndexingFeaturesEXT>(),
 80 |         struct_type: vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_FEATURES_EXT,
 81 |         features: &[
 82 |             "shaderInputAttachmentArrayDynamicIndexing",
 83 |             "shaderUniformTexelBufferArrayDynamicIndexing",
 84 |             "shaderStorageTexelBufferArrayDynamicIndexing",
 85 |             "shaderUniformBufferArrayNonUniformIndexing",
 86 |             "shaderSampledImageArrayNonUniformIndexing",
 87 |             "shaderStorageBufferArrayNonUniformIndexing",
 88 |             "shaderStorageImageArrayNonUniformIndexing",
 89 |             "shaderInputAttachmentArrayNonUniformIndexing",
 90 |             "shaderUniformTexelBufferArrayNonUniformIndexing",
 91 |             "shaderStorageTexelBufferArrayNonUniformIndexing",
 92 |             "descriptorBindingUniformBufferUpdateAfterBind",
 93 |             "descriptorBindingSampledImageUpdateAfterBind",
 94 |             "descriptorBindingStorageImageUpdateAfterBind",
 95 |             "descriptorBindingStorageBufferUpdateAfterBind",
 96 |             "descriptorBindingUniformTexelBufferUpdateAfterBind",
 97 |             "descriptorBindingStorageTexelBufferUpdateAfterBind",
 98 |             "descriptorBindingUpdateUnusedWhilePending",
 99 |             "descriptorBindingPartiallyBound",
100 |             "descriptorBindingVariableDescriptorCount",
101 |             "runtimeDescriptorArray",
102 |         ],
103 |     },
104 |     Extension {
105 |         name_bytes: vk::VK_NV_SCISSOR_EXCLUSIVE_EXTENSION_NAME,
106 |         struct_size: mem::size_of::<vk::VkPhysicalDeviceExclusiveScissorFeaturesNV>(),
107 |         struct_type: vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXCLUSIVE_SCISSOR_FEATURES_NV,
108 |         features: &[
109 |             "exclusiveScissor",
110 |         ],
111 |     },
112 |     Extension {
113 |         name_bytes: vk::VK_KHR_SHADER_FLOAT16_INT8_EXTENSION_NAME,
114 |         struct_size: mem::size_of::<vk::VkPhysicalDeviceShaderFloat16Int8FeaturesKHR>(),
115 |         struct_type: vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_FLOAT16_INT8_FEATURES_KHR,
116 |         features: &[
117 |             "shaderFloat16",
118 |             "shaderInt8",
119 |         ],
120 |     },
121 |     Extension {
122 |         name_bytes: vk::VK_EXT_FRAGMENT_DENSITY_MAP_EXTENSION_NAME,
123 |         struct_size: mem::size_of::<vk::VkPhysicalDeviceFragmentDensityMapFeaturesEXT>(),
124 |         struct_type: vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_FEATURES_EXT,
125 |         features: &[
126 |             "fragmentDensityMap",
127 |             "fragmentDensityMapDynamic",
128 |             "fragmentDensityMapNonSubsampledImages",
129 |         ],
130 |     },
131 |     Extension {
132 |         name_bytes: vk::VK_KHR_FRAGMENT_SHADER_BARYCENTRIC_EXTENSION_NAME,
133 |         struct_size: mem::size_of::<vk::VkPhysicalDeviceFragmentShaderBarycentricFeaturesKHR>(),
134 |         struct_type: vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADER_BARYCENTRIC_FEATURES_KHR,
135 |         features: &[
136 |             "fragmentShaderBarycentric",
137 |         ],
138 |     },
139 |     Extension {
140 |         name_bytes: vk::VK_EXT_INLINE_UNIFORM_BLOCK_EXTENSION_NAME,
141 |         struct_size: mem::size_of::<vk::VkPhysicalDeviceInlineUniformBlockFeaturesEXT>(),
142 |         struct_type: vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INLINE_UNIFORM_BLOCK_FEATURES_EXT,
143 |         features: &[
144 |             "inlineUniformBlock",
145 |             "descriptorBindingInlineUniformBlockUpdateAfterBind",
146 |         ],
147 |     },
148 |     Extension {
149 |         name_bytes: vk::VK_EXT_MEMORY_PRIORITY_EXTENSION_NAME,
150 |         struct_size: mem::size_of::<vk::VkPhysicalDeviceMemoryPriorityFeaturesEXT>(),
151 |         struct_type: vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PRIORITY_FEATURES_EXT,
152 |         features: &[
153 |             "memoryPriority",
154 |         ],
155 |     },
156 |     Extension {
157 |         name_bytes: vk::VK_NV_MESH_SHADER_EXTENSION_NAME,
158 |         struct_size: mem::size_of::<vk::VkPhysicalDeviceMeshShaderFeaturesNV>(),
159 |         struct_type: vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MESH_SHADER_FEATURES_NV,
160 |         features: &[
161 |             "taskShader",
162 |             "meshShader",
163 |         ],
164 |     },
165 |     Extension {
166 |         name_bytes: vk::VK_KHR_MULTIVIEW_EXTENSION_NAME,
167 |         struct_size: mem::size_of::<vk::VkPhysicalDeviceMultiviewFeaturesKHR>(),
168 |         struct_type: vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES_KHR,
169 |         features: &[
170 |             "multiview",
171 |             "multiviewGeometryShader",
172 |             "multiviewTessellationShader",
173 |         ],
174 |     },
175 |     Extension {
176 |         name_bytes: vk::VK_NV_REPRESENTATIVE_FRAGMENT_TEST_EXTENSION_NAME,
177 |         struct_size: mem::size_of::<vk::VkPhysicalDeviceRepresentativeFragmentTestFeaturesNV>(),
178 |         struct_type: vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_REPRESENTATIVE_FRAGMENT_TEST_FEATURES_NV,
179 |         features: &[
180 |             "representativeFragmentTest",
181 |         ],
182 |     },
183 |     Extension {
184 |         name_bytes: vk::VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME,
185 |         struct_size: mem::size_of::<vk::VkPhysicalDeviceSamplerYcbcrConversionFeaturesKHR>(),
186 |         struct_type: vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES_KHR,
187 |         features: &[
188 |             "samplerYcbcrConversion",
189 |         ],
190 |     },
191 |     Extension {
192 |         name_bytes: vk::VK_EXT_SCALAR_BLOCK_LAYOUT_EXTENSION_NAME,
193 |         struct_size: mem::size_of::<vk::VkPhysicalDeviceScalarBlockLayoutFeaturesEXT>(),
194 |         struct_type: vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SCALAR_BLOCK_LAYOUT_FEATURES_EXT,
195 |         features: &[
196 |             "scalarBlockLayout",
197 |         ],
198 |     },
199 |     Extension {
200 |         name_bytes: vk::VK_KHR_SHADER_ATOMIC_INT64_EXTENSION_NAME,
201 |         struct_size: mem::size_of::<vk::VkPhysicalDeviceShaderAtomicInt64FeaturesKHR>(),
202 |         struct_type: vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_INT64_FEATURES_KHR,
203 |         features: &[
204 |             "shaderBufferInt64Atomics",
205 |             "shaderSharedInt64Atomics",
206 |         ],
207 |     },
208 |     Extension {
209 |         name_bytes: vk::VK_NV_SHADER_IMAGE_FOOTPRINT_EXTENSION_NAME,
210 |         struct_size: mem::size_of::<vk::VkPhysicalDeviceShaderImageFootprintFeaturesNV>(),
211 |         struct_type: vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_IMAGE_FOOTPRINT_FEATURES_NV,
212 |         features: &[
213 |             "imageFootprint",
214 |         ],
215 |     },
216 |     Extension {
217 |         name_bytes: vk::VK_NV_SHADING_RATE_IMAGE_EXTENSION_NAME,
218 |         struct_size: mem::size_of::<vk::VkPhysicalDeviceShadingRateImageFeaturesNV>(),
219 |         struct_type: vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADING_RATE_IMAGE_FEATURES_NV,
220 |         features: &[
221 |             "shadingRateImage",
222 |             "shadingRateCoarseSampleOrder",
223 |         ],
224 |     },
225 |     Extension {
226 |         name_bytes: vk::VK_EXT_TRANSFORM_FEEDBACK_EXTENSION_NAME,
227 |         struct_size: mem::size_of::<vk::VkPhysicalDeviceTransformFeedbackFeaturesEXT>(),
228 |         struct_type: vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_FEATURES_EXT,
229 |         features: &[
230 |             "transformFeedback",
231 |             "geometryStreams",
232 |         ],
233 |     },
234 |     Extension {
235 |         name_bytes: vk::VK_KHR_VARIABLE_POINTERS_EXTENSION_NAME,
236 |         struct_size: mem::size_of::<vk::VkPhysicalDeviceVariablePointersFeaturesKHR>(),
237 |         struct_type: vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTERS_FEATURES_KHR,
238 |         features: &[
239 |             "variablePointersStorageBuffer",
240 |             "variablePointers",
241 |         ],
242 |     },
243 |     Extension {
244 |         name_bytes: vk::VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME,
245 |         struct_size: mem::size_of::<vk::VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT>(),
246 |         struct_type: vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_FEATURES_EXT,
247 |         features: &[
248 |             "vertexAttributeInstanceRateDivisor",
249 |             "vertexAttributeInstanceRateZeroDivisor",
250 |         ],
251 |     },
252 |     Extension {
253 |         name_bytes: vk::VK_KHR_VULKAN_MEMORY_MODEL_EXTENSION_NAME,
254 |         struct_size: mem::size_of::<vk::VkPhysicalDeviceVulkanMemoryModelFeaturesKHR>(),
255 |         struct_type: vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_MEMORY_MODEL_FEATURES_KHR,
256 |         features: &[
257 |             "vulkanMemoryModel",
258 |             "vulkanMemoryModelDeviceScope",
259 |             "vulkanMemoryModelAvailabilityVisibilityChains",
260 |         ],
261 |     },
262 |     Extension {
263 |         name_bytes: vk::VK_KHR_COOPERATIVE_MATRIX_EXTENSION_NAME,
264 |         struct_size: mem::size_of::<vk::VkPhysicalDeviceCooperativeMatrixFeaturesKHR>(),
265 |         struct_type: vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COOPERATIVE_MATRIX_FEATURES_KHR,
266 |         features: &[
267 |             "cooperativeMatrix",
268 |             "cooperativeMatrixRobustBufferAccess",
269 |         ],
270 |     },
271 |     Extension {
272 |         name_bytes: vk::VK_EXT_SUBGROUP_SIZE_CONTROL_EXTENSION_NAME,
273 |         struct_size: mem::size_of::<vk::VkPhysicalDeviceSubgroupSizeControlFeaturesEXT>(),
274 |         struct_type: vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_SIZE_CONTROL_FEATURES_EXT,
275 |         features: &[
276 |             "subgroupSizeControl",
277 |             "computeFullSubgroups",
278 |         ],
279 |     },
280 | ];
281 | 
282 | const N_BASE_FEATURES: usize = 55;
283 | 
284 | static BASE_FEATURES: [&'static str; N_BASE_FEATURES] = [
285 |     "robustBufferAccess",
286 |     "fullDrawIndexUint32",
287 |     "imageCubeArray",
288 |     "independentBlend",
289 |     "geometryShader",
290 |     "tessellationShader",
291 |     "sampleRateShading",
292 |     "dualSrcBlend",
293 |     "logicOp",
294 |     "multiDrawIndirect",
295 |     "drawIndirectFirstInstance",
296 |     "depthClamp",
297 |     "depthBiasClamp",
298 |     "fillModeNonSolid",
299 |     "depthBounds",
300 |     "wideLines",
301 |     "largePoints",
302 |     "alphaToOne",
303 |     "multiViewport",
304 |     "samplerAnisotropy",
305 |     "textureCompressionETC2",
306 |     "textureCompressionASTC_LDR",
307 |     "textureCompressionBC",
308 |     "occlusionQueryPrecise",
309 |     "pipelineStatisticsQuery",
310 |     "vertexPipelineStoresAndAtomics",
311 |     "fragmentStoresAndAtomics",
312 |     "shaderTessellationAndGeometryPointSize",
313 |     "shaderImageGatherExtended",
314 |     "shaderStorageImageExtendedFormats",
315 |     "shaderStorageImageMultisample",
316 |     "shaderStorageImageReadWithoutFormat",
317 |     "shaderStorageImageWriteWithoutFormat",
318 |     "shaderUniformBufferArrayDynamicIndexing",
319 |     "shaderSampledImageArrayDynamicIndexing",
320 |     "shaderStorageBufferArrayDynamicIndexing",
321 |     "shaderStorageImageArrayDynamicIndexing",
322 |     "shaderClipDistance",
323 |     "shaderCullDistance",
324 |     "shaderFloat64",
325 |     "shaderInt64",
326 |     "shaderInt16",
327 |     "shaderResourceResidency",
328 |     "shaderResourceMinLod",
329 |     "sparseBinding",
330 |     "sparseResidencyBuffer",
331 |     "sparseResidencyImage2D",
332 |     "sparseResidencyImage3D",
333 |     "sparseResidency2Samples",
334 |     "sparseResidency4Samples",
335 |     "sparseResidency8Samples",
336 |     "sparseResidency16Samples",
337 |     "sparseResidencyAliased",
338 |     "variableMultisampleRate",
339 |     "inheritedQueries",
340 | ];
341 | 
342 | 
```

--------------------------------------------------------------------------------
/vkrunner/include/vk_video/vulkan_video_codec_h264std.h:
--------------------------------------------------------------------------------

```
  1 | #ifndef VULKAN_VIDEO_CODEC_H264STD_H_
  2 | #define VULKAN_VIDEO_CODEC_H264STD_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_h264std is a preprocessor guard. Do not pass it to API calls.
 23 | #define vulkan_video_codec_h264std 1
 24 | #include "vulkan_video_codecs_common.h"
 25 | #define STD_VIDEO_H264_CPB_CNT_LIST_SIZE  32
 26 | #define STD_VIDEO_H264_SCALING_LIST_4X4_NUM_LISTS 6
 27 | #define STD_VIDEO_H264_SCALING_LIST_4X4_NUM_ELEMENTS 16
 28 | #define STD_VIDEO_H264_SCALING_LIST_8X8_NUM_LISTS 6
 29 | #define STD_VIDEO_H264_SCALING_LIST_8X8_NUM_ELEMENTS 64
 30 | #define STD_VIDEO_H264_MAX_NUM_LIST_REF   32
 31 | #define STD_VIDEO_H264_MAX_CHROMA_PLANES  2
 32 | #define STD_VIDEO_H264_NO_REFERENCE_PICTURE 0xFF
 33 | 
 34 | typedef enum StdVideoH264ChromaFormatIdc {
 35 |     STD_VIDEO_H264_CHROMA_FORMAT_IDC_MONOCHROME = 0,
 36 |     STD_VIDEO_H264_CHROMA_FORMAT_IDC_420 = 1,
 37 |     STD_VIDEO_H264_CHROMA_FORMAT_IDC_422 = 2,
 38 |     STD_VIDEO_H264_CHROMA_FORMAT_IDC_444 = 3,
 39 |     STD_VIDEO_H264_CHROMA_FORMAT_IDC_INVALID = 0x7FFFFFFF,
 40 |     STD_VIDEO_H264_CHROMA_FORMAT_IDC_MAX_ENUM = 0x7FFFFFFF
 41 | } StdVideoH264ChromaFormatIdc;
 42 | 
 43 | typedef enum StdVideoH264ProfileIdc {
 44 |     STD_VIDEO_H264_PROFILE_IDC_BASELINE = 66,
 45 |     STD_VIDEO_H264_PROFILE_IDC_MAIN = 77,
 46 |     STD_VIDEO_H264_PROFILE_IDC_HIGH = 100,
 47 |     STD_VIDEO_H264_PROFILE_IDC_HIGH_444_PREDICTIVE = 244,
 48 |     STD_VIDEO_H264_PROFILE_IDC_INVALID = 0x7FFFFFFF,
 49 |     STD_VIDEO_H264_PROFILE_IDC_MAX_ENUM = 0x7FFFFFFF
 50 | } StdVideoH264ProfileIdc;
 51 | 
 52 | typedef enum StdVideoH264LevelIdc {
 53 |     STD_VIDEO_H264_LEVEL_IDC_1_0 = 0,
 54 |     STD_VIDEO_H264_LEVEL_IDC_1_1 = 1,
 55 |     STD_VIDEO_H264_LEVEL_IDC_1_2 = 2,
 56 |     STD_VIDEO_H264_LEVEL_IDC_1_3 = 3,
 57 |     STD_VIDEO_H264_LEVEL_IDC_2_0 = 4,
 58 |     STD_VIDEO_H264_LEVEL_IDC_2_1 = 5,
 59 |     STD_VIDEO_H264_LEVEL_IDC_2_2 = 6,
 60 |     STD_VIDEO_H264_LEVEL_IDC_3_0 = 7,
 61 |     STD_VIDEO_H264_LEVEL_IDC_3_1 = 8,
 62 |     STD_VIDEO_H264_LEVEL_IDC_3_2 = 9,
 63 |     STD_VIDEO_H264_LEVEL_IDC_4_0 = 10,
 64 |     STD_VIDEO_H264_LEVEL_IDC_4_1 = 11,
 65 |     STD_VIDEO_H264_LEVEL_IDC_4_2 = 12,
 66 |     STD_VIDEO_H264_LEVEL_IDC_5_0 = 13,
 67 |     STD_VIDEO_H264_LEVEL_IDC_5_1 = 14,
 68 |     STD_VIDEO_H264_LEVEL_IDC_5_2 = 15,
 69 |     STD_VIDEO_H264_LEVEL_IDC_6_0 = 16,
 70 |     STD_VIDEO_H264_LEVEL_IDC_6_1 = 17,
 71 |     STD_VIDEO_H264_LEVEL_IDC_6_2 = 18,
 72 |     STD_VIDEO_H264_LEVEL_IDC_INVALID = 0x7FFFFFFF,
 73 |     STD_VIDEO_H264_LEVEL_IDC_MAX_ENUM = 0x7FFFFFFF
 74 | } StdVideoH264LevelIdc;
 75 | 
 76 | typedef enum StdVideoH264PocType {
 77 |     STD_VIDEO_H264_POC_TYPE_0 = 0,
 78 |     STD_VIDEO_H264_POC_TYPE_1 = 1,
 79 |     STD_VIDEO_H264_POC_TYPE_2 = 2,
 80 |     STD_VIDEO_H264_POC_TYPE_INVALID = 0x7FFFFFFF,
 81 |     STD_VIDEO_H264_POC_TYPE_MAX_ENUM = 0x7FFFFFFF
 82 | } StdVideoH264PocType;
 83 | 
 84 | typedef enum StdVideoH264AspectRatioIdc {
 85 |     STD_VIDEO_H264_ASPECT_RATIO_IDC_UNSPECIFIED = 0,
 86 |     STD_VIDEO_H264_ASPECT_RATIO_IDC_SQUARE = 1,
 87 |     STD_VIDEO_H264_ASPECT_RATIO_IDC_12_11 = 2,
 88 |     STD_VIDEO_H264_ASPECT_RATIO_IDC_10_11 = 3,
 89 |     STD_VIDEO_H264_ASPECT_RATIO_IDC_16_11 = 4,
 90 |     STD_VIDEO_H264_ASPECT_RATIO_IDC_40_33 = 5,
 91 |     STD_VIDEO_H264_ASPECT_RATIO_IDC_24_11 = 6,
 92 |     STD_VIDEO_H264_ASPECT_RATIO_IDC_20_11 = 7,
 93 |     STD_VIDEO_H264_ASPECT_RATIO_IDC_32_11 = 8,
 94 |     STD_VIDEO_H264_ASPECT_RATIO_IDC_80_33 = 9,
 95 |     STD_VIDEO_H264_ASPECT_RATIO_IDC_18_11 = 10,
 96 |     STD_VIDEO_H264_ASPECT_RATIO_IDC_15_11 = 11,
 97 |     STD_VIDEO_H264_ASPECT_RATIO_IDC_64_33 = 12,
 98 |     STD_VIDEO_H264_ASPECT_RATIO_IDC_160_99 = 13,
 99 |     STD_VIDEO_H264_ASPECT_RATIO_IDC_4_3 = 14,
100 |     STD_VIDEO_H264_ASPECT_RATIO_IDC_3_2 = 15,
101 |     STD_VIDEO_H264_ASPECT_RATIO_IDC_2_1 = 16,
102 |     STD_VIDEO_H264_ASPECT_RATIO_IDC_EXTENDED_SAR = 255,
103 |     STD_VIDEO_H264_ASPECT_RATIO_IDC_INVALID = 0x7FFFFFFF,
104 |     STD_VIDEO_H264_ASPECT_RATIO_IDC_MAX_ENUM = 0x7FFFFFFF
105 | } StdVideoH264AspectRatioIdc;
106 | 
107 | typedef enum StdVideoH264WeightedBipredIdc {
108 |     STD_VIDEO_H264_WEIGHTED_BIPRED_IDC_DEFAULT = 0,
109 |     STD_VIDEO_H264_WEIGHTED_BIPRED_IDC_EXPLICIT = 1,
110 |     STD_VIDEO_H264_WEIGHTED_BIPRED_IDC_IMPLICIT = 2,
111 |     STD_VIDEO_H264_WEIGHTED_BIPRED_IDC_INVALID = 0x7FFFFFFF,
112 |     STD_VIDEO_H264_WEIGHTED_BIPRED_IDC_MAX_ENUM = 0x7FFFFFFF
113 | } StdVideoH264WeightedBipredIdc;
114 | 
115 | typedef enum StdVideoH264ModificationOfPicNumsIdc {
116 |     STD_VIDEO_H264_MODIFICATION_OF_PIC_NUMS_IDC_SHORT_TERM_SUBTRACT = 0,
117 |     STD_VIDEO_H264_MODIFICATION_OF_PIC_NUMS_IDC_SHORT_TERM_ADD = 1,
118 |     STD_VIDEO_H264_MODIFICATION_OF_PIC_NUMS_IDC_LONG_TERM = 2,
119 |     STD_VIDEO_H264_MODIFICATION_OF_PIC_NUMS_IDC_END = 3,
120 |     STD_VIDEO_H264_MODIFICATION_OF_PIC_NUMS_IDC_INVALID = 0x7FFFFFFF,
121 |     STD_VIDEO_H264_MODIFICATION_OF_PIC_NUMS_IDC_MAX_ENUM = 0x7FFFFFFF
122 | } StdVideoH264ModificationOfPicNumsIdc;
123 | 
124 | typedef enum StdVideoH264MemMgmtControlOp {
125 |     STD_VIDEO_H264_MEM_MGMT_CONTROL_OP_END = 0,
126 |     STD_VIDEO_H264_MEM_MGMT_CONTROL_OP_UNMARK_SHORT_TERM = 1,
127 |     STD_VIDEO_H264_MEM_MGMT_CONTROL_OP_UNMARK_LONG_TERM = 2,
128 |     STD_VIDEO_H264_MEM_MGMT_CONTROL_OP_MARK_LONG_TERM = 3,
129 |     STD_VIDEO_H264_MEM_MGMT_CONTROL_OP_SET_MAX_LONG_TERM_INDEX = 4,
130 |     STD_VIDEO_H264_MEM_MGMT_CONTROL_OP_UNMARK_ALL = 5,
131 |     STD_VIDEO_H264_MEM_MGMT_CONTROL_OP_MARK_CURRENT_AS_LONG_TERM = 6,
132 |     STD_VIDEO_H264_MEM_MGMT_CONTROL_OP_INVALID = 0x7FFFFFFF,
133 |     STD_VIDEO_H264_MEM_MGMT_CONTROL_OP_MAX_ENUM = 0x7FFFFFFF
134 | } StdVideoH264MemMgmtControlOp;
135 | 
136 | typedef enum StdVideoH264CabacInitIdc {
137 |     STD_VIDEO_H264_CABAC_INIT_IDC_0 = 0,
138 |     STD_VIDEO_H264_CABAC_INIT_IDC_1 = 1,
139 |     STD_VIDEO_H264_CABAC_INIT_IDC_2 = 2,
140 |     STD_VIDEO_H264_CABAC_INIT_IDC_INVALID = 0x7FFFFFFF,
141 |     STD_VIDEO_H264_CABAC_INIT_IDC_MAX_ENUM = 0x7FFFFFFF
142 | } StdVideoH264CabacInitIdc;
143 | 
144 | typedef enum StdVideoH264DisableDeblockingFilterIdc {
145 |     STD_VIDEO_H264_DISABLE_DEBLOCKING_FILTER_IDC_DISABLED = 0,
146 |     STD_VIDEO_H264_DISABLE_DEBLOCKING_FILTER_IDC_ENABLED = 1,
147 |     STD_VIDEO_H264_DISABLE_DEBLOCKING_FILTER_IDC_PARTIAL = 2,
148 |     STD_VIDEO_H264_DISABLE_DEBLOCKING_FILTER_IDC_INVALID = 0x7FFFFFFF,
149 |     STD_VIDEO_H264_DISABLE_DEBLOCKING_FILTER_IDC_MAX_ENUM = 0x7FFFFFFF
150 | } StdVideoH264DisableDeblockingFilterIdc;
151 | 
152 | typedef enum StdVideoH264SliceType {
153 |     STD_VIDEO_H264_SLICE_TYPE_P = 0,
154 |     STD_VIDEO_H264_SLICE_TYPE_B = 1,
155 |     STD_VIDEO_H264_SLICE_TYPE_I = 2,
156 |     STD_VIDEO_H264_SLICE_TYPE_INVALID = 0x7FFFFFFF,
157 |     STD_VIDEO_H264_SLICE_TYPE_MAX_ENUM = 0x7FFFFFFF
158 | } StdVideoH264SliceType;
159 | 
160 | typedef enum StdVideoH264PictureType {
161 |     STD_VIDEO_H264_PICTURE_TYPE_P = 0,
162 |     STD_VIDEO_H264_PICTURE_TYPE_B = 1,
163 |     STD_VIDEO_H264_PICTURE_TYPE_I = 2,
164 |     STD_VIDEO_H264_PICTURE_TYPE_IDR = 5,
165 |     STD_VIDEO_H264_PICTURE_TYPE_INVALID = 0x7FFFFFFF,
166 |     STD_VIDEO_H264_PICTURE_TYPE_MAX_ENUM = 0x7FFFFFFF
167 | } StdVideoH264PictureType;
168 | 
169 | typedef enum StdVideoH264NonVclNaluType {
170 |     STD_VIDEO_H264_NON_VCL_NALU_TYPE_SPS = 0,
171 |     STD_VIDEO_H264_NON_VCL_NALU_TYPE_PPS = 1,
172 |     STD_VIDEO_H264_NON_VCL_NALU_TYPE_AUD = 2,
173 |     STD_VIDEO_H264_NON_VCL_NALU_TYPE_PREFIX = 3,
174 |     STD_VIDEO_H264_NON_VCL_NALU_TYPE_END_OF_SEQUENCE = 4,
175 |     STD_VIDEO_H264_NON_VCL_NALU_TYPE_END_OF_STREAM = 5,
176 |     STD_VIDEO_H264_NON_VCL_NALU_TYPE_PRECODED = 6,
177 |     STD_VIDEO_H264_NON_VCL_NALU_TYPE_INVALID = 0x7FFFFFFF,
178 |     STD_VIDEO_H264_NON_VCL_NALU_TYPE_MAX_ENUM = 0x7FFFFFFF
179 | } StdVideoH264NonVclNaluType;
180 | typedef struct StdVideoH264SpsVuiFlags {
181 |     uint32_t    aspect_ratio_info_present_flag : 1;
182 |     uint32_t    overscan_info_present_flag : 1;
183 |     uint32_t    overscan_appropriate_flag : 1;
184 |     uint32_t    video_signal_type_present_flag : 1;
185 |     uint32_t    video_full_range_flag : 1;
186 |     uint32_t    color_description_present_flag : 1;
187 |     uint32_t    chroma_loc_info_present_flag : 1;
188 |     uint32_t    timing_info_present_flag : 1;
189 |     uint32_t    fixed_frame_rate_flag : 1;
190 |     uint32_t    bitstream_restriction_flag : 1;
191 |     uint32_t    nal_hrd_parameters_present_flag : 1;
192 |     uint32_t    vcl_hrd_parameters_present_flag : 1;
193 | } StdVideoH264SpsVuiFlags;
194 | 
195 | typedef struct StdVideoH264HrdParameters {
196 |     uint8_t     cpb_cnt_minus1;
197 |     uint8_t     bit_rate_scale;
198 |     uint8_t     cpb_size_scale;
199 |     uint8_t     reserved1;
200 |     uint32_t    bit_rate_value_minus1[STD_VIDEO_H264_CPB_CNT_LIST_SIZE];
201 |     uint32_t    cpb_size_value_minus1[STD_VIDEO_H264_CPB_CNT_LIST_SIZE];
202 |     uint8_t     cbr_flag[STD_VIDEO_H264_CPB_CNT_LIST_SIZE];
203 |     uint32_t    initial_cpb_removal_delay_length_minus1;
204 |     uint32_t    cpb_removal_delay_length_minus1;
205 |     uint32_t    dpb_output_delay_length_minus1;
206 |     uint32_t    time_offset_length;
207 | } StdVideoH264HrdParameters;
208 | 
209 | typedef struct StdVideoH264SequenceParameterSetVui {
210 |     StdVideoH264SpsVuiFlags             flags;
211 |     StdVideoH264AspectRatioIdc          aspect_ratio_idc;
212 |     uint16_t                            sar_width;
213 |     uint16_t                            sar_height;
214 |     uint8_t                             video_format;
215 |     uint8_t                             colour_primaries;
216 |     uint8_t                             transfer_characteristics;
217 |     uint8_t                             matrix_coefficients;
218 |     uint32_t                            num_units_in_tick;
219 |     uint32_t                            time_scale;
220 |     uint8_t                             max_num_reorder_frames;
221 |     uint8_t                             max_dec_frame_buffering;
222 |     uint8_t                             chroma_sample_loc_type_top_field;
223 |     uint8_t                             chroma_sample_loc_type_bottom_field;
224 |     uint32_t                            reserved1;
225 |     const StdVideoH264HrdParameters*    pHrdParameters;
226 | } StdVideoH264SequenceParameterSetVui;
227 | 
228 | typedef struct StdVideoH264SpsFlags {
229 |     uint32_t    constraint_set0_flag : 1;
230 |     uint32_t    constraint_set1_flag : 1;
231 |     uint32_t    constraint_set2_flag : 1;
232 |     uint32_t    constraint_set3_flag : 1;
233 |     uint32_t    constraint_set4_flag : 1;
234 |     uint32_t    constraint_set5_flag : 1;
235 |     uint32_t    direct_8x8_inference_flag : 1;
236 |     uint32_t    mb_adaptive_frame_field_flag : 1;
237 |     uint32_t    frame_mbs_only_flag : 1;
238 |     uint32_t    delta_pic_order_always_zero_flag : 1;
239 |     uint32_t    separate_colour_plane_flag : 1;
240 |     uint32_t    gaps_in_frame_num_value_allowed_flag : 1;
241 |     uint32_t    qpprime_y_zero_transform_bypass_flag : 1;
242 |     uint32_t    frame_cropping_flag : 1;
243 |     uint32_t    seq_scaling_matrix_present_flag : 1;
244 |     uint32_t    vui_parameters_present_flag : 1;
245 | } StdVideoH264SpsFlags;
246 | 
247 | typedef struct StdVideoH264ScalingLists {
248 |     uint16_t    scaling_list_present_mask;
249 |     uint16_t    use_default_scaling_matrix_mask;
250 |     uint8_t     ScalingList4x4[STD_VIDEO_H264_SCALING_LIST_4X4_NUM_LISTS][STD_VIDEO_H264_SCALING_LIST_4X4_NUM_ELEMENTS];
251 |     uint8_t     ScalingList8x8[STD_VIDEO_H264_SCALING_LIST_8X8_NUM_LISTS][STD_VIDEO_H264_SCALING_LIST_8X8_NUM_ELEMENTS];
252 | } StdVideoH264ScalingLists;
253 | 
254 | typedef struct StdVideoH264SequenceParameterSet {
255 |     StdVideoH264SpsFlags                          flags;
256 |     StdVideoH264ProfileIdc                        profile_idc;
257 |     StdVideoH264LevelIdc                          level_idc;
258 |     StdVideoH264ChromaFormatIdc                   chroma_format_idc;
259 |     uint8_t                                       seq_parameter_set_id;
260 |     uint8_t                                       bit_depth_luma_minus8;
261 |     uint8_t                                       bit_depth_chroma_minus8;
262 |     uint8_t                                       log2_max_frame_num_minus4;
263 |     StdVideoH264PocType                           pic_order_cnt_type;
264 |     int32_t                                       offset_for_non_ref_pic;
265 |     int32_t                                       offset_for_top_to_bottom_field;
266 |     uint8_t                                       log2_max_pic_order_cnt_lsb_minus4;
267 |     uint8_t                                       num_ref_frames_in_pic_order_cnt_cycle;
268 |     uint8_t                                       max_num_ref_frames;
269 |     uint8_t                                       reserved1;
270 |     uint32_t                                      pic_width_in_mbs_minus1;
271 |     uint32_t                                      pic_height_in_map_units_minus1;
272 |     uint32_t                                      frame_crop_left_offset;
273 |     uint32_t                                      frame_crop_right_offset;
274 |     uint32_t                                      frame_crop_top_offset;
275 |     uint32_t                                      frame_crop_bottom_offset;
276 |     uint32_t                                      reserved2;
277 |     const int32_t*                                pOffsetForRefFrame;
278 |     const StdVideoH264ScalingLists*               pScalingLists;
279 |     const StdVideoH264SequenceParameterSetVui*    pSequenceParameterSetVui;
280 | } StdVideoH264SequenceParameterSet;
281 | 
282 | typedef struct StdVideoH264PpsFlags {
283 |     uint32_t    transform_8x8_mode_flag : 1;
284 |     uint32_t    redundant_pic_cnt_present_flag : 1;
285 |     uint32_t    constrained_intra_pred_flag : 1;
286 |     uint32_t    deblocking_filter_control_present_flag : 1;
287 |     uint32_t    weighted_pred_flag : 1;
288 |     uint32_t    bottom_field_pic_order_in_frame_present_flag : 1;
289 |     uint32_t    entropy_coding_mode_flag : 1;
290 |     uint32_t    pic_scaling_matrix_present_flag : 1;
291 | } StdVideoH264PpsFlags;
292 | 
293 | typedef struct StdVideoH264PictureParameterSet {
294 |     StdVideoH264PpsFlags               flags;
295 |     uint8_t                            seq_parameter_set_id;
296 |     uint8_t                            pic_parameter_set_id;
297 |     uint8_t                            num_ref_idx_l0_default_active_minus1;
298 |     uint8_t                            num_ref_idx_l1_default_active_minus1;
299 |     StdVideoH264WeightedBipredIdc      weighted_bipred_idc;
300 |     int8_t                             pic_init_qp_minus26;
301 |     int8_t                             pic_init_qs_minus26;
302 |     int8_t                             chroma_qp_index_offset;
303 |     int8_t                             second_chroma_qp_index_offset;
304 |     const StdVideoH264ScalingLists*    pScalingLists;
305 | } StdVideoH264PictureParameterSet;
306 | 
307 | 
308 | #ifdef __cplusplus
309 | }
310 | #endif
311 | 
312 | #endif
313 | 
```

--------------------------------------------------------------------------------
/vkrunner/include/vk_video/vulkan_video_codec_av1std.h:
--------------------------------------------------------------------------------

```
  1 | #ifndef VULKAN_VIDEO_CODEC_AV1STD_H_
  2 | #define VULKAN_VIDEO_CODEC_AV1STD_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_av1std is a preprocessor guard. Do not pass it to API calls.
 23 | #define vulkan_video_codec_av1std 1
 24 | #include "vulkan_video_codecs_common.h"
 25 | #define STD_VIDEO_AV1_NUM_REF_FRAMES      8
 26 | #define STD_VIDEO_AV1_REFS_PER_FRAME      7
 27 | #define STD_VIDEO_AV1_TOTAL_REFS_PER_FRAME 8
 28 | #define STD_VIDEO_AV1_MAX_TILE_COLS       64
 29 | #define STD_VIDEO_AV1_MAX_TILE_ROWS       64
 30 | #define STD_VIDEO_AV1_MAX_SEGMENTS        8
 31 | #define STD_VIDEO_AV1_SEG_LVL_MAX         8
 32 | #define STD_VIDEO_AV1_PRIMARY_REF_NONE    7
 33 | #define STD_VIDEO_AV1_SELECT_INTEGER_MV   2
 34 | #define STD_VIDEO_AV1_SELECT_SCREEN_CONTENT_TOOLS 2
 35 | #define STD_VIDEO_AV1_SKIP_MODE_FRAMES    2
 36 | #define STD_VIDEO_AV1_MAX_LOOP_FILTER_STRENGTHS 4
 37 | #define STD_VIDEO_AV1_LOOP_FILTER_ADJUSTMENTS 2
 38 | #define STD_VIDEO_AV1_MAX_CDEF_FILTER_STRENGTHS 8
 39 | #define STD_VIDEO_AV1_MAX_NUM_PLANES      3
 40 | #define STD_VIDEO_AV1_GLOBAL_MOTION_PARAMS 6
 41 | #define STD_VIDEO_AV1_MAX_NUM_Y_POINTS    14
 42 | #define STD_VIDEO_AV1_MAX_NUM_CB_POINTS   10
 43 | #define STD_VIDEO_AV1_MAX_NUM_CR_POINTS   10
 44 | #define STD_VIDEO_AV1_MAX_NUM_POS_LUMA    24
 45 | #define STD_VIDEO_AV1_MAX_NUM_POS_CHROMA  25
 46 | 
 47 | typedef enum StdVideoAV1Profile {
 48 |     STD_VIDEO_AV1_PROFILE_MAIN = 0,
 49 |     STD_VIDEO_AV1_PROFILE_HIGH = 1,
 50 |     STD_VIDEO_AV1_PROFILE_PROFESSIONAL = 2,
 51 |     STD_VIDEO_AV1_PROFILE_INVALID = 0x7FFFFFFF,
 52 |     STD_VIDEO_AV1_PROFILE_MAX_ENUM = 0x7FFFFFFF
 53 | } StdVideoAV1Profile;
 54 | 
 55 | typedef enum StdVideoAV1Level {
 56 |     STD_VIDEO_AV1_LEVEL_2_0 = 0,
 57 |     STD_VIDEO_AV1_LEVEL_2_1 = 1,
 58 |     STD_VIDEO_AV1_LEVEL_2_2 = 2,
 59 |     STD_VIDEO_AV1_LEVEL_2_3 = 3,
 60 |     STD_VIDEO_AV1_LEVEL_3_0 = 4,
 61 |     STD_VIDEO_AV1_LEVEL_3_1 = 5,
 62 |     STD_VIDEO_AV1_LEVEL_3_2 = 6,
 63 |     STD_VIDEO_AV1_LEVEL_3_3 = 7,
 64 |     STD_VIDEO_AV1_LEVEL_4_0 = 8,
 65 |     STD_VIDEO_AV1_LEVEL_4_1 = 9,
 66 |     STD_VIDEO_AV1_LEVEL_4_2 = 10,
 67 |     STD_VIDEO_AV1_LEVEL_4_3 = 11,
 68 |     STD_VIDEO_AV1_LEVEL_5_0 = 12,
 69 |     STD_VIDEO_AV1_LEVEL_5_1 = 13,
 70 |     STD_VIDEO_AV1_LEVEL_5_2 = 14,
 71 |     STD_VIDEO_AV1_LEVEL_5_3 = 15,
 72 |     STD_VIDEO_AV1_LEVEL_6_0 = 16,
 73 |     STD_VIDEO_AV1_LEVEL_6_1 = 17,
 74 |     STD_VIDEO_AV1_LEVEL_6_2 = 18,
 75 |     STD_VIDEO_AV1_LEVEL_6_3 = 19,
 76 |     STD_VIDEO_AV1_LEVEL_7_0 = 20,
 77 |     STD_VIDEO_AV1_LEVEL_7_1 = 21,
 78 |     STD_VIDEO_AV1_LEVEL_7_2 = 22,
 79 |     STD_VIDEO_AV1_LEVEL_7_3 = 23,
 80 |     STD_VIDEO_AV1_LEVEL_INVALID = 0x7FFFFFFF,
 81 |     STD_VIDEO_AV1_LEVEL_MAX_ENUM = 0x7FFFFFFF
 82 | } StdVideoAV1Level;
 83 | 
 84 | typedef enum StdVideoAV1FrameType {
 85 |     STD_VIDEO_AV1_FRAME_TYPE_KEY = 0,
 86 |     STD_VIDEO_AV1_FRAME_TYPE_INTER = 1,
 87 |     STD_VIDEO_AV1_FRAME_TYPE_INTRA_ONLY = 2,
 88 |     STD_VIDEO_AV1_FRAME_TYPE_SWITCH = 3,
 89 |     STD_VIDEO_AV1_FRAME_TYPE_INVALID = 0x7FFFFFFF,
 90 |     STD_VIDEO_AV1_FRAME_TYPE_MAX_ENUM = 0x7FFFFFFF
 91 | } StdVideoAV1FrameType;
 92 | 
 93 | typedef enum StdVideoAV1ReferenceName {
 94 |     STD_VIDEO_AV1_REFERENCE_NAME_INTRA_FRAME = 0,
 95 |     STD_VIDEO_AV1_REFERENCE_NAME_LAST_FRAME = 1,
 96 |     STD_VIDEO_AV1_REFERENCE_NAME_LAST2_FRAME = 2,
 97 |     STD_VIDEO_AV1_REFERENCE_NAME_LAST3_FRAME = 3,
 98 |     STD_VIDEO_AV1_REFERENCE_NAME_GOLDEN_FRAME = 4,
 99 |     STD_VIDEO_AV1_REFERENCE_NAME_BWDREF_FRAME = 5,
100 |     STD_VIDEO_AV1_REFERENCE_NAME_ALTREF2_FRAME = 6,
101 |     STD_VIDEO_AV1_REFERENCE_NAME_ALTREF_FRAME = 7,
102 |     STD_VIDEO_AV1_REFERENCE_NAME_INVALID = 0x7FFFFFFF,
103 |     STD_VIDEO_AV1_REFERENCE_NAME_MAX_ENUM = 0x7FFFFFFF
104 | } StdVideoAV1ReferenceName;
105 | 
106 | typedef enum StdVideoAV1InterpolationFilter {
107 |     STD_VIDEO_AV1_INTERPOLATION_FILTER_EIGHTTAP = 0,
108 |     STD_VIDEO_AV1_INTERPOLATION_FILTER_EIGHTTAP_SMOOTH = 1,
109 |     STD_VIDEO_AV1_INTERPOLATION_FILTER_EIGHTTAP_SHARP = 2,
110 |     STD_VIDEO_AV1_INTERPOLATION_FILTER_BILINEAR = 3,
111 |     STD_VIDEO_AV1_INTERPOLATION_FILTER_SWITCHABLE = 4,
112 |     STD_VIDEO_AV1_INTERPOLATION_FILTER_INVALID = 0x7FFFFFFF,
113 |     STD_VIDEO_AV1_INTERPOLATION_FILTER_MAX_ENUM = 0x7FFFFFFF
114 | } StdVideoAV1InterpolationFilter;
115 | 
116 | typedef enum StdVideoAV1TxMode {
117 |     STD_VIDEO_AV1_TX_MODE_ONLY_4X4 = 0,
118 |     STD_VIDEO_AV1_TX_MODE_LARGEST = 1,
119 |     STD_VIDEO_AV1_TX_MODE_SELECT = 2,
120 |     STD_VIDEO_AV1_TX_MODE_INVALID = 0x7FFFFFFF,
121 |     STD_VIDEO_AV1_TX_MODE_MAX_ENUM = 0x7FFFFFFF
122 | } StdVideoAV1TxMode;
123 | 
124 | typedef enum StdVideoAV1FrameRestorationType {
125 |     STD_VIDEO_AV1_FRAME_RESTORATION_TYPE_NONE = 0,
126 |     STD_VIDEO_AV1_FRAME_RESTORATION_TYPE_WIENER = 1,
127 |     STD_VIDEO_AV1_FRAME_RESTORATION_TYPE_SGRPROJ = 2,
128 |     STD_VIDEO_AV1_FRAME_RESTORATION_TYPE_SWITCHABLE = 3,
129 |     STD_VIDEO_AV1_FRAME_RESTORATION_TYPE_INVALID = 0x7FFFFFFF,
130 |     STD_VIDEO_AV1_FRAME_RESTORATION_TYPE_MAX_ENUM = 0x7FFFFFFF
131 | } StdVideoAV1FrameRestorationType;
132 | 
133 | typedef enum StdVideoAV1ColorPrimaries {
134 |     STD_VIDEO_AV1_COLOR_PRIMARIES_BT_709 = 1,
135 |     STD_VIDEO_AV1_COLOR_PRIMARIES_UNSPECIFIED = 2,
136 |     STD_VIDEO_AV1_COLOR_PRIMARIES_BT_470_M = 4,
137 |     STD_VIDEO_AV1_COLOR_PRIMARIES_BT_470_B_G = 5,
138 |     STD_VIDEO_AV1_COLOR_PRIMARIES_BT_601 = 6,
139 |     STD_VIDEO_AV1_COLOR_PRIMARIES_SMPTE_240 = 7,
140 |     STD_VIDEO_AV1_COLOR_PRIMARIES_GENERIC_FILM = 8,
141 |     STD_VIDEO_AV1_COLOR_PRIMARIES_BT_2020 = 9,
142 |     STD_VIDEO_AV1_COLOR_PRIMARIES_XYZ = 10,
143 |     STD_VIDEO_AV1_COLOR_PRIMARIES_SMPTE_431 = 11,
144 |     STD_VIDEO_AV1_COLOR_PRIMARIES_SMPTE_432 = 12,
145 |     STD_VIDEO_AV1_COLOR_PRIMARIES_EBU_3213 = 22,
146 |     STD_VIDEO_AV1_COLOR_PRIMARIES_INVALID = 0x7FFFFFFF,
147 |   // STD_VIDEO_AV1_COLOR_PRIMARIES_BT_UNSPECIFIED is a deprecated alias
148 |     STD_VIDEO_AV1_COLOR_PRIMARIES_BT_UNSPECIFIED = STD_VIDEO_AV1_COLOR_PRIMARIES_UNSPECIFIED,
149 |     STD_VIDEO_AV1_COLOR_PRIMARIES_MAX_ENUM = 0x7FFFFFFF
150 | } StdVideoAV1ColorPrimaries;
151 | 
152 | typedef enum StdVideoAV1TransferCharacteristics {
153 |     STD_VIDEO_AV1_TRANSFER_CHARACTERISTICS_RESERVED_0 = 0,
154 |     STD_VIDEO_AV1_TRANSFER_CHARACTERISTICS_BT_709 = 1,
155 |     STD_VIDEO_AV1_TRANSFER_CHARACTERISTICS_UNSPECIFIED = 2,
156 |     STD_VIDEO_AV1_TRANSFER_CHARACTERISTICS_RESERVED_3 = 3,
157 |     STD_VIDEO_AV1_TRANSFER_CHARACTERISTICS_BT_470_M = 4,
158 |     STD_VIDEO_AV1_TRANSFER_CHARACTERISTICS_BT_470_B_G = 5,
159 |     STD_VIDEO_AV1_TRANSFER_CHARACTERISTICS_BT_601 = 6,
160 |     STD_VIDEO_AV1_TRANSFER_CHARACTERISTICS_SMPTE_240 = 7,
161 |     STD_VIDEO_AV1_TRANSFER_CHARACTERISTICS_LINEAR = 8,
162 |     STD_VIDEO_AV1_TRANSFER_CHARACTERISTICS_LOG_100 = 9,
163 |     STD_VIDEO_AV1_TRANSFER_CHARACTERISTICS_LOG_100_SQRT10 = 10,
164 |     STD_VIDEO_AV1_TRANSFER_CHARACTERISTICS_IEC_61966 = 11,
165 |     STD_VIDEO_AV1_TRANSFER_CHARACTERISTICS_BT_1361 = 12,
166 |     STD_VIDEO_AV1_TRANSFER_CHARACTERISTICS_SRGB = 13,
167 |     STD_VIDEO_AV1_TRANSFER_CHARACTERISTICS_BT_2020_10_BIT = 14,
168 |     STD_VIDEO_AV1_TRANSFER_CHARACTERISTICS_BT_2020_12_BIT = 15,
169 |     STD_VIDEO_AV1_TRANSFER_CHARACTERISTICS_SMPTE_2084 = 16,
170 |     STD_VIDEO_AV1_TRANSFER_CHARACTERISTICS_SMPTE_428 = 17,
171 |     STD_VIDEO_AV1_TRANSFER_CHARACTERISTICS_HLG = 18,
172 |     STD_VIDEO_AV1_TRANSFER_CHARACTERISTICS_INVALID = 0x7FFFFFFF,
173 |     STD_VIDEO_AV1_TRANSFER_CHARACTERISTICS_MAX_ENUM = 0x7FFFFFFF
174 | } StdVideoAV1TransferCharacteristics;
175 | 
176 | typedef enum StdVideoAV1MatrixCoefficients {
177 |     STD_VIDEO_AV1_MATRIX_COEFFICIENTS_IDENTITY = 0,
178 |     STD_VIDEO_AV1_MATRIX_COEFFICIENTS_BT_709 = 1,
179 |     STD_VIDEO_AV1_MATRIX_COEFFICIENTS_UNSPECIFIED = 2,
180 |     STD_VIDEO_AV1_MATRIX_COEFFICIENTS_RESERVED_3 = 3,
181 |     STD_VIDEO_AV1_MATRIX_COEFFICIENTS_FCC = 4,
182 |     STD_VIDEO_AV1_MATRIX_COEFFICIENTS_BT_470_B_G = 5,
183 |     STD_VIDEO_AV1_MATRIX_COEFFICIENTS_BT_601 = 6,
184 |     STD_VIDEO_AV1_MATRIX_COEFFICIENTS_SMPTE_240 = 7,
185 |     STD_VIDEO_AV1_MATRIX_COEFFICIENTS_SMPTE_YCGCO = 8,
186 |     STD_VIDEO_AV1_MATRIX_COEFFICIENTS_BT_2020_NCL = 9,
187 |     STD_VIDEO_AV1_MATRIX_COEFFICIENTS_BT_2020_CL = 10,
188 |     STD_VIDEO_AV1_MATRIX_COEFFICIENTS_SMPTE_2085 = 11,
189 |     STD_VIDEO_AV1_MATRIX_COEFFICIENTS_CHROMAT_NCL = 12,
190 |     STD_VIDEO_AV1_MATRIX_COEFFICIENTS_CHROMAT_CL = 13,
191 |     STD_VIDEO_AV1_MATRIX_COEFFICIENTS_ICTCP = 14,
192 |     STD_VIDEO_AV1_MATRIX_COEFFICIENTS_INVALID = 0x7FFFFFFF,
193 |     STD_VIDEO_AV1_MATRIX_COEFFICIENTS_MAX_ENUM = 0x7FFFFFFF
194 | } StdVideoAV1MatrixCoefficients;
195 | 
196 | typedef enum StdVideoAV1ChromaSamplePosition {
197 |     STD_VIDEO_AV1_CHROMA_SAMPLE_POSITION_UNKNOWN = 0,
198 |     STD_VIDEO_AV1_CHROMA_SAMPLE_POSITION_VERTICAL = 1,
199 |     STD_VIDEO_AV1_CHROMA_SAMPLE_POSITION_COLOCATED = 2,
200 |     STD_VIDEO_AV1_CHROMA_SAMPLE_POSITION_RESERVED = 3,
201 |     STD_VIDEO_AV1_CHROMA_SAMPLE_POSITION_INVALID = 0x7FFFFFFF,
202 |     STD_VIDEO_AV1_CHROMA_SAMPLE_POSITION_MAX_ENUM = 0x7FFFFFFF
203 | } StdVideoAV1ChromaSamplePosition;
204 | typedef struct StdVideoAV1ColorConfigFlags {
205 |     uint32_t    mono_chrome : 1;
206 |     uint32_t    color_range : 1;
207 |     uint32_t    separate_uv_delta_q : 1;
208 |     uint32_t    color_description_present_flag : 1;
209 |     uint32_t    reserved : 28;
210 | } StdVideoAV1ColorConfigFlags;
211 | 
212 | typedef struct StdVideoAV1ColorConfig {
213 |     StdVideoAV1ColorConfigFlags           flags;
214 |     uint8_t                               BitDepth;
215 |     uint8_t                               subsampling_x;
216 |     uint8_t                               subsampling_y;
217 |     uint8_t                               reserved1;
218 |     StdVideoAV1ColorPrimaries             color_primaries;
219 |     StdVideoAV1TransferCharacteristics    transfer_characteristics;
220 |     StdVideoAV1MatrixCoefficients         matrix_coefficients;
221 |     StdVideoAV1ChromaSamplePosition       chroma_sample_position;
222 | } StdVideoAV1ColorConfig;
223 | 
224 | typedef struct StdVideoAV1TimingInfoFlags {
225 |     uint32_t    equal_picture_interval : 1;
226 |     uint32_t    reserved : 31;
227 | } StdVideoAV1TimingInfoFlags;
228 | 
229 | typedef struct StdVideoAV1TimingInfo {
230 |     StdVideoAV1TimingInfoFlags    flags;
231 |     uint32_t                      num_units_in_display_tick;
232 |     uint32_t                      time_scale;
233 |     uint32_t                      num_ticks_per_picture_minus_1;
234 | } StdVideoAV1TimingInfo;
235 | 
236 | typedef struct StdVideoAV1LoopFilterFlags {
237 |     uint32_t    loop_filter_delta_enabled : 1;
238 |     uint32_t    loop_filter_delta_update : 1;
239 |     uint32_t    reserved : 30;
240 | } StdVideoAV1LoopFilterFlags;
241 | 
242 | typedef struct StdVideoAV1LoopFilter {
243 |     StdVideoAV1LoopFilterFlags    flags;
244 |     uint8_t                       loop_filter_level[STD_VIDEO_AV1_MAX_LOOP_FILTER_STRENGTHS];
245 |     uint8_t                       loop_filter_sharpness;
246 |     uint8_t                       update_ref_delta;
247 |     int8_t                        loop_filter_ref_deltas[STD_VIDEO_AV1_TOTAL_REFS_PER_FRAME];
248 |     uint8_t                       update_mode_delta;
249 |     int8_t                        loop_filter_mode_deltas[STD_VIDEO_AV1_LOOP_FILTER_ADJUSTMENTS];
250 | } StdVideoAV1LoopFilter;
251 | 
252 | typedef struct StdVideoAV1QuantizationFlags {
253 |     uint32_t    using_qmatrix : 1;
254 |     uint32_t    diff_uv_delta : 1;
255 |     uint32_t    reserved : 30;
256 | } StdVideoAV1QuantizationFlags;
257 | 
258 | typedef struct StdVideoAV1Quantization {
259 |     StdVideoAV1QuantizationFlags    flags;
260 |     uint8_t                         base_q_idx;
261 |     int8_t                          DeltaQYDc;
262 |     int8_t                          DeltaQUDc;
263 |     int8_t                          DeltaQUAc;
264 |     int8_t                          DeltaQVDc;
265 |     int8_t                          DeltaQVAc;
266 |     uint8_t                         qm_y;
267 |     uint8_t                         qm_u;
268 |     uint8_t                         qm_v;
269 | } StdVideoAV1Quantization;
270 | 
271 | typedef struct StdVideoAV1Segmentation {
272 |     uint8_t    FeatureEnabled[STD_VIDEO_AV1_MAX_SEGMENTS];
273 |     int16_t    FeatureData[STD_VIDEO_AV1_MAX_SEGMENTS][STD_VIDEO_AV1_SEG_LVL_MAX];
274 | } StdVideoAV1Segmentation;
275 | 
276 | typedef struct StdVideoAV1TileInfoFlags {
277 |     uint32_t    uniform_tile_spacing_flag : 1;
278 |     uint32_t    reserved : 31;
279 | } StdVideoAV1TileInfoFlags;
280 | 
281 | typedef struct StdVideoAV1TileInfo {
282 |     StdVideoAV1TileInfoFlags    flags;
283 |     uint8_t                     TileCols;
284 |     uint8_t                     TileRows;
285 |     uint16_t                    context_update_tile_id;
286 |     uint8_t                     tile_size_bytes_minus_1;
287 |     uint8_t                     reserved1[7];
288 |     const uint16_t*             pMiColStarts;
289 |     const uint16_t*             pMiRowStarts;
290 |     const uint16_t*             pWidthInSbsMinus1;
291 |     const uint16_t*             pHeightInSbsMinus1;
292 | } StdVideoAV1TileInfo;
293 | 
294 | typedef struct StdVideoAV1CDEF {
295 |     uint8_t    cdef_damping_minus_3;
296 |     uint8_t    cdef_bits;
297 |     uint8_t    cdef_y_pri_strength[STD_VIDEO_AV1_MAX_CDEF_FILTER_STRENGTHS];
298 |     uint8_t    cdef_y_sec_strength[STD_VIDEO_AV1_MAX_CDEF_FILTER_STRENGTHS];
299 |     uint8_t    cdef_uv_pri_strength[STD_VIDEO_AV1_MAX_CDEF_FILTER_STRENGTHS];
300 |     uint8_t    cdef_uv_sec_strength[STD_VIDEO_AV1_MAX_CDEF_FILTER_STRENGTHS];
301 | } StdVideoAV1CDEF;
302 | 
303 | typedef struct StdVideoAV1LoopRestoration {
304 |     StdVideoAV1FrameRestorationType    FrameRestorationType[STD_VIDEO_AV1_MAX_NUM_PLANES];
305 |     uint16_t                           LoopRestorationSize[STD_VIDEO_AV1_MAX_NUM_PLANES];
306 | } StdVideoAV1LoopRestoration;
307 | 
308 | typedef struct StdVideoAV1GlobalMotion {
309 |     uint8_t    GmType[STD_VIDEO_AV1_NUM_REF_FRAMES];
310 |     int32_t    gm_params[STD_VIDEO_AV1_NUM_REF_FRAMES][STD_VIDEO_AV1_GLOBAL_MOTION_PARAMS];
311 | } StdVideoAV1GlobalMotion;
312 | 
313 | typedef struct StdVideoAV1FilmGrainFlags {
314 |     uint32_t    chroma_scaling_from_luma : 1;
315 |     uint32_t    overlap_flag : 1;
316 |     uint32_t    clip_to_restricted_range : 1;
317 |     uint32_t    update_grain : 1;
318 |     uint32_t    reserved : 28;
319 | } StdVideoAV1FilmGrainFlags;
320 | 
321 | typedef struct StdVideoAV1FilmGrain {
322 |     StdVideoAV1FilmGrainFlags    flags;
323 |     uint8_t                      grain_scaling_minus_8;
324 |     uint8_t                      ar_coeff_lag;
325 |     uint8_t                      ar_coeff_shift_minus_6;
326 |     uint8_t                      grain_scale_shift;
327 |     uint16_t                     grain_seed;
328 |     uint8_t                      film_grain_params_ref_idx;
329 |     uint8_t                      num_y_points;
330 |     uint8_t                      point_y_value[STD_VIDEO_AV1_MAX_NUM_Y_POINTS];
331 |     uint8_t                      point_y_scaling[STD_VIDEO_AV1_MAX_NUM_Y_POINTS];
332 |     uint8_t                      num_cb_points;
333 |     uint8_t                      point_cb_value[STD_VIDEO_AV1_MAX_NUM_CB_POINTS];
334 |     uint8_t                      point_cb_scaling[STD_VIDEO_AV1_MAX_NUM_CB_POINTS];
335 |     uint8_t                      num_cr_points;
336 |     uint8_t                      point_cr_value[STD_VIDEO_AV1_MAX_NUM_CR_POINTS];
337 |     uint8_t                      point_cr_scaling[STD_VIDEO_AV1_MAX_NUM_CR_POINTS];
338 |     int8_t                       ar_coeffs_y_plus_128[STD_VIDEO_AV1_MAX_NUM_POS_LUMA];
339 |     int8_t                       ar_coeffs_cb_plus_128[STD_VIDEO_AV1_MAX_NUM_POS_CHROMA];
340 |     int8_t                       ar_coeffs_cr_plus_128[STD_VIDEO_AV1_MAX_NUM_POS_CHROMA];
341 |     uint8_t                      cb_mult;
342 |     uint8_t                      cb_luma_mult;
343 |     uint16_t                     cb_offset;
344 |     uint8_t                      cr_mult;
345 |     uint8_t                      cr_luma_mult;
346 |     uint16_t                     cr_offset;
347 | } StdVideoAV1FilmGrain;
348 | 
349 | typedef struct StdVideoAV1SequenceHeaderFlags {
350 |     uint32_t    still_picture : 1;
351 |     uint32_t    reduced_still_picture_header : 1;
352 |     uint32_t    use_128x128_superblock : 1;
353 |     uint32_t    enable_filter_intra : 1;
354 |     uint32_t    enable_intra_edge_filter : 1;
355 |     uint32_t    enable_interintra_compound : 1;
356 |     uint32_t    enable_masked_compound : 1;
357 |     uint32_t    enable_warped_motion : 1;
358 |     uint32_t    enable_dual_filter : 1;
359 |     uint32_t    enable_order_hint : 1;
360 |     uint32_t    enable_jnt_comp : 1;
361 |     uint32_t    enable_ref_frame_mvs : 1;
362 |     uint32_t    frame_id_numbers_present_flag : 1;
363 |     uint32_t    enable_superres : 1;
364 |     uint32_t    enable_cdef : 1;
365 |     uint32_t    enable_restoration : 1;
366 |     uint32_t    film_grain_params_present : 1;
367 |     uint32_t    timing_info_present_flag : 1;
368 |     uint32_t    initial_display_delay_present_flag : 1;
369 |     uint32_t    reserved : 13;
370 | } StdVideoAV1SequenceHeaderFlags;
371 | 
372 | typedef struct StdVideoAV1SequenceHeader {
373 |     StdVideoAV1SequenceHeaderFlags    flags;
374 |     StdVideoAV1Profile                seq_profile;
375 |     uint8_t                           frame_width_bits_minus_1;
376 |     uint8_t                           frame_height_bits_minus_1;
377 |     uint16_t                          max_frame_width_minus_1;
378 |     uint16_t                          max_frame_height_minus_1;
379 |     uint8_t                           delta_frame_id_length_minus_2;
380 |     uint8_t                           additional_frame_id_length_minus_1;
381 |     uint8_t                           order_hint_bits_minus_1;
382 |     uint8_t                           seq_force_integer_mv;
383 |     uint8_t                           seq_force_screen_content_tools;
384 |     uint8_t                           reserved1[5];
385 |     const StdVideoAV1ColorConfig*     pColorConfig;
386 |     const StdVideoAV1TimingInfo*      pTimingInfo;
387 | } StdVideoAV1SequenceHeader;
388 | 
389 | 
390 | #ifdef __cplusplus
391 | }
392 | #endif
393 | 
394 | #endif
395 | 
```
Page 2/9FirstPrevNextLast