#
tokens: 46473/50000 12/78 files (page 2/7)
lines: off (toggle) GitHub
raw markdown copy
This is page 2 of 7. Use http://codebase.md/mehmetoguzderin/shaderc-vkrunner-mcp?page={x} to view the full context.

# Directory Structure

```
├── .devcontainer
│   ├── devcontainer.json
│   ├── docker-compose.yml
│   └── Dockerfile
├── .gitattributes
├── .github
│   └── workflows
│       └── build-push-image.yml
├── .gitignore
├── .vscode
│   └── mcp.json
├── Cargo.lock
├── Cargo.toml
├── Dockerfile
├── LICENSE
├── README.adoc
├── shaderc-vkrunner-mcp.jpg
├── src
│   └── main.rs
└── vkrunner
    ├── .editorconfig
    ├── .gitignore
    ├── .gitlab-ci.yml
    ├── build.rs
    ├── Cargo.toml
    ├── COPYING
    ├── examples
    │   ├── compute-shader.shader_test
    │   ├── cooperative-matrix.shader_test
    │   ├── depth-buffer.shader_test
    │   ├── desc_set_and_binding.shader_test
    │   ├── entrypoint.shader_test
    │   ├── float-framebuffer.shader_test
    │   ├── frexp.shader_test
    │   ├── geometry.shader_test
    │   ├── indices.shader_test
    │   ├── layouts.shader_test
    │   ├── properties.shader_test
    │   ├── push-constants.shader_test
    │   ├── require-subgroup-size.shader_test
    │   ├── row-major.shader_test
    │   ├── spirv.shader_test
    │   ├── ssbo.shader_test
    │   ├── tolerance.shader_test
    │   ├── tricolore.shader_test
    │   ├── ubo.shader_test
    │   ├── vertex-data-piglit.shader_test
    │   └── vertex-data.shader_test
    ├── include
    │   ├── vk_video
    │   │   ├── vulkan_video_codec_av1std_decode.h
    │   │   ├── vulkan_video_codec_av1std_encode.h
    │   │   ├── vulkan_video_codec_av1std.h
    │   │   ├── vulkan_video_codec_h264std_decode.h
    │   │   ├── vulkan_video_codec_h264std_encode.h
    │   │   ├── vulkan_video_codec_h264std.h
    │   │   ├── vulkan_video_codec_h265std_decode.h
    │   │   ├── vulkan_video_codec_h265std_encode.h
    │   │   ├── vulkan_video_codec_h265std.h
    │   │   └── vulkan_video_codecs_common.h
    │   └── vulkan
    │       ├── vk_platform.h
    │       ├── vulkan_core.h
    │       └── vulkan.h
    ├── precompile-script.py
    ├── README.md
    ├── scripts
    │   └── update-vulkan.sh
    ├── src
    │   └── main.rs
    ├── test-build.sh
    └── vkrunner
        ├── allocate_store.rs
        ├── buffer.rs
        ├── compiler
        │   └── fake_process.rs
        ├── compiler.rs
        ├── config.rs
        ├── context.rs
        ├── enum_table.rs
        ├── env_var_test.rs
        ├── executor.rs
        ├── fake_vulkan.rs
        ├── features.rs
        ├── flush_memory.rs
        ├── format_table.rs
        ├── format.rs
        ├── half_float.rs
        ├── hex.rs
        ├── inspect.rs
        ├── lib.rs
        ├── logger.rs
        ├── make-enums.py
        ├── make-features.py
        ├── make-formats.py
        ├── make-pipeline-key-data.py
        ├── make-vulkan-funcs-data.py
        ├── parse_num.rs
        ├── pipeline_key_data.rs
        ├── pipeline_key.rs
        ├── pipeline_set.rs
        ├── requirements.rs
        ├── result.rs
        ├── script.rs
        ├── shader_stage.rs
        ├── slot.rs
        ├── small_float.rs
        ├── source.rs
        ├── stream.rs
        ├── temp_file.rs
        ├── tester.rs
        ├── tolerance.rs
        ├── util.rs
        ├── vbo.rs
        ├── vk.rs
        ├── vulkan_funcs_data.rs
        ├── vulkan_funcs.rs
        ├── window_format.rs
        └── window.rs
```

# Files

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

```rust
// vkrunner
//
// Copyright (C) 2016, 2017, 2023 Neil Roberts
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice (including the next
// paragraph) shall be included in all copies or substantial portions of the
// Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.

//! Helper functions for allocating Vulkan device memory for a buffer
//! or an image.

use crate::context::Context;
use crate::vk;
use std::ptr;

fn find_memory_type(
    context: &Context,
    mut usable_memory_types: u32,
    memory_type_flags: vk::VkMemoryPropertyFlags,
) -> Result<u32, String> {
    let memory_properties = context.memory_properties();

    while usable_memory_types != 0 {
        let memory_type = usable_memory_types.trailing_zeros();

        if memory_properties.memoryTypes[memory_type as usize].propertyFlags
            & memory_type_flags
            == memory_type_flags
        {
            return Ok(memory_type);
        }

        usable_memory_types &= !(1 << memory_type);
    }

    Err("Couldn’t find suitable memory type to allocate buffer".to_string())
}

fn allocate_memory(
    context: &Context,
    reqs: &vk::VkMemoryRequirements,
    memory_type_flags: vk::VkMemoryPropertyFlags,
) -> Result<(vk::VkDeviceMemory, u32), String> {
    let memory_type_index = find_memory_type(
        context,
        reqs.memoryTypeBits,
        memory_type_flags,
    )?;

    let mut memory = vk::null_handle();

    let allocate_info = vk::VkMemoryAllocateInfo {
        sType: vk::VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
        pNext: ptr::null(),
        allocationSize: reqs.size,
        memoryTypeIndex: memory_type_index,
    };
    let res = unsafe {
        context.device().vkAllocateMemory.unwrap()(
            context.vk_device(),
            ptr::addr_of!(allocate_info),
            ptr::null(), // allocator
            ptr::addr_of_mut!(memory),
        )
    };
    if res == vk::VK_SUCCESS {
        Ok((memory, memory_type_index))
    } else {
        Err("vkAllocateMemory failed".to_string())
    }
}

/// Allocate Vulkan device memory for the given buffer. It will pick
/// the right memory type by querying the device for the memory
/// requirements of the buffer. You can also limit the memory types
/// further by specifying extra flags in `memory_type_flags`. A handle
/// to the newly allocate device memory will be returned along with an
/// index representing the chosen memory type.
///
/// If the allocation fails a `String` will be returned describing the
/// error.
pub fn allocate_buffer(
    context: &Context,
    memory_type_flags: vk::VkMemoryPropertyFlags,
    buffer: vk::VkBuffer,
) -> Result<(vk::VkDeviceMemory, u32), String> {
    let vkdev = context.device();

    let mut reqs = vk::VkMemoryRequirements::default();

    unsafe {
        vkdev.vkGetBufferMemoryRequirements.unwrap()(
            context.vk_device(),
            buffer,
            ptr::addr_of_mut!(reqs),
        );
    }

    let (memory, memory_type_index) =
        allocate_memory(context, &reqs, memory_type_flags)?;

    unsafe {
        vkdev.vkBindBufferMemory.unwrap()(
            context.vk_device(),
            buffer,
            memory,
            0, // memoryOffset
        );
    }

    Ok((memory, memory_type_index))
}

/// Allocate Vulkan device memory for the given image. It will pick
/// the right memory type by querying the device for the memory
/// requirements of the image. You can also limit the memory types
/// further by specifying extra flags in `memory_type_flags`. A handle
/// to the newly allocate device memory will be returned along with an
/// index representing the chosen memory type.
///
/// If the allocation fails a `String` will be returned describing the
/// error.
pub fn allocate_image(
    context: &Context,
    memory_type_flags: vk::VkMemoryPropertyFlags,
    image: vk::VkImage,
) -> Result<(vk::VkDeviceMemory, u32), String> {
    let vkdev = context.device();

    let mut reqs = vk::VkMemoryRequirements::default();

    unsafe {
        vkdev.vkGetImageMemoryRequirements.unwrap()(
            context.vk_device(),
            image,
            ptr::addr_of_mut!(reqs),
        );
    }

    let (memory, memory_type_index) =
        allocate_memory(context, &reqs, memory_type_flags)?;

    unsafe {
        vkdev.vkBindImageMemory.unwrap()(
            context.vk_device(),
            image,
            memory,
            0, // memoryOffset
        );
    }

    Ok((memory, memory_type_index))
}

#[cfg(test)]
mod test {
    use super::*;
    use crate::fake_vulkan::{FakeVulkan, HandleType};
    use crate::requirements::Requirements;

    fn call_with_temp_buffer(
        fake_vulkan: &mut FakeVulkan,
        context: &Context,
        memory_type_flags: vk::VkMemoryPropertyFlags,
    ) -> Result<(vk::VkDeviceMemory, u32), String> {
        let buffer = fake_vulkan.add_handle(
            HandleType::Buffer {
                create_info: Default::default(),
                memory: None,
            }
        );

        let res = allocate_buffer(context, memory_type_flags, buffer);

        fake_vulkan.get_handle_mut(buffer).freed = true;

        res
    }

    fn call_with_temp_image(
        fake_vulkan: &mut FakeVulkan,
        context: &Context,
        memory_type_flags: vk::VkMemoryPropertyFlags,
    ) -> Result<(vk::VkDeviceMemory, u32), String> {
        let image = fake_vulkan.add_handle(HandleType::Image);

        let res = allocate_image(context, memory_type_flags, image);

        fake_vulkan.get_handle_mut(image).freed = true;

        res
    }

    fn do_allocate_buffer(
        memory_property_flags: &[u32],
        memory_type_bits: u32,
        memory_type_flags: vk::VkMemoryPropertyFlags,
    ) -> Result<(vk::VkDeviceMemory, u32, Context, Box<FakeVulkan>), String> {
        let mut fake_vulkan = FakeVulkan::new();
        fake_vulkan.physical_devices.push(Default::default());

        let memory_properties =
            &mut fake_vulkan.physical_devices[0].memory_properties;

        for (i, &flags) in memory_property_flags.iter().enumerate() {
            memory_properties.memoryTypes[i].propertyFlags = flags;
        }
        memory_properties.memoryTypeCount = memory_property_flags.len() as u32;

        fake_vulkan.memory_requirements.memoryTypeBits = memory_type_bits;

        fake_vulkan.set_override();
        let context = Context::new(&mut Requirements::new(), None).unwrap();
        call_with_temp_buffer(
            &mut fake_vulkan,
            &context,
            memory_type_flags,
        ).map(|(memory, memory_type)| (
            memory,
            memory_type,
            context,
            fake_vulkan,
        ))
    }

    #[test]
    fn find_memory() {
        let (device_memory, memory_type, context, fake_vulkan) =
            do_allocate_buffer(
            // Made-up set of memory properties
            &[
                vk::VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT
                    | vk::VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT,
                vk::VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT
                    | vk::VK_MEMORY_PROPERTY_PROTECTED_BIT,
                vk::VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT
                    | vk::VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT
                    | vk::VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT,
                vk::VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT
                    | vk::VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT
                    | vk::VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT
            ],
            // Pretend that the buffer can use types 0, 1 or 3
            0b1011,
            // Pretend we need host visible and lazily allocated. This
            // means either of the last two
            vk::VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT
                | vk::VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT,
        ).unwrap();

        // Only 2 or 3 have the properties we need, but only 3 is
        // allowed for the buffer requirements.
        assert_eq!(memory_type, 3);

        unsafe {
            context.device().vkFreeMemory.unwrap()(
                context.vk_device(),
                device_memory,
                ptr::null(), // allocator
            );
        }

        drop(context);
        drop(fake_vulkan);

        // Try with an impossible combination
        let err = do_allocate_buffer(
            &[
                vk::VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT
                    | vk::VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT,
            ],
            0b1,
            vk::VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT
                | vk::VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT,
        ).unwrap_err();

        assert_eq!(
            err,
            "Couldn’t find suitable memory type to allocate buffer"
        );
    }

    fn make_error_context() -> (Box<FakeVulkan>, Context) {
        let mut fake_vulkan = FakeVulkan::new();
        fake_vulkan.physical_devices.push(Default::default());

        fake_vulkan.physical_devices[0].memory_properties.memoryTypeCount = 1;
        fake_vulkan.memory_requirements.memoryTypeBits = 1;

        fake_vulkan.queue_result(
            "vkAllocateMemory".to_string(),
            vk::VK_ERROR_UNKNOWN
        );

        fake_vulkan.set_override();
        let context = Context::new(&mut Requirements::new(), None).unwrap();

        (fake_vulkan, context)
    }

    #[test]
    fn buffer_error() {
        let (mut fake_vulkan, context) = make_error_context();

        let err = call_with_temp_buffer(
            &mut fake_vulkan,
            &context,
            0, // memory_type_flags
        ).unwrap_err();

        assert_eq!(err, "vkAllocateMemory failed");
    }

    #[test]
    fn image_error() {
        let (mut fake_vulkan, context) = make_error_context();

        let err = call_with_temp_image(
            &mut fake_vulkan,
            &context,
            0, // memory_type_flags
        ).unwrap_err();

        assert_eq!(err, "vkAllocateMemory failed");
    }

    #[test]
    fn image() {
        let mut fake_vulkan = FakeVulkan::new();
        fake_vulkan.physical_devices.push(Default::default());

        fake_vulkan.physical_devices[0].memory_properties.memoryTypeCount = 1;
        fake_vulkan.memory_requirements.memoryTypeBits = 1;

        fake_vulkan.set_override();
        let context = Context::new(&mut Requirements::new(), None).unwrap();

        let (device_memory, memory_type) = call_with_temp_image(
            &mut fake_vulkan,
            &context,
            0, // memory_type_flags
        ).unwrap();

        assert!(device_memory != vk::null_handle());
        assert_eq!(memory_type, 0);

        unsafe {
            context.device().vkFreeMemory.unwrap()(
                context.vk_device(),
                device_memory,
                ptr::null(), // allocator
            );
        }
    }
}

```

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

```rust
// Automatically generated by make-pipeline-key-data.py

const N_BOOL_PROPERTIES: usize = 10;
const N_INT_PROPERTIES: usize = 28;
const N_FLOAT_PROPERTIES: usize = 6;

const TOPOLOGY_PROP_NUM: usize = 0;
const PATCH_CONTROL_POINTS_PROP_NUM: usize = 1;

static PROPERTIES: [Property; 44] = [
    Property {
        prop_type: PropertyType::Int,
        num: 11,
        name: "alphaBlendOp",
    },
    Property {
        prop_type: PropertyType::Int,
        num: 25,
        name: "back.compareMask",
    },
    Property {
        prop_type: PropertyType::Int,
        num: 24,
        name: "back.compareOp",
    },
    Property {
        prop_type: PropertyType::Int,
        num: 23,
        name: "back.depthFailOp",
    },
    Property {
        prop_type: PropertyType::Int,
        num: 21,
        name: "back.failOp",
    },
    Property {
        prop_type: PropertyType::Int,
        num: 22,
        name: "back.passOp",
    },
    Property {
        prop_type: PropertyType::Int,
        num: 27,
        name: "back.reference",
    },
    Property {
        prop_type: PropertyType::Int,
        num: 26,
        name: "back.writeMask",
    },
    Property {
        prop_type: PropertyType::Bool,
        num: 5,
        name: "blendEnable",
    },
    Property {
        prop_type: PropertyType::Int,
        num: 8,
        name: "colorBlendOp",
    },
    Property {
        prop_type: PropertyType::Int,
        num: 12,
        name: "colorWriteMask",
    },
    Property {
        prop_type: PropertyType::Int,
        num: 3,
        name: "cullMode",
    },
    Property {
        prop_type: PropertyType::Float,
        num: 1,
        name: "depthBiasClamp",
    },
    Property {
        prop_type: PropertyType::Float,
        num: 0,
        name: "depthBiasConstantFactor",
    },
    Property {
        prop_type: PropertyType::Bool,
        num: 3,
        name: "depthBiasEnable",
    },
    Property {
        prop_type: PropertyType::Float,
        num: 2,
        name: "depthBiasSlopeFactor",
    },
    Property {
        prop_type: PropertyType::Bool,
        num: 8,
        name: "depthBoundsTestEnable",
    },
    Property {
        prop_type: PropertyType::Bool,
        num: 1,
        name: "depthClampEnable",
    },
    Property {
        prop_type: PropertyType::Int,
        num: 13,
        name: "depthCompareOp",
    },
    Property {
        prop_type: PropertyType::Bool,
        num: 6,
        name: "depthTestEnable",
    },
    Property {
        prop_type: PropertyType::Bool,
        num: 7,
        name: "depthWriteEnable",
    },
    Property {
        prop_type: PropertyType::Int,
        num: 10,
        name: "dstAlphaBlendFactor",
    },
    Property {
        prop_type: PropertyType::Int,
        num: 7,
        name: "dstColorBlendFactor",
    },
    Property {
        prop_type: PropertyType::Int,
        num: 18,
        name: "front.compareMask",
    },
    Property {
        prop_type: PropertyType::Int,
        num: 17,
        name: "front.compareOp",
    },
    Property {
        prop_type: PropertyType::Int,
        num: 16,
        name: "front.depthFailOp",
    },
    Property {
        prop_type: PropertyType::Int,
        num: 14,
        name: "front.failOp",
    },
    Property {
        prop_type: PropertyType::Int,
        num: 15,
        name: "front.passOp",
    },
    Property {
        prop_type: PropertyType::Int,
        num: 20,
        name: "front.reference",
    },
    Property {
        prop_type: PropertyType::Int,
        num: 19,
        name: "front.writeMask",
    },
    Property {
        prop_type: PropertyType::Int,
        num: 4,
        name: "frontFace",
    },
    Property {
        prop_type: PropertyType::Float,
        num: 3,
        name: "lineWidth",
    },
    Property {
        prop_type: PropertyType::Int,
        num: 5,
        name: "logicOp",
    },
    Property {
        prop_type: PropertyType::Bool,
        num: 4,
        name: "logicOpEnable",
    },
    Property {
        prop_type: PropertyType::Float,
        num: 5,
        name: "maxDepthBounds",
    },
    Property {
        prop_type: PropertyType::Float,
        num: 4,
        name: "minDepthBounds",
    },
    Property {
        prop_type: PropertyType::Int,
        num: 1,
        name: "patchControlPoints",
    },
    Property {
        prop_type: PropertyType::Int,
        num: 2,
        name: "polygonMode",
    },
    Property {
        prop_type: PropertyType::Bool,
        num: 0,
        name: "primitiveRestartEnable",
    },
    Property {
        prop_type: PropertyType::Bool,
        num: 2,
        name: "rasterizerDiscardEnable",
    },
    Property {
        prop_type: PropertyType::Int,
        num: 9,
        name: "srcAlphaBlendFactor",
    },
    Property {
        prop_type: PropertyType::Int,
        num: 6,
        name: "srcColorBlendFactor",
    },
    Property {
        prop_type: PropertyType::Bool,
        num: 9,
        name: "stencilTestEnable",
    },
    Property {
        prop_type: PropertyType::Int,
        num: 0,
        name: "topology",
    },
];

fn copy_properties_to_create_info(
    key: &Key,
    s: &mut vk::VkGraphicsPipelineCreateInfo
) {
    {
        let s = unsafe { std::mem::transmute::<_, &mut vk::VkPipelineInputAssemblyStateCreateInfo>(s.pInputAssemblyState) };
        s.topology = key.int_properties[0] as vk::VkPrimitiveTopology;
        s.primitiveRestartEnable = key.bool_properties[0] as vk::VkBool32;
    }
    {
        let s = unsafe { std::mem::transmute::<_, &mut vk::VkPipelineTessellationStateCreateInfo>(s.pTessellationState) };
        s.patchControlPoints = key.int_properties[1] as u32;
    }
    {
        let s = unsafe { std::mem::transmute::<_, &mut vk::VkPipelineRasterizationStateCreateInfo>(s.pRasterizationState) };
        s.depthClampEnable = key.bool_properties[1] as vk::VkBool32;
        s.rasterizerDiscardEnable = key.bool_properties[2] as vk::VkBool32;
        s.polygonMode = key.int_properties[2] as vk::VkPolygonMode;
        s.cullMode = key.int_properties[3] as vk::VkCullModeFlags;
        s.frontFace = key.int_properties[4] as vk::VkFrontFace;
        s.depthBiasEnable = key.bool_properties[3] as vk::VkBool32;
        s.depthBiasConstantFactor = key.float_properties[0] as f32;
        s.depthBiasClamp = key.float_properties[1] as f32;
        s.depthBiasSlopeFactor = key.float_properties[2] as f32;
        s.lineWidth = key.float_properties[3] as f32;
    }
    {
        let s = unsafe { std::mem::transmute::<_, &mut vk::VkPipelineColorBlendStateCreateInfo>(s.pColorBlendState) };
        s.logicOpEnable = key.bool_properties[4] as vk::VkBool32;
        s.logicOp = key.int_properties[5] as vk::VkLogicOp;
        {
            let s = unsafe { std::mem::transmute::<_, &mut vk::VkPipelineColorBlendAttachmentState>(s.pAttachments) };
            s.blendEnable = key.bool_properties[5] as vk::VkBool32;
            s.srcColorBlendFactor = key.int_properties[6] as vk::VkBlendFactor;
            s.dstColorBlendFactor = key.int_properties[7] as vk::VkBlendFactor;
            s.colorBlendOp = key.int_properties[8] as vk::VkBlendOp;
            s.srcAlphaBlendFactor = key.int_properties[9] as vk::VkBlendFactor;
            s.dstAlphaBlendFactor = key.int_properties[10] as vk::VkBlendFactor;
            s.alphaBlendOp = key.int_properties[11] as vk::VkBlendOp;
            s.colorWriteMask = key.int_properties[12] as vk::VkColorComponentFlags;
        }
    }
    {
        let s = unsafe { std::mem::transmute::<_, &mut vk::VkPipelineDepthStencilStateCreateInfo>(s.pDepthStencilState) };
        s.depthTestEnable = key.bool_properties[6] as vk::VkBool32;
        s.depthWriteEnable = key.bool_properties[7] as vk::VkBool32;
        s.depthCompareOp = key.int_properties[13] as vk::VkCompareOp;
        s.depthBoundsTestEnable = key.bool_properties[8] as vk::VkBool32;
        s.stencilTestEnable = key.bool_properties[9] as vk::VkBool32;
        s.front.failOp = key.int_properties[14] as vk::VkStencilOp;
        s.front.passOp = key.int_properties[15] as vk::VkStencilOp;
        s.front.depthFailOp = key.int_properties[16] as vk::VkStencilOp;
        s.front.compareOp = key.int_properties[17] as vk::VkCompareOp;
        s.front.compareMask = key.int_properties[18] as u32;
        s.front.writeMask = key.int_properties[19] as u32;
        s.front.reference = key.int_properties[20] as u32;
        s.back.failOp = key.int_properties[21] as vk::VkStencilOp;
        s.back.passOp = key.int_properties[22] as vk::VkStencilOp;
        s.back.depthFailOp = key.int_properties[23] as vk::VkStencilOp;
        s.back.compareOp = key.int_properties[24] as vk::VkCompareOp;
        s.back.compareMask = key.int_properties[25] as u32;
        s.back.writeMask = key.int_properties[26] as u32;
        s.back.reference = key.int_properties[27] as u32;
        s.minDepthBounds = key.float_properties[4] as f32;
        s.maxDepthBounds = key.float_properties[5] as f32;
    }
}

impl Default for Key {
    fn default() -> Key {
        Key {
            pipeline_type: Type::Graphics,
            source: Source::Rectangle,
            entrypoints: Default::default(),

            bool_properties: [
                false, // primitiveRestartEnable
                false, // depthClampEnable
                false, // rasterizerDiscardEnable
                false, // depthBiasEnable
                false, // logicOpEnable
                false, // blendEnable
                false, // depthTestEnable
                false, // depthWriteEnable
                false, // depthBoundsTestEnable
                false, // stencilTestEnable
            ],
            int_properties: [
                vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP as i32, // topology
                0 as i32, // patchControlPoints
                vk::VK_POLYGON_MODE_FILL as i32, // polygonMode
                vk::VK_CULL_MODE_NONE as i32, // cullMode
                vk::VK_FRONT_FACE_COUNTER_CLOCKWISE as i32, // frontFace
                vk::VK_LOGIC_OP_SET as i32, // logicOp
                vk::VK_BLEND_FACTOR_SRC_ALPHA as i32, // srcColorBlendFactor
                vk::VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA as i32, // dstColorBlendFactor
                vk::VK_BLEND_OP_ADD as i32, // colorBlendOp
                vk::VK_BLEND_FACTOR_SRC_ALPHA as i32, // srcAlphaBlendFactor
                vk::VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA as i32, // dstAlphaBlendFactor
                vk::VK_BLEND_OP_ADD as i32, // alphaBlendOp
                (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
                vk::VK_COMPARE_OP_LESS as i32, // depthCompareOp
                vk::VK_STENCIL_OP_KEEP as i32, // front.failOp
                vk::VK_STENCIL_OP_KEEP as i32, // front.passOp
                vk::VK_STENCIL_OP_KEEP as i32, // front.depthFailOp
                vk::VK_COMPARE_OP_ALWAYS as i32, // front.compareOp
                u32::MAX as i32, // front.compareMask
                u32::MAX as i32, // front.writeMask
                0 as i32, // front.reference
                vk::VK_STENCIL_OP_KEEP as i32, // back.failOp
                vk::VK_STENCIL_OP_KEEP as i32, // back.passOp
                vk::VK_STENCIL_OP_KEEP as i32, // back.depthFailOp
                vk::VK_COMPARE_OP_ALWAYS as i32, // back.compareOp
                u32::MAX as i32, // back.compareMask
                u32::MAX as i32, // back.writeMask
                0 as i32, // back.reference
            ],
            float_properties: [
                0.0, // depthBiasConstantFactor
                0.0, // depthBiasClamp
                0.0, // depthBiasSlopeFactor
                1.0, // lineWidth
                0.0, // minDepthBounds
                0.0, // maxDepthBounds
            ],
        }
    }
}


```

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

