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
},
];
```