```rust
// Copyright (c) The Piglit project 2007
// Copyright 2023 Neil Roberts
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// on the rights to use, copy, modify, merge, publish, distribute, sub
// license, and/or sell copies of the Software, and to permit persons to whom
// the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice (including the next
// paragraph) shall be included in all copies or substantial portions of the
// Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.  IN NO EVENT SHALL
// VA LINUX SYSTEM, IBM AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
// USE OR OTHER DEALINGS IN THE SOFTWARE.

use crate::half_float;
use std::num::{ParseFloatError, ParseIntError};
use std::fmt;
use std::convert::From;

// Based on functions from piglit-util.c

#[derive(Debug)]
pub enum ParseError {
    Float(ParseFloatError),
    Int(ParseIntError),
}

impl fmt::Display for ParseError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            ParseError::Float(e) => e.fmt(f),
            ParseError::Int(e) => e.fmt(f),
        }
    }
}

impl From<ParseFloatError> for ParseError {
    fn from(e: ParseFloatError) -> ParseError {
        ParseError::Float(e)
    }
}

impl From<ParseIntError> for ParseError {
    fn from(e: ParseIntError) -> ParseError {
        ParseError::Int(e)
    }
}

// Similar to haystack.starts_with(needle) but the ASCII characters of
// haystack are converted to lower case before comparing. The needle
// value should already be in lowercase for this to work.
fn starts_with_ignore_case(haystack: &str, needle: &str) -> bool {
    let mut haystack_chars = haystack.chars();

    for needle_c in needle.chars() {
        match haystack_chars.next() {
            None => return false,
            Some(haystack_c) => if haystack_c.to_ascii_lowercase() != needle_c {
                return false;
            },
        }
    }

    true
}

// Checks whether the string slice starts with one of the special
// words allowed in a float string. If so it returns the length of the
// word, otherwise it returns None.
fn starts_with_float_special_word(s: &str) -> Option<usize> {
    for word in ["infinity", "inf", "nan"] {
        if starts_with_ignore_case(s, word) {
            return Some(word.len());
        }
    }

   None
}

// Checks whether the string starts with a valid Number part of a
// float. If so it returns the byte length, otherwise it returns None.
fn count_number(s: &str) -> Option<usize> {
    // Optional units
    let before_digits = count_digits(s);

    let num_end = &s[before_digits..];

    // Optional decimal
    let after_digits;
    let n_points;

    if let Some('.') = num_end.chars().next() {
        n_points = 1;
        let digits = &num_end[1..];
        after_digits = count_digits(digits);
    } else {
        n_points = 0;
        after_digits = 0;
    }

    // Either the units or the decimal must be present
    if before_digits > 0 || after_digits > 0 {
        Some(before_digits + n_points + after_digits)
    } else {
        None
    }
}

// Returns how many ASCII digits are at the start of the string
fn count_digits(s: &str) -> usize {
    s.chars().take_while(char::is_ascii_digit).count()
}

// Checks whether the strings starts with a valid Exp part of a float.
// If so it returns the byte length, otherwise it returns None.
fn count_exp(s: &str) -> Option<usize> {
    if let Some('E' | 'e') = s.chars().next() {
        let mut count = 1;

        if let Some('+' | '-') = s[count..].chars().next() {
            count += 1;
        }

        let digits = count_digits(&s[count..]);

        if digits > 0 {
            Some(count + digits)
        } else {
            None
        }
    } else {
        None
    }
}

// It looks like the rust float parsing functions don’t have an
// equivalent of the `endptr` argument to `strtod`. This function
// tries to work around that by extracting the float part and the rest
// of the string and returning the two string slices as a tuple. It also
// skips leading spaces.
fn split_parts(mut s: &str) -> (&str, &str) {
    // skip only ASCII spaces and tabs
    while !s.is_empty() &&
        (s.as_bytes()[0] == b' ' || s.as_bytes()[0] == b'\t')
    {
        s = &s[1..];
    }

    let mut split_point = 0;

    if s.starts_with("0x") {
        split_point =
            2
            + s[2..]
            .chars()
            .take_while(char::is_ascii_hexdigit)
            .count();
    } else {
        // Optional sign
        if let Some('-' | '+') = s[split_point..].chars().next() {
            split_point += 1;
        }

        if let Some(len) = starts_with_float_special_word(&s[split_point..]) {
            split_point += len;
        } else if let Some(len) = count_number(&s[split_point..]) {
            split_point += len;

            if let Some(len) = count_exp(&s[split_point..]) {
                split_point += len;
            }
        }
    }

    (&s[0..split_point], &s[split_point..])
}

// Wrapper for str.parse<f32> which allows using an exact hex bit
// pattern to generate a float value and ignores trailing data.
//
// If the parsing works, it will return a tuple with the floating
// point value and a string slice pointing to the rest of the string.
pub fn parse_f32(s: &str) -> Result<(f32, &str), ParseError> {
    let (s, tail) = split_parts(s);

    if s.starts_with("0x") {
        Ok((f32::from_bits(u32::from_str_radix(&s[2..], 16)?), tail))
    } else {
        Ok((s.parse::<f32>()?, tail))
    }
}

// Wrapper for str.parse<f64> which allows using an exact hex bit
// pattern to generate a float value and ignores trailing data.
//
// If the parsing works, it will return a tuple with the floating
// point value and a string slice pointing to the rest of the string.
pub fn parse_f64(s: &str) -> Result<(f64, &str), ParseError> {
    let (s, tail) = split_parts(s);

    if s.starts_with("0x") {
        Ok((f64::from_bits(u64::from_str_radix(&s[2..], 16)?), tail))
    } else {
        Ok((s.parse::<f64>()?, tail))
    }
}

// Wrapper for calling half_float::from_f32 on the result of parsing to the
// string to a float but that also allows specifying the value exactly
// as a hexadecimal number.
//
// If the parsing works, it will return a tuple with the half float
// value and a string slice pointing to the rest of the string.
pub fn parse_half_float(s: &str) -> Result<(u16, &str), ParseError> {
    let (s, tail) = split_parts(s);

    if s.starts_with("0x") {
        Ok((u16::from_str_radix(&s[2..], 16)?, tail))
    } else {
        Ok((half_float::from_f32(s.parse::<f32>()?), tail))
    }
}

#[cfg(test)]
mod test {
    use super::*;

    #[test]
    fn test_split_parts() {
        // Skip spaces and tabs
        assert_eq!(split_parts("    0"), ("0", ""));
        assert_eq!(split_parts("  \t  0"), ("0", ""));
        // Don’t skip other whitespace characters
        assert_eq!(split_parts("  \n  0"), ("", "\n  0"));

        // Hex digits
        assert_eq!(split_parts("0xCafeCafeTEA"), ("0xCafeCafe", "TEA"));

        // Signs
        assert_eq!(split_parts("+42 cupcakes"), ("+42", " cupcakes"));
        assert_eq!(split_parts("-42 gerbils"), ("-42", " gerbils"));

        // Special words
        assert_eq!(split_parts("+infinity forever"), ("+infinity", " forever"));
        assert_eq!(split_parts("INf forever"), ("INf", " forever"));
        assert_eq!(split_parts("   -NaN fornever"), ("-NaN", " fornever"));
        assert_eq!(split_parts("infin"), ("inf", "in"));
        assert_eq!(split_parts("NaN12"), ("NaN", "12"));

        // Normal numbers
        assert_eq!(split_parts("12.2"), ("12.2", ""));
        assert_eq!(split_parts("-12.2"), ("-12.2", ""));
        assert_eq!(split_parts("12.2e6"), ("12.2e6", ""));
        assert_eq!(split_parts("12.2E6"), ("12.2E6", ""));
        assert_eq!(split_parts("12.E6"), ("12.E6", ""));
        assert_eq!(split_parts("12.E-6"), ("12.E-6", ""));
        assert_eq!(split_parts("12.E+6"), ("12.E+6", ""));
        assert_eq!(split_parts(".0"), (".0", ""));
        assert_eq!(split_parts("5."), ("5.", ""));
        assert_eq!(split_parts(".5e6"), (".5e6", ""));
        assert_eq!(split_parts("5.e6"), ("5.e6", ""));

        // At least one side of the decimal point must be specified
        assert_eq!(split_parts("+."), ("+", "."));

        // The exponent must have some digits
        assert_eq!(split_parts("12e"), ("12", "e"));
        assert_eq!(split_parts("12e-"), ("12", "e-"));

        // Can’t have the exponent on its own
        assert_eq!(split_parts("e12"), ("", "e12"));
    }

    fn float_matches<T: Into<f64>>(
        res: Result<(T, &str), ParseError>,
        expected_value: T,
        expected_tail: &str
    ) {
        let (value, tail) = res.unwrap();
        let value = value.into();
        let expected_value = expected_value.into();

        assert!((value - expected_value).abs() < 0.0001,
                "value={}, expected_value={}",
                value,
                expected_value);
        assert_eq!(expected_tail, tail);
    }

    #[test]
    fn test_parse_f32() {
        float_matches(parse_f32("1.0"), 1.0, "");
        float_matches(parse_f32("  \t 1.0"), 1.0, "");
        float_matches(parse_f32("-1.0"), -1.0, "");
        float_matches(parse_f32("+1.0"), 1.0, "");
        float_matches(parse_f32("42 monkies"), 42.0, " monkies");

        float_matches(parse_f32("0x0"), 0.0, "");
        assert_eq!(parse_f32("0x7f800000").unwrap().0, f32::INFINITY);

        assert_eq!(parse_f32("-inf").unwrap(), (-f32::INFINITY, ""));
        assert_eq!(parse_f32("infinity 12").unwrap(), (f32::INFINITY, " 12"));
        assert!(parse_f32("NaN").unwrap().0.is_nan());

        assert!(matches!(
            parse_f32(""),
            Err(ParseError::Float(ParseFloatError { .. }))
        ));

        assert!(matches!(
            parse_f32("0xaaaaaaaaa"),
            Err(ParseError::Int(ParseIntError { .. }))
        ));
    }

    #[test]
    fn test_parse_f64() {
        float_matches(parse_f64("1.0"), 1.0, "");
        float_matches(parse_f64("42 monkies"), 42.0, " monkies");

        float_matches(parse_f64("0x0"), 0.0, "");
        assert_eq!(parse_f64("0xfff0000000000000").unwrap().0, -f64::INFINITY);

        assert_eq!(parse_f64("-inf").unwrap(), (-f64::INFINITY, ""));
        assert_eq!(parse_f64("infinity 12").unwrap(), (f64::INFINITY, " 12"));
        assert!(parse_f64("NaN").unwrap().0.is_nan());

        assert!(matches!(
            parse_f64(""),
            Err(ParseError::Float(ParseFloatError { .. }))
        ));

        assert!(matches!(
            parse_f64("0xaaaaaaaaaaaaaaaaa"),
            Err(ParseError::Int(ParseIntError { .. }))
        ));
    }

    #[test]
    fn test_parse_half_float() {
        assert_eq!(parse_half_float("1.0").unwrap(), (0x3c00, ""));

        assert_eq!(parse_half_float("0x7bff").unwrap(), (0x7bff, ""));
        assert_eq!(parse_half_float("0x7c00").unwrap(), (0x7c00, ""));

        assert_eq!(
            parse_half_float("infinity 12").unwrap(),
            (0x7c00, " 12")
        );

        assert!(matches!(
            parse_half_float(""),
            Err(ParseError::Float(ParseFloatError { .. }))
        ));

        assert!(matches!(
            parse_half_float("0xffff1"),
            Err(ParseError::Int(ParseIntError { .. }))
        ));
    }
}

```

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

```python
#!/usr/bin/python3

# Copyright 2023 Neil Roberts

# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the "Software"),
# to deal in the Software without restriction, including without limitation
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
# and/or sell copies of the Software, and to permit persons to whom the
# Software is furnished to do so, subject to the following conditions:

# The above copyright notice and this permission notice (including the next
# paragraph) shall be included in all copies or substantial portions of the
# Software.

# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
# DEALINGS IN THE SOFTWARE.

# This script is used to generate pipeline_key_data.rs. It is not run
# automatically as part of the build process but if need be it can be
# used to update the file as follows:
#
# ./make-pipeline-key-data.py > pipeline_key_data.rs

from mako.template import Template

TEMPLATE="""\
// Automatically generated by make-pipeline-key-data.py

const N_BOOL_PROPERTIES: usize = ${sum(1 for p in props
                                       if p.base_type == "bool")};
const N_INT_PROPERTIES: usize = ${sum(1 for p in props
                                      if p.base_type == "int")};
const N_FLOAT_PROPERTIES: usize = ${sum(1 for p in props
                                        if p.base_type == "float")};

const TOPOLOGY_PROP_NUM: usize = ${next(p for p in props
                                        if p.name == "topology").num};
const PATCH_CONTROL_POINTS_PROP_NUM: usize = ${
    next(p for p in props if p.name == "patchControlPoints").num};

static PROPERTIES: [Property; ${len(props)}] = [
% for prop in sorted(props, key=lambda p: p.name):
    Property {
        prop_type: PropertyType::${prop.base_type.capitalize()},
        num: ${prop.num},
        name: "${prop.name}",
    },
% endfor
];

fn copy_properties_to_create_info(
    key: &Key,
    s: &mut vk::VkGraphicsPipelineCreateInfo
) {
${setters}
}

impl Default for Key {
    fn default() -> Key {
        Key {
            pipeline_type: Type::Graphics,
            source: Source::Rectangle,
            entrypoints: Default::default(),

            bool_properties: [
% for prop in sorted(props, key=lambda p: p.num):
%   if prop.base_type == "bool":
                ${prop.default}, // ${prop.name}
%   endif
% endfor
            ],
            int_properties: [
% for prop in sorted(props, key=lambda p: p.num):
%   if prop.base_type == "int":
                ${prop.default} as i32, // ${prop.name}
%   endif
% endfor
            ],
            float_properties: [
% for prop in sorted(props, key=lambda p: p.num):
%   if prop.base_type == "float":
                ${prop.default}, // ${prop.name}
%   endif
% endfor
            ],
        }
    }
}
"""


class Structure:
    def __init__(self, name, variable, children):
        self.name = name
        self.variable = variable
        self.children = children


class Property:
    def __init__(self, vk_type, name, default):
        self.vk_type = vk_type
        self.base_type = vk_type_as_base_type(vk_type)
        self.name = name
        self.default = default


class Properties:
    def __init__(self):
        self.values = []
        self.counts = {}

    def add(self, prop):
        base_type = prop.base_type
        try:
            self.counts[base_type] += 1
        except KeyError:
            self.counts[base_type] = 1

        prop.num = self.counts[base_type] - 1

        self.values.append(prop)


def vk_type_as_base_type(vk_type):
    if vk_type == "vk::VkBool32":
        return "bool"
    elif vk_type == "f32":
        return "float"
    elif vk_type == "u32":
        return "int"
    elif vk_type.startswith("vk::Vk"):
        return "int"

    raise ValueError("Unsupported Vulkan type: {}".format(vk_type))


STRUCTURES = [
    Structure("VkPipelineInputAssemblyStateCreateInfo",
              "pInputAssemblyState",
              [
                  Property("vk::VkPrimitiveTopology",
                           "topology",
                           "vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP"),
                  Property("vk::VkBool32",
                           "primitiveRestartEnable",
                           "false"),
              ]),

    Structure("VkPipelineTessellationStateCreateInfo",
              "pTessellationState",
              [
                  Property("u32", "patchControlPoints", "0"),
              ]),

    Structure("VkPipelineRasterizationStateCreateInfo",
              "pRasterizationState",
              [
                  Property("vk::VkBool32", "depthClampEnable", "false"),
                  Property("vk::VkBool32", "rasterizerDiscardEnable", "false"),
                  Property("vk::VkPolygonMode",
                           "polygonMode",
                           "vk::VK_POLYGON_MODE_FILL"),
                  Property("vk::VkCullModeFlags",
                           "cullMode",
                           "vk::VK_CULL_MODE_NONE"),
                  Property("vk::VkFrontFace",
                           "frontFace",
                           "vk::VK_FRONT_FACE_COUNTER_CLOCKWISE"),
                  Property("vk::VkBool32", "depthBiasEnable", "false"),
                  Property("f32", "depthBiasConstantFactor", "0.0"),
                  Property("f32", "depthBiasClamp", "0.0"),
                  Property("f32", "depthBiasSlopeFactor", "0.0"),
                  Property("f32", "lineWidth", "1.0"),
              ]),

    Structure("VkPipelineColorBlendStateCreateInfo",
              "pColorBlendState",
              [
                  Property("vk::VkBool32", "logicOpEnable", "false"),
                  Property("vk::VkLogicOp", "logicOp", "vk::VK_LOGIC_OP_SET"),

                  Structure("VkPipelineColorBlendAttachmentState",
                            "pAttachments",
                            [
                                Property("vk::VkBool32",
                                         "blendEnable",
                                         "false"),
                                Property("vk::VkBlendFactor",
                                         "srcColorBlendFactor",
                                         "vk::VK_BLEND_FACTOR_SRC_ALPHA"),
                                Property("vk::VkBlendFactor",
                                         "dstColorBlendFactor",
                                         "vk::VK_BLEND_FACTOR_"
                                         "ONE_MINUS_SRC_ALPHA"),
                                Property("vk::VkBlendOp",
                                         "colorBlendOp",
                                         "vk::VK_BLEND_OP_ADD"),
                                Property("vk::VkBlendFactor",
                                         "srcAlphaBlendFactor",
                                         "vk::VK_BLEND_FACTOR_SRC_ALPHA"),
                                Property("vk::VkBlendFactor",
                                         "dstAlphaBlendFactor",
                                         "vk::VK_BLEND_FACTOR_"
                                         "ONE_MINUS_SRC_ALPHA"),
                                Property("vk::VkBlendOp",
                                         "alphaBlendOp",
                                         "vk::VK_BLEND_OP_ADD"),
                                Property("vk::VkColorComponentFlags",
                                         "colorWriteMask",
                                         "(vk::VK_COLOR_COMPONENT_R_BIT | "
                                         "vk::VK_COLOR_COMPONENT_G_BIT | "
                                         "vk::VK_COLOR_COMPONENT_B_BIT | "
                                         "vk::VK_COLOR_COMPONENT_A_BIT)"),
                            ]),
              ]),

    Structure("VkPipelineDepthStencilStateCreateInfo",
              "pDepthStencilState",
              [
                  Property("vk::VkBool32", "depthTestEnable", "false"),
                  Property("vk::VkBool32", "depthWriteEnable", "false"),
                  Property("vk::VkCompareOp",
                           "depthCompareOp",
                           "vk::VK_COMPARE_OP_LESS"),
                  Property("vk::VkBool32",
                           "depthBoundsTestEnable",
                           "false"),
                  Property("vk::VkBool32",
                           "stencilTestEnable",
                           "false"),
                  Property("vk::VkStencilOp",
                           "front.failOp",
                           "vk::VK_STENCIL_OP_KEEP"),
                  Property("vk::VkStencilOp",
                           "front.passOp",
                           "vk::VK_STENCIL_OP_KEEP"),
                  Property("vk::VkStencilOp",
                           "front.depthFailOp",
                           "vk::VK_STENCIL_OP_KEEP"),
                  Property("vk::VkCompareOp",
                           "front.compareOp",
                           "vk::VK_COMPARE_OP_ALWAYS"),
                  Property("u32",
                           "front.compareMask",
                           "u32::MAX"),
                  Property("u32",
                           "front.writeMask",
                           "u32::MAX"),
                  Property("u32",
                           "front.reference",
                           "0"),
                  Property("vk::VkStencilOp",
                           "back.failOp",
                           "vk::VK_STENCIL_OP_KEEP"),
                  Property("vk::VkStencilOp",
                           "back.passOp",
                           "vk::VK_STENCIL_OP_KEEP"),
                  Property("vk::VkStencilOp",
                           "back.depthFailOp",
                           "vk::VK_STENCIL_OP_KEEP"),
                  Property("vk::VkCompareOp",
                           "back.compareOp",
                           "vk::VK_COMPARE_OP_ALWAYS"),
                  Property("u32",
                           "back.compareMask",
                           "u32::MAX"),
                  Property("u32",
                           "back.writeMask",
                           "u32::MAX"),
                  Property("u32",
                           "back.reference",
                           "0"),
                  Property("f32", "minDepthBounds", "0.0"),
                  Property("f32", "maxDepthBounds", "0.0"),
              ])
]


def get_props(structure, props):
    for child in structure.children:
        if isinstance(child, Property):
            props.add(child)
        elif isinstance(child, Structure):
            get_props(child, props)
        else:
            raise Exception("STRUCTURES array is broken")


def make_setters(structure):
    parts = []

    parts.append("    {")
    parts.append("        let s = unsafe {{ "
                 "std::mem::transmute::<_, &mut vk::{}>(s.{}) }};".format(
                     structure.name,
                     structure.variable))

    for child in structure.children:
        if isinstance(child, Structure):
            parts.extend(map(lambda line: "    " + line,
                             make_setters(child)))
        elif isinstance(child, Property):
            parts.append("        s.{} = key.{}_properties[{}] as {};".format(
                child.name,
                child.base_type,
                child.num,
                child.vk_type))

    parts.append("    }")

    return parts


def main():
    template = Template(TEMPLATE)

    props = Properties()
    for structure in STRUCTURES:
        get_props(structure, props)

    setters = "\n".join(sum(map(make_setters, STRUCTURES), start=[]))

    print(template.render(props = props.values, setters = setters))


if __name__ == '__main__':
    main()

```

--------------------------------------------------------------------------------
/vkrunner/vkrunner/stream.rs:
--------------------------------------------------------------------------------

```rust
// vkrunner
//
// Copyright (C) 2018 Intel Corporation
// Copyright 2023 Neil Roberts
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice (including the next
// paragraph) shall be included in all copies or substantial portions of the
// Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.

use crate::source;
use std::io;
use std::io::BufRead;
use std::fmt;
use std::fs;

// Encapsulates the two possible buf readers (either from a file or
// from a string) that the stream will use. I don’t think we can put
// this behind a boxed trait object because we can’t tell Rust that
// the box won’t outlive the Stream object.
#[derive(Debug)]
enum Reader<'a> {
    File(io::BufReader<fs::File>),
    String(io::BufReader<&'a [u8]>),
}

/// A struct used to read lines from a [Source](source::Source). This
/// will handle concatening lines that end with the line continuation
/// character (`\`) and the token replacements.
#[derive(Debug)]
pub struct Stream<'a> {
    source: &'a source::Source,
    reader: Reader<'a>,

    line_num: usize,
    next_line_num: usize,
    reached_eof: bool,
}

/// An error that can be returned from [Stream::read_line] or [Stream::new].
#[derive(Debug)]
pub enum StreamError {
    IoError(io::Error),
    /// A token replacement causes an infinite loop of replacements to
    /// occur.
    TokenReplacementLoop,
}

impl fmt::Display for StreamError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            StreamError::IoError(e) => e.fmt(f),
            StreamError::TokenReplacementLoop => {
                write!(f, "The token replacements cause an infinite loop")
            },
        }
    }
}

impl std::convert::From<io::Error> for StreamError {
    fn from(value: io::Error) -> StreamError {
        StreamError::IoError(value)
    }
}

impl<'a> Stream<'a> {
    /// Constructs a new [Stream] that will read lines from the given
    /// [Source](source::Source). The construction can fail if the
    /// stream is a file source and opening the file fails. In that
    /// case the returned [StreamError] will contain an
    /// [io::Error](std::io::Error).
    pub fn new(source: &source::Source) -> Result<Stream, StreamError> {
        let reader = match source.data() {
            source::Data::File { filename } => {
                let file = fs::File::open(filename)?;
                Reader::File(io::BufReader::new(file))
            },
            source::Data::String { source } => {
                Reader::String(io::BufReader::new(source.as_bytes()))
            },
        };

        Ok(Stream {
            source,
            reader,
            line_num: 0,
            next_line_num: 1,
            reached_eof: false,
        })
    }

    /// Read a line from the stream and append it to the given String.
    /// This will handle the line continuation characters (`\`) and
    /// the token replacements set on the [Source](source::Source).
    ///
    /// The length of the data appended to the string is returned. If
    /// the end of the source is reached then it will return 0.
    pub fn read_line(
        &mut self,
        line: &mut String
    ) -> Result<usize, StreamError> {
        let start_length = line.len();

        self.line_num = self.next_line_num;

        while !self.reached_eof {
            let length = match &mut self.reader {
                Reader::File(r) => r.read_line(line)?,
                Reader::String(r) => r.read_line(line)?,
            };

            if length == 0 {
                self.reached_eof = true;
                break;
            }

            self.next_line_num += 1;

            if length >= 2 {
                if line.ends_with("\\\n") {
                    line.truncate(line.len() - 2);
                    continue;
                } else if length >= 3 && line.ends_with("\\\r\n") {
                    line.truncate(line.len() - 3);
                    continue;
                }
            }

            break;
        }

        self.process_token_replacements(line, start_length)?;

        Ok(line.len() - start_length)
    }

    /// Returns the line number in the source data of the start of the
    /// last line that was returned by [read_line](Stream::read_line).
    /// For example, if the source file is like this:
    ///
    /// ```text
    /// line one \
    /// continuation of line one.
    /// line two \
    /// continuation of line two.
    /// ```
    ///
    /// then the second time `read_line` is called it will append
    /// “line two continuation of line two” and
    /// [line_num](Stream::line_num) will report 3 because the line
    /// starts on the third line of the source data.
    pub fn line_num(&self) -> usize {
        self.line_num
    }

    fn process_token_replacements(
        &self,
        line: &mut String,
        start_pos: usize
    ) -> Result<(), StreamError> {
        let mut count = 0usize;

        // Loop through each valid position in the line string. We
        // can’t safely use an iterator because we’re going to modify
        // the string as we iterate
        let mut pos = start_pos;

        while pos < line.len() {
            'token_loop: loop {
                for token_replacement in self.source.token_replacements() {
                    if line[pos..].starts_with(&token_replacement.token) {
                        count += 1;

                        // If we’ve replaced at least 1000 tokens then
                        // something has probably gone wrong and this
                        // is never going to finish.
                        if count >= 1000 {
                            return Err(StreamError::TokenReplacementLoop);
                        }

                        line.replace_range(
                            pos..pos + token_replacement.token.len(),
                            &token_replacement.replacement,
                        );

                        // Start looking for tokens from the start of
                        // the list in case the replacement contains
                        // one of the earlier tokens
                        continue 'token_loop;
                    }
                }

                break 'token_loop;
            }

            // Move to the next character. It would be nice if we
            // could do this by just looking at the first byte of the
            // UTF-8 sequence but there doesn’t seem to be a handy
            // Rust API for that.
            pos += line[pos..].chars().next().unwrap().len_utf8();
        }

        Ok(())
    }
}

#[cfg(test)]
mod test {
    use super::*;

    #[test]
    fn test_line_continuation() {
        let source = source::Source::from_string(
            "line one \\\n\
             more line one\n\
             line three \\\n\
             is really long \\\n\
             \\\n\
             and even has blank lines".to_string()
        );
        let mut stream = Stream::new(&source).unwrap();

        let mut line = String::new();
        assert_eq!(stream.read_line(&mut line).unwrap(), 23);
        assert_eq!(line, "line one more line one\n");
        assert_eq!(stream.line_num(), 1);

        assert_eq!(stream.read_line(&mut line).unwrap(), 50);
        assert_eq!(
            &line[23..],
            "line three is really long and even has blank lines",
        );
        assert_eq!(stream.line_num(), 3);

        // The line can also be continued if it has Windows-style line endings
        let source = source::Source::from_string(
            "line one \\\r\n\
             more line one\n\
             line three \r what".to_string()
        );
        let mut stream = Stream::new(&source).unwrap();
        let mut line = String::new();

        assert_eq!(stream.read_line(&mut line).unwrap(), 23);
        assert_eq!(line, "line one more line one\n");
        assert_eq!(stream.line_num(), 1);

        line.clear();
        assert_eq!(stream.read_line(&mut line).unwrap(), 17);
        assert_eq!(line, "line three \r what");
        assert_eq!(stream.line_num(), 3);

        // Backslashes in the middle of the string should just be left alone
        let source = source::Source::from_string(
            "I am happy \\o//".to_string()
        );
        let mut stream = Stream::new(&source).unwrap();
        let mut line = String::new();
        assert_eq!(stream.read_line(&mut line).unwrap(), 15);
        assert_eq!(line, "I am happy \\o//");
    }

    #[test]
    fn test_missing_file() {
        let source = source::Source::from_file(
            "this-file-does-not-exist".to_string().into()
        );
        let e = Stream::new(&source).unwrap_err();
        match e {
            StreamError::IoError(e) => {
                assert_eq!(e.kind(), io::ErrorKind::NotFound);
            },
            _ => unreachable!("expected StreamError::IoError, got: {}", e),
        }
    }

    fn run_test_file_source(filename: String) {
        fs::write(&filename, "my source code").unwrap();

        let source = source::Source::from_file(filename.into());
        let mut stream = Stream::new(&source).unwrap();
        let mut line = String::new();
        assert_eq!(stream.read_line(&mut line).unwrap(), 14);
        assert_eq!(line, "my source code");

        // EOF should return 0
        assert_eq!(stream.read_line(&mut line).unwrap(), 0);
        // It should also work a second time
        assert_eq!(stream.read_line(&mut line).unwrap(), 0);
    }

    #[test]
    fn test_file_source() {
        let mut filename = std::env::temp_dir();
        filename.push("vkrunner-test-file-source");
        let filename_str = filename.to_str().unwrap().to_owned();

        // Catch the unwind to try to remove the file that we created
        // if the test fails
        let r = std::panic::catch_unwind(
            move || run_test_file_source(filename_str)
        );

        if let Err(e) = fs::remove_file(filename) {
            assert_eq!(e.kind(), io::ErrorKind::NotFound);
        }

        if let Err(e) = r {
            std::panic::resume_unwind(e);
        }
    }

    macro_rules! replace_tokens {
        ($source:expr, $expected:expr, $($token:expr, $replacement:expr),*) => {
            let mut source = source::Source::from_string($source.to_owned());

            $(
                {
                    source.add_token_replacement(
                        $token.to_owned(),
                        $replacement.to_owned()
                    );
                }
            )*;

            let mut stream = Stream::new(&source).unwrap();
            let mut line = String::new();

            assert_eq!(stream.read_line(&mut line).unwrap(), $expected.len());
            assert_eq!(line, $expected);
        };
    }

    #[test]
    fn test_token_replacements() {
        // Simple replacement
        replace_tokens!(
            "one two",
            "1 2",
            "one", "1",
            "two", "2"
        );
        // Line continuation within a replacement
        replace_tokens!(
            "tok\\\n\
             ens are neat",
            "replacements are neat",
            "token",
            "replacement"
        );
        // Chain of replacements
        replace_tokens!(
            "I like this",
            "I like tomatoes",
            "this", "thatthing",
            "that", "t",
            "thing", "omatoes"
        );

        let mut source = source::Source::from_string(
            "Infinite recursion!".to_string()
        );
        source.add_token_replacement(
            "recursion".to_string(),
            "deeper".to_string(),
        );
        source.add_token_replacement(
            "deeper".to_string(),
            "keep-going".to_string(),
        );
        source.add_token_replacement(
            "keep-going".to_string(),
            "recursion".to_string(),
        );
        let mut stream = Stream::new(&source).unwrap();
        let mut line = String::new();
        let e = stream.read_line(&mut line).unwrap_err();
        assert!(matches!(e, StreamError::TokenReplacementLoop));
        assert_eq!(
            e.to_string(),
            "The token replacements cause an infinite loop"
        );

        // Try an empty token
        let mut source = source::Source::from_string(
            "Infinite recursion!".to_string()
        );
        source.add_token_replacement(
            "".to_string(),
            "ever longer".to_string(),
        );
        let mut stream = Stream::new(&source).unwrap();
        let mut line = String::new();
        let e = stream.read_line(&mut line).unwrap_err();
        assert!(matches!(e, StreamError::TokenReplacementLoop));
    }
}

```

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

```rust
// Automatically generated by make-features.py

static EXTENSIONS: [Extension; 29] = [
    Extension {
        name_bytes: vk::VK_KHR_16BIT_STORAGE_EXTENSION_NAME,
        struct_size: mem::size_of::<vk::VkPhysicalDevice16BitStorageFeaturesKHR>(),
        struct_type: vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES_KHR,
        features: &[
            "storageBuffer16BitAccess",
            "uniformAndStorageBuffer16BitAccess",
            "storagePushConstant16",
            "storageInputOutput16",
        ],
    },
    Extension {
        name_bytes: vk::VK_KHR_8BIT_STORAGE_EXTENSION_NAME,
        struct_size: mem::size_of::<vk::VkPhysicalDevice8BitStorageFeaturesKHR>(),
        struct_type: vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_8BIT_STORAGE_FEATURES_KHR,
        features: &[
            "storageBuffer8BitAccess",
            "uniformAndStorageBuffer8BitAccess",
            "storagePushConstant8",
        ],
    },
    Extension {
        name_bytes: vk::VK_EXT_ASTC_DECODE_MODE_EXTENSION_NAME,
        struct_size: mem::size_of::<vk::VkPhysicalDeviceASTCDecodeFeaturesEXT>(),
        struct_type: vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ASTC_DECODE_FEATURES_EXT,
        features: &[
            "decodeModeSharedExponent",
        ],
    },
    Extension {
        name_bytes: vk::VK_EXT_BLEND_OPERATION_ADVANCED_EXTENSION_NAME,
        struct_size: mem::size_of::<vk::VkPhysicalDeviceBlendOperationAdvancedFeaturesEXT>(),
        struct_type: vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BLEND_OPERATION_ADVANCED_FEATURES_EXT,
        features: &[
            "advancedBlendCoherentOperations",
        ],
    },
    Extension {
        name_bytes: vk::VK_EXT_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME,
        struct_size: mem::size_of::<vk::VkPhysicalDeviceBufferDeviceAddressFeaturesEXT>(),
        struct_type: vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES_EXT,
        features: &[
            "bufferDeviceAddress",
            "bufferDeviceAddressCaptureReplay",
            "bufferDeviceAddressMultiDevice",
        ],
    },
    Extension {
        name_bytes: vk::VK_KHR_COMPUTE_SHADER_DERIVATIVES_EXTENSION_NAME,
        struct_size: mem::size_of::<vk::VkPhysicalDeviceComputeShaderDerivativesFeaturesKHR>(),
        struct_type: vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COMPUTE_SHADER_DERIVATIVES_FEATURES_KHR,
        features: &[
            "computeDerivativeGroupQuads",
            "computeDerivativeGroupLinear",
        ],
    },
    Extension {
        name_bytes: vk::VK_EXT_CONDITIONAL_RENDERING_EXTENSION_NAME,
        struct_size: mem::size_of::<vk::VkPhysicalDeviceConditionalRenderingFeaturesEXT>(),
        struct_type: vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CONDITIONAL_RENDERING_FEATURES_EXT,
        features: &[
            "conditionalRendering",
            "inheritedConditionalRendering",
        ],
    },
    Extension {
        name_bytes: vk::VK_NV_CORNER_SAMPLED_IMAGE_EXTENSION_NAME,
        struct_size: mem::size_of::<vk::VkPhysicalDeviceCornerSampledImageFeaturesNV>(),
        struct_type: vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CORNER_SAMPLED_IMAGE_FEATURES_NV,
        features: &[
            "cornerSampledImage",
        ],
    },
    Extension {
        name_bytes: vk::VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME,
        struct_size: mem::size_of::<vk::VkPhysicalDeviceDescriptorIndexingFeaturesEXT>(),
        struct_type: vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_FEATURES_EXT,
        features: &[
            "shaderInputAttachmentArrayDynamicIndexing",
            "shaderUniformTexelBufferArrayDynamicIndexing",
            "shaderStorageTexelBufferArrayDynamicIndexing",
            "shaderUniformBufferArrayNonUniformIndexing",
            "shaderSampledImageArrayNonUniformIndexing",
            "shaderStorageBufferArrayNonUniformIndexing",
            "shaderStorageImageArrayNonUniformIndexing",
            "shaderInputAttachmentArrayNonUniformIndexing",
            "shaderUniformTexelBufferArrayNonUniformIndexing",
            "shaderStorageTexelBufferArrayNonUniformIndexing",
            "descriptorBindingUniformBufferUpdateAfterBind",
            "descriptorBindingSampledImageUpdateAfterBind",
            "descriptorBindingStorageImageUpdateAfterBind",
            "descriptorBindingStorageBufferUpdateAfterBind",
            "descriptorBindingUniformTexelBufferUpdateAfterBind",
            "descriptorBindingStorageTexelBufferUpdateAfterBind",
            "descriptorBindingUpdateUnusedWhilePending",
            "descriptorBindingPartiallyBound",
            "descriptorBindingVariableDescriptorCount",
            "runtimeDescriptorArray",
        ],
    },
    Extension {
        name_bytes: vk::VK_NV_SCISSOR_EXCLUSIVE_EXTENSION_NAME,
        struct_size: mem::size_of::<vk::VkPhysicalDeviceExclusiveScissorFeaturesNV>(),
        struct_type: vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXCLUSIVE_SCISSOR_FEATURES_NV,
        features: &[
            "exclusiveScissor",
        ],
    },
    Extension {
        name_bytes: vk::VK_KHR_SHADER_FLOAT16_INT8_EXTENSION_NAME,
        struct_size: mem::size_of::<vk::VkPhysicalDeviceShaderFloat16Int8FeaturesKHR>(),
        struct_type: vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_FLOAT16_INT8_FEATURES_KHR,
        features: &[
            "shaderFloat16",
            "shaderInt8",
        ],
    },
    Extension {
        name_bytes: vk::VK_EXT_FRAGMENT_DENSITY_MAP_EXTENSION_NAME,
        struct_size: mem::size_of::<vk::VkPhysicalDeviceFragmentDensityMapFeaturesEXT>(),
        struct_type: vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_FEATURES_EXT,
        features: &[
            "fragmentDensityMap",
            "fragmentDensityMapDynamic",
            "fragmentDensityMapNonSubsampledImages",
        ],
    },
    Extension {
        name_bytes: vk::VK_KHR_FRAGMENT_SHADER_BARYCENTRIC_EXTENSION_NAME,
        struct_size: mem::size_of::<vk::VkPhysicalDeviceFragmentShaderBarycentricFeaturesKHR>(),
        struct_type: vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADER_BARYCENTRIC_FEATURES_KHR,
        features: &[
            "fragmentShaderBarycentric",
        ],
    },
    Extension {
        name_bytes: vk::VK_EXT_INLINE_UNIFORM_BLOCK_EXTENSION_NAME,
        struct_size: mem::size_of::<vk::VkPhysicalDeviceInlineUniformBlockFeaturesEXT>(),
        struct_type: vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INLINE_UNIFORM_BLOCK_FEATURES_EXT,
        features: &[
            "inlineUniformBlock",
            "descriptorBindingInlineUniformBlockUpdateAfterBind",
        ],
    },
    Extension {
        name_bytes: vk::VK_EXT_MEMORY_PRIORITY_EXTENSION_NAME,
        struct_size: mem::size_of::<vk::VkPhysicalDeviceMemoryPriorityFeaturesEXT>(),
        struct_type: vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PRIORITY_FEATURES_EXT,
        features: &[
            "memoryPriority",
        ],
    },
    Extension {
        name_bytes: vk::VK_NV_MESH_SHADER_EXTENSION_NAME,
        struct_size: mem::size_of::<vk::VkPhysicalDeviceMeshShaderFeaturesNV>(),
        struct_type: vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MESH_SHADER_FEATURES_NV,
        features: &[
            "taskShader",
            "meshShader",
        ],
    },
    Extension {
        name_bytes: vk::VK_KHR_MULTIVIEW_EXTENSION_NAME,
        struct_size: mem::size_of::<vk::VkPhysicalDeviceMultiviewFeaturesKHR>(),
        struct_type: vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES_KHR,
        features: &[
            "multiview",
            "multiviewGeometryShader",
            "multiviewTessellationShader",
        ],
    },
    Extension {
        name_bytes: vk::VK_NV_REPRESENTATIVE_FRAGMENT_TEST_EXTENSION_NAME,
        struct_size: mem::size_of::<vk::VkPhysicalDeviceRepresentativeFragmentTestFeaturesNV>(),
        struct_type: vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_REPRESENTATIVE_FRAGMENT_TEST_FEATURES_NV,
        features: &[
            "representativeFragmentTest",
        ],
    },
    Extension {
        name_bytes: vk::VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME,
        struct_size: mem::size_of::<vk::VkPhysicalDeviceSamplerYcbcrConversionFeaturesKHR>(),
        struct_type: vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES_KHR,
        features: &[
            "samplerYcbcrConversion",
        ],
    },
    Extension {
        name_bytes: vk::VK_EXT_SCALAR_BLOCK_LAYOUT_EXTENSION_NAME,
        struct_size: mem::size_of::<vk::VkPhysicalDeviceScalarBlockLayoutFeaturesEXT>(),
        struct_type: vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SCALAR_BLOCK_LAYOUT_FEATURES_EXT,
        features: &[
            "scalarBlockLayout",
        ],
    },
    Extension {
        name_bytes: vk::VK_KHR_SHADER_ATOMIC_INT64_EXTENSION_NAME,
        struct_size: mem::size_of::<vk::VkPhysicalDeviceShaderAtomicInt64FeaturesKHR>(),
        struct_type: vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_INT64_FEATURES_KHR,
        features: &[
            "shaderBufferInt64Atomics",
            "shaderSharedInt64Atomics",
        ],
    },
    Extension {
        name_bytes: vk::VK_NV_SHADER_IMAGE_FOOTPRINT_EXTENSION_NAME,
        struct_size: mem::size_of::<vk::VkPhysicalDeviceShaderImageFootprintFeaturesNV>(),
        struct_type: vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_IMAGE_FOOTPRINT_FEATURES_NV,
        features: &[
            "imageFootprint",
        ],
    },
    Extension {
        name_bytes: vk::VK_NV_SHADING_RATE_IMAGE_EXTENSION_NAME,
        struct_size: mem::size_of::<vk::VkPhysicalDeviceShadingRateImageFeaturesNV>(),
        struct_type: vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADING_RATE_IMAGE_FEATURES_NV,
        features: &[
            "shadingRateImage",
            "shadingRateCoarseSampleOrder",
        ],
    },
    Extension {
        name_bytes: vk::VK_EXT_TRANSFORM_FEEDBACK_EXTENSION_NAME,
        struct_size: mem::size_of::<vk::VkPhysicalDeviceTransformFeedbackFeaturesEXT>(),
        struct_type: vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_FEATURES_EXT,
        features: &[
            "transformFeedback",
            "geometryStreams",
        ],
    },
    Extension {
        name_bytes: vk::VK_KHR_VARIABLE_POINTERS_EXTENSION_NAME,
        struct_size: mem::size_of::<vk::VkPhysicalDeviceVariablePointersFeaturesKHR>(),
        struct_type: vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTERS_FEATURES_KHR,
        features: &[
            "variablePointersStorageBuffer",
            "variablePointers",
        ],
    },
    Extension {
        name_bytes: vk::VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME,
        struct_size: mem::size_of::<vk::VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT>(),
        struct_type: vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_FEATURES_EXT,
        features: &[
            "vertexAttributeInstanceRateDivisor",
            "vertexAttributeInstanceRateZeroDivisor",
        ],
    },
    Extension {
        name_bytes: vk::VK_KHR_VULKAN_MEMORY_MODEL_EXTENSION_NAME,
        struct_size: mem::size_of::<vk::VkPhysicalDeviceVulkanMemoryModelFeaturesKHR>(),
        struct_type: vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_MEMORY_MODEL_FEATURES_KHR,
        features: &[
            "vulkanMemoryModel",
            "vulkanMemoryModelDeviceScope",
            "vulkanMemoryModelAvailabilityVisibilityChains",
        ],
    },
    Extension {
        name_bytes: vk::VK_KHR_COOPERATIVE_MATRIX_EXTENSION_NAME,
        struct_size: mem::size_of::<vk::VkPhysicalDeviceCooperativeMatrixFeaturesKHR>(),
        struct_type: vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COOPERATIVE_MATRIX_FEATURES_KHR,
        features: &[
            "cooperativeMatrix",
            "cooperativeMatrixRobustBufferAccess",
        ],
    },
    Extension {
        name_bytes: vk::VK_EXT_SUBGROUP_SIZE_CONTROL_EXTENSION_NAME,
        struct_size: mem::size_of::<vk::VkPhysicalDeviceSubgroupSizeControlFeaturesEXT>(),
        struct_type: vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_SIZE_CONTROL_FEATURES_EXT,
        features: &[
            "subgroupSizeControl",
            "computeFullSubgroups",
        ],
    },
];

const N_BASE_FEATURES: usize = 55;

static BASE_FEATURES: [&'static str; N_BASE_FEATURES] = [
    "robustBufferAccess",
    "fullDrawIndexUint32",
    "imageCubeArray",
    "independentBlend",
    "geometryShader",
    "tessellationShader",
    "sampleRateShading",
    "dualSrcBlend",
    "logicOp",
    "multiDrawIndirect",
    "drawIndirectFirstInstance",
    "depthClamp",
    "depthBiasClamp",
    "fillModeNonSolid",
    "depthBounds",
    "wideLines",
    "largePoints",
    "alphaToOne",
    "multiViewport",
    "samplerAnisotropy",
    "textureCompressionETC2",
    "textureCompressionASTC_LDR",
    "textureCompressionBC",
    "occlusionQueryPrecise",
    "pipelineStatisticsQuery",
    "vertexPipelineStoresAndAtomics",
    "fragmentStoresAndAtomics",
    "shaderTessellationAndGeometryPointSize",
    "shaderImageGatherExtended",
    "shaderStorageImageExtendedFormats",
    "shaderStorageImageMultisample",
    "shaderStorageImageReadWithoutFormat",
    "shaderStorageImageWriteWithoutFormat",
    "shaderUniformBufferArrayDynamicIndexing",
    "shaderSampledImageArrayDynamicIndexing",
    "shaderStorageBufferArrayDynamicIndexing",
    "shaderStorageImageArrayDynamicIndexing",
    "shaderClipDistance",
    "shaderCullDistance",
    "shaderFloat64",
    "shaderInt64",
    "shaderInt16",
    "shaderResourceResidency",
    "shaderResourceMinLod",
    "sparseBinding",
    "sparseResidencyBuffer",
    "sparseResidencyImage2D",
    "sparseResidencyImage3D",
    "sparseResidency2Samples",
    "sparseResidency4Samples",
    "sparseResidency8Samples",
    "sparseResidency16Samples",
    "sparseResidencyAliased",
    "variableMultisampleRate",
    "inheritedQueries",
];


```

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

```
#ifndef VULKAN_VIDEO_CODEC_H264STD_H_
#define VULKAN_VIDEO_CODEC_H264STD_H_ 1

/*
** Copyright 2015-2025 The Khronos Group Inc.
**
** SPDX-License-Identifier: Apache-2.0
*/

/*
** This header is generated from the Khronos Vulkan XML API Registry.
**
*/


#ifdef __cplusplus
extern "C" {
#endif



// vulkan_video_codec_h264std is a preprocessor guard. Do not pass it to API calls.
#define vulkan_video_codec_h264std 1
#include "vulkan_video_codecs_common.h"
#define STD_VIDEO_H264_CPB_CNT_LIST_SIZE  32
#define STD_VIDEO_H264_SCALING_LIST_4X4_NUM_LISTS 6
#define STD_VIDEO_H264_SCALING_LIST_4X4_NUM_ELEMENTS 16
#define STD_VIDEO_H264_SCALING_LIST_8X8_NUM_LISTS 6
#define STD_VIDEO_H264_SCALING_LIST_8X8_NUM_ELEMENTS 64
#define STD_VIDEO_H264_MAX_NUM_LIST_REF   32
#define STD_VIDEO_H264_MAX_CHROMA_PLANES  2
#define STD_VIDEO_H264_NO_REFERENCE_PICTURE 0xFF

typedef enum StdVideoH264ChromaFormatIdc {
    STD_VIDEO_H264_CHROMA_FORMAT_IDC_MONOCHROME = 0,
    STD_VIDEO_H264_CHROMA_FORMAT_IDC_420 = 1,
    STD_VIDEO_H264_CHROMA_FORMAT_IDC_422 = 2,
    STD_VIDEO_H264_CHROMA_FORMAT_IDC_444 = 3,
    STD_VIDEO_H264_CHROMA_FORMAT_IDC_INVALID = 0x7FFFFFFF,
    STD_VIDEO_H264_CHROMA_FORMAT_IDC_MAX_ENUM = 0x7FFFFFFF
} StdVideoH264ChromaFormatIdc;

typedef enum StdVideoH264ProfileIdc {
    STD_VIDEO_H264_PROFILE_IDC_BASELINE = 66,
    STD_VIDEO_H264_PROFILE_IDC_MAIN = 77,
    STD_VIDEO_H264_PROFILE_IDC_HIGH = 100,
    STD_VIDEO_H264_PROFILE_IDC_HIGH_444_PREDICTIVE = 244,
    STD_VIDEO_H264_PROFILE_IDC_INVALID = 0x7FFFFFFF,
    STD_VIDEO_H264_PROFILE_IDC_MAX_ENUM = 0x7FFFFFFF
} StdVideoH264ProfileIdc;

typedef enum StdVideoH264LevelIdc {
    STD_VIDEO_H264_LEVEL_IDC_1_0 = 0,
    STD_VIDEO_H264_LEVEL_IDC_1_1 = 1,
    STD_VIDEO_H264_LEVEL_IDC_1_2 = 2,
    STD_VIDEO_H264_LEVEL_IDC_1_3 = 3,
    STD_VIDEO_H264_LEVEL_IDC_2_0 = 4,
    STD_VIDEO_H264_LEVEL_IDC_2_1 = 5,
    STD_VIDEO_H264_LEVEL_IDC_2_2 = 6,
    STD_VIDEO_H264_LEVEL_IDC_3_0 = 7,
    STD_VIDEO_H264_LEVEL_IDC_3_1 = 8,
    STD_VIDEO_H264_LEVEL_IDC_3_2 = 9,
    STD_VIDEO_H264_LEVEL_IDC_4_0 = 10,
    STD_VIDEO_H264_LEVEL_IDC_4_1 = 11,
    STD_VIDEO_H264_LEVEL_IDC_4_2 = 12,
    STD_VIDEO_H264_LEVEL_IDC_5_0 = 13,
    STD_VIDEO_H264_LEVEL_IDC_5_1 = 14,
    STD_VIDEO_H264_LEVEL_IDC_5_2 = 15,
    STD_VIDEO_H264_LEVEL_IDC_6_0 = 16,
    STD_VIDEO_H264_LEVEL_IDC_6_1 = 17,
    STD_VIDEO_H264_LEVEL_IDC_6_2 = 18,
    STD_VIDEO_H264_LEVEL_IDC_INVALID = 0x7FFFFFFF,
    STD_VIDEO_H264_LEVEL_IDC_MAX_ENUM = 0x7FFFFFFF
} StdVideoH264LevelIdc;

typedef enum StdVideoH264PocType {
    STD_VIDEO_H264_POC_TYPE_0 = 0,
    STD_VIDEO_H264_POC_TYPE_1 = 1,
    STD_VIDEO_H264_POC_TYPE_2 = 2,
    STD_VIDEO_H264_POC_TYPE_INVALID = 0x7FFFFFFF,
    STD_VIDEO_H264_POC_TYPE_MAX_ENUM = 0x7FFFFFFF
} StdVideoH264PocType;

typedef enum StdVideoH264AspectRatioIdc {
    STD_VIDEO_H264_ASPECT_RATIO_IDC_UNSPECIFIED = 0,
    STD_VIDEO_H264_ASPECT_RATIO_IDC_SQUARE = 1,
    STD_VIDEO_H264_ASPECT_RATIO_IDC_12_11 = 2,
    STD_VIDEO_H264_ASPECT_RATIO_IDC_10_11 = 3,
    STD_VIDEO_H264_ASPECT_RATIO_IDC_16_11 = 4,
    STD_VIDEO_H264_ASPECT_RATIO_IDC_40_33 = 5,
    STD_VIDEO_H264_ASPECT_RATIO_IDC_24_11 = 6,
    STD_VIDEO_H264_ASPECT_RATIO_IDC_20_11 = 7,
    STD_VIDEO_H264_ASPECT_RATIO_IDC_32_11 = 8,
    STD_VIDEO_H264_ASPECT_RATIO_IDC_80_33 = 9,
    STD_VIDEO_H264_ASPECT_RATIO_IDC_18_11 = 10,
    STD_VIDEO_H264_ASPECT_RATIO_IDC_15_11 = 11,
    STD_VIDEO_H264_ASPECT_RATIO_IDC_64_33 = 12,
    STD_VIDEO_H264_ASPECT_RATIO_IDC_160_99 = 13,
    STD_VIDEO_H264_ASPECT_RATIO_IDC_4_3 = 14,
    STD_VIDEO_H264_ASPECT_RATIO_IDC_3_2 = 15,
    STD_VIDEO_H264_ASPECT_RATIO_IDC_2_1 = 16,
    STD_VIDEO_H264_ASPECT_RATIO_IDC_EXTENDED_SAR = 255,
    STD_VIDEO_H264_ASPECT_RATIO_IDC_INVALID = 0x7FFFFFFF,
    STD_VIDEO_H264_ASPECT_RATIO_IDC_MAX_ENUM = 0x7FFFFFFF
} StdVideoH264AspectRatioIdc;

typedef enum StdVideoH264WeightedBipredIdc {
    STD_VIDEO_H264_WEIGHTED_BIPRED_IDC_DEFAULT = 0,
    STD_VIDEO_H264_WEIGHTED_BIPRED_IDC_EXPLICIT = 1,
    STD_VIDEO_H264_WEIGHTED_BIPRED_IDC_IMPLICIT = 2,
    STD_VIDEO_H264_WEIGHTED_BIPRED_IDC_INVALID = 0x7FFFFFFF,
    STD_VIDEO_H264_WEIGHTED_BIPRED_IDC_MAX_ENUM = 0x7FFFFFFF
} StdVideoH264WeightedBipredIdc;

typedef enum StdVideoH264ModificationOfPicNumsIdc {
    STD_VIDEO_H264_MODIFICATION_OF_PIC_NUMS_IDC_SHORT_TERM_SUBTRACT = 0,
    STD_VIDEO_H264_MODIFICATION_OF_PIC_NUMS_IDC_SHORT_TERM_ADD = 1,
    STD_VIDEO_H264_MODIFICATION_OF_PIC_NUMS_IDC_LONG_TERM = 2,
    STD_VIDEO_H264_MODIFICATION_OF_PIC_NUMS_IDC_END = 3,
    STD_VIDEO_H264_MODIFICATION_OF_PIC_NUMS_IDC_INVALID = 0x7FFFFFFF,
    STD_VIDEO_H264_MODIFICATION_OF_PIC_NUMS_IDC_MAX_ENUM = 0x7FFFFFFF
} StdVideoH264ModificationOfPicNumsIdc;

typedef enum StdVideoH264MemMgmtControlOp {
    STD_VIDEO_H264_MEM_MGMT_CONTROL_OP_END = 0,
    STD_VIDEO_H264_MEM_MGMT_CONTROL_OP_UNMARK_SHORT_TERM = 1,
    STD_VIDEO_H264_MEM_MGMT_CONTROL_OP_UNMARK_LONG_TERM = 2,
    STD_VIDEO_H264_MEM_MGMT_CONTROL_OP_MARK_LONG_TERM = 3,
    STD_VIDEO_H264_MEM_MGMT_CONTROL_OP_SET_MAX_LONG_TERM_INDEX = 4,
    STD_VIDEO_H264_MEM_MGMT_CONTROL_OP_UNMARK_ALL = 5,
    STD_VIDEO_H264_MEM_MGMT_CONTROL_OP_MARK_CURRENT_AS_LONG_TERM = 6,
    STD_VIDEO_H264_MEM_MGMT_CONTROL_OP_INVALID = 0x7FFFFFFF,
    STD_VIDEO_H264_MEM_MGMT_CONTROL_OP_MAX_ENUM = 0x7FFFFFFF
} StdVideoH264MemMgmtControlOp;

typedef enum StdVideoH264CabacInitIdc {
    STD_VIDEO_H264_CABAC_INIT_IDC_0 = 0,
    STD_VIDEO_H264_CABAC_INIT_IDC_1 = 1,
    STD_VIDEO_H264_CABAC_INIT_IDC_2 = 2,
    STD_VIDEO_H264_CABAC_INIT_IDC_INVALID = 0x7FFFFFFF,
    STD_VIDEO_H264_CABAC_INIT_IDC_MAX_ENUM = 0x7FFFFFFF
} StdVideoH264CabacInitIdc;

typedef enum StdVideoH264DisableDeblockingFilterIdc {
    STD_VIDEO_H264_DISABLE_DEBLOCKING_FILTER_IDC_DISABLED = 0,
    STD_VIDEO_H264_DISABLE_DEBLOCKING_FILTER_IDC_ENABLED = 1,
    STD_VIDEO_H264_DISABLE_DEBLOCKING_FILTER_IDC_PARTIAL = 2,
    STD_VIDEO_H264_DISABLE_DEBLOCKING_FILTER_IDC_INVALID = 0x7FFFFFFF,
    STD_VIDEO_H264_DISABLE_DEBLOCKING_FILTER_IDC_MAX_ENUM = 0x7FFFFFFF
} StdVideoH264DisableDeblockingFilterIdc;

typedef enum StdVideoH264SliceType {
    STD_VIDEO_H264_SLICE_TYPE_P = 0,
    STD_VIDEO_H264_SLICE_TYPE_B = 1,
    STD_VIDEO_H264_SLICE_TYPE_I = 2,
    STD_VIDEO_H264_SLICE_TYPE_INVALID = 0x7FFFFFFF,
    STD_VIDEO_H264_SLICE_TYPE_MAX_ENUM = 0x7FFFFFFF
} StdVideoH264SliceType;

typedef enum StdVideoH264PictureType {
    STD_VIDEO_H264_PICTURE_TYPE_P = 0,
    STD_VIDEO_H264_PICTURE_TYPE_B = 1,
    STD_VIDEO_H264_PICTURE_TYPE_I = 2,
    STD_VIDEO_H264_PICTURE_TYPE_IDR = 5,
    STD_VIDEO_H264_PICTURE_TYPE_INVALID = 0x7FFFFFFF,
    STD_VIDEO_H264_PICTURE_TYPE_MAX_ENUM = 0x7FFFFFFF
} StdVideoH264PictureType;

typedef enum StdVideoH264NonVclNaluType {
    STD_VIDEO_H264_NON_VCL_NALU_TYPE_SPS = 0,
    STD_VIDEO_H264_NON_VCL_NALU_TYPE_PPS = 1,
    STD_VIDEO_H264_NON_VCL_NALU_TYPE_AUD = 2,
    STD_VIDEO_H264_NON_VCL_NALU_TYPE_PREFIX = 3,
    STD_VIDEO_H264_NON_VCL_NALU_TYPE_END_OF_SEQUENCE = 4,
    STD_VIDEO_H264_NON_VCL_NALU_TYPE_END_OF_STREAM = 5,
    STD_VIDEO_H264_NON_VCL_NALU_TYPE_PRECODED = 6,
    STD_VIDEO_H264_NON_VCL_NALU_TYPE_INVALID = 0x7FFFFFFF,
    STD_VIDEO_H264_NON_VCL_NALU_TYPE_MAX_ENUM = 0x7FFFFFFF
} StdVideoH264NonVclNaluType;
typedef struct StdVideoH264SpsVuiFlags {
    uint32_t    aspect_ratio_info_present_flag : 1;
    uint32_t    overscan_info_present_flag : 1;
    uint32_t    overscan_appropriate_flag : 1;
    uint32_t    video_signal_type_present_flag : 1;
    uint32_t    video_full_range_flag : 1;
    uint32_t    color_description_present_flag : 1;
    uint32_t    chroma_loc_info_present_flag : 1;
    uint32_t    timing_info_present_flag : 1;
    uint32_t    fixed_frame_rate_flag : 1;
    uint32_t    bitstream_restriction_flag : 1;
    uint32_t    nal_hrd_parameters_present_flag : 1;
    uint32_t    vcl_hrd_parameters_present_flag : 1;
} StdVideoH264SpsVuiFlags;

typedef struct StdVideoH264HrdParameters {
    uint8_t     cpb_cnt_minus1;
    uint8_t     bit_rate_scale;
    uint8_t     cpb_size_scale;
    uint8_t     reserved1;
    uint32_t    bit_rate_value_minus1[STD_VIDEO_H264_CPB_CNT_LIST_SIZE];
    uint32_t    cpb_size_value_minus1[STD_VIDEO_H264_CPB_CNT_LIST_SIZE];
    uint8_t     cbr_flag[STD_VIDEO_H264_CPB_CNT_LIST_SIZE];
    uint32_t    initial_cpb_removal_delay_length_minus1;
    uint32_t    cpb_removal_delay_length_minus1;
    uint32_t    dpb_output_delay_length_minus1;
    uint32_t    time_offset_length;
} StdVideoH264HrdParameters;

typedef struct StdVideoH264SequenceParameterSetVui {
    StdVideoH264SpsVuiFlags             flags;
    StdVideoH264AspectRatioIdc          aspect_ratio_idc;
    uint16_t                            sar_width;
    uint16_t                            sar_height;
    uint8_t                             video_format;
    uint8_t                             colour_primaries;
    uint8_t                             transfer_characteristics;
    uint8_t                             matrix_coefficients;
    uint32_t                            num_units_in_tick;
    uint32_t                            time_scale;
    uint8_t                             max_num_reorder_frames;
    uint8_t                             max_dec_frame_buffering;
    uint8_t                             chroma_sample_loc_type_top_field;
    uint8_t                             chroma_sample_loc_type_bottom_field;
    uint32_t                            reserved1;
    const StdVideoH264HrdParameters*    pHrdParameters;
} StdVideoH264SequenceParameterSetVui;

typedef struct StdVideoH264SpsFlags {
    uint32_t    constraint_set0_flag : 1;
    uint32_t    constraint_set1_flag : 1;
    uint32_t    constraint_set2_flag : 1;
    uint32_t    constraint_set3_flag : 1;
    uint32_t    constraint_set4_flag : 1;
    uint32_t    constraint_set5_flag : 1;
    uint32_t    direct_8x8_inference_flag : 1;
    uint32_t    mb_adaptive_frame_field_flag : 1;
    uint32_t    frame_mbs_only_flag : 1;
    uint32_t    delta_pic_order_always_zero_flag : 1;
    uint32_t    separate_colour_plane_flag : 1;
    uint32_t    gaps_in_frame_num_value_allowed_flag : 1;
    uint32_t    qpprime_y_zero_transform_bypass_flag : 1;
    uint32_t    frame_cropping_flag : 1;
    uint32_t    seq_scaling_matrix_present_flag : 1;
    uint32_t    vui_parameters_present_flag : 1;
} StdVideoH264SpsFlags;

typedef struct StdVideoH264ScalingLists {
    uint16_t    scaling_list_present_mask;
    uint16_t    use_default_scaling_matrix_mask;
    uint8_t     ScalingList4x4[STD_VIDEO_H264_SCALING_LIST_4X4_NUM_LISTS][STD_VIDEO_H264_SCALING_LIST_4X4_NUM_ELEMENTS];
    uint8_t     ScalingList8x8[STD_VIDEO_H264_SCALING_LIST_8X8_NUM_LISTS][STD_VIDEO_H264_SCALING_LIST_8X8_NUM_ELEMENTS];
} StdVideoH264ScalingLists;

typedef struct StdVideoH264SequenceParameterSet {
    StdVideoH264SpsFlags                          flags;
    StdVideoH264ProfileIdc                        profile_idc;
    StdVideoH264LevelIdc                          level_idc;
    StdVideoH264ChromaFormatIdc                   chroma_format_idc;
    uint8_t                                       seq_parameter_set_id;
    uint8_t                                       bit_depth_luma_minus8;
    uint8_t                                       bit_depth_chroma_minus8;
    uint8_t                                       log2_max_frame_num_minus4;
    StdVideoH264PocType                           pic_order_cnt_type;
    int32_t                                       offset_for_non_ref_pic;
    int32_t                                       offset_for_top_to_bottom_field;
    uint8_t                                       log2_max_pic_order_cnt_lsb_minus4;
    uint8_t                                       num_ref_frames_in_pic_order_cnt_cycle;
    uint8_t                                       max_num_ref_frames;
    uint8_t                                       reserved1;
    uint32_t                                      pic_width_in_mbs_minus1;
    uint32_t                                      pic_height_in_map_units_minus1;
    uint32_t                                      frame_crop_left_offset;
    uint32_t                                      frame_crop_right_offset;
    uint32_t                                      frame_crop_top_offset;
    uint32_t                                      frame_crop_bottom_offset;
    uint32_t                                      reserved2;
    const int32_t*                                pOffsetForRefFrame;
    const StdVideoH264ScalingLists*               pScalingLists;
    const StdVideoH264SequenceParameterSetVui*    pSequenceParameterSetVui;
} StdVideoH264SequenceParameterSet;

typedef struct StdVideoH264PpsFlags {
    uint32_t    transform_8x8_mode_flag : 1;
    uint32_t    redundant_pic_cnt_present_flag : 1;
    uint32_t    constrained_intra_pred_flag : 1;
    uint32_t    deblocking_filter_control_present_flag : 1;
    uint32_t    weighted_pred_flag : 1;
    uint32_t    bottom_field_pic_order_in_frame_present_flag : 1;
    uint32_t    entropy_coding_mode_flag : 1;
    uint32_t    pic_scaling_matrix_present_flag : 1;
} StdVideoH264PpsFlags;

typedef struct StdVideoH264PictureParameterSet {
    StdVideoH264PpsFlags               flags;
    uint8_t                            seq_parameter_set_id;
    uint8_t                            pic_parameter_set_id;
    uint8_t                            num_ref_idx_l0_default_active_minus1;
    uint8_t                            num_ref_idx_l1_default_active_minus1;
    StdVideoH264WeightedBipredIdc      weighted_bipred_idc;
    int8_t                             pic_init_qp_minus26;
    int8_t                             pic_init_qs_minus26;
    int8_t                             chroma_qp_index_offset;
    int8_t                             second_chroma_qp_index_offset;
    const StdVideoH264ScalingLists*    pScalingLists;
} StdVideoH264PictureParameterSet;


#ifdef __cplusplus
}
#endif

#endif

```

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

```
#ifndef VULKAN_VIDEO_CODEC_AV1STD_H_
#define VULKAN_VIDEO_CODEC_AV1STD_H_ 1

/*
** Copyright 2015-2025 The Khronos Group Inc.
**
** SPDX-License-Identifier: Apache-2.0
*/

/*
** This header is generated from the Khronos Vulkan XML API Registry.
**
*/


#ifdef __cplusplus
extern "C" {
#endif



// vulkan_video_codec_av1std is a preprocessor guard. Do not pass it to API calls.
#define vulkan_video_codec_av1std 1
#include "vulkan_video_codecs_common.h"
#define STD_VIDEO_AV1_NUM_REF_FRAMES      8
#define STD_VIDEO_AV1_REFS_PER_FRAME      7
#define STD_VIDEO_AV1_TOTAL_REFS_PER_FRAME 8
#define STD_VIDEO_AV1_MAX_TILE_COLS       64
#define STD_VIDEO_AV1_MAX_TILE_ROWS       64
#define STD_VIDEO_AV1_MAX_SEGMENTS        8
#define STD_VIDEO_AV1_SEG_LVL_MAX         8
#define STD_VIDEO_AV1_PRIMARY_REF_NONE    7
#define STD_VIDEO_AV1_SELECT_INTEGER_MV   2
#define STD_VIDEO_AV1_SELECT_SCREEN_CONTENT_TOOLS 2
#define STD_VIDEO_AV1_SKIP_MODE_FRAMES    2
#define STD_VIDEO_AV1_MAX_LOOP_FILTER_STRENGTHS 4
#define STD_VIDEO_AV1_LOOP_FILTER_ADJUSTMENTS 2
#define STD_VIDEO_AV1_MAX_CDEF_FILTER_STRENGTHS 8
#define STD_VIDEO_AV1_MAX_NUM_PLANES      3
#define STD_VIDEO_AV1_GLOBAL_MOTION_PARAMS 6
#define STD_VIDEO_AV1_MAX_NUM_Y_POINTS    14
#define STD_VIDEO_AV1_MAX_NUM_CB_POINTS   10
#define STD_VIDEO_AV1_MAX_NUM_CR_POINTS   10
#define STD_VIDEO_AV1_MAX_NUM_POS_LUMA    24
#define STD_VIDEO_AV1_MAX_NUM_POS_CHROMA  25

typedef enum StdVideoAV1Profile {
    STD_VIDEO_AV1_PROFILE_MAIN = 0,
    STD_VIDEO_AV1_PROFILE_HIGH = 1,
    STD_VIDEO_AV1_PROFILE_PROFESSIONAL = 2,
    STD_VIDEO_AV1_PROFILE_INVALID = 0x7FFFFFFF,
    STD_VIDEO_AV1_PROFILE_MAX_ENUM = 0x7FFFFFFF
} StdVideoAV1Profile;

typedef enum StdVideoAV1Level {
    STD_VIDEO_AV1_LEVEL_2_0 = 0,
    STD_VIDEO_AV1_LEVEL_2_1 = 1,
    STD_VIDEO_AV1_LEVEL_2_2 = 2,
    STD_VIDEO_AV1_LEVEL_2_3 = 3,
    STD_VIDEO_AV1_LEVEL_3_0 = 4,
    STD_VIDEO_AV1_LEVEL_3_1 = 5,
    STD_VIDEO_AV1_LEVEL_3_2 = 6,
    STD_VIDEO_AV1_LEVEL_3_3 = 7,
    STD_VIDEO_AV1_LEVEL_4_0 = 8,
    STD_VIDEO_AV1_LEVEL_4_1 = 9,
    STD_VIDEO_AV1_LEVEL_4_2 = 10,
    STD_VIDEO_AV1_LEVEL_4_3 = 11,
    STD_VIDEO_AV1_LEVEL_5_0 = 12,
    STD_VIDEO_AV1_LEVEL_5_1 = 13,
    STD_VIDEO_AV1_LEVEL_5_2 = 14,
    STD_VIDEO_AV1_LEVEL_5_3 = 15,
    STD_VIDEO_AV1_LEVEL_6_0 = 16,
    STD_VIDEO_AV1_LEVEL_6_1 = 17,
    STD_VIDEO_AV1_LEVEL_6_2 = 18,
    STD_VIDEO_AV1_LEVEL_6_3 = 19,
    STD_VIDEO_AV1_LEVEL_7_0 = 20,
    STD_VIDEO_AV1_LEVEL_7_1 = 21,
    STD_VIDEO_AV1_LEVEL_7_2 = 22,
    STD_VIDEO_AV1_LEVEL_7_3 = 23,
    STD_VIDEO_AV1_LEVEL_INVALID = 0x7FFFFFFF,
    STD_VIDEO_AV1_LEVEL_MAX_ENUM = 0x7FFFFFFF
} StdVideoAV1Level;

typedef enum StdVideoAV1FrameType {
    STD_VIDEO_AV1_FRAME_TYPE_KEY = 0,
    STD_VIDEO_AV1_FRAME_TYPE_INTER = 1,
    STD_VIDEO_AV1_FRAME_TYPE_INTRA_ONLY = 2,
    STD_VIDEO_AV1_FRAME_TYPE_SWITCH = 3,
    STD_VIDEO_AV1_FRAME_TYPE_INVALID = 0x7FFFFFFF,
    STD_VIDEO_AV1_FRAME_TYPE_MAX_ENUM = 0x7FFFFFFF
} StdVideoAV1FrameType;

typedef enum StdVideoAV1ReferenceName {
    STD_VIDEO_AV1_REFERENCE_NAME_INTRA_FRAME = 0,
    STD_VIDEO_AV1_REFERENCE_NAME_LAST_FRAME = 1,
    STD_VIDEO_AV1_REFERENCE_NAME_LAST2_FRAME = 2,
    STD_VIDEO_AV1_REFERENCE_NAME_LAST3_FRAME = 3,
    STD_VIDEO_AV1_REFERENCE_NAME_GOLDEN_FRAME = 4,
    STD_VIDEO_AV1_REFERENCE_NAME_BWDREF_FRAME = 5,
    STD_VIDEO_AV1_REFERENCE_NAME_ALTREF2_FRAME = 6,
    STD_VIDEO_AV1_REFERENCE_NAME_ALTREF_FRAME = 7,
    STD_VIDEO_AV1_REFERENCE_NAME_INVALID = 0x7FFFFFFF,
    STD_VIDEO_AV1_REFERENCE_NAME_MAX_ENUM = 0x7FFFFFFF
} StdVideoAV1ReferenceName;

typedef enum StdVideoAV1InterpolationFilter {
    STD_VIDEO_AV1_INTERPOLATION_FILTER_EIGHTTAP = 0,
    STD_VIDEO_AV1_INTERPOLATION_FILTER_EIGHTTAP_SMOOTH = 1,
    STD_VIDEO_AV1_INTERPOLATION_FILTER_EIGHTTAP_SHARP = 2,
    STD_VIDEO_AV1_INTERPOLATION_FILTER_BILINEAR = 3,
    STD_VIDEO_AV1_INTERPOLATION_FILTER_SWITCHABLE = 4,
    STD_VIDEO_AV1_INTERPOLATION_FILTER_INVALID = 0x7FFFFFFF,
    STD_VIDEO_AV1_INTERPOLATION_FILTER_MAX_ENUM = 0x7FFFFFFF
} StdVideoAV1InterpolationFilter;

typedef enum StdVideoAV1TxMode {
    STD_VIDEO_AV1_TX_MODE_ONLY_4X4 = 0,
    STD_VIDEO_AV1_TX_MODE_LARGEST = 1,
    STD_VIDEO_AV1_TX_MODE_SELECT = 2,
    STD_VIDEO_AV1_TX_MODE_INVALID = 0x7FFFFFFF,
    STD_VIDEO_AV1_TX_MODE_MAX_ENUM = 0x7FFFFFFF
} StdVideoAV1TxMode;

typedef enum StdVideoAV1FrameRestorationType {
    STD_VIDEO_AV1_FRAME_RESTORATION_TYPE_NONE = 0,
    STD_VIDEO_AV1_FRAME_RESTORATION_TYPE_WIENER = 1,
    STD_VIDEO_AV1_FRAME_RESTORATION_TYPE_SGRPROJ = 2,
    STD_VIDEO_AV1_FRAME_RESTORATION_TYPE_SWITCHABLE = 3,
    STD_VIDEO_AV1_FRAME_RESTORATION_TYPE_INVALID = 0x7FFFFFFF,
    STD_VIDEO_AV1_FRAME_RESTORATION_TYPE_MAX_ENUM = 0x7FFFFFFF
} StdVideoAV1FrameRestorationType;

typedef enum StdVideoAV1ColorPrimaries {
    STD_VIDEO_AV1_COLOR_PRIMARIES_BT_709 = 1,
    STD_VIDEO_AV1_COLOR_PRIMARIES_UNSPECIFIED = 2,
    STD_VIDEO_AV1_COLOR_PRIMARIES_BT_470_M = 4,
    STD_VIDEO_AV1_COLOR_PRIMARIES_BT_470_B_G = 5,
    STD_VIDEO_AV1_COLOR_PRIMARIES_BT_601 = 6,
    STD_VIDEO_AV1_COLOR_PRIMARIES_SMPTE_240 = 7,
    STD_VIDEO_AV1_COLOR_PRIMARIES_GENERIC_FILM = 8,
    STD_VIDEO_AV1_COLOR_PRIMARIES_BT_2020 = 9,
    STD_VIDEO_AV1_COLOR_PRIMARIES_XYZ = 10,
    STD_VIDEO_AV1_COLOR_PRIMARIES_SMPTE_431 = 11,
    STD_VIDEO_AV1_COLOR_PRIMARIES_SMPTE_432 = 12,
    STD_VIDEO_AV1_COLOR_PRIMARIES_EBU_3213 = 22,
    STD_VIDEO_AV1_COLOR_PRIMARIES_INVALID = 0x7FFFFFFF,
  // STD_VIDEO_AV1_COLOR_PRIMARIES_BT_UNSPECIFIED is a deprecated alias
    STD_VIDEO_AV1_COLOR_PRIMARIES_BT_UNSPECIFIED = STD_VIDEO_AV1_COLOR_PRIMARIES_UNSPECIFIED,
    STD_VIDEO_AV1_COLOR_PRIMARIES_MAX_ENUM = 0x7FFFFFFF
} StdVideoAV1ColorPrimaries;

typedef enum StdVideoAV1TransferCharacteristics {
    STD_VIDEO_AV1_TRANSFER_CHARACTERISTICS_RESERVED_0 = 0,
    STD_VIDEO_AV1_TRANSFER_CHARACTERISTICS_BT_709 = 1,
    STD_VIDEO_AV1_TRANSFER_CHARACTERISTICS_UNSPECIFIED = 2,
    STD_VIDEO_AV1_TRANSFER_CHARACTERISTICS_RESERVED_3 = 3,
    STD_VIDEO_AV1_TRANSFER_CHARACTERISTICS_BT_470_M = 4,
    STD_VIDEO_AV1_TRANSFER_CHARACTERISTICS_BT_470_B_G = 5,
    STD_VIDEO_AV1_TRANSFER_CHARACTERISTICS_BT_601 = 6,
    STD_VIDEO_AV1_TRANSFER_CHARACTERISTICS_SMPTE_240 = 7,
    STD_VIDEO_AV1_TRANSFER_CHARACTERISTICS_LINEAR = 8,
    STD_VIDEO_AV1_TRANSFER_CHARACTERISTICS_LOG_100 = 9,
    STD_VIDEO_AV1_TRANSFER_CHARACTERISTICS_LOG_100_SQRT10 = 10,
    STD_VIDEO_AV1_TRANSFER_CHARACTERISTICS_IEC_61966 = 11,
    STD_VIDEO_AV1_TRANSFER_CHARACTERISTICS_BT_1361 = 12,
    STD_VIDEO_AV1_TRANSFER_CHARACTERISTICS_SRGB = 13,
    STD_VIDEO_AV1_TRANSFER_CHARACTERISTICS_BT_2020_10_BIT = 14,
    STD_VIDEO_AV1_TRANSFER_CHARACTERISTICS_BT_2020_12_BIT = 15,
    STD_VIDEO_AV1_TRANSFER_CHARACTERISTICS_SMPTE_2084 = 16,
    STD_VIDEO_AV1_TRANSFER_CHARACTERISTICS_SMPTE_428 = 17,
    STD_VIDEO_AV1_TRANSFER_CHARACTERISTICS_HLG = 18,
    STD_VIDEO_AV1_TRANSFER_CHARACTERISTICS_INVALID = 0x7FFFFFFF,
    STD_VIDEO_AV1_TRANSFER_CHARACTERISTICS_MAX_ENUM = 0x7FFFFFFF
} StdVideoAV1TransferCharacteristics;

typedef enum StdVideoAV1MatrixCoefficients {
    STD_VIDEO_AV1_MATRIX_COEFFICIENTS_IDENTITY = 0,
    STD_VIDEO_AV1_MATRIX_COEFFICIENTS_BT_709 = 1,
    STD_VIDEO_AV1_MATRIX_COEFFICIENTS_UNSPECIFIED = 2,
    STD_VIDEO_AV1_MATRIX_COEFFICIENTS_RESERVED_3 = 3,
    STD_VIDEO_AV1_MATRIX_COEFFICIENTS_FCC = 4,
    STD_VIDEO_AV1_MATRIX_COEFFICIENTS_BT_470_B_G = 5,
    STD_VIDEO_AV1_MATRIX_COEFFICIENTS_BT_601 = 6,
    STD_VIDEO_AV1_MATRIX_COEFFICIENTS_SMPTE_240 = 7,
    STD_VIDEO_AV1_MATRIX_COEFFICIENTS_SMPTE_YCGCO = 8,
    STD_VIDEO_AV1_MATRIX_COEFFICIENTS_BT_2020_NCL = 9,
    STD_VIDEO_AV1_MATRIX_COEFFICIENTS_BT_2020_CL = 10,
    STD_VIDEO_AV1_MATRIX_COEFFICIENTS_SMPTE_2085 = 11,
    STD_VIDEO_AV1_MATRIX_COEFFICIENTS_CHROMAT_NCL = 12,
    STD_VIDEO_AV1_MATRIX_COEFFICIENTS_CHROMAT_CL = 13,
    STD_VIDEO_AV1_MATRIX_COEFFICIENTS_ICTCP = 14,
    STD_VIDEO_AV1_MATRIX_COEFFICIENTS_INVALID = 0x7FFFFFFF,
    STD_VIDEO_AV1_MATRIX_COEFFICIENTS_MAX_ENUM = 0x7FFFFFFF
} StdVideoAV1MatrixCoefficients;

typedef enum StdVideoAV1ChromaSamplePosition {
    STD_VIDEO_AV1_CHROMA_SAMPLE_POSITION_UNKNOWN = 0,
    STD_VIDEO_AV1_CHROMA_SAMPLE_POSITION_VERTICAL = 1,
    STD_VIDEO_AV1_CHROMA_SAMPLE_POSITION_COLOCATED = 2,
    STD_VIDEO_AV1_CHROMA_SAMPLE_POSITION_RESERVED = 3,
    STD_VIDEO_AV1_CHROMA_SAMPLE_POSITION_INVALID = 0x7FFFFFFF,
    STD_VIDEO_AV1_CHROMA_SAMPLE_POSITION_MAX_ENUM = 0x7FFFFFFF
} StdVideoAV1ChromaSamplePosition;
typedef struct StdVideoAV1ColorConfigFlags {
    uint32_t    mono_chrome : 1;
    uint32_t    color_range : 1;
    uint32_t    separate_uv_delta_q : 1;
    uint32_t    color_description_present_flag : 1;
    uint32_t    reserved : 28;
} StdVideoAV1ColorConfigFlags;

typedef struct StdVideoAV1ColorConfig {
    StdVideoAV1ColorConfigFlags           flags;
    uint8_t                               BitDepth;
    uint8_t                               subsampling_x;
    uint8_t                               subsampling_y;
    uint8_t                               reserved1;
    StdVideoAV1ColorPrimaries             color_primaries;
    StdVideoAV1TransferCharacteristics    transfer_characteristics;
    StdVideoAV1MatrixCoefficients         matrix_coefficients;
    StdVideoAV1ChromaSamplePosition       chroma_sample_position;
} StdVideoAV1ColorConfig;

typedef struct StdVideoAV1TimingInfoFlags {
    uint32_t    equal_picture_interval : 1;
    uint32_t    reserved : 31;
} StdVideoAV1TimingInfoFlags;

typedef struct StdVideoAV1TimingInfo {
    StdVideoAV1TimingInfoFlags    flags;
    uint32_t                      num_units_in_display_tick;
    uint32_t                      time_scale;
    uint32_t                      num_ticks_per_picture_minus_1;
} StdVideoAV1TimingInfo;

typedef struct StdVideoAV1LoopFilterFlags {
    uint32_t    loop_filter_delta_enabled : 1;
    uint32_t    loop_filter_delta_update : 1;
    uint32_t    reserved : 30;
} StdVideoAV1LoopFilterFlags;

typedef struct StdVideoAV1LoopFilter {
    StdVideoAV1LoopFilterFlags    flags;
    uint8_t                       loop_filter_level[STD_VIDEO_AV1_MAX_LOOP_FILTER_STRENGTHS];
    uint8_t                       loop_filter_sharpness;
    uint8_t                       update_ref_delta;
    int8_t                        loop_filter_ref_deltas[STD_VIDEO_AV1_TOTAL_REFS_PER_FRAME];
    uint8_t                       update_mode_delta;
    int8_t                        loop_filter_mode_deltas[STD_VIDEO_AV1_LOOP_FILTER_ADJUSTMENTS];
} StdVideoAV1LoopFilter;

typedef struct StdVideoAV1QuantizationFlags {
    uint32_t    using_qmatrix : 1;
    uint32_t    diff_uv_delta : 1;
    uint32_t    reserved : 30;
} StdVideoAV1QuantizationFlags;

typedef struct StdVideoAV1Quantization {
    StdVideoAV1QuantizationFlags    flags;
    uint8_t                         base_q_idx;
    int8_t                          DeltaQYDc;
    int8_t                          DeltaQUDc;
    int8_t                          DeltaQUAc;
    int8_t                          DeltaQVDc;
    int8_t                          DeltaQVAc;
    uint8_t                         qm_y;
    uint8_t                         qm_u;
    uint8_t                         qm_v;
} StdVideoAV1Quantization;

typedef struct StdVideoAV1Segmentation {
    uint8_t    FeatureEnabled[STD_VIDEO_AV1_MAX_SEGMENTS];
    int16_t    FeatureData[STD_VIDEO_AV1_MAX_SEGMENTS][STD_VIDEO_AV1_SEG_LVL_MAX];
} StdVideoAV1Segmentation;

typedef struct StdVideoAV1TileInfoFlags {
    uint32_t    uniform_tile_spacing_flag : 1;
    uint32_t    reserved : 31;
} StdVideoAV1TileInfoFlags;

typedef struct StdVideoAV1TileInfo {
    StdVideoAV1TileInfoFlags    flags;
    uint8_t                     TileCols;
    uint8_t                     TileRows;
    uint16_t                    context_update_tile_id;
    uint8_t                     tile_size_bytes_minus_1;
    uint8_t                     reserved1[7];
    const uint16_t*             pMiColStarts;
    const uint16_t*             pMiRowStarts;
    const uint16_t*             pWidthInSbsMinus1;
    const uint16_t*             pHeightInSbsMinus1;
} StdVideoAV1TileInfo;

typedef struct StdVideoAV1CDEF {
    uint8_t    cdef_damping_minus_3;
    uint8_t    cdef_bits;
    uint8_t    cdef_y_pri_strength[STD_VIDEO_AV1_MAX_CDEF_FILTER_STRENGTHS];
    uint8_t    cdef_y_sec_strength[STD_VIDEO_AV1_MAX_CDEF_FILTER_STRENGTHS];
    uint8_t    cdef_uv_pri_strength[STD_VIDEO_AV1_MAX_CDEF_FILTER_STRENGTHS];
    uint8_t    cdef_uv_sec_strength[STD_VIDEO_AV1_MAX_CDEF_FILTER_STRENGTHS];
} StdVideoAV1CDEF;

typedef struct StdVideoAV1LoopRestoration {
    StdVideoAV1FrameRestorationType    FrameRestorationType[STD_VIDEO_AV1_MAX_NUM_PLANES];
    uint16_t                           LoopRestorationSize[STD_VIDEO_AV1_MAX_NUM_PLANES];
} StdVideoAV1LoopRestoration;

typedef struct StdVideoAV1GlobalMotion {
    uint8_t    GmType[STD_VIDEO_AV1_NUM_REF_FRAMES];
    int32_t    gm_params[STD_VIDEO_AV1_NUM_REF_FRAMES][STD_VIDEO_AV1_GLOBAL_MOTION_PARAMS];
} StdVideoAV1GlobalMotion;

typedef struct StdVideoAV1FilmGrainFlags {
    uint32_t    chroma_scaling_from_luma : 1;
    uint32_t    overlap_flag : 1;
    uint32_t    clip_to_restricted_range : 1;
    uint32_t    update_grain : 1;
    uint32_t    reserved : 28;
} StdVideoAV1FilmGrainFlags;

typedef struct StdVideoAV1FilmGrain {
    StdVideoAV1FilmGrainFlags    flags;
    uint8_t                      grain_scaling_minus_8;
    uint8_t                      ar_coeff_lag;
    uint8_t                      ar_coeff_shift_minus_6;
    uint8_t                      grain_scale_shift;
    uint16_t                     grain_seed;
    uint8_t                      film_grain_params_ref_idx;
    uint8_t                      num_y_points;
    uint8_t                      point_y_value[STD_VIDEO_AV1_MAX_NUM_Y_POINTS];
    uint8_t                      point_y_scaling[STD_VIDEO_AV1_MAX_NUM_Y_POINTS];
    uint8_t                      num_cb_points;
    uint8_t                      point_cb_value[STD_VIDEO_AV1_MAX_NUM_CB_POINTS];
    uint8_t                      point_cb_scaling[STD_VIDEO_AV1_MAX_NUM_CB_POINTS];
    uint8_t                      num_cr_points;
    uint8_t                      point_cr_value[STD_VIDEO_AV1_MAX_NUM_CR_POINTS];
    uint8_t                      point_cr_scaling[STD_VIDEO_AV1_MAX_NUM_CR_POINTS];
    int8_t                       ar_coeffs_y_plus_128[STD_VIDEO_AV1_MAX_NUM_POS_LUMA];
    int8_t                       ar_coeffs_cb_plus_128[STD_VIDEO_AV1_MAX_NUM_POS_CHROMA];
    int8_t                       ar_coeffs_cr_plus_128[STD_VIDEO_AV1_MAX_NUM_POS_CHROMA];
    uint8_t                      cb_mult;
    uint8_t                      cb_luma_mult;
    uint16_t                     cb_offset;
    uint8_t                      cr_mult;
    uint8_t                      cr_luma_mult;
    uint16_t                     cr_offset;
} StdVideoAV1FilmGrain;

typedef struct StdVideoAV1SequenceHeaderFlags {
    uint32_t    still_picture : 1;
    uint32_t    reduced_still_picture_header : 1;
    uint32_t    use_128x128_superblock : 1;
    uint32_t    enable_filter_intra : 1;
    uint32_t    enable_intra_edge_filter : 1;
    uint32_t    enable_interintra_compound : 1;
    uint32_t    enable_masked_compound : 1;
    uint32_t    enable_warped_motion : 1;
    uint32_t    enable_dual_filter : 1;
    uint32_t    enable_order_hint : 1;
    uint32_t    enable_jnt_comp : 1;
    uint32_t    enable_ref_frame_mvs : 1;
    uint32_t    frame_id_numbers_present_flag : 1;
    uint32_t    enable_superres : 1;
    uint32_t    enable_cdef : 1;
    uint32_t    enable_restoration : 1;
    uint32_t    film_grain_params_present : 1;
    uint32_t    timing_info_present_flag : 1;
    uint32_t    initial_display_delay_present_flag : 1;
    uint32_t    reserved : 13;
} StdVideoAV1SequenceHeaderFlags;

typedef struct StdVideoAV1SequenceHeader {
    StdVideoAV1SequenceHeaderFlags    flags;
    StdVideoAV1Profile                seq_profile;
    uint8_t                           frame_width_bits_minus_1;
    uint8_t                           frame_height_bits_minus_1;
    uint16_t                          max_frame_width_minus_1;
    uint16_t                          max_frame_height_minus_1;
    uint8_t                           delta_frame_id_length_minus_2;
    uint8_t                           additional_frame_id_length_minus_1;
    uint8_t                           order_hint_bits_minus_1;
    uint8_t                           seq_force_integer_mv;
    uint8_t                           seq_force_screen_content_tools;
    uint8_t                           reserved1[5];
    const StdVideoAV1ColorConfig*     pColorConfig;
    const StdVideoAV1TimingInfo*      pTimingInfo;
} StdVideoAV1SequenceHeader;


#ifdef __cplusplus
}
#endif

#endif

```

--------------------------------------------------------------------------------
/vkrunner/vkrunner/executor.rs:
--------------------------------------------------------------------------------

```rust
// vkrunner
//
// Copyright (C) 2018 Intel Corporation
// Copyright 2023 Neil Roberts
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice (including the next
// paragraph) shall be included in all copies or substantial portions of the
// Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.

use crate::vulkan_funcs;
use crate::context::{self, Context};
use crate::window::{Window, WindowError};
use crate::config::Config;
use crate::script::Script;
use crate::source::Source;
use crate::result;
use crate::vk;
use crate::requirements::Requirements;
use crate::pipeline_set::{self, PipelineSet};
use crate::tester;
use crate::requirements;
use std::ffi::c_void;
use std::fmt;
use std::rc::Rc;
use std::cell::RefCell;

#[derive(Debug)]
pub(crate) enum Error {
    Context(context::Error),
    Window(WindowError),
    PipelineError(pipeline_set::Error),
    TestError(tester::Error),
    ExternalDeviceRequirementsError(requirements::Error),
}

impl Error {
    pub fn result(&self) -> result::Result {
        match self {
            Error::Context(e) => e.result(),
            Error::Window(e) => e.result(),
            Error::ExternalDeviceRequirementsError(e) => e.result(),
            Error::PipelineError(_) => result::Result::Fail,
            Error::TestError(_) => result::Result::Fail,
        }
    }
}

impl From<context::Error> for Error {
    fn from(error: context::Error) -> Error {
        Error::Context(error)
    }
}

impl From<WindowError> for Error {
    fn from(error: WindowError) -> Error {
        Error::Window(error)
    }
}

impl From<pipeline_set::Error> for Error {
    fn from(error: pipeline_set::Error) -> Error {
        Error::PipelineError(error)
    }
}

impl From<tester::Error> for Error {
    fn from(error: tester::Error) -> Error {
        Error::TestError(error)
    }
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            Error::Context(e) => e.fmt(f),
            Error::Window(e) => e.fmt(f),
            Error::PipelineError(e) => e.fmt(f),
            Error::TestError(e) => e.fmt(f),
            Error::ExternalDeviceRequirementsError(e) => e.fmt(f),
        }
    }
}

#[derive(Debug)]
struct ExternalData {
    get_instance_proc_cb: vulkan_funcs::GetInstanceProcFunc,
    user_data: *const c_void,
    physical_device: vk::VkPhysicalDevice,
    queue_family: u32,
    vk_device: vk::VkDevice,
}

#[derive(Debug)]
pub struct Executor {
    config: Rc<RefCell<Config>>,

    window: Option<Rc<Window>>,
    context: Option<Rc<Context>>,
    // A cache of the requirements that the context was created with.
    // Used to detect if the requirements have changed. This won’t be
    // used if the context is external.
    requirements: Requirements,

    external: Option<ExternalData>,
}

impl Executor {
    fn reset_window(&mut self) {
        self.window = None;
    }

    fn reset_context(&mut self) {
        self.reset_window();
        self.context = None;
    }

    fn context_is_compatible(&self, script: &Script) -> bool {
        // If the device is created externally then it’s up to the
        // caller to ensure the device has all the necessary features
        // enabled.
        if self.external.is_some() {
            return true;
        }

        match self.context {
            Some(_) => self.requirements.eq(script.requirements()),
            None => false,
        }
    }

    pub fn new(config: Rc<RefCell<Config>>) -> Executor {
        Executor {
            config,

            window: None,
            context: None,
            requirements: Requirements::new(),
            external: None,
        }
    }

    pub fn set_device(
        &mut self,
        get_instance_proc_cb: vulkan_funcs::GetInstanceProcFunc,
        user_data: *const c_void,
        physical_device: vk::VkPhysicalDevice,
        queue_family: u32,
        vk_device: vk::VkDevice,
    ) {
        self.reset_context();

        self.external = Some(ExternalData {
            get_instance_proc_cb,
            user_data,
            physical_device,
            queue_family,
            vk_device,
        });
    }

    fn create_context(
        &self,
        requirements: &Requirements,
    ) -> Result<Context, Error> {
        match &self.external {
            Some(e) => {
                Ok(Context::new_with_device(
                    e.get_instance_proc_cb,
                    e.user_data,
                    e.physical_device,
                    e.queue_family,
                    e.vk_device,
                )?)
            },
            None => Ok(Context::new(
                requirements,
                self.config.borrow().device_id()
            )?),
        }
    }

    fn context_for_script(
        &mut self,
        script: &Script,
    ) -> Result<Rc<Context>, Error> {
        // Recreate the context if the features or extensions have changed
        if !self.context_is_compatible(script) {
            self.reset_context();
        }

        match &self.context {
            Some(c) => Ok(Rc::clone(c)),
            None => {
                self.requirements.clone_from(script.requirements());
                let context = self.create_context(&self.requirements)?;

                Ok(Rc::clone(self.context.insert(Rc::new(context))))
            }
        }
    }

    fn window_for_script(
        &mut self,
        script: &Script,
        context: Rc<Context>,
    ) -> Result<Rc<Window>, Error> {
        // Recreate the window if the framebuffer format is different
        if let Some(window) = &self.window {
            if !window.format().eq(script.window_format()) {
                self.reset_window();
            }
        }

        match &self.window {
            Some(w) => Ok(Rc::clone(w)),
            None => Ok(Rc::clone(self.window.insert(Rc::new(Window::new(
                context,
                script.window_format(),
            )?)))),
        }
    }

    fn handle_execute_result(
        &self,
        result: Result<(), Error>
    ) -> result::Result {
        match result {
            Ok(()) => result::Result::Pass,
            Err(e) => {
                use std::fmt::Write;
                let _ = writeln!(
                    self.config.borrow_mut().logger().borrow_mut(),
                    "{}",
                    e
                );
                e.result()
            }
        }
    }

    fn execute_script_or_error(
        &mut self,
        script: &Script
    ) -> Result<(), Error> {
        let context = self.context_for_script(script)?;

        if self.external.is_some() {
            if let Err(e) = script.requirements().check(
                context.instance(),
                context.physical_device(),
            ) {
                return Err(Error::ExternalDeviceRequirementsError(e));
            }
        }

        let window = self.window_for_script(script, Rc::clone(&context))?;

        let pipeline_set = PipelineSet::new(
            &mut self.config.borrow().logger().borrow_mut(),
            Rc::clone(&window),
            script,
            self.config.borrow().show_disassembly(),
        )?;

        tester::run(
            window.as_ref(),
            &pipeline_set,
            script,
            self.config.borrow().inspector().clone(),
        )?;

        Ok(())
    }

    pub fn execute_script(
        &mut self,
        script: &Script
    ) -> result::Result {
        let res = self.execute_script_or_error(script);
        self.handle_execute_result(res)
    }

    pub fn execute(
        &mut self,
        source: &Source,
    ) -> result::Result {
        let load_res = Script::load(&self.config.borrow(), source);

        load_res
            .and_then(|script| Some(self.execute_script(&script)))
            .unwrap_or(result::Result::Fail)
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use crate::fake_vulkan::FakeVulkan;
    use crate::config::Config;
    use std::ffi::c_char;

    fn create_fake_vulkan() -> Box<FakeVulkan> {
        let mut fake_vulkan = FakeVulkan::new();
        fake_vulkan.physical_devices.push(Default::default());
        fake_vulkan.physical_devices[0].features.wideLines = vk::VK_TRUE;
        fake_vulkan.physical_devices[0].format_properties.insert(
            vk::VK_FORMAT_B8G8R8A8_UNORM,
            vk::VkFormatProperties {
                linearTilingFeatures: 0,
                optimalTilingFeatures:
                vk::VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT
                    | vk::VK_FORMAT_FEATURE_BLIT_SRC_BIT,
                bufferFeatures: 0,
            },
        );
        fake_vulkan.physical_devices[0].format_properties.insert(
            vk::VK_FORMAT_R8_UNORM,
            vk::VkFormatProperties {
                linearTilingFeatures: 0,
                optimalTilingFeatures:
                vk::VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT
                    | vk::VK_FORMAT_FEATURE_BLIT_SRC_BIT,
                bufferFeatures: 0,
            },
        );

        let memory_properties =
            &mut fake_vulkan.physical_devices[0].memory_properties;
        memory_properties.memoryTypes[0].propertyFlags =
            vk::VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
        memory_properties.memoryTypeCount = 1;
        fake_vulkan.memory_requirements.memoryTypeBits = 1;

        fake_vulkan
    }

    #[test]
    fn recreate_resources() {
        let fake_vulkan = create_fake_vulkan();

        let config = Rc::new(RefCell::new(Config::new()));

        let mut executor = Executor::new(Rc::clone(&config));

        fake_vulkan.set_override();
        assert_eq!(
            executor.execute(&Source::from_string("".to_string())),
            result::Result::Pass,
        );

        let context = Rc::clone(executor.context.as_ref().unwrap());
        let window = Rc::clone(&executor.window.as_ref().unwrap());

        // Run another script that has the same requirements
        assert_eq!(
            executor.execute(&Source::from_string(
                "[test]\n\
                 draw rect -1 -1 2 2".to_string()
            )),
            result::Result::Pass,
        );

        // The context and window shouldn’t have changed
        assert!(Rc::ptr_eq(&context, executor.context.as_ref().unwrap()));
        assert!(Rc::ptr_eq(&window, executor.window.as_ref().unwrap()));

        // Run a script with different requirements
        fake_vulkan.set_override();
        assert_eq!(
            executor.execute(&Source::from_string(
                "[require]\n\
                 wideLines\n\
                 [test]\n\
                 draw rect -1 -1 2 2".to_string()
            )),
            result::Result::Pass,
        );

        // The context and window should have changed
        assert!(!Rc::ptr_eq(&context, executor.context.as_ref().unwrap()));
        assert!(!Rc::ptr_eq(&window, executor.window.as_ref().unwrap()));

        let context = Rc::clone(executor.context.as_ref().unwrap());
        let window = Rc::clone(&executor.window.as_ref().unwrap());

        // Run the same script with a different framebuffer format
        assert_eq!(
            executor.execute(&Source::from_string(
                "[require]\n\
                 wideLines\n\
                 framebuffer R8_UNORM\n\
                 [test]\n\
                 draw rect -1 -1 2 2".to_string()
            )),
            result::Result::Pass,
        );

        // The context should stay the same but the framebuffer should
        // have changed
        assert!(Rc::ptr_eq(&context, executor.context.as_ref().unwrap()));
        assert!(!Rc::ptr_eq(&window, executor.window.as_ref().unwrap()));
    }

    extern "C" fn get_instance_proc_cb(
        func_name: *const c_char,
        user_data: *const c_void,
    ) -> *const c_void {
        unsafe {
            let fake_vulkan = &*(user_data as *const FakeVulkan);

            let func = fake_vulkan.get_function(func_name);

            std::mem::transmute(func)
        }
    }

    #[test]
    fn external_device() {
        let fake_vulkan = create_fake_vulkan();

        fake_vulkan.set_override();
        let context = Context::new(&Requirements::new(), None).unwrap();

        let config = Rc::new(RefCell::new(Config::new()));

        let mut executor = Executor::new(Rc::clone(&config));

        let (queue_family, _) = FakeVulkan::unmake_queue(context.queue());

        executor.set_device(
            get_instance_proc_cb,
            (fake_vulkan.as_ref() as *const FakeVulkan).cast(),
            context.physical_device(),
            queue_family,
            context.vk_device()
        );

        assert_eq!(
            executor.execute(&Source::from_string("".to_string())),
            result::Result::Pass,
        );
    }

    #[test]
    fn external_requirements_error() {
        let fake_vulkan = create_fake_vulkan();

        fake_vulkan.set_override();
        let context = Context::new(&Requirements::new(), None).unwrap();

        let config = Rc::new(RefCell::new(Config::new()));

        let mut executor = Executor::new(Rc::clone(&config));

        let (queue_family, _) = FakeVulkan::unmake_queue(context.queue());

        executor.set_device(
            get_instance_proc_cb,
            (fake_vulkan.as_ref() as *const FakeVulkan).cast(),
            context.physical_device(),
            queue_family,
            context.vk_device()
        );

        let source = Source::from_string(
            "[require]\n\
             logicOp".to_string()
        );
        let script = Script::load(&executor.config.borrow(), &source).unwrap();

        let error = executor.execute_script_or_error(&script).unwrap_err();

        assert_eq!(
            &error.to_string(),
            "Missing required feature: logicOp",
        );
        assert_eq!(
            error.result(),
            result::Result::Skip,
        );
    }

    #[test]
    fn context_error() {
        let fake_vulkan = create_fake_vulkan();

        let config = Rc::new(RefCell::new(Config::new()));
        config.borrow_mut().set_device_id(Some(12));

        let mut executor = Executor::new(Rc::clone(&config));

        let source = Source::from_string("".to_string());
        let script = Script::load(&executor.config.borrow(), &source).unwrap();

        fake_vulkan.set_override();
        let error = executor.execute_script_or_error(&script).unwrap_err();

        assert_eq!(
            &error.to_string(),
            "Device 13 was selected but the Vulkan instance only reported \
             1 device.",
        );
        assert_eq!(
            error.result(),
            result::Result::Fail,
        );
    }

    fn run_script_error(source: &str) -> Error {
        let fake_vulkan = create_fake_vulkan();

        let config = Rc::new(RefCell::new(Config::new()));

        let mut executor = Executor::new(config);

        let source = Source::from_string(source.to_string());
        let script = Script::load(&executor.config.borrow(), &source).unwrap();

        fake_vulkan.set_override();
        executor.execute_script_or_error(&script).unwrap_err()
    }

    #[test]
    fn window_error() {
        let error = run_script_error(
            "[require]\n\
             depthstencil R8_UNORM"
        );

        assert_eq!(
            &error.to_string(),
            "Format R8_UNORM is not supported as a depth/stencil attachment",
        );
        assert_eq!(
            error.result(),
            result::Result::Skip,
        );
    }

    #[test]
    fn pipeline_error() {
        let error = run_script_error(
            "[vertex shader]\n\
             12"
        );

        assert_eq!(
            &error.to_string(),
            "The compiler or assembler generated an invalid SPIR-V binary",
        );
        assert_eq!(
            error.result(),
            result::Result::Fail,
        );
    }

    #[test]
    fn tester_error() {
        let error = run_script_error(
            "[test]\n\
             probe all rgb 1 2 3"
        );

        assert_eq!(
            &error.to_string(),
            "line 2: Probe color at (0,0)\n\
             \x20 Expected: 1 2 3\n\
             \x20 Observed: 0 0 0"
        );
        assert_eq!(
            error.result(),
            result::Result::Fail,
        );
    }
}

```

--------------------------------------------------------------------------------
/vkrunner/vkrunner/compiler.rs:
--------------------------------------------------------------------------------

```rust
// vkrunner
//
// Copyright (C) 2018 Intel Corporation
// Copyright 2023 Neil Roberts
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice (including the next
// paragraph) shall be included in all copies or substantial portions of the
// Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.

use crate::vk;
use crate::shader_stage;
use crate::logger::Logger;
use crate::context::Context;
use crate::script::{Script, Shader};
use crate::temp_file;
use crate::requirements::extract_version;
use std::fmt;
use std::mem;
use std::ptr;
use std::io::{self, Write, Read, BufWriter};
use std::fs::File;
use std::path::Path;
use std::env;
// When testing we’ll divert to a fake command so that we don’t need
// to depend on glslangValidator
#[cfg(test)]
mod fake_process;
#[cfg(test)]
use fake_process::{Command, Output};
#[cfg(not(test))]
use std::process::{Command, Output};
use std::process::Stdio;

/// An error that can be returned by [build_stage].
#[derive(Debug)]
pub enum Error {
    /// There were no shaders for this stage in the script
    MissingStageShaders(shader_stage::Stage),
    /// vkCreateShaderModule returned an error
    CreateShaderModuleFailed,
    /// Error creating a temporary file
    TempFile(temp_file::Error),
    /// Other I/O error
    IoError(io::Error),
    /// A compiler or assembler command returned a non-zero status
    CommandFailed,
    /// The generated shader binary didn’t have the right SPIR-V magic
    /// number or wasn’t a multiple of 32-bit integers.
    InvalidShaderBinary,
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            Error::MissingStageShaders(stage) => write!(
                f,
                "No shaders for stage {:?}",
                stage,
            ),
            Error::CreateShaderModuleFailed => write!(
                f,
                "vkCreateShaderModule failed"
            ),
            Error::TempFile(e) => e.fmt(f),
            Error::IoError(e) => e.fmt(f),
            Error::CommandFailed => write!(
                f,
                "A subprocess failed with a non-zero exit status",
            ),
            Error::InvalidShaderBinary => write!(
                f,
                "The compiler or assembler generated an invalid SPIR-V binary",
            ),
        }
    }
}

impl From<temp_file::Error> for Error {
    fn from(e: temp_file::Error) -> Error {
        Error::TempFile(e)
    }
}

impl From<io::Error> for Error {
    fn from(e: io::Error) -> Error {
        Error::IoError(e)
    }
}

fn stage_name(stage: shader_stage::Stage) -> &'static str {
    match stage {
        shader_stage::Stage::Vertex => "vert",
        shader_stage::Stage::TessCtrl => "tesc",
        shader_stage::Stage::TessEval => "tese",
        shader_stage::Stage::Geometry => "geom",
        shader_stage::Stage::Fragment => "frag",
        shader_stage::Stage::Compute => "comp",
    }
}

fn handle_command_output(
    logger: &mut Logger,
    output: Output,
) -> Result<(), Error> {
    logger.write_all(output.stdout.as_slice())?;
    logger.write_all(output.stderr.as_slice())?;

    if output.status.success() {
        Ok(())
    } else {
        Err(Error::CommandFailed)
    }
}

fn show_disassembly_from_file(
    logger: &mut Logger,
    filename: &Path,
) -> Result<(), Error> {
    let exe = match env::var_os("PIGLIT_SPIRV_DIS_BINARY") {
        Some(exe) => exe,
        None => "spirv-dis".into(),
    };

    handle_command_output(
        logger,
        Command::new(exe)
            .arg(filename)
            .stdout(Stdio::piped())
            .stderr(Stdio::piped())
            .output()?
    )
}

fn create_shader_from_binary(
    context: &Context,
    data: &[u32],
) -> Result<vk::VkShaderModule, Error> {
    let shader_module_create_info = vk::VkShaderModuleCreateInfo {
        sType: vk::VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO,
        pNext: ptr::null(),
        flags: 0,
        codeSize: data.len() * mem::size_of::<u32>(),
        pCode: data.as_ptr(),
    };

    let mut module: vk::VkShaderModule = vk::null_handle();

    let res = unsafe {
        context.device().vkCreateShaderModule.unwrap()(
            context.vk_device(),
            ptr::addr_of!(shader_module_create_info),
            ptr::null(), // allocator
            ptr::addr_of_mut!(module),
        )
    };

    if res == vk::VK_SUCCESS {
        Ok(module)
    } else {
        Err(Error::CreateShaderModuleFailed)
    }
}

fn create_shader_from_binary_file(
    context: &Context,
    file: &mut File,
) -> Result<vk::VkShaderModule, Error> {
    let mut data = Vec::<u32>::new();
    let mut buf = vec![0u8; 512];
    let mut buf_length = 0usize;
    let mut big_endian = false;
    let mut bytes = [0u8; mem::size_of::<u32>()];

    loop {
        let got = file.read(&mut buf[buf_length..])?;

        if got == 0 {
            break;
        }

        buf_length += got;

        for i in 0..buf_length / mem::size_of::<u32>() {
            let buf_start = i * mem::size_of::<u32>();
            bytes.copy_from_slice(&buf[
                buf_start..buf_start + mem::size_of::<u32>()
            ]);

            if data.len() == 0 {
                if bytes == [0x07, 0x23, 0x02, 0x03] {
                    big_endian = true;
                } else if bytes == [0x03, 0x02, 0x23, 0x07] {
                    big_endian = false;
                } else {
                    return Err(Error::InvalidShaderBinary);
                }
            }

            data.push(if big_endian {
                u32::from_be_bytes(bytes)
            } else {
                u32::from_le_bytes(bytes)
            });
        }

        let remainder = buf_length % mem::size_of::<u32>();

        buf.copy_within(buf_length - remainder.., 0);
        buf_length = remainder;
    }

    if buf_length != 0 {
        Err(Error::InvalidShaderBinary)
    } else {
        create_shader_from_binary(context, &data)
    }
}

fn create_temp_file_for_source(
    source: &str
) -> Result<temp_file::TempFile, Error> {
    let mut temp_file = temp_file::TempFile::new()?;
    temp_file.file().unwrap().write_all(source.as_bytes())?;
    temp_file.file().unwrap().flush()?;
    temp_file.close();

    Ok(temp_file)
}

fn version_string(version: u32) -> String {
    let (version_major, version_minor, _) = extract_version(version);
    format!("vulkan{}.{}", version_major, version_minor)
}

fn compile_glsl(
    logger: &mut Logger,
    context: &Context,
    script: &Script,
    stage: shader_stage::Stage,
    show_disassembly: bool,
) -> Result<vk::VkShaderModule, Error> {
    let mut shader_files = Vec::new();

    for shader in script.shaders(stage) {
        let source = match &shader {
            Shader::Glsl(s) => s,
            _ => unreachable!("Unexpected shader type"),
        };
        shader_files.push(create_temp_file_for_source(&source)?);
    }

    let version_str = version_string(script.requirements().version());

    let mut module_file = temp_file::TempFile::new()?;

    let exe = match env::var_os("PIGLIT_GLSLANG_VALIDATOR_BINARY") {
        Some(exe) => exe,
        None => "glslangValidator".into(),
    };

    handle_command_output(
        logger,
        Command::new(exe)
            .args([
                "--quiet",
                "-V",
                "--target-env", &version_str,
                "-S", stage_name(stage),
            ])
            .arg("-o").arg(module_file.filename())
            .args(shader_files.iter().map(|file| file.filename()))
            .stdout(Stdio::piped())
            .stderr(Stdio::piped())
            .output()?
    )?;

    drop(shader_files);

    if show_disassembly {
        show_disassembly_from_file(logger, module_file.filename())?;
    }

    create_shader_from_binary_file(context, module_file.file().unwrap())
}

fn assemble_spirv(
    logger: &mut Logger,
    context: &Context,
    script: &Script,
    source: &str,
    show_disassembly: bool,
) -> Result<vk::VkShaderModule, Error> {
    let version_str = version_string(script.requirements().version());

    let mut module_file = temp_file::TempFile::new()?;

    let source_file = create_temp_file_for_source(source)?;

    let exe = match env::var_os("PIGLIT_SPIRV_AS_BINARY") {
        Some(exe) => exe,
        None => "spirv-as".into(),
    };

    handle_command_output(
        logger,
        Command::new(exe)
            .args(["--target-env", &version_str])
            .arg("-o").arg(module_file.filename())
            .arg(source_file.filename())
            .stdout(Stdio::piped())
            .stderr(Stdio::piped())
            .output()?
    )?;

    drop(source_file);

    if show_disassembly {
        show_disassembly_from_file(logger, module_file.filename())?;
    }

    create_shader_from_binary_file(context, module_file.file().unwrap())
}

fn load_binary_stage(
    logger: &mut Logger,
    context: &Context,
    data: &[u32],
    show_disassembly: bool,
) -> Result<vk::VkShaderModule, Error> {
    if show_disassembly {
        let mut temp_file = temp_file::TempFile::new()?;
        let mut writer = BufWriter::new(temp_file.file().unwrap());

        for value in data {
            writer.write_all(&value.to_ne_bytes())?;
        }

        writer.flush()?;

        drop(writer);

        temp_file.close();

        show_disassembly_from_file(logger, temp_file.filename())?;
    }

    create_shader_from_binary(context, data)
}

pub fn build_stage(
    logger: &mut Logger,
    context: &Context,
    script: &Script,
    stage: shader_stage::Stage,
    show_disassembly: bool,
) -> Result<vk::VkShaderModule, Error> {
    let shaders = script.shaders(stage);

    match shaders.get(0) {
        None => Err(Error::MissingStageShaders(stage)),
        Some(Shader::Glsl(_)) => compile_glsl(
            logger,
            context,
            script,
            stage,
            show_disassembly,
        ),
        Some(Shader::Spirv(source)) => {
            // The script parser should have ensured that there’s
            // only one shader
            assert_eq!(shaders.len(), 1);
            assemble_spirv(
                logger,
                context,
                script,
                source,
                show_disassembly
            )
        },
        Some(Shader::Binary(data)) => {
            // The script parser should have ensured that there’s
            // only one shader
            assert_eq!(shaders.len(), 1);
            load_binary_stage(
                logger,
                context,
                data,
                show_disassembly
            )
        },
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use crate::fake_vulkan::{FakeVulkan, HandleType};
    use crate::context::Context;
    use crate::requirements::Requirements;
    use crate::source::Source;
    use crate::config::Config;
    use std::ffi::{c_char, c_void, CStr};

    struct CompileOutput {
        log: Vec<String>,
        result: Result<Vec<u32>, Error>,
    }

    extern "C" fn log_cb(message: *const c_char, user_data: *mut c_void) {
        unsafe {
            let message = CStr::from_ptr(message).to_str().unwrap().to_owned();
            let log = &mut *(user_data as *mut Vec<String>);
            log.push(message);
        }
    }

    fn compile_script(
        source: &str,
        stage: shader_stage::Stage,
        show_disassembly: bool,
    ) -> CompileOutput {
        let mut fake_vulkan = FakeVulkan::new();
        fake_vulkan.physical_devices.push(Default::default());

        compile_script_with_fake_vulkan(
            &mut fake_vulkan,
            source,
            stage,
            show_disassembly
        )
    }

    fn compile_script_with_fake_vulkan(
        fake_vulkan: &mut FakeVulkan,
        source: &str,
        stage: shader_stage::Stage,
        show_disassembly: bool,
    ) -> CompileOutput {
        fake_vulkan.set_override();
        let context = Context::new(&Requirements::new(), None).unwrap();

        let source = Source::from_string(source.to_owned());
        let script = Script::load(&Config::new(), &source).unwrap();
        let mut log = Vec::new();
        let mut logger = Logger::new(
            Some(log_cb),
            ptr::addr_of_mut!(log).cast(),
        );

        let result = build_stage(
            &mut logger,
            &context,
            &script,
            stage,
            show_disassembly,
        ).map(|module| {
            let code = match &fake_vulkan.get_handle(module).data {
                HandleType::ShaderModule { code } => code.clone(),
                _ => unreachable!("Unexpected Vulkan handle type"),
            };
            unsafe {
                context.device().vkDestroyShaderModule.unwrap()(
                    context.vk_device(),
                    module,
                    ptr::null(), // allocator
                );
            }
            code
        });

        CompileOutput { log, result }
    }

    #[test]
    fn glsl_le() {
        let CompileOutput { log, result } = compile_script(
            "[fragment shader]\n\
             03 02 23 07\n\
             fe ca fe ca\n",
            shader_stage::Stage::Fragment,
            false, // show_disassembly
        );

        assert_eq!(
            &log,
            &[
                "quiet",
                "vulkan_spirv",
                "target_env: vulkan1.0",
                "stage: frag",
            ],
        );

        assert_eq!(result.unwrap(), &[0x07230203, 0xcafecafe]);
    }

    #[test]
    fn glsl_be() {
        let CompileOutput { log, result } = compile_script(
            "[vertex shader]\n\
             07 23 02 03\n\
             ca fe ca fe\n",
            shader_stage::Stage::Vertex,
            false, // show_disassembly
        );

        assert_eq!(
            &log,
            &[
                "quiet",
                "vulkan_spirv",
                "target_env: vulkan1.0",
                "stage: vert",
            ],
        );

        assert_eq!(result.unwrap(), &[0x07230203, 0xcafecafe]);
    }

    #[test]
    fn spirv() {
        let CompileOutput { log, result } = compile_script(
            "[vertex shader spirv]\n\
             07 23 02 03\n\
             f0 0d fe ed\n",
            shader_stage::Stage::Vertex,
            false, // show_disassembly
        );

        assert_eq!(&log, &["target_env: vulkan1.0"]);

        assert_eq!(result.unwrap(), &[0x07230203, 0xf00dfeed]);
    }

    #[test]
    fn binary() {
        let CompileOutput { log, result } = compile_script(
            "[vertex shader binary]\n\
             07230203\n\
             f00dfeed\n",
            shader_stage::Stage::Vertex,
            false, // show_disassembly
        );

        assert!(log.is_empty());

        assert_eq!(result.unwrap(), &[0x07230203, 0xf00dfeed]);
    }

    fn test_stage(
        stage: shader_stage::Stage,
        section_name: &str,
        compiler_argument: &str
    ) {
        let CompileOutput { log, result } = compile_script(
            &format!(
                "[{}]\n\
                 07 23 02 03\n",
                section_name,
            ),
            stage,
            false, // show_disassembly
        );

        assert_eq!(
            &log,
            &[
                "quiet",
                "vulkan_spirv",
                "target_env: vulkan1.0",
                &format!("stage: {}", compiler_argument)
            ]
        );

        assert!(result.is_ok());
    }

    #[test]
    fn all_stages() {
        test_stage(
            shader_stage::Stage::Vertex,
            "vertex shader",
            "vert"
        );
        test_stage(
            shader_stage::Stage::TessCtrl,
            "tessellation control shader",
            "tesc"
        );
        test_stage(
            shader_stage::Stage::TessEval,
            "tessellation evaluation shader",
            "tese"
        );
        test_stage(
            shader_stage::Stage::Geometry,
            "geometry shader",
            "geom"
        );
        test_stage(
            shader_stage::Stage::Fragment,
            "fragment shader",
            "frag"
        );
        test_stage(
            shader_stage::Stage::Compute,
            "compute shader",
            "comp"
        );
    }

    #[test]
    fn no_shaders() {
        let CompileOutput { result, .. } = compile_script(
            "[vertex shader]\n\
             07 23 02 03\n",
            shader_stage::Stage::Fragment,
            false, // show_disassembly
        );
        assert_eq!(
            &result.unwrap_err().to_string(),
            "No shaders for stage Fragment",
        );
    }

    #[test]
    fn create_shader_module_error() {
        let mut fake_vulkan = FakeVulkan::new();
        fake_vulkan.physical_devices.push(Default::default());
        fake_vulkan.queue_result(
            "vkCreateShaderModule".to_string(),
            vk::VK_ERROR_UNKNOWN
        );

        let CompileOutput { result, .. } = compile_script_with_fake_vulkan(
            &mut fake_vulkan,
            "[vertex shader]\n\
             07 23 02 03\n",
            shader_stage::Stage::Vertex,
            false, // show_disassembly
        );
        assert_eq!(
            &result.unwrap_err().to_string(),
            "vkCreateShaderModule failed",
        );
    }

    #[test]
    fn invalid_magic() {
        let CompileOutput { result, .. } = compile_script(
            "[vertex shader]\n\
             12 34 56 78\n",
            shader_stage::Stage::Vertex,
            false, // show_disassembly
        );
        assert_eq!(
            &result.unwrap_err().to_string(),
            "The compiler or assembler generated an invalid SPIR-V binary",
        );
    }

    #[test]
    fn not_multiple_of_u32() {
        let CompileOutput { result, .. } = compile_script(
            "[vertex shader]\n\
             07 23 02 03 9a\n",
            shader_stage::Stage::Vertex,
            false, // show_disassembly
        );
        assert_eq!(
            &result.unwrap_err().to_string(),
            "The compiler or assembler generated an invalid SPIR-V binary",
        );
    }

    #[test]
    fn compiler_failed() {
        let CompileOutput { result, .. } = compile_script(
            "[vertex shader]\n\
             invalid hex values\n",
            shader_stage::Stage::Vertex,
            false, // show_disassembly
        );
        assert_eq!(
            &result.unwrap_err().to_string(),
            "A subprocess failed with a non-zero exit status",
        );
    }

    fn test_show_disassembly(section_suffix: &str) {
        let CompileOutput { log, result } = compile_script(
            &format!(
                "[fragment shader{}]\n\
                 03 02 23 07\n\
                 fe ca fe ca\n",
                section_suffix,
            ),
            shader_stage::Stage::Fragment,
            true, // show_disassembly
        );

        assert!(log.iter().find(|&line| line == "disassembly").is_some());

        assert!(result.is_ok());
    }

    #[test]
    fn show_glsl_disassembly() {
        test_show_disassembly("");
    }

    #[test]
    fn show_spirv_disassembly() {
        test_show_disassembly(" spirv");
    }

    #[test]
    fn show_binary_disassembly() {
        test_show_disassembly(" binary");
    }
}

```

--------------------------------------------------------------------------------
/vkrunner/vkrunner/format.rs:
--------------------------------------------------------------------------------

```rust
// vkrunner
//
// Copyright (C) 2018 Intel Corporation
// Copyright 2023 Neil Roberts
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// on the rights to use, copy, modify, merge, publish, distribute, sub
// license, and/or sell copies of the Software, and to permit persons to whom
// the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice (including the next
// paragraph) shall be included in all copies or substantial portions of the
// Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.  IN NO EVENT SHALL
// VA LINUX SYSTEM, IBM AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
// USE OR OTHER DEALINGS IN THE SOFTWARE.

use crate::small_float;
use crate::half_float;
use crate::vk;
use std::convert::TryInto;
use std::num::NonZeroUsize;

#[derive(Debug)]
pub struct Format {
    pub(crate) vk_format: vk::VkFormat,
    pub(crate) name: &'static str,
    pub(crate) packed_size: Option<NonZeroUsize>,
    n_parts: usize,
    parts: [Part; 4],
}

#[derive(Debug, Eq, PartialEq, Copy, Clone)]
pub(crate) enum Component {
    R,
    G,
    B,
    A,
    D,
    S,
    X,
}

#[derive(Debug, Eq, PartialEq, Copy, Clone)]
pub(crate) enum Mode {
    UNORM,
    SNORM,
    USCALED,
    SSCALED,
    UINT,
    SINT,
    UFLOAT,
    SFLOAT,
    SRGB,
}

#[derive(Debug, PartialEq, Eq)]
pub(crate) struct Part {
    pub bits: usize,
    pub component: Component,
    pub mode: Mode,
}

include!{"format_table.rs"}

impl PartialEq for Format {
    #[inline]
    fn eq(&self, other: &Format) -> bool {
        // If the Vulkan format enum is the same then everything else
        // about the format should be the same too
        self.vk_format == other.vk_format
    }
}

impl PartialEq<vk::VkFormat> for Format {
    #[inline]
    fn eq(&self, other: &vk::VkFormat) -> bool {
        self.vk_format == *other
    }
}

impl PartialEq<Format> for vk::VkFormat {
    #[inline]
    fn eq(&self, other: &Format) -> bool {
        *self == other.vk_format
    }
}

impl Format {
    pub(crate) fn lookup_by_name(name: &str) -> Option<&'static Format> {
        match FORMATS.binary_search_by(|format| format.name.cmp(name)) {
            Ok(pos) => Some(&FORMATS[pos]),
            Err(_) => None,
        }
    }

    pub(crate) fn lookup_by_vk_format(
        vk_format: vk::VkFormat
    ) -> &'static Format {
        for format in FORMATS.iter() {
            if format.vk_format == vk_format {
                return format;
            }
        }

        unreachable!("lookup failed for format {:?}", vk_format);
    }

    pub(crate) fn lookup_by_details(
        bit_size: usize,
        mode: Mode,
        n_components: usize
    ) -> Option<&'static Format> {
        static COMP_ORDER: [Component; 4] = [
            Component::R,
            Component::G,
            Component::B,
            Component::A,
        ];

        'format_loop: for format in FORMATS.iter() {
            if format.n_parts != n_components {
                continue;
            }

            if let Some(_) = format.packed_size {
                continue;
            }

            for (i, part) in format.parts().iter().enumerate() {
                if part.bits != bit_size
                    || part.component != COMP_ORDER[i]
                    || part.mode != mode
                {
                    continue 'format_loop;
                }
            }

            return Some(format);
        }

        None
    }

    pub(crate) fn parts(&self) -> &[Part] {
        &self.parts[0..self.n_parts]
    }

    pub fn size(&self) -> usize {
        match self.packed_size {
            Some(size) => usize::from(size) / 8,
            None => self.parts().iter().map(|p| p.bits).sum::<usize>() / 8,
        }
    }

    pub(crate) fn packed_size(&self) -> Option<usize> {
        self.packed_size.map(|s| usize::from(s))
    }

    pub(crate) fn alignment(&self) -> usize {
        match self.packed_size {
            Some(size) => usize::from(size) / 8,
            None => self.parts().iter().map(|p| p.bits).max().unwrap() / 8,
        }
    }

    pub(crate) fn depth_stencil_aspect_flags(&self) -> vk::VkImageAspectFlags {
        self.parts().iter().map(|part| match part.component {
            Component::D => vk::VK_IMAGE_ASPECT_DEPTH_BIT,
            Component::S => vk::VK_IMAGE_ASPECT_STENCIL_BIT,
            _ => 0,
        }).fold(0, |a, b| a | b)
    }
}

impl Mode {
    fn load_packed_part(&self, part: u32, bits: usize) -> f64 {
        assert!(bits < 32);

        match self {
            Mode::SRGB | Mode::UNORM => part as f64 / ((1 << bits) - 1) as f64,
            Mode::SNORM => {
                sign_extend(part, bits) as f64 / ((1 << (bits - 1)) - 1) as f64
            },
            Mode::UINT | Mode::USCALED => part as f64,
            Mode::SSCALED | Mode::SINT => sign_extend(part, bits) as f64,
            Mode::UFLOAT => {
                match bits {
                    10 => small_float::load_unsigned(part, 5, 5),
                    11 => small_float::load_unsigned(part, 5, 6),
                    _ => {
                        unreachable!(
                            "unknown bit size {} in packed UFLOAT \
                             format",
                            bits
                        )
                    },
                }
            },
            Mode::SFLOAT => unreachable!("Unexpected packed SFLOAT format"),
        }
    }

    fn load_part(&self, bits: usize, fb: &[u8]) -> f64 {
        match self {
            Mode::SRGB | Mode::UNORM => {
                match bits {
                    8 => fb[0] as f64 / u8::MAX as f64,
                    16 => {
                        u16::from_ne_bytes(fb[0..2].try_into().unwrap()) as f64
                            / u16::MAX as f64
                    },
                    24 => extract_u24(fb) as f64 / 16777215.0,
                    32 => {
                        u32::from_ne_bytes(fb[0..4].try_into().unwrap()) as f64
                            / u32::MAX as f64
                    },
                    64 => {
                        u64::from_ne_bytes(fb[0..8].try_into().unwrap()) as f64
                            / u64::MAX as f64
                    },
                    _=> unreachable!("unsupported component bit size {}", bits),
                }
            },
            Mode::SNORM => {
                match bits {
                    8 => fb[0] as i8 as f64 / i8::MAX as f64,
                    16 => {
                        i16::from_ne_bytes(fb[0..2].try_into().unwrap()) as f64
                            / i16::MAX as f64
                    },
                    32 => {
                        i32::from_ne_bytes(fb[0..4].try_into().unwrap()) as f64
                            / i32::MAX as f64
                    },
                    64 => {
                        i64::from_ne_bytes(fb[0..8].try_into().unwrap()) as f64
                            / i64::MAX as f64
                    },
                    _=> unreachable!("unsupported component bit size {}", bits),
                }
            },
            Mode::UINT | Mode::USCALED => {
                match bits {
                    8 => fb[0] as f64,
                    16 => {
                        u16::from_ne_bytes(fb[0..2].try_into().unwrap()) as f64
                    },
                    32 => {
                        u32::from_ne_bytes(fb[0..4].try_into().unwrap()) as f64
                    },
                    64 => {
                        u64::from_ne_bytes(fb[0..8].try_into().unwrap()) as f64
                    },
                    _=> unreachable!("unsupported component bit size {}", bits),
                }
            },
            Mode::SINT | Mode::SSCALED => {
                match bits {
                    8 => fb[0] as i8 as f64,
                    16 => {
                        i16::from_ne_bytes(fb[0..2].try_into().unwrap()) as f64
                    },
                    32 => {
                        i32::from_ne_bytes(fb[0..4].try_into().unwrap()) as f64
                    },
                    64 => {
                        i64::from_ne_bytes(fb[0..8].try_into().unwrap()) as f64
                    },
                    _=> unreachable!("unsupported component bit size {}", bits),
                }
            },
            Mode::UFLOAT => unreachable!("unexpected unpacked UFLOAT part"),
            Mode::SFLOAT => {
                match bits {
                    16 => {
                        let bits =
                            u16::from_ne_bytes(fb[0..2].try_into().unwrap());
                        half_float::to_f64(bits)
                    },
                    32 => {
                        f32::from_ne_bytes(fb[0..4].try_into().unwrap()) as f64
                    },
                    64 => f64::from_ne_bytes(fb[0..8].try_into().unwrap()),
                    _ => {
                        unreachable!(
                            "unsupported unpacked SFLOAT size {}",
                            bits
                        );
                    },
                }
            },
        }
    }
}

impl Format {
    fn load_packed_parts(&self, source: &[u8], parts: &mut [f64]) {
        let mut packed_parts = match self.packed_size().unwrap() {
            8 => source[0] as u32,
            16 => u16::from_ne_bytes(source[0..2].try_into().unwrap()) as u32,
            32 => u32::from_ne_bytes(source[0..4].try_into().unwrap()),
            _ => {
                unreachable!(
                    "unsupported packed bit size {}",
                    self.packed_size.unwrap()
                );
            },
        };

        for (i, part) in self.parts().iter().enumerate().rev() {
            let part_bits =
                packed_parts
                & (u32::MAX >> (u32::BITS - part.bits as u32));
            parts[i] = part.mode.load_packed_part(part_bits, part.bits);
            packed_parts >>= part.bits;
        }
    }

    pub fn load_pixel(&self, source: &[u8]) -> [f64; 4] {
        assert!(source.len() >= self.size());
        assert!(self.n_parts <= 4);

        let mut parts = [0.0; 4];

        match self.packed_size {
            Some(_) => self.load_packed_parts(source, &mut parts),
            None => {
                let mut source = source;

                for (i, part) in self.parts().iter().enumerate() {
                    parts[i] = part.mode.load_part(part.bits, source);
                    source = &source[part.bits / 8..];
                }
            },
        }

        // Set all the colour components to zero in case they aren’t
        // contained in the format. The alpha component default to 1.0
        // if it’s not in the format.
        let mut pixel = [0.0, 0.0, 0.0, 1.0];

        for (i, part) in self.parts().iter().enumerate() {
            match part.component {
                Component::R => pixel[0] = parts[i],
                Component::G => pixel[1] = parts[i],
                Component::B => pixel[2] = parts[i],
                Component::A => pixel[3] = parts[i],
                Component::D | Component::S | Component:: X => (),
            }
        }

        pixel
    }
}

fn sign_extend(part: u32, bits: usize) -> i32
{
    let uresult = if part & (1 << (bits - 1)) != 0 {
        ((u32::MAX) << bits) | part
    } else {
        part
    };

    uresult as i32
}

fn extract_u24(bytes: &[u8]) -> u32 {
    let mut value = 0;

    for i in 0..3 {
        let byte_pos;

        #[cfg(target_endian = "little")]
        {
            byte_pos = 2 - i;
        }
        #[cfg(not(target_endian = "little"))]
        {
            byte_pos = i;
        }

        value = ((value) << 8) | bytes[byte_pos] as u32;
    }

    value
}

#[cfg(test)]
mod test {
    use super::*;

    #[test]
    fn test_lookup_by_name() {
        // Test that we can find every name
        for format in FORMATS.iter() {
            let other_format = match Format::lookup_by_name(format.name) {
                Some(f) => f,
                None => unreachable!("lookup for {} failed", format.name),
            };

            // Assert that it returns a reference to the same object
            assert!(std::ptr::eq(format, other_format));
        }

        // Test that a similar name fails
        assert!(matches!(Format::lookup_by_name("B8G8R8_SRGBC"), None));
    }

    #[test]
    fn test_lookup_by_vk_format() {
        // Test that we can find every format
        for format in FORMATS.iter() {
            let other_format = Format::lookup_by_vk_format(format.vk_format);
            // Assert that it returns a reference to the same object
            assert!(std::ptr::eq(format, other_format));
        }
    }

    #[test]
    fn test_lookup_by_details() {
        let expected_format =
            Format::lookup_by_vk_format(vk::VK_FORMAT_R8G8B8_UNORM);
        assert_eq!(
            Format::lookup_by_details(8, Mode::UNORM, 3),
            Some(expected_format),
        );
        let expected_format =
            Format::lookup_by_vk_format(vk::VK_FORMAT_R64G64B64A64_SFLOAT);
        assert_eq!(
            Format::lookup_by_details(64, Mode::SFLOAT, 4),
            Some(expected_format),
        );
        assert_eq!(
            Format::lookup_by_details(64, Mode::UFLOAT, 4),
            None
        );
    }

    #[test]
    fn test_parts() {
        // Check that parts returns the right size slice for each type
        for format in FORMATS.iter() {
            assert_eq!(format.parts().len(), format.n_parts);
        }

        // Check some types
        assert_eq!(
            Format::lookup_by_vk_format(vk::VK_FORMAT_R8_UINT).parts(),
            &[Part { bits: 8, component: Component::R, mode: Mode::UINT }]
        );
        assert_eq!(
            Format::lookup_by_vk_format(vk::VK_FORMAT_B5G6R5_UNORM_PACK16)
                .parts(),
            &[
                Part { bits: 5, component: Component::B, mode: Mode::UNORM },
                Part { bits: 6, component: Component::G, mode: Mode::UNORM },
                Part { bits: 5, component: Component::R, mode: Mode::UNORM },
            ]
        );
    }

    #[test]
    fn test_size() {
        assert_eq!(
            Format::lookup_by_vk_format(vk::VK_FORMAT_B8G8R8_UINT).size(),
            3
        );
        assert_eq!(
            Format::lookup_by_vk_format(vk::VK_FORMAT_R16G16_SINT).size(),
            4
        );
        assert_eq!(
            Format::lookup_by_vk_format(vk::VK_FORMAT_B5G6R5_UNORM_PACK16)
                .size(),
            2
        );
    }

    #[test]
    fn test_sign_extend() {
        assert_eq!(sign_extend(0xff, 8), -1);
        assert_eq!(sign_extend(1, 8), 1);
    }

    fn assert_float_equal(a: f64, b: f64) {
        assert!((a - b).abs() < 0.01, "a={}, b={}", a, b);
    }

    #[test]
    fn test_load_packed_part() {
        // Test that there are no formats with unsupported packed modes
        for format in FORMATS.iter() {
            if let Some(_) = format.packed_size {
                for part in format.parts().iter() {
                    part.mode.load_packed_part(0, part.bits);
                }
            }
        }

        assert_float_equal(Mode::SRGB.load_packed_part(0x80, 8), 0.5);
        assert_float_equal(Mode::SNORM.load_packed_part(0x80, 8), -1.0);
        assert_float_equal(Mode::SNORM.load_packed_part(0x7f, 8), 1.0);
        assert_float_equal(Mode::UINT.load_packed_part(42, 8), 42.0);
        assert_float_equal(Mode::SINT.load_packed_part(0xff, 8), -1.0);
        assert_float_equal(Mode::UFLOAT.load_packed_part(0x1e0, 10), 1.0);
        assert_float_equal(Mode::UFLOAT.load_packed_part(0x3c0, 11), 1.0);
    }

    fn load_part(mode: Mode, bits: usize, fb_bytes: u64) -> f64 {
        let mut fb = Vec::new();
        let n_bytes = bits / 8;

        for i in 0..n_bytes {
            let byte_pos;

            #[cfg(target_endian = "little")]
            {
                byte_pos = i
            }
            #[cfg(not(target_endian = "little"))]
            {
                byte_pos = n_bytes - 1 - i
            }

            fb.push(((fb_bytes >> (byte_pos * 8)) & 0xff) as u8);
        }

        mode.load_part(bits, &fb)
    }

    #[test]
    fn test_load_part() {
        let dummy_array = [0u8; 8];

        // Test that there are no formats with unsupported unpacked modes
        for format in FORMATS.iter() {
            if let None = format.packed_size {
                for part in format.parts().iter() {
                    assert!(part.bits <= dummy_array.len() * 8);
                    part.mode.load_part(part.bits, &dummy_array);
                }
            }
        }

        assert_float_equal(load_part(Mode::UNORM, 8, 0x80), 0.5);
        assert_float_equal(load_part(Mode::UNORM, 16, 0x8000), 0.5);
        assert_float_equal(load_part(Mode::UNORM, 24, 0x800000), 0.5);
        assert_float_equal(load_part(Mode::UNORM, 32, 0x80000000), 0.5);
        assert_float_equal(load_part(Mode::UNORM, 64, 0x8000000000000000), 0.5);
        assert_float_equal(load_part(Mode::SNORM, 8, 0x81), -1.0);
        assert_float_equal(load_part(Mode::SNORM, 16, 0x8001), -1.0);
        assert_float_equal(load_part(Mode::SNORM, 32, 0x80000001), -1.0);
        assert_float_equal(
            load_part(Mode::SNORM, 64, 0x8000000000000001),
            -1.0
        );
        assert_float_equal(load_part(Mode::UINT, 8, 0x80), 128.0);
        assert_float_equal(load_part(Mode::UINT, 16, 0x8000), 32768.0);
        assert_float_equal(load_part(Mode::UINT, 32, 0x80000000), 2147483648.0);
        assert_float_equal(
            load_part(Mode::UINT, 64, 0x200000000),
            8589934592.0,
        );
        assert_float_equal(load_part(Mode::SINT, 8, 0x80), -128.0);
        assert_float_equal(load_part(Mode::SINT, 16, 0x8000), -32768.0);
        assert_float_equal(
            load_part(Mode::SINT, 32, 0x80000000),
            -2147483648.0
        );
        assert_float_equal(
            load_part(Mode::SINT, 64, u64::MAX),
            -1.0,
        );
        assert_float_equal(load_part(Mode::SFLOAT, 16, 0x3c00), 1.0);
        assert_float_equal(load_part(Mode::SFLOAT, 32, 0x3f800000), 1.0);
        assert_float_equal(
            load_part(Mode::SFLOAT, 64, 0xbfe0000000000000),
            -0.5
        );
    }

    #[test]
    fn test_load_pixel() {
        let dummy_source = [0u8; 32];

        // Test that the code handles every format
        for format in FORMATS.iter() {
            format.load_pixel(&dummy_source);
        }

        let source_data = [5.0f64, 4.0f64, -3.0f64, 0.5f64];
        let pixel: Vec<u8> = source_data
            .iter()
            .map(|v| v.to_ne_bytes())
            .flatten()
            .collect();
        let format =
            Format::lookup_by_vk_format(vk::VK_FORMAT_R64G64B64A64_SFLOAT);
        assert_eq!(format.load_pixel(&pixel), source_data);

        // Try a depth-stencil format. This should just return the
        // default rgb values.
        let format =
            Format::lookup_by_vk_format(vk::VK_FORMAT_D24_UNORM_S8_UINT);
        assert_eq!(format.load_pixel(&[0xff; 4]), [0.0, 0.0, 0.0, 1.0]);

        // Packed format
        let format =
            Format::lookup_by_vk_format(vk::VK_FORMAT_R5G6B5_UNORM_PACK16);
        let pixel = format.load_pixel(&0xae27u16.to_ne_bytes());
        let expected = [
            0b10101 as f64 / 0b11111 as f64,
            0b110001 as f64 / 0b111111 as f64,
            0b00111 as f64 / 0b11111 as f64,
            1.0,
        ];
        for (i, &pixel_comp) in pixel.iter().enumerate() {
            assert_float_equal(pixel_comp, expected[i]);
        }
    }

    #[test]
    fn test_alignment() {
        let format =
            Format::lookup_by_vk_format(vk::VK_FORMAT_R5G6B5_UNORM_PACK16);
        assert_eq!(format.alignment(), 2);

        let format =
            Format::lookup_by_vk_format(vk::VK_FORMAT_D24_UNORM_S8_UINT);
        assert_eq!(format.alignment(), 3);

        let format =
            Format::lookup_by_vk_format(vk::VK_FORMAT_R8G8B8_UNORM);
        assert_eq!(format.alignment(), 1);
    }
}

```

--------------------------------------------------------------------------------
/vkrunner/vkrunner/enum_table.rs:
--------------------------------------------------------------------------------

```rust
// Automatically generated by make-enums.py
static ENUM_VALUES: [EnumValue; 174] = [
    EnumValue {
        name: "VK_BLEND_FACTOR_CONSTANT_ALPHA",
        value: vk::VK_BLEND_FACTOR_CONSTANT_ALPHA as i32
    },
    EnumValue {
        name: "VK_BLEND_FACTOR_CONSTANT_COLOR",
        value: vk::VK_BLEND_FACTOR_CONSTANT_COLOR as i32
    },
    EnumValue {
        name: "VK_BLEND_FACTOR_DST_ALPHA",
        value: vk::VK_BLEND_FACTOR_DST_ALPHA as i32
    },
    EnumValue {
        name: "VK_BLEND_FACTOR_DST_COLOR",
        value: vk::VK_BLEND_FACTOR_DST_COLOR as i32
    },
    EnumValue {
        name: "VK_BLEND_FACTOR_MAX_ENUM",
        value: vk::VK_BLEND_FACTOR_MAX_ENUM as i32
    },
    EnumValue {
        name: "VK_BLEND_FACTOR_ONE",
        value: vk::VK_BLEND_FACTOR_ONE as i32
    },
    EnumValue {
        name: "VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA",
        value: vk::VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA as i32
    },
    EnumValue {
        name: "VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR",
        value: vk::VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR as i32
    },
    EnumValue {
        name: "VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA",
        value: vk::VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA as i32
    },
    EnumValue {
        name: "VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR",
        value: vk::VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR as i32
    },
    EnumValue {
        name: "VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA",
        value: vk::VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA as i32
    },
    EnumValue {
        name: "VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR",
        value: vk::VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR as i32
    },
    EnumValue {
        name: "VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA",
        value: vk::VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA as i32
    },
    EnumValue {
        name: "VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR",
        value: vk::VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR as i32
    },
    EnumValue {
        name: "VK_BLEND_FACTOR_SRC1_ALPHA",
        value: vk::VK_BLEND_FACTOR_SRC1_ALPHA as i32
    },
    EnumValue {
        name: "VK_BLEND_FACTOR_SRC1_COLOR",
        value: vk::VK_BLEND_FACTOR_SRC1_COLOR as i32
    },
    EnumValue {
        name: "VK_BLEND_FACTOR_SRC_ALPHA",
        value: vk::VK_BLEND_FACTOR_SRC_ALPHA as i32
    },
    EnumValue {
        name: "VK_BLEND_FACTOR_SRC_ALPHA_SATURATE",
        value: vk::VK_BLEND_FACTOR_SRC_ALPHA_SATURATE as i32
    },
    EnumValue {
        name: "VK_BLEND_FACTOR_SRC_COLOR",
        value: vk::VK_BLEND_FACTOR_SRC_COLOR as i32
    },
    EnumValue {
        name: "VK_BLEND_FACTOR_ZERO",
        value: vk::VK_BLEND_FACTOR_ZERO as i32
    },
    EnumValue {
        name: "VK_BLEND_OP_ADD",
        value: vk::VK_BLEND_OP_ADD as i32
    },
    EnumValue {
        name: "VK_BLEND_OP_BLUE_EXT",
        value: vk::VK_BLEND_OP_BLUE_EXT as i32
    },
    EnumValue {
        name: "VK_BLEND_OP_COLORBURN_EXT",
        value: vk::VK_BLEND_OP_COLORBURN_EXT as i32
    },
    EnumValue {
        name: "VK_BLEND_OP_COLORDODGE_EXT",
        value: vk::VK_BLEND_OP_COLORDODGE_EXT as i32
    },
    EnumValue {
        name: "VK_BLEND_OP_CONTRAST_EXT",
        value: vk::VK_BLEND_OP_CONTRAST_EXT as i32
    },
    EnumValue {
        name: "VK_BLEND_OP_DARKEN_EXT",
        value: vk::VK_BLEND_OP_DARKEN_EXT as i32
    },
    EnumValue {
        name: "VK_BLEND_OP_DIFFERENCE_EXT",
        value: vk::VK_BLEND_OP_DIFFERENCE_EXT as i32
    },
    EnumValue {
        name: "VK_BLEND_OP_DST_ATOP_EXT",
        value: vk::VK_BLEND_OP_DST_ATOP_EXT as i32
    },
    EnumValue {
        name: "VK_BLEND_OP_DST_EXT",
        value: vk::VK_BLEND_OP_DST_EXT as i32
    },
    EnumValue {
        name: "VK_BLEND_OP_DST_IN_EXT",
        value: vk::VK_BLEND_OP_DST_IN_EXT as i32
    },
    EnumValue {
        name: "VK_BLEND_OP_DST_OUT_EXT",
        value: vk::VK_BLEND_OP_DST_OUT_EXT as i32
    },
    EnumValue {
        name: "VK_BLEND_OP_DST_OVER_EXT",
        value: vk::VK_BLEND_OP_DST_OVER_EXT as i32
    },
    EnumValue {
        name: "VK_BLEND_OP_EXCLUSION_EXT",
        value: vk::VK_BLEND_OP_EXCLUSION_EXT as i32
    },
    EnumValue {
        name: "VK_BLEND_OP_GREEN_EXT",
        value: vk::VK_BLEND_OP_GREEN_EXT as i32
    },
    EnumValue {
        name: "VK_BLEND_OP_HARDLIGHT_EXT",
        value: vk::VK_BLEND_OP_HARDLIGHT_EXT as i32
    },
    EnumValue {
        name: "VK_BLEND_OP_HARDMIX_EXT",
        value: vk::VK_BLEND_OP_HARDMIX_EXT as i32
    },
    EnumValue {
        name: "VK_BLEND_OP_HSL_COLOR_EXT",
        value: vk::VK_BLEND_OP_HSL_COLOR_EXT as i32
    },
    EnumValue {
        name: "VK_BLEND_OP_HSL_HUE_EXT",
        value: vk::VK_BLEND_OP_HSL_HUE_EXT as i32
    },
    EnumValue {
        name: "VK_BLEND_OP_HSL_LUMINOSITY_EXT",
        value: vk::VK_BLEND_OP_HSL_LUMINOSITY_EXT as i32
    },
    EnumValue {
        name: "VK_BLEND_OP_HSL_SATURATION_EXT",
        value: vk::VK_BLEND_OP_HSL_SATURATION_EXT as i32
    },
    EnumValue {
        name: "VK_BLEND_OP_INVERT_EXT",
        value: vk::VK_BLEND_OP_INVERT_EXT as i32
    },
    EnumValue {
        name: "VK_BLEND_OP_INVERT_OVG_EXT",
        value: vk::VK_BLEND_OP_INVERT_OVG_EXT as i32
    },
    EnumValue {
        name: "VK_BLEND_OP_INVERT_RGB_EXT",
        value: vk::VK_BLEND_OP_INVERT_RGB_EXT as i32
    },
    EnumValue {
        name: "VK_BLEND_OP_LIGHTEN_EXT",
        value: vk::VK_BLEND_OP_LIGHTEN_EXT as i32
    },
    EnumValue {
        name: "VK_BLEND_OP_LINEARBURN_EXT",
        value: vk::VK_BLEND_OP_LINEARBURN_EXT as i32
    },
    EnumValue {
        name: "VK_BLEND_OP_LINEARDODGE_EXT",
        value: vk::VK_BLEND_OP_LINEARDODGE_EXT as i32
    },
    EnumValue {
        name: "VK_BLEND_OP_LINEARLIGHT_EXT",
        value: vk::VK_BLEND_OP_LINEARLIGHT_EXT as i32
    },
    EnumValue {
        name: "VK_BLEND_OP_MAX",
        value: vk::VK_BLEND_OP_MAX as i32
    },
    EnumValue {
        name: "VK_BLEND_OP_MAX_ENUM",
        value: vk::VK_BLEND_OP_MAX_ENUM as i32
    },
    EnumValue {
        name: "VK_BLEND_OP_MIN",
        value: vk::VK_BLEND_OP_MIN as i32
    },
    EnumValue {
        name: "VK_BLEND_OP_MINUS_CLAMPED_EXT",
        value: vk::VK_BLEND_OP_MINUS_CLAMPED_EXT as i32
    },
    EnumValue {
        name: "VK_BLEND_OP_MINUS_EXT",
        value: vk::VK_BLEND_OP_MINUS_EXT as i32
    },
    EnumValue {
        name: "VK_BLEND_OP_MULTIPLY_EXT",
        value: vk::VK_BLEND_OP_MULTIPLY_EXT as i32
    },
    EnumValue {
        name: "VK_BLEND_OP_OVERLAY_EXT",
        value: vk::VK_BLEND_OP_OVERLAY_EXT as i32
    },
    EnumValue {
        name: "VK_BLEND_OP_PINLIGHT_EXT",
        value: vk::VK_BLEND_OP_PINLIGHT_EXT as i32
    },
    EnumValue {
        name: "VK_BLEND_OP_PLUS_CLAMPED_ALPHA_EXT",
        value: vk::VK_BLEND_OP_PLUS_CLAMPED_ALPHA_EXT as i32
    },
    EnumValue {
        name: "VK_BLEND_OP_PLUS_CLAMPED_EXT",
        value: vk::VK_BLEND_OP_PLUS_CLAMPED_EXT as i32
    },
    EnumValue {
        name: "VK_BLEND_OP_PLUS_DARKER_EXT",
        value: vk::VK_BLEND_OP_PLUS_DARKER_EXT as i32
    },
    EnumValue {
        name: "VK_BLEND_OP_PLUS_EXT",
        value: vk::VK_BLEND_OP_PLUS_EXT as i32
    },
    EnumValue {
        name: "VK_BLEND_OP_RED_EXT",
        value: vk::VK_BLEND_OP_RED_EXT as i32
    },
    EnumValue {
        name: "VK_BLEND_OP_REVERSE_SUBTRACT",
        value: vk::VK_BLEND_OP_REVERSE_SUBTRACT as i32
    },
    EnumValue {
        name: "VK_BLEND_OP_SCREEN_EXT",
        value: vk::VK_BLEND_OP_SCREEN_EXT as i32
    },
    EnumValue {
        name: "VK_BLEND_OP_SOFTLIGHT_EXT",
        value: vk::VK_BLEND_OP_SOFTLIGHT_EXT as i32
    },
    EnumValue {
        name: "VK_BLEND_OP_SRC_ATOP_EXT",
        value: vk::VK_BLEND_OP_SRC_ATOP_EXT as i32
    },
    EnumValue {
        name: "VK_BLEND_OP_SRC_EXT",
        value: vk::VK_BLEND_OP_SRC_EXT as i32
    },
    EnumValue {
        name: "VK_BLEND_OP_SRC_IN_EXT",
        value: vk::VK_BLEND_OP_SRC_IN_EXT as i32
    },
    EnumValue {
        name: "VK_BLEND_OP_SRC_OUT_EXT",
        value: vk::VK_BLEND_OP_SRC_OUT_EXT as i32
    },
    EnumValue {
        name: "VK_BLEND_OP_SRC_OVER_EXT",
        value: vk::VK_BLEND_OP_SRC_OVER_EXT as i32
    },
    EnumValue {
        name: "VK_BLEND_OP_SUBTRACT",
        value: vk::VK_BLEND_OP_SUBTRACT as i32
    },
    EnumValue {
        name: "VK_BLEND_OP_VIVIDLIGHT_EXT",
        value: vk::VK_BLEND_OP_VIVIDLIGHT_EXT as i32
    },
    EnumValue {
        name: "VK_BLEND_OP_XOR_EXT",
        value: vk::VK_BLEND_OP_XOR_EXT as i32
    },
    EnumValue {
        name: "VK_BLEND_OP_ZERO_EXT",
        value: vk::VK_BLEND_OP_ZERO_EXT as i32
    },
    EnumValue {
        name: "VK_COLOR_COMPONENT_A_BIT",
        value: vk::VK_COLOR_COMPONENT_A_BIT as i32
    },
    EnumValue {
        name: "VK_COLOR_COMPONENT_B_BIT",
        value: vk::VK_COLOR_COMPONENT_B_BIT as i32
    },
    EnumValue {
        name: "VK_COLOR_COMPONENT_FLAG_BITS_MAX_ENUM",
        value: vk::VK_COLOR_COMPONENT_FLAG_BITS_MAX_ENUM as i32
    },
    EnumValue {
        name: "VK_COLOR_COMPONENT_G_BIT",
        value: vk::VK_COLOR_COMPONENT_G_BIT as i32
    },
    EnumValue {
        name: "VK_COLOR_COMPONENT_R_BIT",
        value: vk::VK_COLOR_COMPONENT_R_BIT as i32
    },
    EnumValue {
        name: "VK_COMPARE_OP_ALWAYS",
        value: vk::VK_COMPARE_OP_ALWAYS as i32
    },
    EnumValue {
        name: "VK_COMPARE_OP_EQUAL",
        value: vk::VK_COMPARE_OP_EQUAL as i32
    },
    EnumValue {
        name: "VK_COMPARE_OP_GREATER",
        value: vk::VK_COMPARE_OP_GREATER as i32
    },
    EnumValue {
        name: "VK_COMPARE_OP_GREATER_OR_EQUAL",
        value: vk::VK_COMPARE_OP_GREATER_OR_EQUAL as i32
    },
    EnumValue {
        name: "VK_COMPARE_OP_LESS",
        value: vk::VK_COMPARE_OP_LESS as i32
    },
    EnumValue {
        name: "VK_COMPARE_OP_LESS_OR_EQUAL",
        value: vk::VK_COMPARE_OP_LESS_OR_EQUAL as i32
    },
    EnumValue {
        name: "VK_COMPARE_OP_MAX_ENUM",
        value: vk::VK_COMPARE_OP_MAX_ENUM as i32
    },
    EnumValue {
        name: "VK_COMPARE_OP_NEVER",
        value: vk::VK_COMPARE_OP_NEVER as i32
    },
    EnumValue {
        name: "VK_COMPARE_OP_NOT_EQUAL",
        value: vk::VK_COMPARE_OP_NOT_EQUAL as i32
    },
    EnumValue {
        name: "VK_COMPONENT_TYPE_BFLOAT16_KHR",
        value: vk::VK_COMPONENT_TYPE_BFLOAT16_KHR as i32
    },
    EnumValue {
        name: "VK_COMPONENT_TYPE_FLOAT16_KHR",
        value: vk::VK_COMPONENT_TYPE_FLOAT16_KHR as i32
    },
    EnumValue {
        name: "VK_COMPONENT_TYPE_FLOAT16_NV",
        value: vk::VK_COMPONENT_TYPE_FLOAT16_NV as i32
    },
    EnumValue {
        name: "VK_COMPONENT_TYPE_FLOAT32_KHR",
        value: vk::VK_COMPONENT_TYPE_FLOAT32_KHR as i32
    },
    EnumValue {
        name: "VK_COMPONENT_TYPE_FLOAT32_NV",
        value: vk::VK_COMPONENT_TYPE_FLOAT32_NV as i32
    },
    EnumValue {
        name: "VK_COMPONENT_TYPE_FLOAT64_KHR",
        value: vk::VK_COMPONENT_TYPE_FLOAT64_KHR as i32
    },
    EnumValue {
        name: "VK_COMPONENT_TYPE_FLOAT64_NV",
        value: vk::VK_COMPONENT_TYPE_FLOAT64_NV as i32
    },
    EnumValue {
        name: "VK_COMPONENT_TYPE_FLOAT_E4M3_NV",
        value: vk::VK_COMPONENT_TYPE_FLOAT_E4M3_NV as i32
    },
    EnumValue {
        name: "VK_COMPONENT_TYPE_FLOAT_E5M2_NV",
        value: vk::VK_COMPONENT_TYPE_FLOAT_E5M2_NV as i32
    },
    EnumValue {
        name: "VK_COMPONENT_TYPE_MAX_ENUM_KHR",
        value: vk::VK_COMPONENT_TYPE_MAX_ENUM_KHR as i32
    },
    EnumValue {
        name: "VK_COMPONENT_TYPE_SINT16_KHR",
        value: vk::VK_COMPONENT_TYPE_SINT16_KHR as i32
    },
    EnumValue {
        name: "VK_COMPONENT_TYPE_SINT16_NV",
        value: vk::VK_COMPONENT_TYPE_SINT16_NV as i32
    },
    EnumValue {
        name: "VK_COMPONENT_TYPE_SINT32_KHR",
        value: vk::VK_COMPONENT_TYPE_SINT32_KHR as i32
    },
    EnumValue {
        name: "VK_COMPONENT_TYPE_SINT32_NV",
        value: vk::VK_COMPONENT_TYPE_SINT32_NV as i32
    },
    EnumValue {
        name: "VK_COMPONENT_TYPE_SINT64_KHR",
        value: vk::VK_COMPONENT_TYPE_SINT64_KHR as i32
    },
    EnumValue {
        name: "VK_COMPONENT_TYPE_SINT64_NV",
        value: vk::VK_COMPONENT_TYPE_SINT64_NV as i32
    },
    EnumValue {
        name: "VK_COMPONENT_TYPE_SINT8_KHR",
        value: vk::VK_COMPONENT_TYPE_SINT8_KHR as i32
    },
    EnumValue {
        name: "VK_COMPONENT_TYPE_SINT8_NV",
        value: vk::VK_COMPONENT_TYPE_SINT8_NV as i32
    },
    EnumValue {
        name: "VK_COMPONENT_TYPE_SINT8_PACKED_NV",
        value: vk::VK_COMPONENT_TYPE_SINT8_PACKED_NV as i32
    },
    EnumValue {
        name: "VK_COMPONENT_TYPE_UINT16_KHR",
        value: vk::VK_COMPONENT_TYPE_UINT16_KHR as i32
    },
    EnumValue {
        name: "VK_COMPONENT_TYPE_UINT16_NV",
        value: vk::VK_COMPONENT_TYPE_UINT16_NV as i32
    },
    EnumValue {
        name: "VK_COMPONENT_TYPE_UINT32_KHR",
        value: vk::VK_COMPONENT_TYPE_UINT32_KHR as i32
    },
    EnumValue {
        name: "VK_COMPONENT_TYPE_UINT32_NV",
        value: vk::VK_COMPONENT_TYPE_UINT32_NV as i32
    },
    EnumValue {
        name: "VK_COMPONENT_TYPE_UINT64_KHR",
        value: vk::VK_COMPONENT_TYPE_UINT64_KHR as i32
    },
    EnumValue {
        name: "VK_COMPONENT_TYPE_UINT64_NV",
        value: vk::VK_COMPONENT_TYPE_UINT64_NV as i32
    },
    EnumValue {
        name: "VK_COMPONENT_TYPE_UINT8_KHR",
        value: vk::VK_COMPONENT_TYPE_UINT8_KHR as i32
    },
    EnumValue {
        name: "VK_COMPONENT_TYPE_UINT8_NV",
        value: vk::VK_COMPONENT_TYPE_UINT8_NV as i32
    },
    EnumValue {
        name: "VK_COMPONENT_TYPE_UINT8_PACKED_NV",
        value: vk::VK_COMPONENT_TYPE_UINT8_PACKED_NV as i32
    },
    EnumValue {
        name: "VK_CULL_MODE_BACK_BIT",
        value: vk::VK_CULL_MODE_BACK_BIT as i32
    },
    EnumValue {
        name: "VK_CULL_MODE_FLAG_BITS_MAX_ENUM",
        value: vk::VK_CULL_MODE_FLAG_BITS_MAX_ENUM as i32
    },
    EnumValue {
        name: "VK_CULL_MODE_FRONT_AND_BACK",
        value: vk::VK_CULL_MODE_FRONT_AND_BACK as i32
    },
    EnumValue {
        name: "VK_CULL_MODE_FRONT_BIT",
        value: vk::VK_CULL_MODE_FRONT_BIT as i32
    },
    EnumValue {
        name: "VK_CULL_MODE_NONE",
        value: vk::VK_CULL_MODE_NONE as i32
    },
    EnumValue {
        name: "VK_FRONT_FACE_CLOCKWISE",
        value: vk::VK_FRONT_FACE_CLOCKWISE as i32
    },
    EnumValue {
        name: "VK_FRONT_FACE_COUNTER_CLOCKWISE",
        value: vk::VK_FRONT_FACE_COUNTER_CLOCKWISE as i32
    },
    EnumValue {
        name: "VK_FRONT_FACE_MAX_ENUM",
        value: vk::VK_FRONT_FACE_MAX_ENUM as i32
    },
    EnumValue {
        name: "VK_LOGIC_OP_AND",
        value: vk::VK_LOGIC_OP_AND as i32
    },
    EnumValue {
        name: "VK_LOGIC_OP_AND_INVERTED",
        value: vk::VK_LOGIC_OP_AND_INVERTED as i32
    },
    EnumValue {
        name: "VK_LOGIC_OP_AND_REVERSE",
        value: vk::VK_LOGIC_OP_AND_REVERSE as i32
    },
    EnumValue {
        name: "VK_LOGIC_OP_CLEAR",
        value: vk::VK_LOGIC_OP_CLEAR as i32
    },
    EnumValue {
        name: "VK_LOGIC_OP_COPY",
        value: vk::VK_LOGIC_OP_COPY as i32
    },
    EnumValue {
        name: "VK_LOGIC_OP_COPY_INVERTED",
        value: vk::VK_LOGIC_OP_COPY_INVERTED as i32
    },
    EnumValue {
        name: "VK_LOGIC_OP_EQUIVALENT",
        value: vk::VK_LOGIC_OP_EQUIVALENT as i32
    },
    EnumValue {
        name: "VK_LOGIC_OP_INVERT",
        value: vk::VK_LOGIC_OP_INVERT as i32
    },
    EnumValue {
        name: "VK_LOGIC_OP_MAX_ENUM",
        value: vk::VK_LOGIC_OP_MAX_ENUM as i32
    },
    EnumValue {
        name: "VK_LOGIC_OP_NAND",
        value: vk::VK_LOGIC_OP_NAND as i32
    },
    EnumValue {
        name: "VK_LOGIC_OP_NOR",
        value: vk::VK_LOGIC_OP_NOR as i32
    },
    EnumValue {
        name: "VK_LOGIC_OP_NO_OP",
        value: vk::VK_LOGIC_OP_NO_OP as i32
    },
    EnumValue {
        name: "VK_LOGIC_OP_OR",
        value: vk::VK_LOGIC_OP_OR as i32
    },
    EnumValue {
        name: "VK_LOGIC_OP_OR_INVERTED",
        value: vk::VK_LOGIC_OP_OR_INVERTED as i32
    },
    EnumValue {
        name: "VK_LOGIC_OP_OR_REVERSE",
        value: vk::VK_LOGIC_OP_OR_REVERSE as i32
    },
    EnumValue {
        name: "VK_LOGIC_OP_SET",
        value: vk::VK_LOGIC_OP_SET as i32
    },
    EnumValue {
        name: "VK_LOGIC_OP_XOR",
        value: vk::VK_LOGIC_OP_XOR as i32
    },
    EnumValue {
        name: "VK_POLYGON_MODE_FILL",
        value: vk::VK_POLYGON_MODE_FILL as i32
    },
    EnumValue {
        name: "VK_POLYGON_MODE_FILL_RECTANGLE_NV",
        value: vk::VK_POLYGON_MODE_FILL_RECTANGLE_NV as i32
    },
    EnumValue {
        name: "VK_POLYGON_MODE_LINE",
        value: vk::VK_POLYGON_MODE_LINE as i32
    },
    EnumValue {
        name: "VK_POLYGON_MODE_MAX_ENUM",
        value: vk::VK_POLYGON_MODE_MAX_ENUM as i32
    },
    EnumValue {
        name: "VK_POLYGON_MODE_POINT",
        value: vk::VK_POLYGON_MODE_POINT as i32
    },
    EnumValue {
        name: "VK_PRIMITIVE_TOPOLOGY_LINE_LIST",
        value: vk::VK_PRIMITIVE_TOPOLOGY_LINE_LIST as i32
    },
    EnumValue {
        name: "VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY",
        value: vk::VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY as i32
    },
    EnumValue {
        name: "VK_PRIMITIVE_TOPOLOGY_LINE_STRIP",
        value: vk::VK_PRIMITIVE_TOPOLOGY_LINE_STRIP as i32
    },
    EnumValue {
        name: "VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY",
        value: vk::VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY as i32
    },
    EnumValue {
        name: "VK_PRIMITIVE_TOPOLOGY_MAX_ENUM",
        value: vk::VK_PRIMITIVE_TOPOLOGY_MAX_ENUM as i32
    },
    EnumValue {
        name: "VK_PRIMITIVE_TOPOLOGY_PATCH_LIST",
        value: vk::VK_PRIMITIVE_TOPOLOGY_PATCH_LIST as i32
    },
    EnumValue {
        name: "VK_PRIMITIVE_TOPOLOGY_POINT_LIST",
        value: vk::VK_PRIMITIVE_TOPOLOGY_POINT_LIST as i32
    },
    EnumValue {
        name: "VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN",
        value: vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN as i32
    },
    EnumValue {
        name: "VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST",
        value: vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST as i32
    },
    EnumValue {
        name: "VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY",
        value: vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY as i32
    },
    EnumValue {
        name: "VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP",
        value: vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP as i32
    },
    EnumValue {
        name: "VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY",
        value: vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY as i32
    },
    EnumValue {
        name: "VK_SCOPE_DEVICE_KHR",
        value: vk::VK_SCOPE_DEVICE_KHR as i32
    },
    EnumValue {
        name: "VK_SCOPE_DEVICE_NV",
        value: vk::VK_SCOPE_DEVICE_NV as i32
    },
    EnumValue {
        name: "VK_SCOPE_MAX_ENUM_KHR",
        value: vk::VK_SCOPE_MAX_ENUM_KHR as i32
    },
    EnumValue {
        name: "VK_SCOPE_QUEUE_FAMILY_KHR",
        value: vk::VK_SCOPE_QUEUE_FAMILY_KHR as i32
    },
    EnumValue {
        name: "VK_SCOPE_QUEUE_FAMILY_NV",
        value: vk::VK_SCOPE_QUEUE_FAMILY_NV as i32
    },
    EnumValue {
        name: "VK_SCOPE_SUBGROUP_KHR",
        value: vk::VK_SCOPE_SUBGROUP_KHR as i32
    },
    EnumValue {
        name: "VK_SCOPE_SUBGROUP_NV",
        value: vk::VK_SCOPE_SUBGROUP_NV as i32
    },
    EnumValue {
        name: "VK_SCOPE_WORKGROUP_KHR",
        value: vk::VK_SCOPE_WORKGROUP_KHR as i32
    },
    EnumValue {
        name: "VK_SCOPE_WORKGROUP_NV",
        value: vk::VK_SCOPE_WORKGROUP_NV as i32
    },
    EnumValue {
        name: "VK_STENCIL_OP_DECREMENT_AND_CLAMP",
        value: vk::VK_STENCIL_OP_DECREMENT_AND_CLAMP as i32
    },
    EnumValue {
        name: "VK_STENCIL_OP_DECREMENT_AND_WRAP",
        value: vk::VK_STENCIL_OP_DECREMENT_AND_WRAP as i32
    },
    EnumValue {
        name: "VK_STENCIL_OP_INCREMENT_AND_CLAMP",
        value: vk::VK_STENCIL_OP_INCREMENT_AND_CLAMP as i32
    },
    EnumValue {
        name: "VK_STENCIL_OP_INCREMENT_AND_WRAP",
        value: vk::VK_STENCIL_OP_INCREMENT_AND_WRAP as i32
    },
    EnumValue {
        name: "VK_STENCIL_OP_INVERT",
        value: vk::VK_STENCIL_OP_INVERT as i32
    },
    EnumValue {
        name: "VK_STENCIL_OP_KEEP",
        value: vk::VK_STENCIL_OP_KEEP as i32
    },
    EnumValue {
        name: "VK_STENCIL_OP_MAX_ENUM",
        value: vk::VK_STENCIL_OP_MAX_ENUM as i32
    },
    EnumValue {
        name: "VK_STENCIL_OP_REPLACE",
        value: vk::VK_STENCIL_OP_REPLACE as i32
    },
    EnumValue {
        name: "VK_STENCIL_OP_ZERO",
        value: vk::VK_STENCIL_OP_ZERO as i32
    },
];

```
Page 2/7FirstPrevNextLast