From 542439c351538f0d54e6bbf9a7d450042f03c980 Mon Sep 17 00:00:00 2001 From: polymonster Date: Mon, 3 Nov 2025 18:57:59 +0000 Subject: [PATCH 01/62] - macos compiling and shader building with metal backend --- .cargo/config.toml | 4 ++ .vscode/launch.json | 12 ++++++ config.jsn | 34 +++++++++------ config.toml | 2 - examples/bindless/main.rs | 4 +- src/gfx.rs | 54 ++++++++++++------------ src/gfx/mtl.rs | 89 ++++++++++++++++++++++++++------------- src/lib.rs | 2 +- 8 files changed, 129 insertions(+), 72 deletions(-) create mode 100644 .cargo/config.toml delete mode 100644 config.toml diff --git a/.cargo/config.toml b/.cargo/config.toml new file mode 100644 index 00000000..301ac966 --- /dev/null +++ b/.cargo/config.toml @@ -0,0 +1,4 @@ +[build] +rustflags = ["-A unused"] + +# "-C", "link-arg=-fuse-ld=lld", \ No newline at end of file diff --git a/.vscode/launch.json b/.vscode/launch.json index 361f8458..99f74520 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -88,6 +88,18 @@ "console": "externalTerminal", "preLaunchTask": "examples" }, + { + "name": "bindful (macOS|Debug)", + "type": "lldb", + "request": "launch", + "program": "${workspaceFolder}/target/debug/examples/bindful", + "args": [], + "stopAtEntry": false, + // "cwd": "${fileDirname}", + "environment": [], + "console": "externalTerminal", + // "preLaunchTask": "examples" + }, { "name": "imgui_demo (Win32|Debug)", "type": "cppvsdbg", diff --git a/config.jsn b/config.jsn index f86f9054..d0b5a8ee 100644 --- a/config.jsn +++ b/config.jsn @@ -6,6 +6,10 @@ pmfx_dev: "py -3 ../pmfx-shader/pmfx.py" } + tools: { + pmfx_dev: "python3 ../pmfx-shader/pmfx.py" + } + tools_help: { pmfx: { help_arg: "-help" @@ -15,7 +19,7 @@ } pmfx_dev(pmfx): {} } - + tools_update: { pmfx: { tag_name: latest @@ -144,21 +148,27 @@ } } - rt_shaders: { - jsn_vars: { - output_dir: "target/data/shaders" - } - shell: { - commands: [ - "hotline-data\\bin\\win32\\pmfx\\bin\\dxc\\dxc.exe -T lib_6_3 -E MyRaygenShader -Fo ${output_dir}/raygen.cso -I . shaders/raytracing_example.hlsl" - "hotline-data\\bin\\win32\\pmfx\\bin\\dxc\\dxc.exe -T lib_6_3 -E MyClosestHitShader -Fo ${output_dir}/closesthit.cso -I . shaders/raytracing_example.hlsl" - "hotline-data\\bin\\win32\\pmfx\\bin\\dxc\\dxc.exe -T lib_6_3 -E MyMissShader -Fo ${output_dir}/miss.cso -I . shaders/raytracing_example.hlsl" - "hotline-data\\bin\\win32\\pmfx\\bin\\dxc\\dxc.exe -T lib_6_3 -Fo ${output_dir}/lib.cso -I . shaders/raytracing_example.hlsl" + mac-data(base): { + pmfx_dev: { + explicit: true + args: [ + "-shader_platform metal" + "-shader_version 6_0" + "-metal_version 2.3" + "-metal_sdk macosx" + "-discrete_binding 0" + "-discrete_binding 1" + "-i ${src_shader_dir}" + "-o ${data_dir}/shaders" + "-t ${temp_dir}/shaders" + "-num_threads 1" + "-f" + "-args" + "-Zpr" ] } } - // win32 debug client, plugins and data win32-debug(win32-data, hotline): { copy: { diff --git a/config.toml b/config.toml deleted file mode 100644 index 678266e5..00000000 --- a/config.toml +++ /dev/null @@ -1,2 +0,0 @@ -[build] -rustflags = ["-C", "link-arg=-fuse-ld=lld"] \ No newline at end of file diff --git a/examples/bindless/main.rs b/examples/bindless/main.rs index a80b8bb0..5dc4c87a 100644 --- a/examples/bindless/main.rs +++ b/examples/bindless/main.rs @@ -198,9 +198,10 @@ fn main() -> Result<(), hotline_rs::Error> { swap_chain.update::(&mut dev, &win, &mut cmdbuffer); cmdbuffer.reset(&swap_chain); + /* // compute pass cmdbuffer.set_marker(0xff00ffff, "Frame Start"); - + cmdbuffer.begin_event(0xff0000ff, "Compute Pass"); cmdbuffer.set_compute_pipeline(pso_compute); cmdbuffer.set_heap(pso_compute, dev.get_shader_heap()); @@ -237,6 +238,7 @@ fn main() -> Result<(), hotline_rs::Error> { state_after: gfx::ResourceState::ShaderResource, }); cmdbuffer.end_event(); + */ // main pass cmdbuffer.begin_event(0xff0000ff, "Main Pass"); diff --git a/src/gfx.rs b/src/gfx.rs index e66762c6..437d4fe5 100644 --- a/src/gfx.rs +++ b/src/gfx.rs @@ -5,14 +5,16 @@ pub mod null; #[cfg(target_os = "windows")] pub mod d3d12; +/// Implemets this interface with a metal backend. +#[cfg(target_os = "macos")] +pub mod mtl; + use crate::os; use std::any::Any; use serde::{Deserialize, Serialize}; use std::hash::Hash; use maths_rs::max; -use null::*; - type Error = super::Error; /// Macro to pass data!\[expression\] or data!\[\] (None) to a create function, so you don't have to deduce a 'T'. @@ -237,7 +239,7 @@ pub struct PipelineStatistics { /// Information to pass to `Device::create_swap_chain`. pub struct SwapChainInfo { - /// Number of internal buffers to keep behind the scenes, which are swapped between each frame + /// Number of internal buffers to keep behind the scenes, which are swapped between each frame /// to allow overlapped CPU/GPU command buffer producer / consumer pub num_buffers: u32, /// Must be BGRA8n, RGBA8n or RGBA16f. @@ -419,7 +421,7 @@ pub struct PipelineLayout { pub bindings: Option>, /// Small amounts of data that can be pushed into a command buffer and available as data in shaders pub push_constants: Option>, - /// Static samplers that come along with the pipeline, + /// Static samplers that come along with the pipeline, pub static_samplers: Option>, } @@ -479,7 +481,7 @@ pub struct ResourceViewInfo { pub num_elements: usize } -/// Describes space in the shader to send data to via `CmdBuf::push_constants`. +/// Describes space in the shader to send data to via `CmdBuf::push_constants`. #[derive(Clone, Serialize, Deserialize)] pub struct PushConstantInfo { /// The shader stage the constants will be accessible to. @@ -1005,7 +1007,7 @@ pub enum ResourceState { CopyDst, /// Used as destination to read back data from buffers / queries GenericRead, - /// Used for argument buffer in `execute_indirect` calls + /// Used for argument buffer in `execute_indirect` calls IndirectArgument, /// Used for destination acceleration structure buffers AccelerationStructure @@ -1077,7 +1079,7 @@ pub trait Pipeline { /// Returns the `PipelineSlotInfo` of which slot to bind a heap to based on the reequested `register` and `descriptor_type` /// if `None` is returned the pipeline does not contain bindings for the requested information fn get_pipeline_slot(&self, register: u32, space: u32, descriptor_type: DescriptorType) -> Option<&PipelineSlotInfo>; - /// Returns a vec of all pipeline slot indices + /// Returns a vec of all pipeline slot indices fn get_pipeline_slots(&self) -> &Vec; /// Returns the pipeline type fn get_pipeline_type() -> PipelineType; @@ -1144,7 +1146,7 @@ pub struct IndirectArgument { pub arguments: Option } -/// Structure of arguments which can be used to execute `draw_instanced` calls indirectly +/// Structure of arguments which can be used to execute `draw_instanced` calls indirectly #[repr(C)] #[derive(Clone, Copy)] pub struct DrawArguments { @@ -1154,7 +1156,7 @@ pub struct DrawArguments { pub start_instance_location: u32 } -/// Structure of arguments which can be used to execute `draw_indexed_instanced` calls indirectly +/// Structure of arguments which can be used to execute `draw_indexed_instanced` calls indirectly #[repr(C)] #[derive(Clone, Copy)] pub struct DrawIndexedArguments { @@ -1240,7 +1242,7 @@ pub trait Device: 'static + Send + Sync + Sized + Any + Clone { window: &A::Window, ) -> Result; /// Create a new `CmdBuf` with `num_buffers` internal buffers, the buffers can be swapped and syncronised - /// with a new `SwapChain` to allow in-flight gpu/cpu overlapped prodicer consumers + /// with a new `SwapChain` to allow in-flight gpu/cpu overlapped prodicer consumers fn create_cmd_buf(&self, num_buffers: u32) -> Self::CmdBuf; /// Create a new `Shader` from `ShaderInfo` fn create_shader(&self, info: &ShaderInfo, src: &[T]) -> Result; @@ -1333,7 +1335,7 @@ pub trait Device: 'static + Send + Sync + Sized + Any + Clone { ) -> Result; /// Create a command signature for `execute_indirect` commands associated on the `RenderPipeline` fn create_indirect_render_command( - &mut self, + &mut self, arguments: Vec, pipeline: Option<&Self::RenderPipeline> ) -> Result; @@ -1356,7 +1358,7 @@ pub trait Device: 'static + Send + Sync + Sized + Any + Clone { /// Read back u64 timestamp values as values in seconds, the vector will be empty if the buffer is yet to be written /// on the GPU fn read_timestamps(&self, swap_chain: &Self::SwapChain, buffer: &Self::Buffer, size_bytes: usize, frame_written_fence: u64) -> Vec; - /// Read back a single pipeline statistics query, assuming `buffer` was created with `create_read_back_buffer` + /// Read back a single pipeline statistics query, assuming `buffer` was created with `create_read_back_buffer` /// and is of size `get_pipeline_statistics_size_bytes()`. None is returned if the buffer is not ready fn read_pipeline_statistics(&self, swap_chain: &Self::SwapChain, buffer: &Self::Buffer, frame_written_fence: u64) -> Option; /// Reorts internal graphics api backend resources @@ -1402,7 +1404,7 @@ pub trait SwapChain: 'static + Sized + Any + Send + Sync + Clone { /// Call swap at the end of the frame to swap the back buffer, we rotate through n-buffers fn swap(&mut self, device: &D); } - + /// Responsible for buffering graphics commands. Internally it will contain a platform specific /// command list for each buffer in the associated swap chain. /// At the start of each frame `reset` must be called with an associated swap chain to internally switch @@ -1412,10 +1414,10 @@ pub trait CmdBuf: Send + Sync + Clone { /// Reset the `CmdBuf` for use on a new frame, it will be syncronised with the `SwapChain` so that /// in-flight command buffers are not overwritten fn reset(&mut self, swap_chain: &D::SwapChain); - /// Call close to the command buffer after all commands have been added and before passing to `Device::execute` + /// Call close to the command buffer after all commands have been added and before passing to `Device::execute` fn close(&mut self) -> Result<(), Error>; /// Internally the `CmdBuf` contains a set of buffers which it rotates through to allow inflight operations - /// to complete, this value indicates the buffer number you should `write` to during the current frame + /// to complete, this value indicates the buffer number you should `write` to during the current frame fn get_backbuffer_index(&self) -> u32; /// Begins a render pass, end must be called fn begin_render_pass(&mut self, render_pass: &D::RenderPass); @@ -1432,7 +1434,7 @@ pub trait CmdBuf: Send + Sync + Clone { fn timestamp_query(&mut self, heap: &mut D::QueryHeap, resolve_buffer: &mut D::Buffer); /// Begin a new query in the heap, it will allocate an index which is returned as `usize` fn begin_query(&mut self, heap: &mut D::QueryHeap, query_type: QueryType) -> usize; - /// End a query that was made on the heap results will be pushed into the `resolve_buffer` + /// End a query that was made on the heap results will be pushed into the `resolve_buffer` /// the data can be read by `Device::read_buffer` or specialisations such as `read_pipeline_statistics` fn end_query(&mut self, heap: &mut D::QueryHeap, query_type: QueryType, index: usize, resolve_buffer: &mut D::Buffer); /// Add a transition barrier for resources to change states based on info supplied in `TransitionBarrier` @@ -1486,9 +1488,9 @@ pub trait CmdBuf: Send + Sync + Clone { /// Issue indirect commands with signature created from `create_indirect_render_command` fn execute_indirect( &mut self, - command: &D::CommandSignature, - max_command_count: u32, - argument_buffer: &D::Buffer, + command: &D::CommandSignature, + max_command_count: u32, + argument_buffer: &D::Buffer, argument_buffer_offset: usize, counter_buffer: Option<&D::Buffer>, counter_buffer_offset: usize @@ -1499,21 +1501,21 @@ pub trait CmdBuf: Send + Sync + Clone { fn update_raytracing_tlas(&mut self, tlas: &D::RaytracingTLAS, instance_buffer: &D::Buffer, instance_count: usize, mode: AccelerationStructureRebuildMode); /// Resolves the `subresource` (mip index, 3d texture slice or array slice) fn resolve_texture_subresource(&mut self, texture: &D::Texture, subresource: u32) -> Result<(), Error>; - /// Generates a full mip chain for the specified `texture` where `heap` is the shader heap the texture was created on + /// Generates a full mip chain for the specified `texture` where `heap` is the shader heap the texture was created on fn generate_mip_maps(&mut self, texture: &D::Texture, device: &D, heap: &D::Heap) -> Result<(), Error>; /// Read back the swapchains contents to CPU fn read_back_backbuffer(&mut self, swap_chain: &D::SwapChain) -> Result; /// Copy from one buffer to another with offsets fn copy_buffer_region( - &mut self, - dst_buffer: &D::Buffer, - dst_offset: usize, - src_buffer: &D::Buffer, + &mut self, + dst_buffer: &D::Buffer, + dst_offset: usize, + src_buffer: &D::Buffer, src_offset: usize, num_bytes: usize ); /// Copy from one texture to another with offsets, if `None` is specified for `src_region` - /// it will copy the full size of src + /// it will copy the full size of src fn copy_texture_region( &mut self, dst_texture: &D::Texture, @@ -1533,7 +1535,7 @@ pub trait Buffer: Send + Sync { /// this function internally will map and unmap fn update(&mut self, offset: usize, data: &[T]) -> Result<(), Error>; // TODO: should be mut surely? // write data directly to the buffer, the buffer is required to be persistently mapped - fn write(&mut self, offset: usize, data: &[T]) -> Result<(), Error>; + fn write(&mut self, offset: usize, data: &[T]) -> Result<(), Error>; /// maps the entire buffer for reading or writing... see MapInfo fn map(&mut self, info: &MapInfo) -> *mut u8; /// unmap buffer... see UnmapInfo diff --git a/src/gfx/mtl.rs b/src/gfx/mtl.rs index c3ab3da5..b6e10aa1 100644 --- a/src/gfx/mtl.rs +++ b/src/gfx/mtl.rs @@ -251,7 +251,7 @@ impl super::CmdBuf for CmdBuf { unimplemented!() } - fn set_viewport(&self, viewport: &super::Viewport) { + fn set_viewport(&mut self, viewport: &super::Viewport) { objc::rc::autoreleasepool(|| { self.render_encoder .as_ref() @@ -267,7 +267,7 @@ impl super::CmdBuf for CmdBuf { }); } - fn set_scissor_rect(&self, scissor_rect: &super::ScissorRect) { + fn set_scissor_rect(&mut self, scissor_rect: &super::ScissorRect) { objc::rc::autoreleasepool(|| { self.render_encoder .as_ref() @@ -281,7 +281,7 @@ impl super::CmdBuf for CmdBuf { }); } - fn set_vertex_buffer(&self, buffer: &Buffer, slot: u32) { + fn set_vertex_buffer(&mut self, buffer: &Buffer, slot: u32) { objc::rc::autoreleasepool(|| { self.render_encoder .as_ref() @@ -295,7 +295,7 @@ impl super::CmdBuf for CmdBuf { self.bound_index_stride = buffer.element_stride; } - fn set_render_pipeline(&self, pipeline: &RenderPipeline) { + fn set_render_pipeline(&mut self, pipeline: &RenderPipeline) { objc::rc::autoreleasepool(|| { self.render_encoder .as_ref() @@ -310,24 +310,22 @@ impl super::CmdBuf for CmdBuf { }); } - fn set_compute_pipeline(&self, pipeline: &ComputePipeline) { + fn set_compute_pipeline(&mut self, pipeline: &ComputePipeline) { } - fn set_raytracing_pipeline(&self, pipeline: &RaytracingPipeline) { + fn set_raytracing_pipeline(&mut self, pipeline: &RaytracingPipeline) { unimplemented!() } - fn set_heap(&self, pipeline: &T, heap: &Heap) { - - } - - fn set_heap_render(&self, pipeline: &RenderPipeline, heap: &Heap) { + fn set_heap(&mut self, pipeline: &T, heap: &Heap) { self.render_encoder .as_ref() .expect("hotline_rs::gfx::metal expected a call to begin render pass before using render commands") .use_heap_at(&heap.mtl_heap, metal::MTLRenderStages::Fragment); + let pipeline = (pipeline as *const T) as *const RenderPipeline; + let pipeline = unsafe { &*pipeline }; pipeline.fragment_descriptor_slots.iter().enumerate().for_each(|(slot_index, slot)| { if let Some(slot) = slot { @@ -346,7 +344,6 @@ impl super::CmdBuf for CmdBuf { } }); - /* pipeline.vertex_descriptor_slots.iter().enumerate().for_each(|(slot_index, slot)| { if let Some(slot) = slot { slot.argument_encoder.set_argument_buffer(&slot.argument_buffer, 0); @@ -354,18 +351,17 @@ impl super::CmdBuf for CmdBuf { // TODO: need to know data types (Texture, Buffer) // assign textures to slots heap.texture_slots.iter().enumerate().for_each(|(index, texture)| { - slot.argument_encoder.set_texture(index as u64, texture); + slot.argument_encoder.set_texture(index as u64, texture.as_ref().unwrap()); }); // TODO: need to know what stages to bind on self.render_encoder.as_ref().unwrap().set_vertex_buffer(slot_index as u64, Some(&slot.argument_buffer), 0); } }); - */ } // TODO: needs stage - fn set_binding(&self, pipeline: &T, heap: &Heap, slot: u32, offset: usize) { + fn set_binding(&mut self, pipeline: &T, heap: &Heap, slot: u32, offset: usize) { let rp : &RenderPipeline = unsafe { std::mem::transmute(pipeline) }; if rp.fragment_descriptor_slots.len() > 0 { if let Some(d) = rp.fragment_descriptor_slots[0].as_ref() { @@ -377,6 +373,7 @@ impl super::CmdBuf for CmdBuf { } } + #[cfg(target_os = "ignore")] fn set_texture(&mut self, texture: &Texture, slot: u32) { self.render_encoder.as_ref().unwrap().set_fragment_texture(slot as u64, Some(&texture.metal_texture)); } @@ -384,7 +381,7 @@ impl super::CmdBuf for CmdBuf { fn set_marker(&mut self, colour: u32, name: &str) { } - fn push_render_constants(&self, slot: u32, num_values: u32, dest_offset: u32, data: &[T]) { + fn push_render_constants(&mut self, slot: u32, num_values: u32, dest_offset: u32, data: &[T]) { // TODO: need to know the stages and the buffer offset self.render_encoder .as_ref() @@ -394,11 +391,11 @@ impl super::CmdBuf for CmdBuf { .set_vertex_bytes(1, num_values as u64 * 4, data.as_ptr() as _); } - fn push_compute_constants(&self, slot: u32, num_values: u32, dest_offset: u32, data: &[T]) { + fn push_compute_constants(&mut self, slot: u32, num_values: u32, dest_offset: u32, data: &[T]) { } fn draw_instanced( - &self, + &mut self, vertex_count: u32, instance_count: u32, start_vertex: u32, @@ -419,7 +416,7 @@ impl super::CmdBuf for CmdBuf { } fn draw_indexed_instanced( - &self, + &mut self, index_count: u32, instance_count: u32, start_index: u32, @@ -443,11 +440,11 @@ impl super::CmdBuf for CmdBuf { }) } - fn dispatch(&self, group_count: Size3, _numthreads: Size3) { + fn dispatch(&mut self, group_count: Size3, _numthreads: Size3) { } fn execute_indirect( - &self, + &mut self, command: &CommandSignature, max_command_count: u32, argument_buffer: &Buffer, @@ -463,7 +460,7 @@ impl super::CmdBuf for CmdBuf { }) } - fn resolve_texture_subresource(&self, texture: &Texture, subresource: u32) -> result::Result<(), super::Error> { + fn resolve_texture_subresource(&mut self, texture: &Texture, subresource: u32) -> result::Result<(), super::Error> { Ok(()) } @@ -493,7 +490,7 @@ impl super::CmdBuf for CmdBuf { ) { } - fn dispatch_rays(&self, sbt: &RaytracingShaderBindingTable, numthreads: Size3) { + fn dispatch_rays(&mut self, sbt: &RaytracingShaderBindingTable, numthreads: Size3) { unimplemented!() } @@ -1452,13 +1449,6 @@ impl super::Device for Device { unimplemented!() } - fn create_raytracing_tlas( - &mut self, - info: &RaytracingTLASInfo - ) -> result::Result { - unimplemented!() - } - fn create_compute_pipeline( &self, info: &super::ComputePipelineInfo, @@ -1531,6 +1521,45 @@ impl super::Device for Device { fn get_counter_alignment() -> usize { 0 } + + fn create_upload_buffer( + &mut self, + data: &[T] + ) -> Result { + unimplemented!() + } + + fn create_raytracing_instance_buffer( + &mut self, + instances: &Vec> + ) -> Result { + unimplemented!() + } + + fn create_raytracing_tlas( + &mut self, + info: &RaytracingTLASInfo + ) -> Result { + unimplemented!() + } + + fn create_resource_view( + &mut self, + info: &ResourceViewInfo, + resource: Resource, + heap: &mut Heap + ) -> Result { + unimplemented!() + } + + fn create_raytracing_tlas_with_heap( + &mut self, + info: &RaytracingTLASInfo, + heap: &mut Heap + ) -> Result { + unimplemented!() + } + } unsafe impl Send for Device {} diff --git a/src/lib.rs b/src/lib.rs index e3a551e7..29481a6c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -256,7 +256,7 @@ pub use os::macos as os_platform; /// This is a hardcoded compile time selection of os backend for macos as null #[cfg(target_os = "macos")] -pub use gfx::null as gfx_platform; +pub use gfx::mtl as gfx_platform; /// This is a hardcoded compile time selection of os backend for macos as null #[cfg(target_os = "macos")] From 488a855b4836b672e53c4a058940c13cdd6884b8 Mon Sep 17 00:00:00 2001 From: polymonster Date: Thu, 26 Feb 2026 09:10:14 +0000 Subject: [PATCH 02/62] - build config macos --- .cargo/config.toml | 5 +++-- Cargo.toml | 3 +++ build.rs | 5 +++++ 3 files changed, 11 insertions(+), 2 deletions(-) create mode 100644 build.rs diff --git a/.cargo/config.toml b/.cargo/config.toml index 301ac966..26422587 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -1,4 +1,5 @@ [build] -rustflags = ["-A unused"] +rustflags = ["-A", "unused"] -# "-C", "link-arg=-fuse-ld=lld", \ No newline at end of file +[build.env] +MACOSX_DEPLOYMENT_TARGET = "15.0" \ No newline at end of file diff --git a/Cargo.toml b/Cargo.toml index 10d89ca7..0619ea51 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,6 +25,9 @@ libloading = "0.7.4" bevy_ecs = "0.15.0" ddsfile = "0.5.1" +[build-dependencies] +htwv = { path = "../htwv" } + [dependencies.imgui-sys] version = "0.9.0" features = ["docking"] diff --git a/build.rs b/build.rs new file mode 100644 index 00000000..972ab642 --- /dev/null +++ b/build.rs @@ -0,0 +1,5 @@ +use htwv; + +fn main() { + htwv::compile_dir("shaders", "target/shaders").unwrap(); +} \ No newline at end of file From 83dc742ff2bd7dc123ff2598f35ece8e5485d044 Mon Sep 17 00:00:00 2001 From: polymonster Date: Thu, 26 Feb 2026 11:59:21 +0000 Subject: [PATCH 03/62] - compo fixes --- .claude/settings.local.json | 4 +++- build.rs | 31 ++++++++++++++++++++++++++++--- shaders/bindful.hlsl | 6 ++++-- src/gfx/mtl.rs | 8 +++----- src/lib.rs | 14 ++++++++++++++ 5 files changed, 52 insertions(+), 11 deletions(-) diff --git a/.claude/settings.local.json b/.claude/settings.local.json index d218751e..cac78b01 100644 --- a/.claude/settings.local.json +++ b/.claude/settings.local.json @@ -3,7 +3,9 @@ "allow": [ "Bash(dir:*)", "Bash(grep:*)", - "Bash(cargo build:*)" + "Bash(cargo build:*)", + "Bash(ls:*)", + "Bash(python3:*)" ] } } diff --git a/build.rs b/build.rs index d2974119..498a3fb2 100644 --- a/build.rs +++ b/build.rs @@ -2,7 +2,10 @@ use htwv; use std::process::Command; +#[cfg(target_os = "windows")] fn main() { + println!("cargo:rerun-if-changed=shaders"); + if std::env::var("CARGO_FEATURE_BUILD_DATA").is_ok() { let pmbuild = "hotline-data\\pmbuild.cmd"; @@ -14,10 +17,32 @@ fn main() { if !status.success() { panic!("pmbuild win32-data failed with status: {status}"); } + } +} + +#[cfg(target_os = "macos")] +fn main() { + // Tell Cargo to rerun build.rs when shaders change + println!("cargo:rerun-if-changed=shaders"); + + if std::env::var("CARGO_FEATURE_BUILD_DATA").is_ok() { + use core::panic; + + let pmbuild = "pmbuild"; + + let status = Command::new(pmbuild) + .args(["mac-data"]) + .status() + .unwrap_or_else(|e| panic!("failed to run '{pmbuild}': {e}")); + + if !status.success() { + panic!("pmbuild mac-data failed with status: {status}"); + } - #[cfg(target_os = "macos")] - { - htwv::compile_dir("shaders", "target/shaders").unwrap(); + println!("cargo:warning=Compiling shaders..."); + match htwv::compile_dir("shaders", "target/shaders") { + Ok(_) => println!("cargo:warning=Shader compilation succeeded"), + Err(e) => panic!("Shader compilation failed: {e}"), } } } \ No newline at end of file diff --git a/shaders/bindful.hlsl b/shaders/bindful.hlsl index 6dda7c24..059fd511 100644 --- a/shaders/bindful.hlsl +++ b/shaders/bindful.hlsl @@ -1,7 +1,7 @@ //#pragma argument(developmentfeatures) struct vs_input { - float3 position : POSITION; + float3 position : POSITION; float4 uv : TEXCOORD0; }; @@ -54,5 +54,7 @@ float4 ps_main(ps_input input) : SV_Target { final = r3 * r3.a; } - return final; + // return final; + + return float4(1.0, 0.0, 1.0, 1.0); } diff --git a/src/gfx/mtl.rs b/src/gfx/mtl.rs index 7ffac096..5bee5b4c 100644 --- a/src/gfx/mtl.rs +++ b/src/gfx/mtl.rs @@ -361,12 +361,8 @@ impl super::CmdBuf for CmdBuf { } // TODO: needs stage -<<<<<<< HEAD - fn set_binding(&mut self, pipeline: &T, heap: &Heap, slot: u32, offset: usize) { -======= - fn set_binding(&self, pipeline: &T, register: u32, space: u32, descriptor_type: super::DescriptorType, heap: &Heap, offset: usize) -> Option<()> { + fn set_binding(&mut self, pipeline: &T, register: u32, space: u32, descriptor_type: super::DescriptorType, heap: &Heap, offset: usize) -> Option<()> { let slot = pipeline.get_pipeline_slot(register, space, descriptor_type)?; ->>>>>>> master let rp : &RenderPipeline = unsafe { std::mem::transmute(pipeline) }; if rp.fragment_descriptor_slots.len() > 0 { if let Some(d) = rp.fragment_descriptor_slots[0].as_ref() { @@ -379,10 +375,12 @@ impl super::CmdBuf for CmdBuf { Some(()) } + /* #[cfg(target_os = "ignore")] fn set_texture(&mut self, texture: &Texture, slot: u32) { self.render_encoder.as_ref().unwrap().set_fragment_texture(slot as u64, Some(&texture.metal_texture)); } + */ fn set_marker(&mut self, colour: u32, name: &str) { } diff --git a/src/lib.rs b/src/lib.rs index 4e592fdc..84df5dba 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -245,13 +245,27 @@ pub mod prelude { pmfx, imgui, + // platform specific + gfx_platform, + os_platform, + // traits + ecs_base::*, gfx::{Device, SwapChain, CmdBuf, Texture, RenderPass, Pipeline, Buffer}, + pmfx::{DrawData, MaterialData, PointLightData, SpotLightData, DirectionalLightData, WorldBufferReserveInfo, WorldBufferInfo}, os::{App, Window}, pmfx::Pmfx, imgui::ImGui, imdraw::ImDraw, + client::{Client, HotlineInfo, PluginInfo}, + plugin::{Plugin}, av::{VideoPlayer}, + + // macros + hotline_plugin, + system_func, + demos, + systems }; } From 1d22ba462f9a7b02a85c7fccd2592027d5660961 Mon Sep 17 00:00:00 2001 From: polymonster Date: Thu, 26 Feb 2026 13:10:55 +0000 Subject: [PATCH 04/62] - bindful working with incorrect offset applied due to push constants --- build.rs | 6 +- shaders/bindful.hlsl | 4 +- src/gfx.rs | 2 +- src/gfx/mtl.rs | 475 +++++++++++++++++++++++++------------------ 4 files changed, 276 insertions(+), 211 deletions(-) diff --git a/build.rs b/build.rs index 498a3fb2..1c532dc7 100644 --- a/build.rs +++ b/build.rs @@ -26,8 +26,6 @@ fn main() { println!("cargo:rerun-if-changed=shaders"); if std::env::var("CARGO_FEATURE_BUILD_DATA").is_ok() { - use core::panic; - let pmbuild = "pmbuild"; let status = Command::new(pmbuild) @@ -40,9 +38,9 @@ fn main() { } println!("cargo:warning=Compiling shaders..."); - match htwv::compile_dir("shaders", "target/shaders") { + match htwv::compile_dir("shaders", "target/data/shaders") { Ok(_) => println!("cargo:warning=Shader compilation succeeded"), - Err(e) => panic!("Shader compilation failed: {e}"), + Err(e) => {} // panic!("Shader compilation failed: {e}"), } } } \ No newline at end of file diff --git a/shaders/bindful.hlsl b/shaders/bindful.hlsl index 059fd511..14a01990 100644 --- a/shaders/bindful.hlsl +++ b/shaders/bindful.hlsl @@ -54,7 +54,5 @@ float4 ps_main(ps_input input) : SV_Target { final = r3 * r3.a; } - // return final; - - return float4(1.0, 0.0, 1.0, 1.0); + return final; } diff --git a/src/gfx.rs b/src/gfx.rs index e2011308..1bb4182f 100644 --- a/src/gfx.rs +++ b/src/gfx.rs @@ -629,7 +629,7 @@ pub struct DescriptorBinding { } /// Describes the type of descriptor binding to create. -#[derive(Clone, Copy, Serialize, Deserialize, Hash)] +#[derive(Clone, Copy, Serialize, Deserialize, Hash, PartialEq, Eq)] pub enum DescriptorType { /// Used for textures or structured buffers. ShaderResource, diff --git a/src/gfx/mtl.rs b/src/gfx/mtl.rs index 5bee5b4c..84bf7da7 100644 --- a/src/gfx/mtl.rs +++ b/src/gfx/mtl.rs @@ -171,14 +171,29 @@ impl super::SwapChain for SwapChain { } } -#[derive(Clone)] pub struct CmdBuf { cmd_queue: metal::CommandQueue, cmd: Option, render_encoder: Option, compute_encoder: Option, bound_index_buffer: Option, - bound_index_stride: usize + bound_index_stride: usize, + /// Raw pointer to bound render pipeline (valid during render pass) + bound_render_pipeline: Option<*const RenderPipeline>, +} + +impl Clone for CmdBuf { + fn clone(&self) -> Self { + CmdBuf { + cmd_queue: self.cmd_queue.clone(), + cmd: self.cmd.clone(), + render_encoder: self.render_encoder.clone(), + compute_encoder: self.compute_encoder.clone(), + bound_index_buffer: self.bound_index_buffer.clone(), + bound_index_stride: self.bound_index_stride, + bound_render_pipeline: self.bound_render_pipeline, + } + } } impl super::CmdBuf for CmdBuf { @@ -302,11 +317,17 @@ impl super::CmdBuf for CmdBuf { .expect("hotline_rs::gfx::metal expected a call to begin render pass before using render commands") .set_render_pipeline_state(&pipeline.pipeline_state); - // bind static samplers - for sampler in &pipeline.static_samplers { - self.render_encoder.as_ref().unwrap().set_fragment_sampler_state( - sampler.slot as u64, Some(&sampler.sampler)) + // Bind sampler argument buffer at buffer(4) per htwv convention + if let Some(ref sampler_arg_buffer) = pipeline.sampler_argument_buffer { + self.render_encoder.as_ref().unwrap().set_fragment_buffer( + 4, // samplers_offset from htwv + Some(sampler_arg_buffer), + 0 + ); } + + // Store pipeline pointer for push_render_constants + self.bound_render_pipeline = Some(pipeline as *const RenderPipeline); }); } @@ -319,60 +340,42 @@ impl super::CmdBuf for CmdBuf { } fn set_heap(&mut self, pipeline: &T, heap: &Heap) { - self.render_encoder + let encoder = self.render_encoder .as_ref() - .expect("hotline_rs::gfx::metal expected a call to begin render pass before using render commands") - .use_heap_at(&heap.mtl_heap, metal::MTLRenderStages::Fragment); - - let pipeline = (pipeline as *const T) as *const RenderPipeline; - let pipeline = unsafe { &*pipeline }; + .expect("hotline_rs::gfx::metal expected a call to begin render pass before using render commands"); - pipeline.fragment_descriptor_slots.iter().enumerate().for_each(|(slot_index, slot)| { - if let Some(slot) = slot { - slot.argument_encoder.set_argument_buffer(&slot.argument_buffer, 0); - - // TODO: need to know data types (Texture, Buffer) - // assign textures to slots - heap.texture_slots.iter().enumerate().for_each(|(index, texture)| { - if let Some(texture) = texture { - slot.argument_encoder.set_texture(index as u64, texture); - } - }); + // Make the heap accessible to shaders - actual texture binding happens via set_binding + encoder.use_heap_at(&heap.mtl_heap, metal::MTLRenderStages::Fragment); + encoder.use_heap_at(&heap.mtl_heap, metal::MTLRenderStages::Vertex); + } - // TODO: need to know what stages to bind on - self.render_encoder.as_ref().unwrap().set_fragment_buffer(slot_index as u64, Some(&slot.argument_buffer), 0); - } - }); + fn set_binding(&mut self, pipeline: &T, register: u32, space: u32, descriptor_type: super::DescriptorType, heap: &Heap, offset: usize) -> Option<()> { + let encoder = self.render_encoder.as_ref() + .expect("hotline_rs::gfx::metal expected a call to begin render pass before using render commands"); - pipeline.vertex_descriptor_slots.iter().enumerate().for_each(|(slot_index, slot)| { - if let Some(slot) = slot { - slot.argument_encoder.set_argument_buffer(&slot.argument_buffer, 0); + let rp: &RenderPipeline = unsafe { std::mem::transmute(pipeline) }; - // TODO: need to know data types (Texture, Buffer) - // assign textures to slots - heap.texture_slots.iter().enumerate().for_each(|(index, texture)| { - slot.argument_encoder.set_texture(index as u64, texture.as_ref().unwrap()); - }); + // Look up the slot by (register, space, descriptor_type) + if let Some(slot) = rp.slot_lookup.get(&(register, space, descriptor_type)) { + slot.argument_encoder.set_argument_buffer(&slot.argument_buffer, 0); - // TODO: need to know what stages to bind on - self.render_encoder.as_ref().unwrap().set_vertex_buffer(slot_index as u64, Some(&slot.argument_buffer), 0); + // Set texture from heap at offset + if let Some(texture) = heap.texture_slots.get(offset).and_then(|t| t.as_ref()) { + slot.argument_encoder.set_texture(0, texture); } - }); - } - // TODO: needs stage - fn set_binding(&mut self, pipeline: &T, register: u32, space: u32, descriptor_type: super::DescriptorType, heap: &Heap, offset: usize) -> Option<()> { - let slot = pipeline.get_pipeline_slot(register, space, descriptor_type)?; - let rp : &RenderPipeline = unsafe { std::mem::transmute(pipeline) }; - if rp.fragment_descriptor_slots.len() > 0 { - if let Some(d) = rp.fragment_descriptor_slots[0].as_ref() { - d.argument_encoder.set_argument_buffer(&d.argument_buffer, 0); - if let Some(texture) = heap.texture_slots[offset].as_ref() { - d.argument_encoder.set_texture(slot.index as u64, &texture); - } + // Bind to appropriate stage(s) + if let Some(vertex_idx) = slot.vertex_buffer_index { + encoder.set_vertex_buffer(vertex_idx as u64, Some(&slot.argument_buffer), 0); + } + if let Some(fragment_idx) = slot.fragment_buffer_index { + encoder.set_fragment_buffer(fragment_idx as u64, Some(&slot.argument_buffer), 0); } + + Some(()) + } else { + None } - Some(()) } /* @@ -386,13 +389,59 @@ impl super::CmdBuf for CmdBuf { } fn push_render_constants(&mut self, slot: u32, num_values: u32, dest_offset: u32, data: &[T]) { - // TODO: need to know the stages and the buffer offset - self.render_encoder - .as_ref() - .expect("hotline_rs::gfx::metal expected a call to begin render pass before using render commands") - // .set_fragment_bytes(slot as u64 + 2, num_values as u64 * 4, data.as_ptr() as _); - // .set_vertex_bytes(slot as u64 + 2, num_values as u64 * 4, data.as_ptr() as _); - .set_vertex_bytes(1, num_values as u64 * 4, data.as_ptr() as _); + let encoder = self.render_encoder + .as_ref() + .expect("hotline_rs::gfx::metal expected a call to begin render pass before using render commands"); + + // Find the pipeline slot by buffer index + if let Some(pipeline_ptr) = self.bound_render_pipeline { + let pipeline = unsafe { &*pipeline_ptr }; + + // Find slot with matching buffer index + for pipeline_slot in pipeline.slot_lookup.values() { + if pipeline_slot.info.index == slot && pipeline_slot.data_buffer.is_some() { + // Copy data to the data buffer + if let Some(ref data_buffer) = pipeline_slot.data_buffer { + let data_bytes = unsafe { + std::slice::from_raw_parts( + data.as_ptr() as *const u8, + std::mem::size_of_val(data) + ) + }; + let dest_ptr = data_buffer.contents() as *mut u8; + let dest_offset_bytes = dest_offset as usize * 4; + unsafe { + std::ptr::copy_nonoverlapping( + data_bytes.as_ptr(), + dest_ptr.add(dest_offset_bytes), + data_bytes.len() + ); + } + + // Re-encode the buffer pointer into the argument buffer + pipeline_slot.argument_encoder.set_argument_buffer(&pipeline_slot.argument_buffer, 0); + pipeline_slot.argument_encoder.set_buffer(0, data_buffer, 0); + + // Bind the argument buffer to the appropriate stage(s) + if let Some(vertex_idx) = pipeline_slot.vertex_buffer_index { + encoder.set_vertex_buffer( + vertex_idx as u64, + Some(&pipeline_slot.argument_buffer), + 0 + ); + } + if let Some(fragment_idx) = pipeline_slot.fragment_buffer_index { + encoder.set_fragment_buffer( + fragment_idx as u64, + Some(&pipeline_slot.argument_buffer), + 0 + ); + } + } + return; + } + } + } } fn push_compute_constants(&mut self, slot: u32, num_values: u32, dest_offset: u32, data: &[T]) { @@ -566,62 +615,43 @@ struct MetalSamplerBinding { sampler: metal::SamplerState } -#[derive(Clone)] -pub struct DescriptorMember { - offset: u32, - num: u32, - info: PipelineSlotInfo +/// Unified pipeline slot for both descriptors and push constants +/// Supports per-stage buffer indices for Metal argument buffers +pub struct PipelineSlot { + /// Metal buffer index for vertex stage (None if not visible to vertex) + pub vertex_buffer_index: Option, + /// Metal buffer index for fragment stage (None if not visible to fragment) + pub fragment_buffer_index: Option, + /// Argument encoder for encoding resources into argument buffer + pub argument_encoder: metal::ArgumentEncoder, + /// Argument buffer containing encoded resource pointers + pub argument_buffer: metal::Buffer, + /// Data buffer for push constants (None for regular descriptors) + pub data_buffer: Option, + /// Slot info for API compatibility + pub info: PipelineSlotInfo, + /// Visibility for this slot + pub visibility: ShaderVisibility, } -type DescriptorMemberArray = Vec>; -#[derive(Clone)] -pub struct DescriptorSlot { - argument_buffer: metal::Buffer, - argument_encoder: metal::ArgumentEncoder, - members: Vec>, -} -type DescriptorSlotArray = Vec>; +/// Key for slot lookup: (register, space, descriptor_type) +type SlotKey = (u32, u32, DescriptorType); -pub struct PushConstantSlot { - buffer: metal::Buffer, - slot: u32, - visibility: ShaderVisibility -} pub struct RenderPipeline { pipeline_state: metal::RenderPipelineState, static_samplers: Vec, slots: Vec, - vertex_descriptor_slots: DescriptorSlotArray, - fragment_descriptor_slots: DescriptorSlotArray, - vertex_push_constant_slots: Vec, - fragment_push_constant_slots: Vec + /// Unified slot lookup by (register, space, descriptor_type) + slot_lookup: HashMap, + /// Sampler argument buffer (at buffer(4) per htwv convention) + sampler_argument_buffer: Option, } impl super::RenderPipeline for RenderPipeline {} impl super::Pipeline for RenderPipeline { fn get_pipeline_slot(&self, register: u32, space: u32, descriptor_type: DescriptorType) -> Option<&super::PipelineSlotInfo> { - if (space as usize) < self.fragment_descriptor_slots.len() { - if let Some(set) = self.fragment_descriptor_slots[space as usize].as_ref() { - if (register as usize) < set.members.len() { - if let Some(member) = set.members[(register as usize)].as_ref() { - Some(&member.info) - } - else { - None - } - } - else { - None - } - } - else { - None - } - } - else { - None - } + self.slot_lookup.get(&(register, space, descriptor_type)).map(|slot| &slot.info) } fn get_pipeline_slots(&self) -> &Vec { @@ -852,113 +882,128 @@ impl Device { } } - fn to_mtl_descriptor_slot(&self, visibility: super::ShaderVisibility, pipeline_bindings: &Option>) -> DescriptorSlotArray { - // argument buffer to descriptor slot style - let mut descriptor_slots : DescriptorSlotArray = Vec::new(); + /// Build unified slot lookup following htwv convention: + /// - Slots 0-3: Reserved for vertex buffers + /// - Slot 4: Samplers + /// - Slot 5+: Push constants + /// - Slot N+: Regular bindings (after push constants) + fn build_slot_lookup( + &self, + pipeline_bindings: &Option>, + pipeline_push_constants: &Option>, + ) -> HashMap { + let mut slot_lookup: HashMap = HashMap::new(); - // register spaces, and shader registers may not be ordered and may not be sequential or have gaps - if let Some(bindings) = pipeline_bindings.as_ref() { - // make space for enough shader register spaces - let mut space_count = 0; - for binding in bindings.iter().filter(|b| b.visibility == visibility || b.visibility == ShaderVisibility::All) { - space_count = binding.register_space.max(space_count); - } - descriptor_slots.resize((space_count + 1) as usize, None); - - // iterate over descriptor slots and find members - descriptor_slots.iter_mut().enumerate().for_each(|(space, descriptor_slot)| { - let mut members : DescriptorMemberArray = Vec::new(); - for binding in bindings.iter().filter(|b| b.visibility == visibility || b.visibility == ShaderVisibility::All) { - if binding.register_space == space as u32 { - if members.len() < (binding.shader_register + 1) as usize { - members.resize((binding.shader_register + 1) as usize, None); - } + // htwv convention: samplers at 4, push constants start at 5 + let samplers_offset: u32 = 4; + let mut binding_offset: u32 = samplers_offset + 1; // 5 for first push constant - // get num - let num = if let Some(num) = binding.num_descriptors { - num - } - else { - 1 - }; + // Add push constant slots first (they come before regular bindings in htwv) + if let Some(push_constants) = pipeline_push_constants.as_ref() { + for push_constant in push_constants { + let buffer_index = binding_offset; - // assign member info - members[binding.shader_register as usize] = Some( - DescriptorMember { - offset: 0, - num: num, - info: PipelineSlotInfo { - index: binding.shader_register, - count: binding.num_descriptors - } - } - ); - } - } + // Create argument descriptor for pointer type (push constants use pointers in argument buffers) + let arg_desc = metal::ArgumentDescriptor::new(); + arg_desc.set_index(0); + arg_desc.set_data_type(metal::MTLDataType::Pointer); + arg_desc.set_access(metal::MTLArgumentAccess::ReadOnly); - // now work out the offsets of the members within the space - let mut offset = 0; - for member in &mut members { - if let Some(member) = member { - member.offset = offset; - offset += member.num; - } - } + let argument_encoder = self.metal_device.new_argument_encoder( + metal::Array::from_owned_slice(&[arg_desc.to_owned()]) + ); + let argument_buffer = self.metal_device.new_buffer( + argument_encoder.encoded_length(), + metal::MTLResourceOptions::StorageModeShared + ); - // finally if we have members and not an empty space - // create an argument buffer - if members.len() > 0 { - let mut member_descriptors = Vec::new(); + // Data buffer holds the actual push constant values + let data_buffer = self.metal_device.new_buffer( + push_constant.num_values as u64 * 4, + metal::MTLResourceOptions::StorageModeShared + ); - let mut total_num = 0; - for member in &members { - if let Some(member) = member { - let descriptor = metal::ArgumentDescriptor::new(); - descriptor.set_index(member.offset as u64); - descriptor.set_array_length(member.num as u64); + // Encode the data buffer pointer into the argument buffer + argument_encoder.set_argument_buffer(&argument_buffer, 0); + argument_encoder.set_buffer(0, &data_buffer, 0); - // TODO: types / access - descriptor.set_data_type(metal::MTLDataType::Texture); - descriptor.set_access(metal::MTLArgumentAccess::ReadOnly); + // Determine stage indices based on visibility + let (vertex_idx, fragment_idx) = match push_constant.visibility { + ShaderVisibility::Vertex => (Some(buffer_index), None), + ShaderVisibility::Fragment => (None, Some(buffer_index)), + ShaderVisibility::All => (Some(buffer_index), Some(buffer_index)), + _ => (None, None), + }; - // push metal argument descriptor - member_descriptors.push(descriptor.to_owned()); + slot_lookup.insert( + (push_constant.shader_register, push_constant.register_space, DescriptorType::PushConstants), + PipelineSlot { + vertex_buffer_index: vertex_idx, + fragment_buffer_index: fragment_idx, + argument_encoder, + argument_buffer, + data_buffer: Some(data_buffer), + info: PipelineSlotInfo { + index: buffer_index, + count: Some(push_constant.num_values), + }, + visibility: push_constant.visibility, + }, + ); - total_num += member.num; - } - } + binding_offset += 1; + } + } - // create encoder and argument buffer - let argument_encoder = self.metal_device.new_argument_encoder(metal::Array::from_owned_slice(member_descriptors.as_slice())); - let argument_buffer_size = argument_encoder.encoded_length() * total_num as u64; - let argument_buffer = self.metal_device.new_buffer(argument_buffer_size, metal::MTLResourceOptions::empty()); + // Add regular binding slots + if let Some(bindings) = pipeline_bindings.as_ref() { + for binding in bindings { + let buffer_index = binding_offset; + + // Create argument descriptor for texture type + let arg_desc = metal::ArgumentDescriptor::new(); + arg_desc.set_index(0); + arg_desc.set_array_length(binding.num_descriptors.unwrap_or(1) as u64); + arg_desc.set_data_type(metal::MTLDataType::Texture); + arg_desc.set_access(metal::MTLArgumentAccess::ReadOnly); + + let argument_encoder = self.metal_device.new_argument_encoder( + metal::Array::from_owned_slice(&[arg_desc.to_owned()]) + ); + let argument_buffer = self.metal_device.new_buffer( + argument_encoder.encoded_length(), + metal::MTLResourceOptions::StorageModeShared + ); - *descriptor_slot = Some( - DescriptorSlot { - argument_encoder, - argument_buffer, - members - } - ) - } - }); - } + // Determine stage indices based on visibility + let (vertex_idx, fragment_idx) = match binding.visibility { + ShaderVisibility::Vertex => (Some(buffer_index), None), + ShaderVisibility::Fragment => (None, Some(buffer_index)), + ShaderVisibility::All => (Some(buffer_index), Some(buffer_index)), + _ => (None, None), + }; - descriptor_slots - } + slot_lookup.insert( + (binding.shader_register, binding.register_space, binding.binding_type), + PipelineSlot { + vertex_buffer_index: vertex_idx, + fragment_buffer_index: fragment_idx, + argument_encoder, + argument_buffer, + data_buffer: None, + info: PipelineSlotInfo { + index: buffer_index, + count: binding.num_descriptors, + }, + visibility: binding.visibility, + }, + ); - fn to_mtl_push_constant_slot(&self, visibility: super::ShaderVisibility, pipeline_push_constants: &Option>, binding_offset: u32) -> Vec { - let mut push_constant_slots : Vec = Vec::new(); - if let Some(push_constants) = pipeline_push_constants.as_ref() { - push_constants.iter().filter(|b| b.visibility == visibility || b.visibility == ShaderVisibility::All).enumerate().for_each(|(index, push_constant)| { - push_constant_slots.push(PushConstantSlot{ - buffer: self.metal_device.new_buffer(push_constant.num_values as u64 * 4, metal::MTLResourceOptions::StorageModeShared), - slot: binding_offset + index as u32, - visibility: ShaderVisibility::All - }) - }); + binding_offset += 1; + } } - push_constant_slots + + slot_lookup } } @@ -1082,7 +1127,8 @@ impl super::Device for Device { render_encoder: None, compute_encoder: None, bound_index_buffer: None, - bound_index_stride: 0 + bound_index_stride: 0, + bound_render_pipeline: None, } }) } @@ -1160,8 +1206,10 @@ impl super::Device for Device { // TODO: raster - // TODO: samplers? + // Create static samplers and argument buffer (at buffer(4) per htwv convention) let mut pipeline_static_samplers = Vec::new(); + let mut sampler_argument_buffer = None; + if let Some(static_samplers) = &info.pipeline_layout.static_samplers { for sampler in static_samplers { let desc = metal::SamplerDescriptor::new(); @@ -1178,12 +1226,35 @@ impl super::Device for Device { sampler: self.metal_device.new_sampler(&desc) }) } + + // Create argument buffer for samplers at buffer(4) + if !pipeline_static_samplers.is_empty() { + let arg_desc = metal::ArgumentDescriptor::new(); + arg_desc.set_index(0); + arg_desc.set_data_type(metal::MTLDataType::Sampler); + arg_desc.set_access(metal::MTLArgumentAccess::ReadOnly); + + let argument_encoder = self.metal_device.new_argument_encoder( + metal::Array::from_owned_slice(&[arg_desc.to_owned()]) + ); + let arg_buffer = self.metal_device.new_buffer( + argument_encoder.encoded_length(), + metal::MTLResourceOptions::StorageModeShared + ); + + // Encode sampler into argument buffer + argument_encoder.set_argument_buffer(&arg_buffer, 0); + argument_encoder.set_sampler_state(0, &pipeline_static_samplers[0].sampler); + + sampler_argument_buffer = Some(arg_buffer); + } } - let vertex_descriptor_slots = self.to_mtl_descriptor_slot(ShaderVisibility::Vertex, &info.pipeline_layout.bindings); - let fragment_descriptor_slots = self.to_mtl_descriptor_slot(ShaderVisibility::Fragment, &info.pipeline_layout.bindings); - let vertex_push_constant_slots = self.to_mtl_push_constant_slot(ShaderVisibility::Vertex, &info.pipeline_layout.push_constants, vertex_descriptor_slots.len() as u32); - let fragment_push_constant_slots = self.to_mtl_push_constant_slot(ShaderVisibility::Fragment, &info.pipeline_layout.push_constants, fragment_descriptor_slots.len() as u32); + // Build unified slot lookup + let slot_lookup = self.build_slot_lookup( + &info.pipeline_layout.bindings, + &info.pipeline_layout.push_constants, + ); let pipeline_state = self.metal_device.new_render_pipeline_state(&pipeline_state_descriptor)?; @@ -1191,10 +1262,8 @@ impl super::Device for Device { pipeline_state, slots: Vec::new(), static_samplers: pipeline_static_samplers, - fragment_descriptor_slots, - vertex_descriptor_slots, - vertex_push_constant_slots, - fragment_push_constant_slots + slot_lookup, + sampler_argument_buffer, }) }) } From 212fe7e4a2efdb6ba0956b5f6cf493556f376ed3 Mon Sep 17 00:00:00 2001 From: polymonster Date: Thu, 26 Feb 2026 13:37:42 +0000 Subject: [PATCH 05/62] - separated vs/ps binding offsets@ --- .claude/settings.local.json | 3 +- src/gfx/mtl.rs | 71 +++++++++++++++++++++++++------------ 2 files changed, 51 insertions(+), 23 deletions(-) diff --git a/.claude/settings.local.json b/.claude/settings.local.json index cac78b01..a831cab5 100644 --- a/.claude/settings.local.json +++ b/.claude/settings.local.json @@ -5,7 +5,8 @@ "Bash(grep:*)", "Bash(cargo build:*)", "Bash(ls:*)", - "Bash(python3:*)" + "Bash(python3:*)", + "Bash(cargo check:*)" ] } } diff --git a/src/gfx/mtl.rs b/src/gfx/mtl.rs index 84bf7da7..8a4f4dcb 100644 --- a/src/gfx/mtl.rs +++ b/src/gfx/mtl.rs @@ -895,13 +895,16 @@ impl Device { let mut slot_lookup: HashMap = HashMap::new(); // htwv convention: samplers at 4, push constants start at 5 + // Track binding offsets separately per stage since different numbers of + // bindings and push constants might be active on each stage let samplers_offset: u32 = 4; - let mut binding_offset: u32 = samplers_offset + 1; // 5 for first push constant + let start_offset: u32 = samplers_offset + 1; // 5 for first push constant + let mut vertex_binding_offset: u32 = start_offset; + let mut fragment_binding_offset: u32 = start_offset; // Add push constant slots first (they come before regular bindings in htwv) if let Some(push_constants) = pipeline_push_constants.as_ref() { for push_constant in push_constants { - let buffer_index = binding_offset; // Create argument descriptor for pointer type (push constants use pointers in argument buffers) let arg_desc = metal::ArgumentDescriptor::new(); @@ -927,12 +930,27 @@ impl Device { argument_encoder.set_argument_buffer(&argument_buffer, 0); argument_encoder.set_buffer(0, &data_buffer, 0); - // Determine stage indices based on visibility - let (vertex_idx, fragment_idx) = match push_constant.visibility { - ShaderVisibility::Vertex => (Some(buffer_index), None), - ShaderVisibility::Fragment => (None, Some(buffer_index)), - ShaderVisibility::All => (Some(buffer_index), Some(buffer_index)), - _ => (None, None), + // Determine stage indices based on visibility, using per-stage offsets + let (vertex_idx, fragment_idx, canonical_index) = match push_constant.visibility { + ShaderVisibility::Vertex => { + let idx = vertex_binding_offset; + vertex_binding_offset += 1; + (Some(idx), None, idx) + }, + ShaderVisibility::Fragment => { + let idx = fragment_binding_offset; + fragment_binding_offset += 1; + (None, Some(idx), idx) + }, + ShaderVisibility::All => { + let v_idx = vertex_binding_offset; + let f_idx = fragment_binding_offset; + vertex_binding_offset += 1; + fragment_binding_offset += 1; + // Use vertex index as canonical for lookup + (Some(v_idx), Some(f_idx), v_idx) + }, + _ => (None, None, 0), }; slot_lookup.insert( @@ -944,22 +962,18 @@ impl Device { argument_buffer, data_buffer: Some(data_buffer), info: PipelineSlotInfo { - index: buffer_index, + index: canonical_index, count: Some(push_constant.num_values), }, visibility: push_constant.visibility, }, ); - - binding_offset += 1; } } // Add regular binding slots if let Some(bindings) = pipeline_bindings.as_ref() { for binding in bindings { - let buffer_index = binding_offset; - // Create argument descriptor for texture type let arg_desc = metal::ArgumentDescriptor::new(); arg_desc.set_index(0); @@ -975,12 +989,27 @@ impl Device { metal::MTLResourceOptions::StorageModeShared ); - // Determine stage indices based on visibility - let (vertex_idx, fragment_idx) = match binding.visibility { - ShaderVisibility::Vertex => (Some(buffer_index), None), - ShaderVisibility::Fragment => (None, Some(buffer_index)), - ShaderVisibility::All => (Some(buffer_index), Some(buffer_index)), - _ => (None, None), + // Determine stage indices based on visibility, using per-stage offsets + let (vertex_idx, fragment_idx, canonical_index) = match binding.visibility { + ShaderVisibility::Vertex => { + let idx = vertex_binding_offset; + vertex_binding_offset += 1; + (Some(idx), None, idx) + }, + ShaderVisibility::Fragment => { + let idx = fragment_binding_offset; + fragment_binding_offset += 1; + (None, Some(idx), idx) + }, + ShaderVisibility::All => { + let v_idx = vertex_binding_offset; + let f_idx = fragment_binding_offset; + vertex_binding_offset += 1; + fragment_binding_offset += 1; + // Use vertex index as canonical for lookup + (Some(v_idx), Some(f_idx), v_idx) + }, + _ => (None, None, 0), }; slot_lookup.insert( @@ -992,14 +1021,12 @@ impl Device { argument_buffer, data_buffer: None, info: PipelineSlotInfo { - index: buffer_index, + index: canonical_index, count: binding.num_descriptors, }, visibility: binding.visibility, }, ); - - binding_offset += 1; } } From f3694d6ea00fcce0b76bf72f088b12618011958a Mon Sep 17 00:00:00 2001 From: polymonster Date: Thu, 26 Feb 2026 15:18:12 +0000 Subject: [PATCH 06/62] - bindful working, bindless missing textures --- build.rs | 2 +- src/gfx/mtl.rs | 15 ++++++++------- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/build.rs b/build.rs index 1c532dc7..87fb4738 100644 --- a/build.rs +++ b/build.rs @@ -40,7 +40,7 @@ fn main() { println!("cargo:warning=Compiling shaders..."); match htwv::compile_dir("shaders", "target/data/shaders") { Ok(_) => println!("cargo:warning=Shader compilation succeeded"), - Err(e) => {} // panic!("Shader compilation failed: {e}"), + Err(e) => {} //panic!("Shader compilation failed: {e}"), } } } \ No newline at end of file diff --git a/src/gfx/mtl.rs b/src/gfx/mtl.rs index 8a4f4dcb..5c97c361 100644 --- a/src/gfx/mtl.rs +++ b/src/gfx/mtl.rs @@ -317,10 +317,10 @@ impl super::CmdBuf for CmdBuf { .expect("hotline_rs::gfx::metal expected a call to begin render pass before using render commands") .set_render_pipeline_state(&pipeline.pipeline_state); - // Bind sampler argument buffer at buffer(4) per htwv convention + // Bind sampler argument buffer at buffer(0) in fragment shader if let Some(ref sampler_arg_buffer) = pipeline.sampler_argument_buffer { self.render_encoder.as_ref().unwrap().set_fragment_buffer( - 4, // samplers_offset from htwv + 0, Some(sampler_arg_buffer), 0 ); @@ -894,13 +894,14 @@ impl Device { ) -> HashMap { let mut slot_lookup: HashMap = HashMap::new(); - // htwv convention: samplers at 4, push constants start at 5 + // htwv convention: samplers at 2 on vs + // samplers at 0 on ps // Track binding offsets separately per stage since different numbers of // bindings and push constants might be active on each stage - let samplers_offset: u32 = 4; - let start_offset: u32 = samplers_offset + 1; // 5 for first push constant - let mut vertex_binding_offset: u32 = start_offset; - let mut fragment_binding_offset: u32 = start_offset; + let vertex_samplers_offset: u32 = 2; + let fragment_samplers_offset: u32 = 0; + let mut vertex_binding_offset: u32 = vertex_samplers_offset + 1; + let mut fragment_binding_offset: u32 = fragment_samplers_offset + 1; // Add push constant slots first (they come before regular bindings in htwv) if let Some(push_constants) = pipeline_push_constants.as_ref() { From 598858a3e65a2034f51262c0799120cba20a8515 Mon Sep 17 00:00:00 2001 From: polymonster Date: Thu, 26 Feb 2026 15:27:26 +0000 Subject: [PATCH 07/62] - bindless working --- src/gfx/mtl.rs | 41 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 39 insertions(+), 2 deletions(-) diff --git a/src/gfx/mtl.rs b/src/gfx/mtl.rs index 5c97c361..2b997525 100644 --- a/src/gfx/mtl.rs +++ b/src/gfx/mtl.rs @@ -344,9 +344,43 @@ impl super::CmdBuf for CmdBuf { .as_ref() .expect("hotline_rs::gfx::metal expected a call to begin render pass before using render commands"); - // Make the heap accessible to shaders - actual texture binding happens via set_binding + // Make the heap accessible to shaders encoder.use_heap_at(&heap.mtl_heap, metal::MTLRenderStages::Fragment); encoder.use_heap_at(&heap.mtl_heap, metal::MTLRenderStages::Vertex); + + // Cast pipeline to RenderPipeline to access slot_lookup + let rp: &RenderPipeline = unsafe { std::mem::transmute(pipeline) }; + + // Bind texture arrays for all ShaderResource slots (default binding at offset 0) + for ((_register, _space, descriptor_type), slot) in &rp.slot_lookup { + // Only process ShaderResource bindings (textures) + if *descriptor_type != DescriptorType::ShaderResource { + continue; + } + // Skip push constants (they have data_buffer) + if slot.data_buffer.is_some() { + continue; + } + + // Set up the argument buffer for encoding + slot.argument_encoder.set_argument_buffer(&slot.argument_buffer, 0); + + // Encode all available textures from the heap into the argument buffer + let num_textures = slot.info.count.unwrap_or(heap.texture_slots.len() as u32) as usize; + for i in 0..num_textures.min(heap.texture_slots.len()) { + if let Some(texture) = heap.texture_slots.get(i).and_then(|t| t.as_ref()) { + slot.argument_encoder.set_texture(i as u64, texture); + } + } + + // Bind the argument buffer to appropriate shader stages + if let Some(vertex_idx) = slot.vertex_buffer_index { + encoder.set_vertex_buffer(vertex_idx as u64, Some(&slot.argument_buffer), 0); + } + if let Some(fragment_idx) = slot.fragment_buffer_index { + encoder.set_fragment_buffer(fragment_idx as u64, Some(&slot.argument_buffer), 0); + } + } } fn set_binding(&mut self, pipeline: &T, register: u32, space: u32, descriptor_type: super::DescriptorType, heap: &Heap, offset: usize) -> Option<()> { @@ -973,12 +1007,15 @@ impl Device { } // Add regular binding slots + const MAX_BINDLESS_TEXTURES: u64 = 1024; if let Some(bindings) = pipeline_bindings.as_ref() { for binding in bindings { // Create argument descriptor for texture type let arg_desc = metal::ArgumentDescriptor::new(); arg_desc.set_index(0); - arg_desc.set_array_length(binding.num_descriptors.unwrap_or(1) as u64); + // Use MAX_BINDLESS_TEXTURES for unbounded arrays (None) + let array_len = binding.num_descriptors.map(|n| n as u64).unwrap_or(MAX_BINDLESS_TEXTURES); + arg_desc.set_array_length(array_len); arg_desc.set_data_type(metal::MTLDataType::Texture); arg_desc.set_access(metal::MTLArgumentAccess::ReadOnly); From 3eecd07670055658d1687d942baf9a57d53dcccb Mon Sep 17 00:00:00 2001 From: polymonster Date: Thu, 26 Feb 2026 15:45:11 +0000 Subject: [PATCH 08/62] - add limit on descriptor size --- shaders/ecs.hlsl | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/shaders/ecs.hlsl b/shaders/ecs.hlsl index 15e16a21..b79bb24d 100644 --- a/shaders/ecs.hlsl +++ b/shaders/ecs.hlsl @@ -2,7 +2,7 @@ // contains core descriptor layout to be used among different / shared ecs systems // -// generic (fat) + non-skinned mesh vertex layout +// generic (fat) + non-skinned mesh vertex layout struct vs_input_mesh { float3 position: POSITION; float2 texcoord: TEXCOORD0; @@ -130,33 +130,33 @@ struct extent_data { } // structures of arrays for indriect / bindless lookups -StructuredBuffer draws[] : register(t0, space0); -StructuredBuffer extents[] : register(t0, space1); -StructuredBuffer materials[] : register(t0, space2); -StructuredBuffer point_lights[] : register(t0, space3); -StructuredBuffer spot_lights[] : register(t0, space4); -StructuredBuffer directional_lights[] : register(t0, space5); -StructuredBuffer shadow_matrices[] : register(t0, space6); - -// textures -Texture2D textures[] : register(t0, space7); -Texture2DMS msaa8x_textures[] : register(t0, space8); -TextureCube cubemaps[] : register(t0, space9); -Texture2DArray texture_arrays[] : register(t0, space10); -Texture3D volume_textures[] : register(t0, space11); +StructuredBuffer draws[1024] : register(t0, space0); +StructuredBuffer extents[1024] : register(t0, space1); +StructuredBuffer materials[1024] : register(t0, space2); +StructuredBuffer point_lights[1024] : register(t0, space3); +StructuredBuffer spot_lights[1024] : register(t0, space4); +StructuredBuffer directional_lights[1024] : register(t0, space5); +StructuredBuffer shadow_matrices[1024] : register(t0, space6); + +// textures +Texture2D textures[1024] : register(t0, space7); +Texture2DMS msaa8x_textures[1024] : register(t0, space8); +TextureCube cubemaps[1024] : register(t0, space9); +Texture2DArray texture_arrays[1024] : register(t0, space10); +Texture3D volume_textures[1024] : register(t0, space11); // tlas -RaytracingAccelerationStructure scene_tlas[] : register(t0, space12); +RaytracingAccelerationStructure scene_tlas[1024] : register(t0, space12); // uav textures -RWTexture2D rw_textures[] : register(u0, space0); -RWTexture3D rw_volume_textures[] : register(u0, space1); +RWTexture2D rw_textures[1024] : register(u0, space0); +RWTexture3D rw_volume_textures[1024] : register(u0, space1); // main constants to obtain the indices of the buffer types ConstantBuffer world_buffer_info : register(b2); // camera data for bindless camera lookups -ConstantBuffer cameras[] : register(b3); +ConstantBuffer cameras[1024] : register(b3); // samplers SamplerState sampler0 : register(s0); From 32c37e520e2225766ff6ac87c8a96df47914feda Mon Sep 17 00:00:00 2001 From: polymonster Date: Thu, 26 Feb 2026 15:57:34 +0000 Subject: [PATCH 09/62] - properly obtain push constants slot in imgui --- src/imgui.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/imgui.rs b/src/imgui.rs index 92814dfb..8dbe7c04 100644 --- a/src/imgui.rs +++ b/src/imgui.rs @@ -13,6 +13,7 @@ use crate::gfx::CmdBuf; use crate::gfx::Device; use crate::gfx::SwapChain; use crate::gfx::Texture; +use crate::gfx::Pipeline; use maths_rs::Vec4f; @@ -454,7 +455,10 @@ fn render_draw_data( cmd.set_vertex_buffer(&buffers.vb, 0); cmd.set_index_buffer(&buffers.ib); cmd.set_render_pipeline(pipeline); - cmd.push_render_constants(0, 16, 0, &mvp); + + if let Some(c0) = pipeline.get_pipeline_slot(0, 0, gfx::DescriptorType::PushConstants) { + cmd.push_render_constants(c0.index, 16, 0, &mvp); + } let clip_off = draw_data.DisplayPos; let mut global_vtx_offset = 0; From 91f35b9c5bf83d1fe7aa893629a63eebdc6b3242 Mon Sep 17 00:00:00 2001 From: polymonster Date: Thu, 26 Feb 2026 16:06:17 +0000 Subject: [PATCH 10/62] - imgui almost --- .vscode/launch.json | 24 ++++++++++++++++++++++++ src/gfx/mtl.rs | 2 +- 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index e0d4d8db..7465efd8 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -100,6 +100,30 @@ "console": "externalTerminal", // "preLaunchTask": "examples" }, + { + "name": "bindless (macOS|Debug)", + "type": "lldb", + "request": "launch", + "program": "${workspaceFolder}/target/debug/examples/bindless", + "args": [], + "stopAtEntry": false, + // "cwd": "${fileDirname}", + "environment": [], + "console": "externalTerminal", + // "preLaunchTask": "examples" + }, + { + "name": "imgui_demo (macOS|Debug)", + "type": "lldb", + "request": "launch", + "program": "${workspaceFolder}/target/debug/examples/imgui_demo", + "args": [], + "stopAtEntry": false, + // "cwd": "${fileDirname}", + "environment": [], + "console": "externalTerminal", + // "preLaunchTask": "examples" + }, { "name": "imgui_demo (Win32|Debug)", "type": "cppvsdbg", diff --git a/src/gfx/mtl.rs b/src/gfx/mtl.rs index 2b997525..15900a79 100644 --- a/src/gfx/mtl.rs +++ b/src/gfx/mtl.rs @@ -832,7 +832,7 @@ impl super::Heap for Heap { } fn get_heap_id(&self) -> u16 { - 0 + self.id } } From 26a1c399a0214b8910415b1f1bc45da126c30393 Mon Sep 17 00:00:00 2001 From: polymonster Date: Thu, 26 Feb 2026 16:52:32 +0000 Subject: [PATCH 11/62] - imgui is working --- examples/bindful/main.rs | 2 - shaders/imgui.hlsl | 2 +- shaders/imgui.pmfx | 15 ++++- src/gfx/mtl.rs | 121 ++++++++++++++++++++++++++++++++++----- src/os/macos.rs | 1 - 5 files changed, 122 insertions(+), 19 deletions(-) diff --git a/examples/bindful/main.rs b/examples/bindful/main.rs index 3b516d31..5fc2fdca 100644 --- a/examples/bindful/main.rs +++ b/examples/bindful/main.rs @@ -153,8 +153,6 @@ fn main() -> Result<(), hotline_rs::Error> { cmdbuffer.set_scissor_rect(&scissor); cmdbuffer.set_render_pipeline(pso_pmfx); - cmdbuffer.set_heap(pso_pmfx, dev.get_shader_heap()); - let srv0 = textures[0].get_srv_index().unwrap(); let srv1 = textures[1].get_srv_index().unwrap(); let srv2 = textures[2].get_srv_index().unwrap(); diff --git a/shaders/imgui.hlsl b/shaders/imgui.hlsl index 64601d0c..120bdb27 100644 --- a/shaders/imgui.hlsl +++ b/shaders/imgui.hlsl @@ -21,7 +21,7 @@ struct PS_INPUT PS_INPUT vs_main(VS_INPUT input) { PS_INPUT output; - output.pos = mul(float4(input.pos.xy, 0.0, 1.0), ProjectionMatrix); + output.pos = mul(ProjectionMatrix, float4(input.pos.xy, 0.0, 1.0)); output.col = input.col; output.uv = input.uv; return output; diff --git a/shaders/imgui.pmfx b/shaders/imgui.pmfx index 009cc1f1..ba5a3b7d 100644 --- a/shaders/imgui.pmfx +++ b/shaders/imgui.pmfx @@ -10,6 +10,18 @@ address_w: "Wrap", } } + render_target_blend_states: { + alpha: { + blend_enabled: true + src_blend: SrcAlpha + dst_blend: InvSrcAlpha + } + } + blend_states: { + alpha: { + render_target: ["alpha"] + } + } pipelines: { default: { vs: vs_main, @@ -19,7 +31,8 @@ ], static_samplers: { sampler0: "wrap_linear" - } + }, + blend_state: "alpha" } } } diff --git a/src/gfx/mtl.rs b/src/gfx/mtl.rs index 15900a79..2f8318a5 100644 --- a/src/gfx/mtl.rs +++ b/src/gfx/mtl.rs @@ -49,7 +49,7 @@ const fn to_mtl_vertex_format(format: super::Format) -> MTLVertexFormat { super::Format::RGB32u => MTLVertexFormat::UInt3, super::Format::RGB32i => MTLVertexFormat::Int3, super::Format::RGB32f => MTLVertexFormat::Float3, - super::Format::RGBA8n => MTLVertexFormat::Char4Normalized, + super::Format::RGBA8n => MTLVertexFormat::UChar4Normalized, super::Format::RGBA8u => MTLVertexFormat::UChar4, super::Format::RGBA8i => MTLVertexFormat::Char4, super::Format::RGBA16u => MTLVertexFormat::UShort4, @@ -62,6 +62,66 @@ const fn to_mtl_vertex_format(format: super::Format) -> MTLVertexFormat { } } +fn to_mtl_primitive_type(topology: Topology) -> metal::MTLPrimitiveType { + match topology { + Topology::PointList => metal::MTLPrimitiveType::Point, + Topology::LineList => metal::MTLPrimitiveType::Line, + Topology::LineStrip => metal::MTLPrimitiveType::LineStrip, + Topology::TriangleList => metal::MTLPrimitiveType::Triangle, + Topology::TriangleStrip => metal::MTLPrimitiveType::TriangleStrip, + _ => metal::MTLPrimitiveType::Triangle, + } +} + +fn to_mtl_blend_factor(factor: &super::BlendFactor) -> metal::MTLBlendFactor { + match factor { + super::BlendFactor::Zero => metal::MTLBlendFactor::Zero, + super::BlendFactor::One => metal::MTLBlendFactor::One, + super::BlendFactor::SrcColour => metal::MTLBlendFactor::SourceColor, + super::BlendFactor::InvSrcColour => metal::MTLBlendFactor::OneMinusSourceColor, + super::BlendFactor::SrcAlpha => metal::MTLBlendFactor::SourceAlpha, + super::BlendFactor::InvSrcAlpha => metal::MTLBlendFactor::OneMinusSourceAlpha, + super::BlendFactor::DstAlpha => metal::MTLBlendFactor::DestinationAlpha, + super::BlendFactor::InvDstAlpha => metal::MTLBlendFactor::OneMinusDestinationAlpha, + super::BlendFactor::DstColour => metal::MTLBlendFactor::DestinationColor, + super::BlendFactor::InvDstColour => metal::MTLBlendFactor::OneMinusDestinationColor, + super::BlendFactor::SrcAlphaSat => metal::MTLBlendFactor::SourceAlphaSaturated, + super::BlendFactor::BlendFactor => metal::MTLBlendFactor::BlendColor, + super::BlendFactor::InvBlendFactor => metal::MTLBlendFactor::OneMinusBlendColor, + super::BlendFactor::Src1Colour => metal::MTLBlendFactor::Source1Color, + super::BlendFactor::InvSrc1Colour => metal::MTLBlendFactor::OneMinusSource1Color, + super::BlendFactor::Src1Alpha => metal::MTLBlendFactor::Source1Alpha, + super::BlendFactor::InvSrc1Alpha => metal::MTLBlendFactor::OneMinusSource1Alpha, + } +} + +fn to_mtl_blend_op(op: &super::BlendOp) -> metal::MTLBlendOperation { + match op { + super::BlendOp::Add => metal::MTLBlendOperation::Add, + super::BlendOp::Subtract => metal::MTLBlendOperation::Subtract, + super::BlendOp::RevSubtract => metal::MTLBlendOperation::ReverseSubtract, + super::BlendOp::Min => metal::MTLBlendOperation::Min, + super::BlendOp::Max => metal::MTLBlendOperation::Max, + } +} + +fn to_mtl_write_mask(mask: &super::WriteMask) -> metal::MTLColorWriteMask { + let mut mtl_mask = metal::MTLColorWriteMask::empty(); + if mask.contains(super::WriteMask::RED) { + mtl_mask |= metal::MTLColorWriteMask::Red; + } + if mask.contains(super::WriteMask::GREEN) { + mtl_mask |= metal::MTLColorWriteMask::Green; + } + if mask.contains(super::WriteMask::BLUE) { + mtl_mask |= metal::MTLColorWriteMask::Blue; + } + if mask.contains(super::WriteMask::ALPHA) { + mtl_mask |= metal::MTLColorWriteMask::Alpha; + } + mtl_mask +} + fn to_mtl_texture_usage(usage: TextureUsage) -> MTLTextureUsage { let mut mtl_usage : MTLTextureUsage = MTLTextureUsage::Unknown; if usage.contains(super::TextureUsage::SHADER_RESOURCE) { @@ -387,6 +447,10 @@ impl super::CmdBuf for CmdBuf { let encoder = self.render_encoder.as_ref() .expect("hotline_rs::gfx::metal expected a call to begin render pass before using render commands"); + // Make the heap accessible to shaders + encoder.use_heap_at(&heap.mtl_heap, metal::MTLRenderStages::Fragment); + encoder.use_heap_at(&heap.mtl_heap, metal::MTLRenderStages::Vertex); + let rp: &RenderPipeline = unsafe { std::mem::transmute(pipeline) }; // Look up the slot by (register, space, descriptor_type) @@ -511,11 +575,16 @@ impl super::CmdBuf for CmdBuf { start_instance: u32, ) { objc::rc::autoreleasepool(|| { + let primitive_type = self.bound_render_pipeline + .map(|p| unsafe { (*p).topology }) + .map(to_mtl_primitive_type) + .unwrap_or(metal::MTLPrimitiveType::Triangle); + self.render_encoder .as_ref() .expect("hotline_rs::gfx::metal expected a call to begin render pass before using render commands") .draw_indexed_primitives_instanced_base_instance( - metal::MTLPrimitiveType::TriangleStrip, + primitive_type, index_count as u64, metal::MTLIndexType::UInt16, &self.bound_index_buffer.as_ref().unwrap(), @@ -594,8 +663,10 @@ pub struct Buffer { impl super::Buffer for Buffer { fn update(&mut self, offset: usize, data: &[T]) -> result::Result<(), super::Error> { unsafe { - let data_ptr = self.metal_buffer.contents(); - std::ptr::copy_nonoverlapping(data.as_ptr() as *mut u8, data_ptr as *mut u8, data.len()); + let data_ptr = self.metal_buffer.contents() as *mut u8; + let dest_ptr = data_ptr.add(offset); + let byte_len = data.len() * std::mem::size_of::(); + std::ptr::copy_nonoverlapping(data.as_ptr() as *const u8, dest_ptr, byte_len); } Ok(()) } @@ -679,6 +750,8 @@ pub struct RenderPipeline { slot_lookup: HashMap, /// Sampler argument buffer (at buffer(4) per htwv convention) sampler_argument_buffer: Option, + /// Primitive topology for draw calls + topology: Topology, } impl super::RenderPipeline for RenderPipeline {} @@ -766,7 +839,8 @@ impl super::ReadBackRequest for ReadBackRequest { #[derive(Clone)] pub struct RenderPass { - desc: metal::RenderPassDescriptor + desc: metal::RenderPassDescriptor, + pixel_format: metal::MTLPixelFormat, } impl super::RenderPass for RenderPass { @@ -1258,14 +1332,26 @@ impl super::Device for Device { .color_attachments() .object_at(0) .unwrap(); - attachment.set_pixel_format(metal::MTLPixelFormat::BGRA8Unorm); - attachment.set_blending_enabled(false); - attachment.set_rgb_blend_operation(metal::MTLBlendOperation::Add); - attachment.set_alpha_blend_operation(metal::MTLBlendOperation::Add); - attachment.set_source_rgb_blend_factor(metal::MTLBlendFactor::SourceAlpha); - attachment.set_source_alpha_blend_factor(metal::MTLBlendFactor::SourceAlpha); - attachment.set_destination_rgb_blend_factor(metal::MTLBlendFactor::OneMinusSourceAlpha); - attachment.set_destination_alpha_blend_factor(metal::MTLBlendFactor::OneMinusSourceAlpha); + + // Get pixel format from pass, or default to BGRA8Unorm + let pixel_format = info.pass + .map(|p| p.pixel_format) + .unwrap_or(metal::MTLPixelFormat::BGRA8Unorm); + attachment.set_pixel_format(pixel_format); + + // Apply blend state from pipeline info + if let Some(b) = info.blend_info.render_target.first() { + attachment.set_blending_enabled(b.blend_enabled); + attachment.set_rgb_blend_operation(to_mtl_blend_op(&b.blend_op)); + attachment.set_alpha_blend_operation(to_mtl_blend_op(&b.blend_op_alpha)); + attachment.set_source_rgb_blend_factor(to_mtl_blend_factor(&b.src_blend)); + attachment.set_source_alpha_blend_factor(to_mtl_blend_factor(&b.src_blend_alpha)); + attachment.set_destination_rgb_blend_factor(to_mtl_blend_factor(&b.dst_blend)); + attachment.set_destination_alpha_blend_factor(to_mtl_blend_factor(&b.dst_blend_alpha)); + attachment.set_write_mask(to_mtl_write_mask(&b.write_mask)); + } else { + attachment.set_blending_enabled(false); + } // TODO: depth stencil @@ -1329,6 +1415,7 @@ impl super::Device for Device { static_samplers: pipeline_static_samplers, slot_lookup, sampler_argument_buffer, + topology: info.topology, }) }) } @@ -1560,8 +1647,14 @@ impl super::Device for Device { } } + // Get pixel format from first render target + let pixel_format = info.render_targets.first() + .map(|rt| rt.metal_texture.pixel_format()) + .unwrap_or(metal::MTLPixelFormat::BGRA8Unorm); + Ok(RenderPass{ - desc: descriptor.to_owned() + desc: descriptor.to_owned(), + pixel_format, }) }) } diff --git a/src/os/macos.rs b/src/os/macos.rs index 7f9c2a0d..28aef350 100644 --- a/src/os/macos.rs +++ b/src/os/macos.rs @@ -121,7 +121,6 @@ impl super::App for App { /// Retuns the mouse in screen coordinates fn get_mouse_pos(&self) -> super::Point { - // TODO: super::Point { x: 0, y: 0 From 9f217ac0daf767b9b89081042893f13626d64567 Mon Sep 17 00:00:00 2001 From: polymonster Date: Fri, 27 Feb 2026 10:37:23 +0000 Subject: [PATCH 12/62] - refactor to contain all bindings in a single descriptor set --- src/gfx/mtl.rs | 167 ++++++++++++++++++++++++++++--------------------- 1 file changed, 97 insertions(+), 70 deletions(-) diff --git a/src/gfx/mtl.rs b/src/gfx/mtl.rs index 2f8318a5..980e16db 100644 --- a/src/gfx/mtl.rs +++ b/src/gfx/mtl.rs @@ -411,7 +411,11 @@ impl super::CmdBuf for CmdBuf { // Cast pipeline to RenderPipeline to access slot_lookup let rp: &RenderPipeline = unsafe { std::mem::transmute(pipeline) }; - // Bind texture arrays for all ShaderResource slots (default binding at offset 0) + // Track which argument buffers we've already bound (they're shared across texture slots) + let mut bound_vertex_buffers: std::collections::HashSet = std::collections::HashSet::new(); + let mut bound_fragment_buffers: std::collections::HashSet = std::collections::HashSet::new(); + + // Encode textures and bind shared argument buffer for ((_register, _space, descriptor_type), slot) in &rp.slot_lookup { // Only process ShaderResource bindings (textures) if *descriptor_type != DescriptorType::ShaderResource { @@ -425,20 +429,32 @@ impl super::CmdBuf for CmdBuf { // Set up the argument buffer for encoding slot.argument_encoder.set_argument_buffer(&slot.argument_buffer, 0); - // Encode all available textures from the heap into the argument buffer - let num_textures = slot.info.count.unwrap_or(heap.texture_slots.len() as u32) as usize; - for i in 0..num_textures.min(heap.texture_slots.len()) { - if let Some(texture) = heap.texture_slots.get(i).and_then(|t| t.as_ref()) { - slot.argument_encoder.set_texture(i as u64, texture); + // Check if this is an array binding (bindless) or single texture (bindful) + let count = slot.info.count.unwrap_or(1) as usize; + if count > 1 { + // Array binding (bindless) - encode ALL textures from heap + for i in 0..count.min(heap.texture_slots.len()) { + if let Some(texture) = heap.texture_slots.get(i).and_then(|t| t.as_ref()) { + slot.argument_encoder.set_texture(i as u64, texture); + } + } + } else { + // Single texture binding (bindful) - encode at binding_index + if let Some(texture) = heap.texture_slots.get(slot.binding_index as usize).and_then(|t| t.as_ref()) { + slot.argument_encoder.set_texture(slot.binding_index as u64, texture); } } - // Bind the argument buffer to appropriate shader stages + // Bind the argument buffer only once per stage (it's shared across all texture slots) if let Some(vertex_idx) = slot.vertex_buffer_index { - encoder.set_vertex_buffer(vertex_idx as u64, Some(&slot.argument_buffer), 0); + if bound_vertex_buffers.insert(vertex_idx as u64) { + encoder.set_vertex_buffer(vertex_idx as u64, Some(&slot.argument_buffer), 0); + } } if let Some(fragment_idx) = slot.fragment_buffer_index { - encoder.set_fragment_buffer(fragment_idx as u64, Some(&slot.argument_buffer), 0); + if bound_fragment_buffers.insert(fragment_idx as u64) { + encoder.set_fragment_buffer(fragment_idx as u64, Some(&slot.argument_buffer), 0); + } } } } @@ -457,9 +473,9 @@ impl super::CmdBuf for CmdBuf { if let Some(slot) = rp.slot_lookup.get(&(register, space, descriptor_type)) { slot.argument_encoder.set_argument_buffer(&slot.argument_buffer, 0); - // Set texture from heap at offset + // Set texture from heap at offset, using binding_index for position in shared buffer if let Some(texture) = heap.texture_slots.get(offset).and_then(|t| t.as_ref()) { - slot.argument_encoder.set_texture(0, texture); + slot.argument_encoder.set_texture(slot.binding_index as u64, texture); } // Bind to appropriate stage(s) @@ -476,13 +492,6 @@ impl super::CmdBuf for CmdBuf { } } - /* - #[cfg(target_os = "ignore")] - fn set_texture(&mut self, texture: &Texture, slot: u32) { - self.render_encoder.as_ref().unwrap().set_fragment_texture(slot as u64, Some(&texture.metal_texture)); - } - */ - fn set_marker(&mut self, colour: u32, name: &str) { } @@ -731,6 +740,8 @@ pub struct PipelineSlot { pub argument_encoder: metal::ArgumentEncoder, /// Argument buffer containing encoded resource pointers pub argument_buffer: metal::Buffer, + /// Index within the shared argument buffer (for texture bindings) + pub binding_index: u32, /// Data buffer for push constants (None for regular descriptors) pub data_buffer: Option, /// Slot info for API compatibility @@ -990,11 +1001,7 @@ impl Device { } } - /// Build unified slot lookup following htwv convention: - /// - Slots 0-3: Reserved for vertex buffers - /// - Slot 4: Samplers - /// - Slot 5+: Push constants - /// - Slot N+: Regular bindings (after push constants) + /// Build unified slot lookup fn build_slot_lookup( &self, pipeline_bindings: &Option>, @@ -1069,6 +1076,7 @@ impl Device { fragment_buffer_index: fragment_idx, argument_encoder, argument_buffer, + binding_index: 0, // Not used for push constants data_buffer: Some(data_buffer), info: PipelineSlotInfo { index: canonical_index, @@ -1080,65 +1088,84 @@ impl Device { } } - // Add regular binding slots + // Add regular binding slots - ALL share ONE argument buffer const MAX_BINDLESS_TEXTURES: u64 = 1024; if let Some(bindings) = pipeline_bindings.as_ref() { - for binding in bindings { - // Create argument descriptor for texture type - let arg_desc = metal::ArgumentDescriptor::new(); - arg_desc.set_index(0); - // Use MAX_BINDLESS_TEXTURES for unbounded arrays (None) - let array_len = binding.num_descriptors.map(|n| n as u64).unwrap_or(MAX_BINDLESS_TEXTURES); - arg_desc.set_array_length(array_len); - arg_desc.set_data_type(metal::MTLDataType::Texture); - arg_desc.set_access(metal::MTLArgumentAccess::ReadOnly); + if !bindings.is_empty() { + // Build argument descriptors - one per binding with unique indices + let arg_descs: Vec = bindings.iter().enumerate() + .map(|(i, binding)| { + let arg_desc = metal::ArgumentDescriptor::new(); + arg_desc.set_index(i as u64); // Each binding gets unique index + let array_len = binding.num_descriptors.map(|n| n as u64).unwrap_or(MAX_BINDLESS_TEXTURES); + arg_desc.set_array_length(array_len); + arg_desc.set_data_type(metal::MTLDataType::Texture); + arg_desc.set_access(metal::MTLArgumentAccess::ReadOnly); + arg_desc.to_owned() + }) + .collect(); + // Create SINGLE encoder/buffer for ALL bindings let argument_encoder = self.metal_device.new_argument_encoder( - metal::Array::from_owned_slice(&[arg_desc.to_owned()]) + metal::Array::from_owned_slice(&arg_descs) ); let argument_buffer = self.metal_device.new_buffer( argument_encoder.encoded_length(), metal::MTLResourceOptions::StorageModeShared ); - // Determine stage indices based on visibility, using per-stage offsets - let (vertex_idx, fragment_idx, canonical_index) = match binding.visibility { - ShaderVisibility::Vertex => { - let idx = vertex_binding_offset; - vertex_binding_offset += 1; - (Some(idx), None, idx) - }, - ShaderVisibility::Fragment => { - let idx = fragment_binding_offset; - fragment_binding_offset += 1; - (None, Some(idx), idx) - }, - ShaderVisibility::All => { - let v_idx = vertex_binding_offset; - let f_idx = fragment_binding_offset; - vertex_binding_offset += 1; - fragment_binding_offset += 1; - // Use vertex index as canonical for lookup - (Some(v_idx), Some(f_idx), v_idx) - }, - _ => (None, None, 0), + // Determine if any binding needs vertex or fragment visibility + let needs_vertex = bindings.iter().any(|b| + matches!(b.visibility, ShaderVisibility::Vertex | ShaderVisibility::All)); + let needs_fragment = bindings.iter().any(|b| + matches!(b.visibility, ShaderVisibility::Fragment | ShaderVisibility::All)); + + // Single buffer index per stage (only increment once, not per binding!) + let vertex_idx = if needs_vertex { + let idx = vertex_binding_offset; + vertex_binding_offset += 1; + Some(idx) + } else { + None }; - - slot_lookup.insert( - (binding.shader_register, binding.register_space, binding.binding_type), - PipelineSlot { - vertex_buffer_index: vertex_idx, - fragment_buffer_index: fragment_idx, - argument_encoder, - argument_buffer, - data_buffer: None, - info: PipelineSlotInfo { - index: canonical_index, - count: binding.num_descriptors, + let fragment_idx = if needs_fragment { + let idx = fragment_binding_offset; + fragment_binding_offset += 1; + Some(idx) + } else { + None + }; + let canonical_index = vertex_idx.or(fragment_idx).unwrap_or(0); + + // Each binding shares buffer but has unique binding_index + for (i, binding) in bindings.iter().enumerate() { + // Per-slot visibility based on the binding's visibility + let slot_vertex_idx = match binding.visibility { + ShaderVisibility::Vertex | ShaderVisibility::All => vertex_idx, + _ => None, + }; + let slot_fragment_idx = match binding.visibility { + ShaderVisibility::Fragment | ShaderVisibility::All => fragment_idx, + _ => None, + }; + + slot_lookup.insert( + (binding.shader_register, binding.register_space, binding.binding_type), + PipelineSlot { + vertex_buffer_index: slot_vertex_idx, + fragment_buffer_index: slot_fragment_idx, + argument_encoder: argument_encoder.clone(), + argument_buffer: argument_buffer.clone(), + binding_index: i as u32, // 0, 1, 2, 3 matching shader [[id()]] + data_buffer: None, + info: PipelineSlotInfo { + index: canonical_index, + count: binding.num_descriptors, + }, + visibility: binding.visibility, }, - visibility: binding.visibility, - }, - ); + ); + } } } From f763eecfe3f7c9cea21d7f1da805c6ae14b1438d Mon Sep 17 00:00:00 2001 From: polymonster Date: Fri, 27 Feb 2026 11:05:30 +0000 Subject: [PATCH 13/62] - add provision for handling buffer vs texture bindings --- src/gfx.rs | 1 - src/gfx/mtl.rs | 84 ++++++++++++++++++++++++++++++++++++++------------ 2 files changed, 64 insertions(+), 21 deletions(-) diff --git a/src/gfx.rs b/src/gfx.rs index 1bb4182f..e78ddb39 100644 --- a/src/gfx.rs +++ b/src/gfx.rs @@ -587,7 +587,6 @@ pub enum ResourceType { /// Cubemap texture (TextureCube) TextureCube, /// Multi-sampled 2D texture (Texture2DMS) - #[serde(rename = "Texture2DMS")] Texture2DMS, /// Read-write 2D texture (RWTexture2D) RWTexture2D, diff --git a/src/gfx/mtl.rs b/src/gfx/mtl.rs index 980e16db..abc68294 100644 --- a/src/gfx/mtl.rs +++ b/src/gfx/mtl.rs @@ -140,6 +140,18 @@ fn to_mtl_texture_usage(usage: TextureUsage) -> MTLTextureUsage { mtl_usage } +fn to_mtl_data_type(resource_type: super::ResourceType) -> metal::MTLDataType { + match resource_type { + super::ResourceType::StructuredBuffer | + super::ResourceType::RWStructuredBuffer | + super::ResourceType::ConstantBuffer | + super::ResourceType::ByteAddressBuffer | + super::ResourceType::RWByteAddressBuffer | + super::ResourceType::Buffer => metal::MTLDataType::Pointer, + _ => metal::MTLDataType::Texture, // Texture2D, RWTexture2D, etc. + } +} + #[derive(Clone)] pub struct Device { metal_device: metal::Device, @@ -415,12 +427,8 @@ impl super::CmdBuf for CmdBuf { let mut bound_vertex_buffers: std::collections::HashSet = std::collections::HashSet::new(); let mut bound_fragment_buffers: std::collections::HashSet = std::collections::HashSet::new(); - // Encode textures and bind shared argument buffer - for ((_register, _space, descriptor_type), slot) in &rp.slot_lookup { - // Only process ShaderResource bindings (textures) - if *descriptor_type != DescriptorType::ShaderResource { - continue; - } + // Encode resources and bind shared argument buffer + for ((_register, _space, _descriptor_type), slot) in &rp.slot_lookup { // Skip push constants (they have data_buffer) if slot.data_buffer.is_some() { continue; @@ -429,23 +437,45 @@ impl super::CmdBuf for CmdBuf { // Set up the argument buffer for encoding slot.argument_encoder.set_argument_buffer(&slot.argument_buffer, 0); - // Check if this is an array binding (bindless) or single texture (bindful) + // Check if this is an array binding (bindless) or single resource (bindful) let count = slot.info.count.unwrap_or(1) as usize; - if count > 1 { - // Array binding (bindless) - encode ALL textures from heap - for i in 0..count.min(heap.texture_slots.len()) { - if let Some(texture) = heap.texture_slots.get(i).and_then(|t| t.as_ref()) { - slot.argument_encoder.set_texture(i as u64, texture); + + match slot.data_type { + Some(metal::MTLDataType::Pointer) => { + // Buffer binding + if count > 1 { + for i in 0..count.min(heap.buffer_slots.len()) { + if let Some(buffer) = heap.buffer_slots.get(i).and_then(|b| b.as_ref()) { + slot.argument_encoder.set_buffer(i as u64, buffer, 0); + } + } } - } - } else { - // Single texture binding (bindful) - encode at binding_index - if let Some(texture) = heap.texture_slots.get(slot.binding_index as usize).and_then(|t| t.as_ref()) { - slot.argument_encoder.set_texture(slot.binding_index as u64, texture); + else { + if let Some(buffer) = heap.buffer_slots.get(slot.binding_index as usize).and_then(|b| b.as_ref()) { + slot.argument_encoder.set_buffer(slot.binding_index as u64, buffer, 0); + } + } + }, + Some(metal::MTLDataType::Texture) => { + // Texture binding + if count > 1 { + for i in 0..count.min(heap.texture_slots.len()) { + if let Some(texture) = heap.texture_slots.get(i).and_then(|t| t.as_ref()) { + slot.argument_encoder.set_texture(i as u64, texture); + } + } + } else { + if let Some(texture) = heap.texture_slots.get(slot.binding_index as usize).and_then(|t| t.as_ref()) { + slot.argument_encoder.set_texture(slot.binding_index as u64, texture); + } + } + }, + _ => { + unimplemented!(); } } - // Bind the argument buffer only once per stage (it's shared across all texture slots) + // Bind the argument buffer only once per stage (it's shared across all slots) if let Some(vertex_idx) = slot.vertex_buffer_index { if bound_vertex_buffers.insert(vertex_idx as u64) { encoder.set_vertex_buffer(vertex_idx as u64, Some(&slot.argument_buffer), 0); @@ -742,6 +772,8 @@ pub struct PipelineSlot { pub argument_buffer: metal::Buffer, /// Index within the shared argument buffer (for texture bindings) pub binding_index: u32, + /// Metal Data type, for bindings this is Texture or Pointer (Buffer) + pub data_type: Option, /// Data buffer for push constants (None for regular descriptors) pub data_buffer: Option, /// Slot info for API compatibility @@ -1077,6 +1109,7 @@ impl Device { argument_encoder, argument_buffer, binding_index: 0, // Not used for push constants + data_type: None, // Not used for push constants data_buffer: Some(data_buffer), info: PipelineSlotInfo { index: canonical_index, @@ -1099,8 +1132,18 @@ impl Device { arg_desc.set_index(i as u64); // Each binding gets unique index let array_len = binding.num_descriptors.map(|n| n as u64).unwrap_or(MAX_BINDLESS_TEXTURES); arg_desc.set_array_length(array_len); - arg_desc.set_data_type(metal::MTLDataType::Texture); - arg_desc.set_access(metal::MTLArgumentAccess::ReadOnly); + + // Determine data type from resource_type (texture vs buffer/pointer) + let data_type = to_mtl_data_type(binding.resource_type.expect("hotline_rs::gfx::mtl: requires resource type to be set for descriptor binding")); + + // Determine access from binding_type (read vs read-write) + let access = match binding.binding_type { + DescriptorType::UnorderedAccess => metal::MTLArgumentAccess::ReadWrite, + _ => metal::MTLArgumentAccess::ReadOnly, + }; + + arg_desc.set_data_type(data_type); + arg_desc.set_access(access); arg_desc.to_owned() }) .collect(); @@ -1157,6 +1200,7 @@ impl Device { argument_encoder: argument_encoder.clone(), argument_buffer: argument_buffer.clone(), binding_index: i as u32, // 0, 1, 2, 3 matching shader [[id()]] + data_type: Some(to_mtl_data_type(binding.resource_type.expect("hotline_rs::gfx::mtl: requires resource type to be set for descriptor binding"))), data_buffer: None, info: PipelineSlotInfo { index: canonical_index, From c3f9c41c685806a95f7f98db38b7efbd7e10e739 Mon Sep 17 00:00:00 2001 From: polymonster Date: Fri, 27 Feb 2026 11:19:28 +0000 Subject: [PATCH 14/62] - formatting --- src/gfx/mtl.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/gfx/mtl.rs b/src/gfx/mtl.rs index abc68294..a8e490bb 100644 --- a/src/gfx/mtl.rs +++ b/src/gfx/mtl.rs @@ -1200,7 +1200,8 @@ impl Device { argument_encoder: argument_encoder.clone(), argument_buffer: argument_buffer.clone(), binding_index: i as u32, // 0, 1, 2, 3 matching shader [[id()]] - data_type: Some(to_mtl_data_type(binding.resource_type.expect("hotline_rs::gfx::mtl: requires resource type to be set for descriptor binding"))), + data_type: Some(to_mtl_data_type( + binding.resource_type.expect("hotline_rs::gfx::mtl: requires resource type to be set for descriptor binding"))), data_buffer: None, info: PipelineSlotInfo { index: canonical_index, From 5ce2e60918ed3ec6b7586b782c04cfc25ba8e7f5 Mon Sep 17 00:00:00 2001 From: polymonster Date: Fri, 27 Feb 2026 11:51:42 +0000 Subject: [PATCH 15/62] - mouse / keyboard in macos backend --- src/os/macos.rs | 340 +++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 282 insertions(+), 58 deletions(-) diff --git a/src/os/macos.rs b/src/os/macos.rs index 28aef350..dc89c1e1 100644 --- a/src/os/macos.rs +++ b/src/os/macos.rs @@ -3,21 +3,83 @@ extern crate objc; use core::panic; +use std::collections::HashMap; use std::time::Duration; use std::sync::Arc; use std::sync::RwLock; use winit::{ - dpi::{LogicalPosition, LogicalSize}, event::{Event, WindowEvent}, event_loop::{self, ControlFlow}, platform::pump_events::{EventLoopExtPumpEvents, PumpStatus}, raw_window_handle::{HasWindowHandle, RawWindowHandle} + dpi::{LogicalPosition, LogicalSize}, + event::{Event, WindowEvent, ElementState}, + event_loop::{self, ControlFlow}, + keyboard::{Key, PhysicalKey, KeyCode}, + platform::pump_events::{EventLoopExtPumpEvents, PumpStatus}, + raw_window_handle::{HasWindowHandle, RawWindowHandle} }; -use cocoa::{appkit::{NSEvent, NSLeftArrowFunctionKey, NSNextFunctionKey, NSView}, base::id as cocoa_id }; +use cocoa::base::id as cocoa_id; use crate::os::Rect; +/// Input state tracking (similar to ProcData in win32.rs) +#[derive(Clone)] +struct InputState { + // Mouse state - screen coordinates + mouse_pos: super::Point, + mouse_pos_prev: super::Point, + // Mouse state - window-local coordinates (from CursorMoved) + mouse_client_pos: super::Point, + mouse_down: [bool; super::MouseButton::Count as usize], + mouse_wheel: f32, + mouse_hwheel: f32, + hovered_window_id: Option, + + // Keyboard state + key_down: [bool; 256], + key_press: [bool; 256], + key_debounce: [bool; 256], + + // System keys (Ctrl, Shift, Alt) + sys_key_down: [bool; super::SysKey::Count as usize], + sys_key_press: [bool; super::SysKey::Count as usize], + sys_key_debounce: [bool; super::SysKey::Count as usize], + + // Text input + utf16_inputs: Vec, + + // Input enabled flags + keyboard_enabled: bool, + mouse_enabled: bool, +} + +impl InputState { + fn new() -> Self { + InputState { + mouse_pos: super::Point { x: 0, y: 0 }, + mouse_pos_prev: super::Point { x: 0, y: 0 }, + mouse_client_pos: super::Point { x: 0, y: 0 }, + mouse_down: [false; super::MouseButton::Count as usize], + mouse_wheel: 0.0, + mouse_hwheel: 0.0, + hovered_window_id: None, + key_down: [false; 256], + key_press: [false; 256], + key_debounce: [false; 256], + sys_key_down: [false; super::SysKey::Count as usize], + sys_key_press: [false; super::SysKey::Count as usize], + sys_key_debounce: [false; super::SysKey::Count as usize], + utf16_inputs: Vec::new(), + keyboard_enabled: true, + mouse_enabled: true, + } + } +} + #[derive(Clone)] pub struct App { - event_loop: Arc>> + event_loop: Arc>>, + input_state: Arc>, + windows: Arc>>>, } unsafe impl Send for App {} @@ -25,7 +87,10 @@ unsafe impl Sync for App {} #[derive(Clone)] pub struct Window { - winit_window: Arc + winit_window: Arc, + window_id: winit::window::WindowId, + input_state: Arc>, + events: Arc>, } unsafe impl Send for Window {} @@ -56,6 +121,71 @@ pub fn isize_id_from_window(window: &Window) -> isize { } } +impl InputState { + /// Debounce logic for keys - updates press and debounce based on current down state + fn debounce_keys(&mut self) { + for i in 0..256 { + if self.key_down[i] && !self.key_press[i] && !self.key_debounce[i] { + // First frame key down: trigger press + self.key_press[i] = true; + self.key_debounce[i] = true; + } else if self.key_press[i] { + // Subsequent frames: clear press + self.key_press[i] = false; + } else if !self.key_down[i] { + // Key released: clear debounce + self.key_debounce[i] = false; + } + } + } + + /// Debounce logic for system keys + fn debounce_sys_keys(&mut self) { + for i in 0..super::SysKey::Count as usize { + if self.sys_key_down[i] && !self.sys_key_press[i] && !self.sys_key_debounce[i] { + self.sys_key_press[i] = true; + self.sys_key_debounce[i] = true; + } else if self.sys_key_press[i] { + self.sys_key_press[i] = false; + } else if !self.sys_key_down[i] { + self.sys_key_debounce[i] = false; + } + } + } +} + +impl App { + /// Update input state at the start of each frame + fn update_input_state(&self) { + let mut state = self.input_state.write().unwrap(); + + // Reset per-frame values + state.mouse_wheel = 0.0; + state.mouse_hwheel = 0.0; + state.utf16_inputs.clear(); + + // Store previous mouse position for delta calculation + // Current mouse_pos is computed on-demand in get_mouse_pos() + state.mouse_pos_prev = state.mouse_pos; + + // Compute current screen position from window + client pos + if let Some(window_id) = state.hovered_window_id { + if let Some(window) = self.windows.read().unwrap().get(&window_id) { + if let Ok(pos) = window.outer_position() { + state.mouse_pos = super::Point { + x: pos.x + state.mouse_client_pos.x, + y: pos.y + state.mouse_client_pos.y, + }; + } + } + } + + // Debounce keys + state.debounce_keys(); + state.debounce_sys_keys(); + } +} + impl super::App for App { type Window = Window; type NativeHandle = NativeHandle; @@ -63,7 +193,9 @@ impl super::App for App { /// Create an application instance fn create(info: super::AppInfo) -> Self { App { - event_loop: Arc::new(RwLock::new(winit::event_loop::EventLoop::new().unwrap())) + event_loop: Arc::new(RwLock::new(winit::event_loop::EventLoop::new().unwrap())), + input_state: Arc::new(RwLock::new(InputState::new())), + windows: Arc::new(RwLock::new(HashMap::new())), } } @@ -75,8 +207,17 @@ impl super::App for App { .with_title(info.title) .build(&*self.event_loop.read().unwrap()) .unwrap(); + let window_id = window.id(); + let winit_window = Arc::new(window); + + // Register window for position lookups + self.windows.write().unwrap().insert(window_id, winit_window.clone()); + Window { - winit_window: Arc::new(window) + winit_window, + window_id, + input_state: self.input_state.clone(), + events: Arc::new(RwLock::new(super::WindowEventFlags::NONE)), } } @@ -88,23 +229,120 @@ impl super::App for App { /// Call to update windows and os state each frame, when false is returned the app has been requested to close fn run(&mut self) -> bool { objc::rc::autoreleasepool(|| { + // Update input state at frame start + self.update_input_state(); + let mut resume = true; + let input_state = self.input_state.clone(); + let _ = self.event_loop.write().and_then(|mut event_loop| { - let status = event_loop.pump_events(Some(Duration::ZERO), |event, elwt| { + let _status = event_loop.pump_events(Some(Duration::ZERO), |event, _elwt| { match event { - Event::WindowEvent { event, .. } => match event { - WindowEvent::CloseRequested => { - resume = false; - } - WindowEvent::RedrawRequested => { + Event::WindowEvent { event, window_id } => { + let mut state = input_state.write().unwrap(); + + match event { + WindowEvent::CloseRequested => { + resume = false; + } + WindowEvent::RedrawRequested => {} + + // Mouse cursor position (window-relative from winit) + WindowEvent::CursorMoved { position, .. } => { + if state.mouse_enabled { + // winit gives us logical coordinates relative to window content area + state.mouse_client_pos = super::Point { + x: position.x as i32, + y: position.y as i32, + }; + state.hovered_window_id = Some(window_id); + } + } + + // Mouse enter/leave for hover tracking + WindowEvent::CursorEntered { .. } => { + state.hovered_window_id = Some(window_id); + } + WindowEvent::CursorLeft { .. } => { + if state.hovered_window_id == Some(window_id) { + state.hovered_window_id = None; + } + } + + // Mouse buttons + WindowEvent::MouseInput { state: element_state, button, .. } => { + if state.mouse_enabled { + let pressed = element_state == ElementState::Pressed; + // Map to MouseButton enum order: Left=0, Middle=1, Right=2, X1=3, X2=4 + let index = match button { + winit::event::MouseButton::Left => Some(super::MouseButton::Left as usize), + winit::event::MouseButton::Middle => Some(super::MouseButton::Middle as usize), + winit::event::MouseButton::Right => Some(super::MouseButton::Right as usize), + winit::event::MouseButton::Back => Some(super::MouseButton::X1 as usize), + winit::event::MouseButton::Forward => Some(super::MouseButton::X2 as usize), + winit::event::MouseButton::Other(_) => None, + }; + if let Some(idx) = index { + state.mouse_down[idx] = pressed; + } + } + } + + // Mouse wheel + WindowEvent::MouseWheel { delta, .. } => { + if state.mouse_enabled { + match delta { + winit::event::MouseScrollDelta::LineDelta(h, v) => { + state.mouse_wheel += v; + state.mouse_hwheel += h; + } + winit::event::MouseScrollDelta::PixelDelta(pos) => { + // Convert pixel delta to line delta (approximate) + state.mouse_wheel += (pos.y / 20.0) as f32; + state.mouse_hwheel += (pos.x / 20.0) as f32; + } + } + } + } + + // Keyboard input + WindowEvent::KeyboardInput { event, .. } => { + if state.keyboard_enabled { + let pressed = event.state == ElementState::Pressed; + + // Get physical key code for key_down array + if let PhysicalKey::Code(key_code) = event.physical_key { + let code = key_code as usize; + if code < 256 { + state.key_down[code] = pressed; + } + } + + // Handle text input from logical key + if pressed { + if let Key::Character(ref c) = event.logical_key { + for ch in c.encode_utf16() { + state.utf16_inputs.push(ch); + } + } + } + } + } + + // Modifier keys + WindowEvent::ModifiersChanged(modifiers) => { + if state.keyboard_enabled { + let mods = modifiers.state(); + state.sys_key_down[super::SysKey::Ctrl as usize] = mods.control_key(); + state.sys_key_down[super::SysKey::Shift as usize] = mods.shift_key(); + state.sys_key_down[super::SysKey::Alt as usize] = mods.alt_key(); + } + } + + _ => {} } - _ => { - - } - } - _ => { - } + _ => {} } }); @@ -121,69 +359,57 @@ impl super::App for App { /// Retuns the mouse in screen coordinates fn get_mouse_pos(&self) -> super::Point { - super::Point { - x: 0, - y: 0 - } + self.input_state.read().unwrap().mouse_pos } /// Retuns the mouse vertical wheel position fn get_mouse_wheel(&self) -> f32 { - //panic!(); - // TODO: - 0.0 + self.input_state.read().unwrap().mouse_wheel } /// Retuns the mouse horizontal wheel positions fn get_mouse_hwheel(&self) -> f32 { - // panic!(); - 0.0 + self.input_state.read().unwrap().mouse_hwheel } /// Retuns the mouse button states, up or down fn get_mouse_buttons(&self) -> [bool; super::MouseButton::Count as usize] { - // panic!(); - [false; 5] + self.input_state.read().unwrap().mouse_down } /// Returns the distance the mouse has moved since the last frame fn get_mouse_pos_delta(&self) -> super::Size { - // panic!(); + let state = self.input_state.read().unwrap(); super::Size { - x: 0, - y: 0 + x: state.mouse_pos.x - state.mouse_pos_prev.x, + y: state.mouse_pos.y - state.mouse_pos_prev.y, } } /// Returns a vector of utf-16 characters that have been input since the last frame fn get_utf16_input(&self) -> Vec { - // panic!(); - vec![] + self.input_state.read().unwrap().utf16_inputs.clone() } /// Returns an array of bools containing 0-256 keys down (true) or up (false) fn get_keys_down(&self) -> [bool; 256] { - // panic!(); - [false; 256] + self.input_state.read().unwrap().key_down } /// Returns an array of bools containing 0-256 of keys pressed, will trigger only once and then require debouce fn get_keys_pressed(&self) -> [bool; 256] { - // panic!(); - [false; 256] + self.input_state.read().unwrap().key_press } /// Returns true if the sys key is down and false if the key is up fn is_sys_key_down(&self, key: super::SysKey) -> bool { - // panic!(); - false + self.input_state.read().unwrap().sys_key_down[key as usize] } /// Returns true if the sys key is pressed this frame and /// requires debounce until it is pressed again fn is_sys_key_pressed(&self, key: super::SysKey) -> bool { - // panic!(); - false + self.input_state.read().unwrap().sys_key_press[key as usize] } /// Get os system virtual key code from Key @@ -210,13 +436,15 @@ impl super::App for App { /// Set's whethere input from keybpard or mouse is available or not fn set_input_enabled(&mut self, keyboard: bool, mouse: bool) { - panic!(); + let mut state = self.input_state.write().unwrap(); + state.keyboard_enabled = keyboard; + state.mouse_enabled = mouse; } /// Get value for whether (keyboard, mouse) input is enabled fn get_input_enabled(&self) -> (bool, bool) { - panic!(); - (false, false) + let state = self.input_state.read().unwrap(); + (state.keyboard_enabled, state.mouse_enabled) } fn enumerate_display_monitors(&self) -> Vec { @@ -321,8 +549,8 @@ impl super::Window for Window { /// Returns true if the mouse if hovering this window fn is_mouse_hovered(&self) -> bool { - // TODO: - false + let state = self.input_state.read().unwrap(); + state.hovered_window_id == Some(self.window_id) } /// Set the window display title that appears on the title bar @@ -385,12 +613,10 @@ impl super::Window for Window { } /// Return mouse position in relative coordinates from the top left corner of the window - fn get_mouse_client_pos(&self, mouse_pos: super::Point) -> super::Point { - // panic!(); - super::Point { - x: 0, - y: 0 - } + fn get_mouse_client_pos(&self, _mouse_pos: super::Point) -> super::Point { + // Use the tracked client position from CursorMoved events + // which is already in window-local coordinates + self.input_state.read().unwrap().mouse_client_pos } /// Return the dpi scale for the current monitor the window is on @@ -407,14 +633,12 @@ impl super::Window for Window { /// Gets window events tracked from os update, to handle events inside external systems fn get_events(&self) -> super::WindowEventFlags { - panic!(); - super::WindowEventFlags { - bits: 0 - } + *self.events.read().unwrap() } + /// Clears events after they have been responded to fn clear_events(&mut self) { - panic!(); + *self.events.write().unwrap() = super::WindowEventFlags::NONE; } /// Const pointer From 027a736626f9ffaed76831d6ca849c67ca84950b Mon Sep 17 00:00:00 2001 From: polymonster Date: Fri, 27 Feb 2026 11:58:08 +0000 Subject: [PATCH 16/62] - fix imgui cleanup issue --- src/imgui.rs | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/imgui.rs b/src/imgui.rs index 8dbe7c04..68b61f28 100644 --- a/src/imgui.rs +++ b/src/imgui.rs @@ -595,7 +595,7 @@ impl ImGui where D: Device, A: App, D::RenderPipeline: gfx::Pipeline let io = &mut *igGetIO(); io.ConfigFlags |= ImGuiConfigFlags_DockingEnable as i32; - io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable as i32; + // io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable as i32; // construct path for ini to be along side the exe let exe_path = std::env::current_exe().ok().unwrap(); @@ -1572,10 +1572,23 @@ impl ImGui where D: Device, A: App, D::RenderPipeline: gfx::Pipeline impl Drop for ImGui where D: Device, A: App { fn drop(&mut self) { unsafe { - igDestroyPlatformWindows(); + // Clean up main viewport's user data (set during create) + let main_vp = &mut *igGetMainViewport(); + if !main_vp.PlatformUserData.is_null() { + std::ptr::drop_in_place(main_vp.PlatformUserData as *mut ViewportData); + main_vp.PlatformUserData = std::ptr::null_mut(); + } + if !main_vp.PlatformHandle.is_null() { + std::ptr::drop_in_place(main_vp.PlatformHandle as *mut A::NativeHandle); + main_vp.PlatformHandle = std::ptr::null_mut(); + } + let platform_io = &mut *igGetPlatformIO(); std::ptr::drop_in_place(platform_io.Monitors.Data as *mut ImGuiPlatformMonitor); platform_io.Monitors.Data = std::ptr::null_mut(); + + // Destroy non-main viewport windows + igDestroyPlatformWindows(); } } } From e0608135935911a45775d98d3160dc68b4c9c344 Mon Sep 17 00:00:00 2001 From: polymonster Date: Fri, 27 Feb 2026 15:15:53 +0000 Subject: [PATCH 17/62] - move htwv into repo --- .gitmodules | 6 + Cargo.toml | 3 +- build.rs | 24 +- crates/htwv/Cargo.toml | 21 + crates/htwv/build.rs | 213 + crates/htwv/src/lib.rs | 33 + crates/htwv/src/macos_impl.rs | 416 ++ crates/htwv/src/spirv_cross_bindings.rs | 5530 +++++++++++++++++++++++ crates/htwv/third_party/SPIRV-Cross | 1 + crates/htwv/third_party/pmfx-shader | 1 + 10 files changed, 6242 insertions(+), 6 deletions(-) create mode 100644 crates/htwv/Cargo.toml create mode 100644 crates/htwv/build.rs create mode 100644 crates/htwv/src/lib.rs create mode 100644 crates/htwv/src/macos_impl.rs create mode 100644 crates/htwv/src/spirv_cross_bindings.rs create mode 160000 crates/htwv/third_party/SPIRV-Cross create mode 160000 crates/htwv/third_party/pmfx-shader diff --git a/.gitmodules b/.gitmodules index 0994c715..cc8da8c6 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,9 @@ [submodule "hotline-data"] path = hotline-data url = https://github.com/polymonster/hotline-data.git +[submodule "crates/htwv/third_party/SPIRV-Cross"] + path = crates/htwv/third_party/SPIRV-Cross + url = https://github.com/KhronosGroup/SPIRV-Cross.git +[submodule "crates/htwv/third_party/pmfx-shader"] + path = crates/htwv/third_party/pmfx-shader + url = https://github.com/polymonster/pmfx-shader.git diff --git a/Cargo.toml b/Cargo.toml index 2addf1d8..69f9b06f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,6 +2,7 @@ resolver = "2" members = [ ".", + "crates/htwv", "plugins/empty", "plugins/ecs", "plugins/ecs_examples", @@ -45,7 +46,7 @@ bevy_ecs.workspace = true ddsfile = "0.5.1" [build-dependencies] -htwv = { path = "../htwv" } +htwv = { path = "crates/htwv" } [dependencies.imgui-sys] version = "0.9.0" diff --git a/build.rs b/build.rs index 87fb4738..e3f65391 100644 --- a/build.rs +++ b/build.rs @@ -22,10 +22,22 @@ fn main() { #[cfg(target_os = "macos")] fn main() { - // Tell Cargo to rerun build.rs when shaders change + use std::path::Path; + + // Rerun when source shaders change println!("cargo:rerun-if-changed=shaders"); + // Rerun when output dir changes (including deletion) + println!("cargo:rerun-if-changed=target/data/shaders"); if std::env::var("CARGO_FEATURE_BUILD_DATA").is_ok() { + let output_dir = Path::new("target/data/shaders"); + + // Check if we actually need to rebuild + let needs_build = !output_dir.exists() + || std::fs::read_dir(output_dir) + .map(|mut d| d.next().is_none()) + .unwrap_or(true); + let pmbuild = "pmbuild"; let status = Command::new(pmbuild) @@ -37,10 +49,12 @@ fn main() { panic!("pmbuild mac-data failed with status: {status}"); } - println!("cargo:warning=Compiling shaders..."); - match htwv::compile_dir("shaders", "target/data/shaders") { - Ok(_) => println!("cargo:warning=Shader compilation succeeded"), - Err(e) => {} //panic!("Shader compilation failed: {e}"), + if needs_build { + println!("cargo:warning=Compiling shaders..."); + match htwv::compile_dir("shaders", "target/data/shaders") { + Ok(_) => println!("cargo:warning=Shader compilation succeeded"), + Err(e) => {} //panic!("Shader compilation failed: {e}"), + } } } } \ No newline at end of file diff --git a/crates/htwv/Cargo.toml b/crates/htwv/Cargo.toml new file mode 100644 index 00000000..24e06e40 --- /dev/null +++ b/crates/htwv/Cargo.toml @@ -0,0 +1,21 @@ +[package] +name = "htwv" +version = "0.1.0" +edition = "2021" +description = "HLSL to Vulkan to Metal shader compilation toolchain" + +[dependencies] +glob = "0.3" +serde = { version = "1.0", features = ["derive"] } +serde_json = "1.0.81" + +# Build dependencies only needed on macOS +[target.'cfg(target_os = "macos")'.build-dependencies] +bindgen = "0.65.1" +cmake = "0.1" + +[features] +# Use Release build for C++ (faster shader compilation) +cpp-release = [] +# For regenerating bindings (developer use only) +generate-bindings = [] diff --git a/crates/htwv/build.rs b/crates/htwv/build.rs new file mode 100644 index 00000000..9f34935b --- /dev/null +++ b/crates/htwv/build.rs @@ -0,0 +1,213 @@ +fn main() { + #[cfg(target_os = "macos")] + macos_build(); +} + +#[cfg(target_os = "macos")] +fn macos_build() { + use std::path::Path; + use std::process::{Command, Stdio}; + + let manifest_dir = + std::env::var("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR not set"); + let out_dir = std::env::var("OUT_DIR").expect("OUT_DIR not set"); + + let spirv_cross_src = format!("{}/third_party/SPIRV-Cross", manifest_dir); + let pmfx_shader_src = format!("{}/third_party/pmfx-shader", manifest_dir); + + // Ensure third-party dependencies exist (download if missing for crates.io) + ensure_spirv_cross(&spirv_cross_src); + ensure_pmfx_shader(&pmfx_shader_src); + + // Rerun if SPIRV-Cross source changes + println!("cargo:rerun-if-changed={}/spirv_cross_c.h", spirv_cross_src); + + // Select build profile + let profile = if std::env::var("CARGO_FEATURE_CPP_RELEASE").is_ok() { + "Release" + } else { + match std::env::var("PROFILE") + .unwrap_or_default() + .as_str() + { + "debug" => "Debug", + _ => "Release", + } + }; + + // Build SPIRV-Cross in OUT_DIR + let build_dir = format!("{}/SPIRV-Cross", out_dir); + std::fs::create_dir_all(&build_dir).unwrap(); + + // Configure CMake + let status = Command::new("cmake") + .args([ + "-S", + &spirv_cross_src, + "-B", + &build_dir, + &format!("-DCMAKE_BUILD_TYPE={}", profile), + "-DCMAKE_OSX_DEPLOYMENT_TARGET=15.0", + "-DCMAKE_CXX_COMPILER=clang++", + ]) + .stdout(Stdio::inherit()) + .stderr(Stdio::inherit()) + .status() + .expect("Failed to run cmake configure"); + + if !status.success() { + panic!("CMake configure failed"); + } + + // Build + let status = Command::new("cmake") + .args(["--build", &build_dir, "--config", profile]) + .status() + .expect("Failed to run cmake build"); + + if !status.success() { + panic!("CMake build failed"); + } + + // Optionally regenerate bindings + if std::env::var("CARGO_FEATURE_GENERATE_BINDINGS").is_ok() { + let bindings = bindgen::Builder::default() + .header(format!("{}/spirv_cross_c.h", spirv_cross_src)) + .generate() + .expect("Failed to generate bindings for spirv_cross_c.h"); + + bindings + .write_to_file(format!("{}/src/spirv_cross_bindings.rs", manifest_dir)) + .expect("Couldn't write bindings!"); + } + + // Setup link paths + println!("cargo:rustc-link-search=native={}", build_dir); + println!("cargo:rustc-link-lib=static=spirv-cross-c"); + println!("cargo:rustc-link-lib=static=spirv-cross-core"); + println!("cargo:rustc-link-lib=static=spirv-cross-cpp"); + println!("cargo:rustc-link-lib=static=spirv-cross-glsl"); + println!("cargo:rustc-link-lib=static=spirv-cross-hlsl"); + println!("cargo:rustc-link-lib=static=spirv-cross-msl"); + println!("cargo:rustc-link-lib=static=spirv-cross-reflect"); + println!("cargo:rustc-link-lib=static=spirv-cross-util"); + println!("cargo:rustc-link-lib=c++"); +} + +#[cfg(target_os = "macos")] +fn ensure_spirv_cross(spirv_cross_dir: &str) { + use std::path::Path; + use std::process::{Command, Stdio}; + + let marker = Path::new(spirv_cross_dir).join("CMakeLists.txt"); + if marker.exists() { + return; // Already populated (submodule or previous download) + } + + println!("cargo:warning=SPIRV-Cross not found, downloading..."); + + // Pin to a specific release for reproducibility + const SPIRV_CROSS_VERSION: &str = "vulkan-sdk-1.3.275.0"; + let url = format!( + "https://github.com/KhronosGroup/SPIRV-Cross/archive/refs/tags/{}.tar.gz", + SPIRV_CROSS_VERSION + ); + + let parent = Path::new(spirv_cross_dir) + .parent() + .expect("Invalid spirv_cross_dir"); + std::fs::create_dir_all(parent).expect("Failed to create third_party dir"); + + // Download and extract + let status = Command::new("curl") + .args(["-L", "-o", "/tmp/spirv-cross.tar.gz", &url]) + .stdout(Stdio::inherit()) + .stderr(Stdio::inherit()) + .status() + .expect("Failed to download SPIRV-Cross"); + + if !status.success() { + panic!("Failed to download SPIRV-Cross from {}", url); + } + + let status = Command::new("tar") + .args([ + "-xzf", + "/tmp/spirv-cross.tar.gz", + "-C", + parent.to_str().unwrap(), + ]) + .status() + .expect("Failed to extract SPIRV-Cross"); + + if !status.success() { + panic!("Failed to extract SPIRV-Cross"); + } + + // Rename extracted directory + let extracted_name = format!("SPIRV-Cross-{}", SPIRV_CROSS_VERSION); + let extracted_path = parent.join(&extracted_name); + std::fs::rename(&extracted_path, spirv_cross_dir) + .expect("Failed to rename extracted SPIRV-Cross directory"); + + println!("cargo:warning=SPIRV-Cross downloaded successfully"); +} + +#[cfg(target_os = "macos")] +fn ensure_pmfx_shader(pmfx_shader_dir: &str) { + use std::path::Path; + use std::process::{Command, Stdio}; + + let marker = Path::new(pmfx_shader_dir).join("pmfx.py"); + if marker.exists() { + return; // Already populated + } + + println!("cargo:warning=pmfx-shader not found, downloading..."); + + // Pin to a specific commit/tag for reproducibility + const PMFX_SHADER_REF: &str = "master"; // TODO: pin to specific tag/commit + let url = format!( + "https://github.com/polymonster/pmfx-shader/archive/refs/heads/{}.tar.gz", + PMFX_SHADER_REF + ); + + let parent = Path::new(pmfx_shader_dir) + .parent() + .expect("Invalid pmfx_shader_dir"); + std::fs::create_dir_all(parent).expect("Failed to create third_party dir"); + + // Download and extract + let status = Command::new("curl") + .args(["-L", "-o", "/tmp/pmfx-shader.tar.gz", &url]) + .stdout(Stdio::inherit()) + .stderr(Stdio::inherit()) + .status() + .expect("Failed to download pmfx-shader"); + + if !status.success() { + panic!("Failed to download pmfx-shader from {}", url); + } + + let status = Command::new("tar") + .args([ + "-xzf", + "/tmp/pmfx-shader.tar.gz", + "-C", + parent.to_str().unwrap(), + ]) + .status() + .expect("Failed to extract pmfx-shader"); + + if !status.success() { + panic!("Failed to extract pmfx-shader"); + } + + // Rename extracted directory + let extracted_name = format!("pmfx-shader-{}", PMFX_SHADER_REF); + let extracted_path = parent.join(&extracted_name); + std::fs::rename(&extracted_path, pmfx_shader_dir) + .expect("Failed to rename extracted pmfx-shader directory"); + + println!("cargo:warning=pmfx-shader downloaded successfully"); +} diff --git a/crates/htwv/src/lib.rs b/crates/htwv/src/lib.rs new file mode 100644 index 00000000..79e067bf --- /dev/null +++ b/crates/htwv/src/lib.rs @@ -0,0 +1,33 @@ +//! HTWV - HLSL To Vulkan to Metal shader compilation toolchain +//! +//! This crate compiles HLSL shaders through SPIR-V to Metal Shading Language (MSL). +//! It is only functional on macOS - on other platforms it provides stub functions +//! that return errors. + +#[cfg(target_os = "macos")] +#[allow(warnings)] +mod spirv_cross_bindings; + +#[cfg(target_os = "macos")] +mod macos_impl; + +#[cfg(target_os = "macos")] +pub use macos_impl::*; + +// Stub implementations for non-macOS platforms +#[cfg(not(target_os = "macos"))] +pub fn compile_dir( + _input_dir: &str, + _output_dir: &str, +) -> Result<(), Box> { + Err("htwv shader compilation is only available on macOS".into()) +} + +#[cfg(not(target_os = "macos"))] +pub fn compile_piepline( + _filepath: &str, + _input_dir: &str, + _output_dir: &str, +) -> Result<(), Box> { + Err("htwv shader compilation is only available on macOS".into()) +} diff --git a/crates/htwv/src/macos_impl.rs b/crates/htwv/src/macos_impl.rs new file mode 100644 index 00000000..3b6c55aa --- /dev/null +++ b/crates/htwv/src/macos_impl.rs @@ -0,0 +1,416 @@ +use std::collections::HashMap; +use std::error::Error; +use std::fs::{self, File}; +use std::io::Read; +use std::path::Path; +use std::process::{Command, Stdio}; +use std::string::FromUtf8Error; + +use glob::glob; +use serde::{Deserialize, Serialize}; + +use crate::spirv_cross_bindings::*; + +fn print_cstr(msg: *const ::std::os::raw::c_char) { + println!("{}", cstr_to_string(msg).unwrap()); +} + +unsafe extern "C" fn error_callback( + _: *mut ::std::os::raw::c_void, + error: *const ::std::os::raw::c_char, +) { + print_cstr(error); +} + +fn cstr_to_string(msg: *const ::std::os::raw::c_char) -> Result { + let mut buf: Vec = Vec::new(); + unsafe { + let mut msg_iter = msg; + loop { + if *msg_iter != 0 { + buf.push(*msg_iter as u8); + } else { + break; + } + msg_iter = msg_iter.offset(1); + } + } + String::from_utf8(buf) +} + +fn load_spirv_file(path: &str) -> Vec { + println!("{}", path); + + let mut file = File::open(path).expect("failed to open .spv file"); + let mut buffer = Vec::new(); + file.read_to_end(&mut buffer) + .expect("failed to read .spv file"); + + // Convert byte buffer to u32 vector + assert!( + buffer.len() % 4 == 0, + ".spv file must align to 32-bit words" + ); + buffer + .chunks_exact(4) + .map(|chunk| u32::from_le_bytes([chunk[0], chunk[1], chunk[2], chunk[3]])) + .collect() +} + +#[derive(Serialize, Deserialize, Clone, PartialEq)] +enum ShaderStage { + Vertex, + Fragment, + Compute, + All, +} + +#[derive(Serialize, Deserialize, Clone)] +struct Resource { + name: String, + visibility: ShaderStage, +} + +#[derive(Serialize, Deserialize, Clone)] +struct PipelineLayout { + bindings: Vec, + push_constants: Vec, + static_samplers: Vec, +} + +#[derive(Serialize, Deserialize, Clone)] +struct Pipeline { + vs: Option, + ps: Option, + cs: Option, + lib: Option>, + pipeline_layout: PipelineLayout, +} +type PipelinePermutations = HashMap; + +#[derive(Serialize, Deserialize, Clone)] +struct Pmfx { + pipelines: HashMap, +} + +fn compile_shader_spirv( + filepath: &str, + input_dir: &str, + output_dir: &str, + pipeline: &Pipeline, + stage: ShaderStage, +) -> Result<(), Box> { + unsafe { + let temp_spirv = filepath + .replace(".vsc", ".spirv") + .replace(".psc", ".spirv") + .replace(".csc", ".spirv"); + + let spirv_file = format!("{}/{}", input_dir, temp_spirv); + let output_file = format!("{}/{}", output_dir, filepath); + + let spirv_binary = load_spirv_file(&spirv_file); + + let mut ctx = std::ptr::null_mut(); + let res = spvc_context_create(&mut ctx); + assert_eq!(res, spvc_result_SPVC_SUCCESS); + + // set error callback + spvc_context_set_error_callback(ctx, Some(error_callback), std::ptr::null_mut()); + + // parse IR + let mut ir = std::ptr::null_mut(); + let result = + spvc_context_parse_spirv(ctx, spirv_binary.as_ptr(), spirv_binary.len(), &mut ir); + assert_eq!(result, spvc_result_SPVC_SUCCESS); + + // create a pssl compiler + let mut compiler = std::ptr::null_mut(); + spvc_context_create_compiler( + ctx, + spvc_backend_SPVC_BACKEND_MSL, + ir, + spvc_capture_mode_SPVC_CAPTURE_MODE_TAKE_OWNERSHIP, + &mut compiler, + ); + + // create compiler options + let mut compiler_options = std::ptr::null_mut(); + let result = spvc_compiler_create_compiler_options(compiler, &mut compiler_options); + assert_eq!(result, spvc_result_SPVC_SUCCESS); + + // set compiler options + + // set MSL version + spvc_compiler_options_set_uint( + compiler_options, + spvc_compiler_option_SPVC_COMPILER_OPTION_MSL_VERSION, + 202300, // example: MSL version 2.3.0 + ); + + // Enable MSL argument buffers + spvc_compiler_options_set_bool( + compiler_options, + spvc_compiler_option_SPVC_COMPILER_OPTION_MSL_ARGUMENT_BUFFERS, + 1, + ); + + spvc_compiler_options_set_bool( + compiler_options, + spvc_compiler_option_SPVC_COMPILER_OPTION_MSL_FORCE_ACTIVE_ARGUMENT_BUFFER_RESOURCES, + 1, + ); + + // Set argument buffer tier (0 or 1) + spvc_compiler_options_set_uint( + compiler_options, + spvc_compiler_option_SPVC_COMPILER_OPTION_MSL_ARGUMENT_BUFFERS_TIER, + 1, + ); + + let result = spvc_compiler_install_compiler_options(compiler, compiler_options); + assert_eq!(result, spvc_result_SPVC_SUCCESS); + + // set bindings + + // Assume you already have a valid compiler and resources + let mut resources: spvc_resources = std::ptr::null_mut(); + let result = spvc_compiler_create_shader_resources(compiler, &mut resources); + assert_eq!(result, spvc_result_SPVC_SUCCESS); + + let resource_types = vec![ + spvc_resource_type_SPVC_RESOURCE_TYPE_UNIFORM_BUFFER, + spvc_resource_type_SPVC_RESOURCE_TYPE_STORAGE_BUFFER, + spvc_resource_type_SPVC_RESOURCE_TYPE_SEPARATE_IMAGE, + spvc_resource_type_SPVC_RESOURCE_TYPE_STORAGE_IMAGE, + spvc_resource_type_SPVC_RESOURCE_TYPE_SAMPLED_IMAGE, + spvc_resource_type_SPVC_RESOURCE_TYPE_SEPARATE_SAMPLERS, + ]; + + let resources: Vec<_> = resource_types + .into_iter() + .flat_map(|x| { + // Choose the resource type you want to query + let resource_type = x; + + // Prepare output pointers + let mut resource_list: *const spvc_reflected_resource = std::ptr::null(); + let mut resource_count: usize = 0; + + // Get the list of resources of the given type + let list_result = spvc_resources_get_resource_list_for_type( + resources, + resource_type, + &mut resource_list, + &mut resource_count, + ); + assert_eq!(list_result, spvc_result_SPVC_SUCCESS); + + (0..resource_count).map(move |i| *resource_list.add(i)) + }) + .collect(); + + let samplers_offset = if filepath.ends_with(".vsc") { 2 } else { 0 }; + + // put samplers first all in single argument buffer + for resource in &resources { + for push_constant in &pipeline.pipeline_layout.static_samplers { + let name = cstr_to_string(resource.name)?; + if push_constant.name == name.strip_prefix("type.").unwrap_or(&name) { + spvc_compiler_set_decoration( + compiler, + resource.id, + SpvDecoration__SpvDecorationDescriptorSet, + samplers_offset as u32, + ); + } + } + } + + // put push constants next + let mut binding_offset = samplers_offset + 1; + for resource in &resources { + for push_constant in &pipeline.pipeline_layout.push_constants { + let name = cstr_to_string(resource.name)?; + if push_constant.name == name.strip_prefix("type.").unwrap_or(&name) { + spvc_compiler_set_decoration( + compiler, + resource.id, + SpvDecoration__SpvDecorationDescriptorSet, + binding_offset as u32, + ); + binding_offset += 1 + } + } + } + + // set bindings based on pipeline layout + let mut binding_sub_offset = 0; + for resource in &resources { + for (_, binding) in pipeline.pipeline_layout.bindings.iter().enumerate() { + if binding.visibility == stage || binding.visibility == ShaderStage::All { + let name = cstr_to_string(resource.name)?; + if &binding.name == name.strip_prefix("type.").unwrap_or(&name) { + spvc_compiler_set_decoration( + compiler, + resource.id, + SpvDecoration__SpvDecorationDescriptorSet, + binding_offset as u32, + ); + spvc_compiler_set_decoration( + compiler, + resource.id, + SpvDecoration__SpvDecorationBinding, + binding_sub_offset as u32, + ); + binding_sub_offset += 1; + } + } + } + } + + let mut msl_src = std::ptr::null(); + let result = spvc_compiler_compile(compiler, &mut msl_src); + if result == spvc_result_SPVC_ERROR_UNSUPPORTED_SPIRV { + println!("spirv_to_pssl: spirv binary is unsupported"); + spvc_context_destroy(ctx); + } + + if result != spvc_result_SPVC_SUCCESS { + return Err(format!("SPIRV-Cross compilation failed for {}", filepath).into()); + } + + let msl_source = cstr_to_string(msl_src)?; + + // Ensure output directory exists + if let Some(parent) = Path::new(&output_file).parent() { + fs::create_dir_all(parent)?; + } + + // Write MSL source to temp .metal file + let temp_metal_file = format!("{}.metal", output_file); + fs::write(&temp_metal_file, &msl_source)?; + + // Compile .metal to .air + let air_file = format!("{}.air", output_file); + let compile_status = Command::new("xcrun") + .args([ + "-sdk", + "macosx", + "metal", + "-c", + "-frecord-sources", + &temp_metal_file, + "-o", + &air_file, + ]) + .stdout(Stdio::inherit()) + .stderr(Stdio::inherit()) + .status()?; + + if !compile_status.success() { + return Err(format!("Metal compilation failed for {}", temp_metal_file).into()); + } + + // Link .air to final output (metallib) + let link_status = Command::new("xcrun") + .args(["-sdk", "macosx", "metal", &air_file, "-o", &output_file]) + .stdout(Stdio::inherit()) + .stderr(Stdio::inherit()) + .status()?; + + if !link_status.success() { + return Err(format!("Metal linking failed for {}", air_file).into()); + } + + // Clean up intermediate files + // let _ = fs::remove_file(&temp_metal_file); + let _ = fs::remove_file(&air_file); + + println!("Compiled Metal shader: {}", output_file); + Ok(()) + } +} + +pub fn compile_piepline( + filepath: &str, + input_dir: &str, + output_dir: &str, +) -> Result<(), Box> { + let file_data = std::fs::read(filepath).unwrap(); + let file: Pmfx = serde_json::from_slice(&file_data)?; + for (_, permutation) in file.pipelines { + for (_, pipeline) in &permutation { + if let Some(vs) = &pipeline.vs { + compile_shader_spirv(&vs, input_dir, output_dir, &pipeline, ShaderStage::Vertex)?; + } + if let Some(ps) = &pipeline.ps { + compile_shader_spirv(&ps, input_dir, output_dir, &pipeline, ShaderStage::Fragment)?; + } + if let Some(cs) = &pipeline.cs { + compile_shader_spirv(&cs, input_dir, output_dir, &pipeline, ShaderStage::Compute)?; + } + } + } + + Ok(()) +} + +pub fn compile_dir(input_dir: &str, output_dir: &str) -> Result<(), Box> { + let temp_dir = "target/temp/shaders"; + + // Use CARGO_MANIFEST_DIR to locate pmfx.py relative to this crate + let pmfx_path = format!( + "{}/third_party/pmfx-shader/pmfx.py", + env!("CARGO_MANIFEST_DIR") + ); + + let status = Command::new("python3") + .args(&[ + &pmfx_path, + "-shader_platform", + "spirv", + "-shader_version", + "6_5", + "-i", + input_dir, + "-o", + output_dir, + "-t", + temp_dir, + "-num_threads", + "1", + "-f", + "-args", + "-Zpr", + "-ignores", + "raytracing", + "compute_frustum_cull", + "mesh_lit_rt_shadow", + "mesh_lit_rt_shadow2", + "mip_chain_texture2d", + "heightmap_mrt_resolve", + ]) + .stdout(Stdio::inherit()) + .stderr(Stdio::inherit()) + .status() + .expect("failed compiling pmfx"); + + assert!(status.code().unwrap() == 0); + + for entry in glob(&format!("{output_dir}/**/*.json")).expect("") { + if let Ok(path) = entry { + compile_piepline(path.to_str().unwrap(), temp_dir, output_dir)?; + } + } + + Ok(()) +} + +#[cfg(test)] +mod tests { + #[test] + fn run() { + super::compile_dir("../hotline/shaders", "target/shaders").unwrap(); + } +} diff --git a/crates/htwv/src/spirv_cross_bindings.rs b/crates/htwv/src/spirv_cross_bindings.rs new file mode 100644 index 00000000..e59a889d --- /dev/null +++ b/crates/htwv/src/spirv_cross_bindings.rs @@ -0,0 +1,5530 @@ +/* automatically generated by rust-bindgen 0.65.1 */ + +pub const _VCRT_COMPILER_PREPROCESSOR: u32 = 1; +pub const _SAL_VERSION: u32 = 20; +pub const __SAL_H_VERSION: u32 = 180000000; +pub const _USE_DECLSPECS_FOR_SAL: u32 = 0; +pub const _USE_ATTRIBUTES_FOR_SAL: u32 = 0; +pub const _CRT_PACKING: u32 = 8; +pub const _HAS_EXCEPTIONS: u32 = 1; +pub const _STL_LANG: u32 = 0; +pub const _HAS_CXX17: u32 = 0; +pub const _HAS_CXX20: u32 = 0; +pub const _HAS_CXX23: u32 = 0; +pub const _HAS_NODISCARD: u32 = 0; +pub const _ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE: u32 = 1; +pub const _CRT_BUILD_DESKTOP_APP: u32 = 1; +pub const _ARGMAX: u32 = 100; +pub const _CRT_INT_MAX: u32 = 2147483647; +pub const _CRT_FUNCTIONS_REQUIRED: u32 = 1; +pub const _CRT_HAS_CXX17: u32 = 0; +pub const _CRT_HAS_C11: u32 = 1; +pub const _CRT_INTERNAL_NONSTDC_NAMES: u32 = 1; +pub const __STDC_SECURE_LIB__: u32 = 200411; +pub const __GOT_SECURE_LIB__: u32 = 200411; +pub const __STDC_WANT_SECURE_LIB__: u32 = 1; +pub const _SECURECRT_FILL_BUFFER_PATTERN: u32 = 254; +pub const _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES: u32 = 0; +pub const _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES_COUNT: u32 = 0; +pub const _CRT_SECURE_CPP_OVERLOAD_SECURE_NAMES: u32 = 1; +pub const _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES_MEMORY: u32 = 0; +pub const _CRT_SECURE_CPP_OVERLOAD_SECURE_NAMES_MEMORY: u32 = 0; +pub const SPV_VERSION: u32 = 67072; +pub const SPV_REVISION: u32 = 1; +pub const SPVC_C_API_VERSION_MAJOR: u32 = 0; +pub const SPVC_C_API_VERSION_MINOR: u32 = 67; +pub const SPVC_C_API_VERSION_PATCH: u32 = 0; +pub const SPVC_COMPILER_OPTION_COMMON_BIT: u32 = 16777216; +pub const SPVC_COMPILER_OPTION_GLSL_BIT: u32 = 33554432; +pub const SPVC_COMPILER_OPTION_HLSL_BIT: u32 = 67108864; +pub const SPVC_COMPILER_OPTION_MSL_BIT: u32 = 134217728; +pub const SPVC_COMPILER_OPTION_LANG_BITS: u32 = 251658240; +pub const SPVC_COMPILER_OPTION_ENUM_BITS: u32 = 16777215; +pub const SPVC_MSL_PUSH_CONSTANT_DESC_SET: i32 = -1; +pub const SPVC_MSL_PUSH_CONSTANT_BINDING: u32 = 0; +pub const SPVC_MSL_SWIZZLE_BUFFER_BINDING: i32 = -2; +pub const SPVC_MSL_BUFFER_SIZE_BUFFER_BINDING: i32 = -3; +pub const SPVC_MSL_ARGUMENT_BUFFER_BINDING: i32 = -4; +pub const SPVC_MSL_AUX_BUFFER_STRUCT_VERSION: u32 = 1; +pub const SPVC_HLSL_PUSH_CONSTANT_DESC_SET: i32 = -1; +pub const SPVC_HLSL_PUSH_CONSTANT_BINDING: u32 = 0; +pub type va_list = *mut ::std::os::raw::c_char; +extern "C" { + pub fn __va_start(arg1: *mut *mut ::std::os::raw::c_char, ...); +} +pub type __vcrt_bool = bool; +pub type wchar_t = ::std::os::raw::c_ushort; +extern "C" { + pub fn __security_init_cookie(); +} +extern "C" { + pub fn __security_check_cookie(_StackCookie: usize); +} +extern "C" { + pub fn __report_gsfailure(_StackCookie: usize) -> !; +} +extern "C" { + pub static mut __security_cookie: usize; +} +pub type __crt_bool = bool; +extern "C" { + pub fn _invalid_parameter_noinfo(); +} +extern "C" { + pub fn _invalid_parameter_noinfo_noreturn() -> !; +} +extern "C" { + pub fn _invoke_watson( + _Expression: *const wchar_t, + _FunctionName: *const wchar_t, + _FileName: *const wchar_t, + _LineNo: ::std::os::raw::c_uint, + _Reserved: usize, + ) -> !; +} +pub type errno_t = ::std::os::raw::c_int; +pub type wint_t = ::std::os::raw::c_ushort; +pub type wctype_t = ::std::os::raw::c_ushort; +pub type __time32_t = ::std::os::raw::c_long; +pub type __time64_t = ::std::os::raw::c_longlong; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct __crt_locale_data_public { + pub _locale_pctype: *const ::std::os::raw::c_ushort, + pub _locale_mb_cur_max: ::std::os::raw::c_int, + pub _locale_lc_codepage: ::std::os::raw::c_uint, +} +#[test] +fn bindgen_test_layout___crt_locale_data_public() { + const UNINIT: ::std::mem::MaybeUninit<__crt_locale_data_public> = + ::std::mem::MaybeUninit::uninit(); + let ptr = UNINIT.as_ptr(); + assert_eq!( + ::std::mem::size_of::<__crt_locale_data_public>(), + 16usize, + concat!("Size of: ", stringify!(__crt_locale_data_public)) + ); + assert_eq!( + ::std::mem::align_of::<__crt_locale_data_public>(), + 8usize, + concat!("Alignment of ", stringify!(__crt_locale_data_public)) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr)._locale_pctype) as usize - ptr as usize }, + 0usize, + concat!( + "Offset of field: ", + stringify!(__crt_locale_data_public), + "::", + stringify!(_locale_pctype) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr)._locale_mb_cur_max) as usize - ptr as usize }, + 8usize, + concat!( + "Offset of field: ", + stringify!(__crt_locale_data_public), + "::", + stringify!(_locale_mb_cur_max) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr)._locale_lc_codepage) as usize - ptr as usize }, + 12usize, + concat!( + "Offset of field: ", + stringify!(__crt_locale_data_public), + "::", + stringify!(_locale_lc_codepage) + ) + ); +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct __crt_locale_pointers { + pub locinfo: *mut __crt_locale_data, + pub mbcinfo: *mut __crt_multibyte_data, +} +#[test] +fn bindgen_test_layout___crt_locale_pointers() { + const UNINIT: ::std::mem::MaybeUninit<__crt_locale_pointers> = + ::std::mem::MaybeUninit::uninit(); + let ptr = UNINIT.as_ptr(); + assert_eq!( + ::std::mem::size_of::<__crt_locale_pointers>(), + 16usize, + concat!("Size of: ", stringify!(__crt_locale_pointers)) + ); + assert_eq!( + ::std::mem::align_of::<__crt_locale_pointers>(), + 8usize, + concat!("Alignment of ", stringify!(__crt_locale_pointers)) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).locinfo) as usize - ptr as usize }, + 0usize, + concat!( + "Offset of field: ", + stringify!(__crt_locale_pointers), + "::", + stringify!(locinfo) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).mbcinfo) as usize - ptr as usize }, + 8usize, + concat!( + "Offset of field: ", + stringify!(__crt_locale_pointers), + "::", + stringify!(mbcinfo) + ) + ); +} +pub type _locale_t = *mut __crt_locale_pointers; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct _Mbstatet { + pub _Wchar: ::std::os::raw::c_ulong, + pub _Byte: ::std::os::raw::c_ushort, + pub _State: ::std::os::raw::c_ushort, +} +#[test] +fn bindgen_test_layout__Mbstatet() { + const UNINIT: ::std::mem::MaybeUninit<_Mbstatet> = ::std::mem::MaybeUninit::uninit(); + let ptr = UNINIT.as_ptr(); + assert_eq!( + ::std::mem::size_of::<_Mbstatet>(), + 8usize, + concat!("Size of: ", stringify!(_Mbstatet)) + ); + assert_eq!( + ::std::mem::align_of::<_Mbstatet>(), + 4usize, + concat!("Alignment of ", stringify!(_Mbstatet)) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr)._Wchar) as usize - ptr as usize }, + 0usize, + concat!( + "Offset of field: ", + stringify!(_Mbstatet), + "::", + stringify!(_Wchar) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr)._Byte) as usize - ptr as usize }, + 4usize, + concat!( + "Offset of field: ", + stringify!(_Mbstatet), + "::", + stringify!(_Byte) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr)._State) as usize - ptr as usize }, + 6usize, + concat!( + "Offset of field: ", + stringify!(_Mbstatet), + "::", + stringify!(_State) + ) + ); +} +pub type mbstate_t = _Mbstatet; +pub type time_t = __time64_t; +pub type rsize_t = usize; +extern "C" { + pub fn _errno() -> *mut ::std::os::raw::c_int; +} +extern "C" { + pub fn _set_errno(_Value: ::std::os::raw::c_int) -> errno_t; +} +extern "C" { + pub fn _get_errno(_Value: *mut ::std::os::raw::c_int) -> errno_t; +} +extern "C" { + pub fn __threadid() -> ::std::os::raw::c_ulong; +} +extern "C" { + pub fn __threadhandle() -> usize; +} +pub type SpvId = ::std::os::raw::c_uint; +pub const SpvMagicNumber: ::std::os::raw::c_uint = 119734787; +pub const SpvVersion: ::std::os::raw::c_uint = 67072; +pub const SpvRevision: ::std::os::raw::c_uint = 1; +pub const SpvOpCodeMask: ::std::os::raw::c_uint = 65535; +pub const SpvWordCountShift: ::std::os::raw::c_uint = 16; +pub const SpvSourceLanguage__SpvSourceLanguageUnknown: SpvSourceLanguage_ = 0; +pub const SpvSourceLanguage__SpvSourceLanguageESSL: SpvSourceLanguage_ = 1; +pub const SpvSourceLanguage__SpvSourceLanguageGLSL: SpvSourceLanguage_ = 2; +pub const SpvSourceLanguage__SpvSourceLanguageOpenCL_C: SpvSourceLanguage_ = 3; +pub const SpvSourceLanguage__SpvSourceLanguageOpenCL_CPP: SpvSourceLanguage_ = 4; +pub const SpvSourceLanguage__SpvSourceLanguageHLSL: SpvSourceLanguage_ = 5; +pub const SpvSourceLanguage__SpvSourceLanguageCPP_for_OpenCL: SpvSourceLanguage_ = 6; +pub const SpvSourceLanguage__SpvSourceLanguageSYCL: SpvSourceLanguage_ = 7; +pub const SpvSourceLanguage__SpvSourceLanguageHERO_C: SpvSourceLanguage_ = 8; +pub const SpvSourceLanguage__SpvSourceLanguageNZSL: SpvSourceLanguage_ = 9; +pub const SpvSourceLanguage__SpvSourceLanguageWGSL: SpvSourceLanguage_ = 10; +pub const SpvSourceLanguage__SpvSourceLanguageSlang: SpvSourceLanguage_ = 11; +pub const SpvSourceLanguage__SpvSourceLanguageZig: SpvSourceLanguage_ = 12; +pub const SpvSourceLanguage__SpvSourceLanguageRust: SpvSourceLanguage_ = 13; +pub const SpvSourceLanguage__SpvSourceLanguageMax: SpvSourceLanguage_ = 2147483647; +pub type SpvSourceLanguage_ = ::std::os::raw::c_int; +pub use self::SpvSourceLanguage_ as SpvSourceLanguage; +pub const SpvExecutionModel__SpvExecutionModelVertex: SpvExecutionModel_ = 0; +pub const SpvExecutionModel__SpvExecutionModelTessellationControl: SpvExecutionModel_ = 1; +pub const SpvExecutionModel__SpvExecutionModelTessellationEvaluation: SpvExecutionModel_ = 2; +pub const SpvExecutionModel__SpvExecutionModelGeometry: SpvExecutionModel_ = 3; +pub const SpvExecutionModel__SpvExecutionModelFragment: SpvExecutionModel_ = 4; +pub const SpvExecutionModel__SpvExecutionModelGLCompute: SpvExecutionModel_ = 5; +pub const SpvExecutionModel__SpvExecutionModelKernel: SpvExecutionModel_ = 6; +pub const SpvExecutionModel__SpvExecutionModelTaskNV: SpvExecutionModel_ = 5267; +pub const SpvExecutionModel__SpvExecutionModelMeshNV: SpvExecutionModel_ = 5268; +pub const SpvExecutionModel__SpvExecutionModelRayGenerationKHR: SpvExecutionModel_ = 5313; +pub const SpvExecutionModel__SpvExecutionModelRayGenerationNV: SpvExecutionModel_ = 5313; +pub const SpvExecutionModel__SpvExecutionModelIntersectionKHR: SpvExecutionModel_ = 5314; +pub const SpvExecutionModel__SpvExecutionModelIntersectionNV: SpvExecutionModel_ = 5314; +pub const SpvExecutionModel__SpvExecutionModelAnyHitKHR: SpvExecutionModel_ = 5315; +pub const SpvExecutionModel__SpvExecutionModelAnyHitNV: SpvExecutionModel_ = 5315; +pub const SpvExecutionModel__SpvExecutionModelClosestHitKHR: SpvExecutionModel_ = 5316; +pub const SpvExecutionModel__SpvExecutionModelClosestHitNV: SpvExecutionModel_ = 5316; +pub const SpvExecutionModel__SpvExecutionModelMissKHR: SpvExecutionModel_ = 5317; +pub const SpvExecutionModel__SpvExecutionModelMissNV: SpvExecutionModel_ = 5317; +pub const SpvExecutionModel__SpvExecutionModelCallableKHR: SpvExecutionModel_ = 5318; +pub const SpvExecutionModel__SpvExecutionModelCallableNV: SpvExecutionModel_ = 5318; +pub const SpvExecutionModel__SpvExecutionModelTaskEXT: SpvExecutionModel_ = 5364; +pub const SpvExecutionModel__SpvExecutionModelMeshEXT: SpvExecutionModel_ = 5365; +pub const SpvExecutionModel__SpvExecutionModelMax: SpvExecutionModel_ = 2147483647; +pub type SpvExecutionModel_ = ::std::os::raw::c_int; +pub use self::SpvExecutionModel_ as SpvExecutionModel; +pub const SpvAddressingModel__SpvAddressingModelLogical: SpvAddressingModel_ = 0; +pub const SpvAddressingModel__SpvAddressingModelPhysical32: SpvAddressingModel_ = 1; +pub const SpvAddressingModel__SpvAddressingModelPhysical64: SpvAddressingModel_ = 2; +pub const SpvAddressingModel__SpvAddressingModelPhysicalStorageBuffer64: SpvAddressingModel_ = 5348; +pub const SpvAddressingModel__SpvAddressingModelPhysicalStorageBuffer64EXT: SpvAddressingModel_ = + 5348; +pub const SpvAddressingModel__SpvAddressingModelMax: SpvAddressingModel_ = 2147483647; +pub type SpvAddressingModel_ = ::std::os::raw::c_int; +pub use self::SpvAddressingModel_ as SpvAddressingModel; +pub const SpvMemoryModel__SpvMemoryModelSimple: SpvMemoryModel_ = 0; +pub const SpvMemoryModel__SpvMemoryModelGLSL450: SpvMemoryModel_ = 1; +pub const SpvMemoryModel__SpvMemoryModelOpenCL: SpvMemoryModel_ = 2; +pub const SpvMemoryModel__SpvMemoryModelVulkan: SpvMemoryModel_ = 3; +pub const SpvMemoryModel__SpvMemoryModelVulkanKHR: SpvMemoryModel_ = 3; +pub const SpvMemoryModel__SpvMemoryModelMax: SpvMemoryModel_ = 2147483647; +pub type SpvMemoryModel_ = ::std::os::raw::c_int; +pub use self::SpvMemoryModel_ as SpvMemoryModel; +pub const SpvExecutionMode__SpvExecutionModeInvocations: SpvExecutionMode_ = 0; +pub const SpvExecutionMode__SpvExecutionModeSpacingEqual: SpvExecutionMode_ = 1; +pub const SpvExecutionMode__SpvExecutionModeSpacingFractionalEven: SpvExecutionMode_ = 2; +pub const SpvExecutionMode__SpvExecutionModeSpacingFractionalOdd: SpvExecutionMode_ = 3; +pub const SpvExecutionMode__SpvExecutionModeVertexOrderCw: SpvExecutionMode_ = 4; +pub const SpvExecutionMode__SpvExecutionModeVertexOrderCcw: SpvExecutionMode_ = 5; +pub const SpvExecutionMode__SpvExecutionModePixelCenterInteger: SpvExecutionMode_ = 6; +pub const SpvExecutionMode__SpvExecutionModeOriginUpperLeft: SpvExecutionMode_ = 7; +pub const SpvExecutionMode__SpvExecutionModeOriginLowerLeft: SpvExecutionMode_ = 8; +pub const SpvExecutionMode__SpvExecutionModeEarlyFragmentTests: SpvExecutionMode_ = 9; +pub const SpvExecutionMode__SpvExecutionModePointMode: SpvExecutionMode_ = 10; +pub const SpvExecutionMode__SpvExecutionModeXfb: SpvExecutionMode_ = 11; +pub const SpvExecutionMode__SpvExecutionModeDepthReplacing: SpvExecutionMode_ = 12; +pub const SpvExecutionMode__SpvExecutionModeDepthGreater: SpvExecutionMode_ = 14; +pub const SpvExecutionMode__SpvExecutionModeDepthLess: SpvExecutionMode_ = 15; +pub const SpvExecutionMode__SpvExecutionModeDepthUnchanged: SpvExecutionMode_ = 16; +pub const SpvExecutionMode__SpvExecutionModeLocalSize: SpvExecutionMode_ = 17; +pub const SpvExecutionMode__SpvExecutionModeLocalSizeHint: SpvExecutionMode_ = 18; +pub const SpvExecutionMode__SpvExecutionModeInputPoints: SpvExecutionMode_ = 19; +pub const SpvExecutionMode__SpvExecutionModeInputLines: SpvExecutionMode_ = 20; +pub const SpvExecutionMode__SpvExecutionModeInputLinesAdjacency: SpvExecutionMode_ = 21; +pub const SpvExecutionMode__SpvExecutionModeTriangles: SpvExecutionMode_ = 22; +pub const SpvExecutionMode__SpvExecutionModeInputTrianglesAdjacency: SpvExecutionMode_ = 23; +pub const SpvExecutionMode__SpvExecutionModeQuads: SpvExecutionMode_ = 24; +pub const SpvExecutionMode__SpvExecutionModeIsolines: SpvExecutionMode_ = 25; +pub const SpvExecutionMode__SpvExecutionModeOutputVertices: SpvExecutionMode_ = 26; +pub const SpvExecutionMode__SpvExecutionModeOutputPoints: SpvExecutionMode_ = 27; +pub const SpvExecutionMode__SpvExecutionModeOutputLineStrip: SpvExecutionMode_ = 28; +pub const SpvExecutionMode__SpvExecutionModeOutputTriangleStrip: SpvExecutionMode_ = 29; +pub const SpvExecutionMode__SpvExecutionModeVecTypeHint: SpvExecutionMode_ = 30; +pub const SpvExecutionMode__SpvExecutionModeContractionOff: SpvExecutionMode_ = 31; +pub const SpvExecutionMode__SpvExecutionModeInitializer: SpvExecutionMode_ = 33; +pub const SpvExecutionMode__SpvExecutionModeFinalizer: SpvExecutionMode_ = 34; +pub const SpvExecutionMode__SpvExecutionModeSubgroupSize: SpvExecutionMode_ = 35; +pub const SpvExecutionMode__SpvExecutionModeSubgroupsPerWorkgroup: SpvExecutionMode_ = 36; +pub const SpvExecutionMode__SpvExecutionModeSubgroupsPerWorkgroupId: SpvExecutionMode_ = 37; +pub const SpvExecutionMode__SpvExecutionModeLocalSizeId: SpvExecutionMode_ = 38; +pub const SpvExecutionMode__SpvExecutionModeLocalSizeHintId: SpvExecutionMode_ = 39; +pub const SpvExecutionMode__SpvExecutionModeNonCoherentColorAttachmentReadEXT: SpvExecutionMode_ = + 4169; +pub const SpvExecutionMode__SpvExecutionModeNonCoherentDepthAttachmentReadEXT: SpvExecutionMode_ = + 4170; +pub const SpvExecutionMode__SpvExecutionModeNonCoherentStencilAttachmentReadEXT: SpvExecutionMode_ = + 4171; +pub const SpvExecutionMode__SpvExecutionModeSubgroupUniformControlFlowKHR: SpvExecutionMode_ = 4421; +pub const SpvExecutionMode__SpvExecutionModePostDepthCoverage: SpvExecutionMode_ = 4446; +pub const SpvExecutionMode__SpvExecutionModeDenormPreserve: SpvExecutionMode_ = 4459; +pub const SpvExecutionMode__SpvExecutionModeDenormFlushToZero: SpvExecutionMode_ = 4460; +pub const SpvExecutionMode__SpvExecutionModeSignedZeroInfNanPreserve: SpvExecutionMode_ = 4461; +pub const SpvExecutionMode__SpvExecutionModeRoundingModeRTE: SpvExecutionMode_ = 4462; +pub const SpvExecutionMode__SpvExecutionModeRoundingModeRTZ: SpvExecutionMode_ = 4463; +pub const SpvExecutionMode__SpvExecutionModeNonCoherentTileAttachmentReadQCOM: SpvExecutionMode_ = + 4489; +pub const SpvExecutionMode__SpvExecutionModeTileShadingRateQCOM: SpvExecutionMode_ = 4490; +pub const SpvExecutionMode__SpvExecutionModeEarlyAndLateFragmentTestsAMD: SpvExecutionMode_ = 5017; +pub const SpvExecutionMode__SpvExecutionModeStencilRefReplacingEXT: SpvExecutionMode_ = 5027; +pub const SpvExecutionMode__SpvExecutionModeCoalescingAMDX: SpvExecutionMode_ = 5069; +pub const SpvExecutionMode__SpvExecutionModeIsApiEntryAMDX: SpvExecutionMode_ = 5070; +pub const SpvExecutionMode__SpvExecutionModeMaxNodeRecursionAMDX: SpvExecutionMode_ = 5071; +pub const SpvExecutionMode__SpvExecutionModeStaticNumWorkgroupsAMDX: SpvExecutionMode_ = 5072; +pub const SpvExecutionMode__SpvExecutionModeShaderIndexAMDX: SpvExecutionMode_ = 5073; +pub const SpvExecutionMode__SpvExecutionModeMaxNumWorkgroupsAMDX: SpvExecutionMode_ = 5077; +pub const SpvExecutionMode__SpvExecutionModeStencilRefUnchangedFrontAMD: SpvExecutionMode_ = 5079; +pub const SpvExecutionMode__SpvExecutionModeStencilRefGreaterFrontAMD: SpvExecutionMode_ = 5080; +pub const SpvExecutionMode__SpvExecutionModeStencilRefLessFrontAMD: SpvExecutionMode_ = 5081; +pub const SpvExecutionMode__SpvExecutionModeStencilRefUnchangedBackAMD: SpvExecutionMode_ = 5082; +pub const SpvExecutionMode__SpvExecutionModeStencilRefGreaterBackAMD: SpvExecutionMode_ = 5083; +pub const SpvExecutionMode__SpvExecutionModeStencilRefLessBackAMD: SpvExecutionMode_ = 5084; +pub const SpvExecutionMode__SpvExecutionModeQuadDerivativesKHR: SpvExecutionMode_ = 5088; +pub const SpvExecutionMode__SpvExecutionModeRequireFullQuadsKHR: SpvExecutionMode_ = 5089; +pub const SpvExecutionMode__SpvExecutionModeSharesInputWithAMDX: SpvExecutionMode_ = 5102; +pub const SpvExecutionMode__SpvExecutionModeOutputLinesEXT: SpvExecutionMode_ = 5269; +pub const SpvExecutionMode__SpvExecutionModeOutputLinesNV: SpvExecutionMode_ = 5269; +pub const SpvExecutionMode__SpvExecutionModeOutputPrimitivesEXT: SpvExecutionMode_ = 5270; +pub const SpvExecutionMode__SpvExecutionModeOutputPrimitivesNV: SpvExecutionMode_ = 5270; +pub const SpvExecutionMode__SpvExecutionModeDerivativeGroupQuadsKHR: SpvExecutionMode_ = 5289; +pub const SpvExecutionMode__SpvExecutionModeDerivativeGroupQuadsNV: SpvExecutionMode_ = 5289; +pub const SpvExecutionMode__SpvExecutionModeDerivativeGroupLinearKHR: SpvExecutionMode_ = 5290; +pub const SpvExecutionMode__SpvExecutionModeDerivativeGroupLinearNV: SpvExecutionMode_ = 5290; +pub const SpvExecutionMode__SpvExecutionModeOutputTrianglesEXT: SpvExecutionMode_ = 5298; +pub const SpvExecutionMode__SpvExecutionModeOutputTrianglesNV: SpvExecutionMode_ = 5298; +pub const SpvExecutionMode__SpvExecutionModePixelInterlockOrderedEXT: SpvExecutionMode_ = 5366; +pub const SpvExecutionMode__SpvExecutionModePixelInterlockUnorderedEXT: SpvExecutionMode_ = 5367; +pub const SpvExecutionMode__SpvExecutionModeSampleInterlockOrderedEXT: SpvExecutionMode_ = 5368; +pub const SpvExecutionMode__SpvExecutionModeSampleInterlockUnorderedEXT: SpvExecutionMode_ = 5369; +pub const SpvExecutionMode__SpvExecutionModeShadingRateInterlockOrderedEXT: SpvExecutionMode_ = + 5370; +pub const SpvExecutionMode__SpvExecutionModeShadingRateInterlockUnorderedEXT: SpvExecutionMode_ = + 5371; +pub const SpvExecutionMode__SpvExecutionModeSharedLocalMemorySizeINTEL: SpvExecutionMode_ = 5618; +pub const SpvExecutionMode__SpvExecutionModeRoundingModeRTPINTEL: SpvExecutionMode_ = 5620; +pub const SpvExecutionMode__SpvExecutionModeRoundingModeRTNINTEL: SpvExecutionMode_ = 5621; +pub const SpvExecutionMode__SpvExecutionModeFloatingPointModeALTINTEL: SpvExecutionMode_ = 5622; +pub const SpvExecutionMode__SpvExecutionModeFloatingPointModeIEEEINTEL: SpvExecutionMode_ = 5623; +pub const SpvExecutionMode__SpvExecutionModeMaxWorkgroupSizeINTEL: SpvExecutionMode_ = 5893; +pub const SpvExecutionMode__SpvExecutionModeMaxWorkDimINTEL: SpvExecutionMode_ = 5894; +pub const SpvExecutionMode__SpvExecutionModeNoGlobalOffsetINTEL: SpvExecutionMode_ = 5895; +pub const SpvExecutionMode__SpvExecutionModeNumSIMDWorkitemsINTEL: SpvExecutionMode_ = 5896; +pub const SpvExecutionMode__SpvExecutionModeSchedulerTargetFmaxMhzINTEL: SpvExecutionMode_ = 5903; +pub const SpvExecutionMode__SpvExecutionModeMaximallyReconvergesKHR: SpvExecutionMode_ = 6023; +pub const SpvExecutionMode__SpvExecutionModeFPFastMathDefault: SpvExecutionMode_ = 6028; +pub const SpvExecutionMode__SpvExecutionModeStreamingInterfaceINTEL: SpvExecutionMode_ = 6154; +pub const SpvExecutionMode__SpvExecutionModeRegisterMapInterfaceINTEL: SpvExecutionMode_ = 6160; +pub const SpvExecutionMode__SpvExecutionModeNamedBarrierCountINTEL: SpvExecutionMode_ = 6417; +pub const SpvExecutionMode__SpvExecutionModeMaximumRegistersINTEL: SpvExecutionMode_ = 6461; +pub const SpvExecutionMode__SpvExecutionModeMaximumRegistersIdINTEL: SpvExecutionMode_ = 6462; +pub const SpvExecutionMode__SpvExecutionModeNamedMaximumRegistersINTEL: SpvExecutionMode_ = 6463; +pub const SpvExecutionMode__SpvExecutionModeMax: SpvExecutionMode_ = 2147483647; +pub type SpvExecutionMode_ = ::std::os::raw::c_int; +pub use self::SpvExecutionMode_ as SpvExecutionMode; +pub const SpvStorageClass__SpvStorageClassUniformConstant: SpvStorageClass_ = 0; +pub const SpvStorageClass__SpvStorageClassInput: SpvStorageClass_ = 1; +pub const SpvStorageClass__SpvStorageClassUniform: SpvStorageClass_ = 2; +pub const SpvStorageClass__SpvStorageClassOutput: SpvStorageClass_ = 3; +pub const SpvStorageClass__SpvStorageClassWorkgroup: SpvStorageClass_ = 4; +pub const SpvStorageClass__SpvStorageClassCrossWorkgroup: SpvStorageClass_ = 5; +pub const SpvStorageClass__SpvStorageClassPrivate: SpvStorageClass_ = 6; +pub const SpvStorageClass__SpvStorageClassFunction: SpvStorageClass_ = 7; +pub const SpvStorageClass__SpvStorageClassGeneric: SpvStorageClass_ = 8; +pub const SpvStorageClass__SpvStorageClassPushConstant: SpvStorageClass_ = 9; +pub const SpvStorageClass__SpvStorageClassAtomicCounter: SpvStorageClass_ = 10; +pub const SpvStorageClass__SpvStorageClassImage: SpvStorageClass_ = 11; +pub const SpvStorageClass__SpvStorageClassStorageBuffer: SpvStorageClass_ = 12; +pub const SpvStorageClass__SpvStorageClassTileImageEXT: SpvStorageClass_ = 4172; +pub const SpvStorageClass__SpvStorageClassTileAttachmentQCOM: SpvStorageClass_ = 4491; +pub const SpvStorageClass__SpvStorageClassNodePayloadAMDX: SpvStorageClass_ = 5068; +pub const SpvStorageClass__SpvStorageClassCallableDataKHR: SpvStorageClass_ = 5328; +pub const SpvStorageClass__SpvStorageClassCallableDataNV: SpvStorageClass_ = 5328; +pub const SpvStorageClass__SpvStorageClassIncomingCallableDataKHR: SpvStorageClass_ = 5329; +pub const SpvStorageClass__SpvStorageClassIncomingCallableDataNV: SpvStorageClass_ = 5329; +pub const SpvStorageClass__SpvStorageClassRayPayloadKHR: SpvStorageClass_ = 5338; +pub const SpvStorageClass__SpvStorageClassRayPayloadNV: SpvStorageClass_ = 5338; +pub const SpvStorageClass__SpvStorageClassHitAttributeKHR: SpvStorageClass_ = 5339; +pub const SpvStorageClass__SpvStorageClassHitAttributeNV: SpvStorageClass_ = 5339; +pub const SpvStorageClass__SpvStorageClassIncomingRayPayloadKHR: SpvStorageClass_ = 5342; +pub const SpvStorageClass__SpvStorageClassIncomingRayPayloadNV: SpvStorageClass_ = 5342; +pub const SpvStorageClass__SpvStorageClassShaderRecordBufferKHR: SpvStorageClass_ = 5343; +pub const SpvStorageClass__SpvStorageClassShaderRecordBufferNV: SpvStorageClass_ = 5343; +pub const SpvStorageClass__SpvStorageClassPhysicalStorageBuffer: SpvStorageClass_ = 5349; +pub const SpvStorageClass__SpvStorageClassPhysicalStorageBufferEXT: SpvStorageClass_ = 5349; +pub const SpvStorageClass__SpvStorageClassHitObjectAttributeNV: SpvStorageClass_ = 5385; +pub const SpvStorageClass__SpvStorageClassTaskPayloadWorkgroupEXT: SpvStorageClass_ = 5402; +pub const SpvStorageClass__SpvStorageClassCodeSectionINTEL: SpvStorageClass_ = 5605; +pub const SpvStorageClass__SpvStorageClassDeviceOnlyINTEL: SpvStorageClass_ = 5936; +pub const SpvStorageClass__SpvStorageClassHostOnlyINTEL: SpvStorageClass_ = 5937; +pub const SpvStorageClass__SpvStorageClassMax: SpvStorageClass_ = 2147483647; +pub type SpvStorageClass_ = ::std::os::raw::c_int; +pub use self::SpvStorageClass_ as SpvStorageClass; +pub const SpvDim__SpvDim1D: SpvDim_ = 0; +pub const SpvDim__SpvDim2D: SpvDim_ = 1; +pub const SpvDim__SpvDim3D: SpvDim_ = 2; +pub const SpvDim__SpvDimCube: SpvDim_ = 3; +pub const SpvDim__SpvDimRect: SpvDim_ = 4; +pub const SpvDim__SpvDimBuffer: SpvDim_ = 5; +pub const SpvDim__SpvDimSubpassData: SpvDim_ = 6; +pub const SpvDim__SpvDimTileImageDataEXT: SpvDim_ = 4173; +pub const SpvDim__SpvDimMax: SpvDim_ = 2147483647; +pub type SpvDim_ = ::std::os::raw::c_int; +pub use self::SpvDim_ as SpvDim; +pub const SpvSamplerAddressingMode__SpvSamplerAddressingModeNone: SpvSamplerAddressingMode_ = 0; +pub const SpvSamplerAddressingMode__SpvSamplerAddressingModeClampToEdge: SpvSamplerAddressingMode_ = + 1; +pub const SpvSamplerAddressingMode__SpvSamplerAddressingModeClamp: SpvSamplerAddressingMode_ = 2; +pub const SpvSamplerAddressingMode__SpvSamplerAddressingModeRepeat: SpvSamplerAddressingMode_ = 3; +pub const SpvSamplerAddressingMode__SpvSamplerAddressingModeRepeatMirrored: + SpvSamplerAddressingMode_ = 4; +pub const SpvSamplerAddressingMode__SpvSamplerAddressingModeMax: SpvSamplerAddressingMode_ = + 2147483647; +pub type SpvSamplerAddressingMode_ = ::std::os::raw::c_int; +pub use self::SpvSamplerAddressingMode_ as SpvSamplerAddressingMode; +pub const SpvSamplerFilterMode__SpvSamplerFilterModeNearest: SpvSamplerFilterMode_ = 0; +pub const SpvSamplerFilterMode__SpvSamplerFilterModeLinear: SpvSamplerFilterMode_ = 1; +pub const SpvSamplerFilterMode__SpvSamplerFilterModeMax: SpvSamplerFilterMode_ = 2147483647; +pub type SpvSamplerFilterMode_ = ::std::os::raw::c_int; +pub use self::SpvSamplerFilterMode_ as SpvSamplerFilterMode; +pub const SpvImageFormat__SpvImageFormatUnknown: SpvImageFormat_ = 0; +pub const SpvImageFormat__SpvImageFormatRgba32f: SpvImageFormat_ = 1; +pub const SpvImageFormat__SpvImageFormatRgba16f: SpvImageFormat_ = 2; +pub const SpvImageFormat__SpvImageFormatR32f: SpvImageFormat_ = 3; +pub const SpvImageFormat__SpvImageFormatRgba8: SpvImageFormat_ = 4; +pub const SpvImageFormat__SpvImageFormatRgba8Snorm: SpvImageFormat_ = 5; +pub const SpvImageFormat__SpvImageFormatRg32f: SpvImageFormat_ = 6; +pub const SpvImageFormat__SpvImageFormatRg16f: SpvImageFormat_ = 7; +pub const SpvImageFormat__SpvImageFormatR11fG11fB10f: SpvImageFormat_ = 8; +pub const SpvImageFormat__SpvImageFormatR16f: SpvImageFormat_ = 9; +pub const SpvImageFormat__SpvImageFormatRgba16: SpvImageFormat_ = 10; +pub const SpvImageFormat__SpvImageFormatRgb10A2: SpvImageFormat_ = 11; +pub const SpvImageFormat__SpvImageFormatRg16: SpvImageFormat_ = 12; +pub const SpvImageFormat__SpvImageFormatRg8: SpvImageFormat_ = 13; +pub const SpvImageFormat__SpvImageFormatR16: SpvImageFormat_ = 14; +pub const SpvImageFormat__SpvImageFormatR8: SpvImageFormat_ = 15; +pub const SpvImageFormat__SpvImageFormatRgba16Snorm: SpvImageFormat_ = 16; +pub const SpvImageFormat__SpvImageFormatRg16Snorm: SpvImageFormat_ = 17; +pub const SpvImageFormat__SpvImageFormatRg8Snorm: SpvImageFormat_ = 18; +pub const SpvImageFormat__SpvImageFormatR16Snorm: SpvImageFormat_ = 19; +pub const SpvImageFormat__SpvImageFormatR8Snorm: SpvImageFormat_ = 20; +pub const SpvImageFormat__SpvImageFormatRgba32i: SpvImageFormat_ = 21; +pub const SpvImageFormat__SpvImageFormatRgba16i: SpvImageFormat_ = 22; +pub const SpvImageFormat__SpvImageFormatRgba8i: SpvImageFormat_ = 23; +pub const SpvImageFormat__SpvImageFormatR32i: SpvImageFormat_ = 24; +pub const SpvImageFormat__SpvImageFormatRg32i: SpvImageFormat_ = 25; +pub const SpvImageFormat__SpvImageFormatRg16i: SpvImageFormat_ = 26; +pub const SpvImageFormat__SpvImageFormatRg8i: SpvImageFormat_ = 27; +pub const SpvImageFormat__SpvImageFormatR16i: SpvImageFormat_ = 28; +pub const SpvImageFormat__SpvImageFormatR8i: SpvImageFormat_ = 29; +pub const SpvImageFormat__SpvImageFormatRgba32ui: SpvImageFormat_ = 30; +pub const SpvImageFormat__SpvImageFormatRgba16ui: SpvImageFormat_ = 31; +pub const SpvImageFormat__SpvImageFormatRgba8ui: SpvImageFormat_ = 32; +pub const SpvImageFormat__SpvImageFormatR32ui: SpvImageFormat_ = 33; +pub const SpvImageFormat__SpvImageFormatRgb10a2ui: SpvImageFormat_ = 34; +pub const SpvImageFormat__SpvImageFormatRg32ui: SpvImageFormat_ = 35; +pub const SpvImageFormat__SpvImageFormatRg16ui: SpvImageFormat_ = 36; +pub const SpvImageFormat__SpvImageFormatRg8ui: SpvImageFormat_ = 37; +pub const SpvImageFormat__SpvImageFormatR16ui: SpvImageFormat_ = 38; +pub const SpvImageFormat__SpvImageFormatR8ui: SpvImageFormat_ = 39; +pub const SpvImageFormat__SpvImageFormatR64ui: SpvImageFormat_ = 40; +pub const SpvImageFormat__SpvImageFormatR64i: SpvImageFormat_ = 41; +pub const SpvImageFormat__SpvImageFormatMax: SpvImageFormat_ = 2147483647; +pub type SpvImageFormat_ = ::std::os::raw::c_int; +pub use self::SpvImageFormat_ as SpvImageFormat; +pub const SpvImageChannelOrder__SpvImageChannelOrderR: SpvImageChannelOrder_ = 0; +pub const SpvImageChannelOrder__SpvImageChannelOrderA: SpvImageChannelOrder_ = 1; +pub const SpvImageChannelOrder__SpvImageChannelOrderRG: SpvImageChannelOrder_ = 2; +pub const SpvImageChannelOrder__SpvImageChannelOrderRA: SpvImageChannelOrder_ = 3; +pub const SpvImageChannelOrder__SpvImageChannelOrderRGB: SpvImageChannelOrder_ = 4; +pub const SpvImageChannelOrder__SpvImageChannelOrderRGBA: SpvImageChannelOrder_ = 5; +pub const SpvImageChannelOrder__SpvImageChannelOrderBGRA: SpvImageChannelOrder_ = 6; +pub const SpvImageChannelOrder__SpvImageChannelOrderARGB: SpvImageChannelOrder_ = 7; +pub const SpvImageChannelOrder__SpvImageChannelOrderIntensity: SpvImageChannelOrder_ = 8; +pub const SpvImageChannelOrder__SpvImageChannelOrderLuminance: SpvImageChannelOrder_ = 9; +pub const SpvImageChannelOrder__SpvImageChannelOrderRx: SpvImageChannelOrder_ = 10; +pub const SpvImageChannelOrder__SpvImageChannelOrderRGx: SpvImageChannelOrder_ = 11; +pub const SpvImageChannelOrder__SpvImageChannelOrderRGBx: SpvImageChannelOrder_ = 12; +pub const SpvImageChannelOrder__SpvImageChannelOrderDepth: SpvImageChannelOrder_ = 13; +pub const SpvImageChannelOrder__SpvImageChannelOrderDepthStencil: SpvImageChannelOrder_ = 14; +pub const SpvImageChannelOrder__SpvImageChannelOrdersRGB: SpvImageChannelOrder_ = 15; +pub const SpvImageChannelOrder__SpvImageChannelOrdersRGBx: SpvImageChannelOrder_ = 16; +pub const SpvImageChannelOrder__SpvImageChannelOrdersRGBA: SpvImageChannelOrder_ = 17; +pub const SpvImageChannelOrder__SpvImageChannelOrdersBGRA: SpvImageChannelOrder_ = 18; +pub const SpvImageChannelOrder__SpvImageChannelOrderABGR: SpvImageChannelOrder_ = 19; +pub const SpvImageChannelOrder__SpvImageChannelOrderMax: SpvImageChannelOrder_ = 2147483647; +pub type SpvImageChannelOrder_ = ::std::os::raw::c_int; +pub use self::SpvImageChannelOrder_ as SpvImageChannelOrder; +pub const SpvImageChannelDataType__SpvImageChannelDataTypeSnormInt8: SpvImageChannelDataType_ = 0; +pub const SpvImageChannelDataType__SpvImageChannelDataTypeSnormInt16: SpvImageChannelDataType_ = 1; +pub const SpvImageChannelDataType__SpvImageChannelDataTypeUnormInt8: SpvImageChannelDataType_ = 2; +pub const SpvImageChannelDataType__SpvImageChannelDataTypeUnormInt16: SpvImageChannelDataType_ = 3; +pub const SpvImageChannelDataType__SpvImageChannelDataTypeUnormShort565: SpvImageChannelDataType_ = + 4; +pub const SpvImageChannelDataType__SpvImageChannelDataTypeUnormShort555: SpvImageChannelDataType_ = + 5; +pub const SpvImageChannelDataType__SpvImageChannelDataTypeUnormInt101010: SpvImageChannelDataType_ = + 6; +pub const SpvImageChannelDataType__SpvImageChannelDataTypeSignedInt8: SpvImageChannelDataType_ = 7; +pub const SpvImageChannelDataType__SpvImageChannelDataTypeSignedInt16: SpvImageChannelDataType_ = 8; +pub const SpvImageChannelDataType__SpvImageChannelDataTypeSignedInt32: SpvImageChannelDataType_ = 9; +pub const SpvImageChannelDataType__SpvImageChannelDataTypeUnsignedInt8: SpvImageChannelDataType_ = + 10; +pub const SpvImageChannelDataType__SpvImageChannelDataTypeUnsignedInt16: SpvImageChannelDataType_ = + 11; +pub const SpvImageChannelDataType__SpvImageChannelDataTypeUnsignedInt32: SpvImageChannelDataType_ = + 12; +pub const SpvImageChannelDataType__SpvImageChannelDataTypeHalfFloat: SpvImageChannelDataType_ = 13; +pub const SpvImageChannelDataType__SpvImageChannelDataTypeFloat: SpvImageChannelDataType_ = 14; +pub const SpvImageChannelDataType__SpvImageChannelDataTypeUnormInt24: SpvImageChannelDataType_ = 15; +pub const SpvImageChannelDataType__SpvImageChannelDataTypeUnormInt101010_2: + SpvImageChannelDataType_ = 16; +pub const SpvImageChannelDataType__SpvImageChannelDataTypeUnormInt10X6EXT: + SpvImageChannelDataType_ = 17; +pub const SpvImageChannelDataType__SpvImageChannelDataTypeUnsignedIntRaw10EXT: + SpvImageChannelDataType_ = 19; +pub const SpvImageChannelDataType__SpvImageChannelDataTypeUnsignedIntRaw12EXT: + SpvImageChannelDataType_ = 20; +pub const SpvImageChannelDataType__SpvImageChannelDataTypeUnormInt2_101010EXT: + SpvImageChannelDataType_ = 21; +pub const SpvImageChannelDataType__SpvImageChannelDataTypeUnsignedInt10X6EXT: + SpvImageChannelDataType_ = 22; +pub const SpvImageChannelDataType__SpvImageChannelDataTypeUnsignedInt12X4EXT: + SpvImageChannelDataType_ = 23; +pub const SpvImageChannelDataType__SpvImageChannelDataTypeUnsignedInt14X2EXT: + SpvImageChannelDataType_ = 24; +pub const SpvImageChannelDataType__SpvImageChannelDataTypeUnormInt12X4EXT: + SpvImageChannelDataType_ = 25; +pub const SpvImageChannelDataType__SpvImageChannelDataTypeUnormInt14X2EXT: + SpvImageChannelDataType_ = 26; +pub const SpvImageChannelDataType__SpvImageChannelDataTypeMax: SpvImageChannelDataType_ = + 2147483647; +pub type SpvImageChannelDataType_ = ::std::os::raw::c_int; +pub use self::SpvImageChannelDataType_ as SpvImageChannelDataType; +pub const SpvImageOperandsShift__SpvImageOperandsBiasShift: SpvImageOperandsShift_ = 0; +pub const SpvImageOperandsShift__SpvImageOperandsLodShift: SpvImageOperandsShift_ = 1; +pub const SpvImageOperandsShift__SpvImageOperandsGradShift: SpvImageOperandsShift_ = 2; +pub const SpvImageOperandsShift__SpvImageOperandsConstOffsetShift: SpvImageOperandsShift_ = 3; +pub const SpvImageOperandsShift__SpvImageOperandsOffsetShift: SpvImageOperandsShift_ = 4; +pub const SpvImageOperandsShift__SpvImageOperandsConstOffsetsShift: SpvImageOperandsShift_ = 5; +pub const SpvImageOperandsShift__SpvImageOperandsSampleShift: SpvImageOperandsShift_ = 6; +pub const SpvImageOperandsShift__SpvImageOperandsMinLodShift: SpvImageOperandsShift_ = 7; +pub const SpvImageOperandsShift__SpvImageOperandsMakeTexelAvailableShift: SpvImageOperandsShift_ = + 8; +pub const SpvImageOperandsShift__SpvImageOperandsMakeTexelAvailableKHRShift: + SpvImageOperandsShift_ = 8; +pub const SpvImageOperandsShift__SpvImageOperandsMakeTexelVisibleShift: SpvImageOperandsShift_ = 9; +pub const SpvImageOperandsShift__SpvImageOperandsMakeTexelVisibleKHRShift: SpvImageOperandsShift_ = + 9; +pub const SpvImageOperandsShift__SpvImageOperandsNonPrivateTexelShift: SpvImageOperandsShift_ = 10; +pub const SpvImageOperandsShift__SpvImageOperandsNonPrivateTexelKHRShift: SpvImageOperandsShift_ = + 10; +pub const SpvImageOperandsShift__SpvImageOperandsVolatileTexelShift: SpvImageOperandsShift_ = 11; +pub const SpvImageOperandsShift__SpvImageOperandsVolatileTexelKHRShift: SpvImageOperandsShift_ = 11; +pub const SpvImageOperandsShift__SpvImageOperandsSignExtendShift: SpvImageOperandsShift_ = 12; +pub const SpvImageOperandsShift__SpvImageOperandsZeroExtendShift: SpvImageOperandsShift_ = 13; +pub const SpvImageOperandsShift__SpvImageOperandsNontemporalShift: SpvImageOperandsShift_ = 14; +pub const SpvImageOperandsShift__SpvImageOperandsOffsetsShift: SpvImageOperandsShift_ = 16; +pub const SpvImageOperandsShift__SpvImageOperandsMax: SpvImageOperandsShift_ = 2147483647; +pub type SpvImageOperandsShift_ = ::std::os::raw::c_int; +pub use self::SpvImageOperandsShift_ as SpvImageOperandsShift; +pub const SpvImageOperandsMask__SpvImageOperandsMaskNone: SpvImageOperandsMask_ = 0; +pub const SpvImageOperandsMask__SpvImageOperandsBiasMask: SpvImageOperandsMask_ = 1; +pub const SpvImageOperandsMask__SpvImageOperandsLodMask: SpvImageOperandsMask_ = 2; +pub const SpvImageOperandsMask__SpvImageOperandsGradMask: SpvImageOperandsMask_ = 4; +pub const SpvImageOperandsMask__SpvImageOperandsConstOffsetMask: SpvImageOperandsMask_ = 8; +pub const SpvImageOperandsMask__SpvImageOperandsOffsetMask: SpvImageOperandsMask_ = 16; +pub const SpvImageOperandsMask__SpvImageOperandsConstOffsetsMask: SpvImageOperandsMask_ = 32; +pub const SpvImageOperandsMask__SpvImageOperandsSampleMask: SpvImageOperandsMask_ = 64; +pub const SpvImageOperandsMask__SpvImageOperandsMinLodMask: SpvImageOperandsMask_ = 128; +pub const SpvImageOperandsMask__SpvImageOperandsMakeTexelAvailableMask: SpvImageOperandsMask_ = 256; +pub const SpvImageOperandsMask__SpvImageOperandsMakeTexelAvailableKHRMask: SpvImageOperandsMask_ = + 256; +pub const SpvImageOperandsMask__SpvImageOperandsMakeTexelVisibleMask: SpvImageOperandsMask_ = 512; +pub const SpvImageOperandsMask__SpvImageOperandsMakeTexelVisibleKHRMask: SpvImageOperandsMask_ = + 512; +pub const SpvImageOperandsMask__SpvImageOperandsNonPrivateTexelMask: SpvImageOperandsMask_ = 1024; +pub const SpvImageOperandsMask__SpvImageOperandsNonPrivateTexelKHRMask: SpvImageOperandsMask_ = + 1024; +pub const SpvImageOperandsMask__SpvImageOperandsVolatileTexelMask: SpvImageOperandsMask_ = 2048; +pub const SpvImageOperandsMask__SpvImageOperandsVolatileTexelKHRMask: SpvImageOperandsMask_ = 2048; +pub const SpvImageOperandsMask__SpvImageOperandsSignExtendMask: SpvImageOperandsMask_ = 4096; +pub const SpvImageOperandsMask__SpvImageOperandsZeroExtendMask: SpvImageOperandsMask_ = 8192; +pub const SpvImageOperandsMask__SpvImageOperandsNontemporalMask: SpvImageOperandsMask_ = 16384; +pub const SpvImageOperandsMask__SpvImageOperandsOffsetsMask: SpvImageOperandsMask_ = 65536; +pub type SpvImageOperandsMask_ = ::std::os::raw::c_int; +pub use self::SpvImageOperandsMask_ as SpvImageOperandsMask; +pub const SpvFPFastMathModeShift__SpvFPFastMathModeNotNaNShift: SpvFPFastMathModeShift_ = 0; +pub const SpvFPFastMathModeShift__SpvFPFastMathModeNotInfShift: SpvFPFastMathModeShift_ = 1; +pub const SpvFPFastMathModeShift__SpvFPFastMathModeNSZShift: SpvFPFastMathModeShift_ = 2; +pub const SpvFPFastMathModeShift__SpvFPFastMathModeAllowRecipShift: SpvFPFastMathModeShift_ = 3; +pub const SpvFPFastMathModeShift__SpvFPFastMathModeFastShift: SpvFPFastMathModeShift_ = 4; +pub const SpvFPFastMathModeShift__SpvFPFastMathModeAllowContractShift: SpvFPFastMathModeShift_ = 16; +pub const SpvFPFastMathModeShift__SpvFPFastMathModeAllowContractFastINTELShift: + SpvFPFastMathModeShift_ = 16; +pub const SpvFPFastMathModeShift__SpvFPFastMathModeAllowReassocShift: SpvFPFastMathModeShift_ = 17; +pub const SpvFPFastMathModeShift__SpvFPFastMathModeAllowReassocINTELShift: SpvFPFastMathModeShift_ = + 17; +pub const SpvFPFastMathModeShift__SpvFPFastMathModeAllowTransformShift: SpvFPFastMathModeShift_ = + 18; +pub const SpvFPFastMathModeShift__SpvFPFastMathModeMax: SpvFPFastMathModeShift_ = 2147483647; +pub type SpvFPFastMathModeShift_ = ::std::os::raw::c_int; +pub use self::SpvFPFastMathModeShift_ as SpvFPFastMathModeShift; +pub const SpvFPFastMathModeMask__SpvFPFastMathModeMaskNone: SpvFPFastMathModeMask_ = 0; +pub const SpvFPFastMathModeMask__SpvFPFastMathModeNotNaNMask: SpvFPFastMathModeMask_ = 1; +pub const SpvFPFastMathModeMask__SpvFPFastMathModeNotInfMask: SpvFPFastMathModeMask_ = 2; +pub const SpvFPFastMathModeMask__SpvFPFastMathModeNSZMask: SpvFPFastMathModeMask_ = 4; +pub const SpvFPFastMathModeMask__SpvFPFastMathModeAllowRecipMask: SpvFPFastMathModeMask_ = 8; +pub const SpvFPFastMathModeMask__SpvFPFastMathModeFastMask: SpvFPFastMathModeMask_ = 16; +pub const SpvFPFastMathModeMask__SpvFPFastMathModeAllowContractMask: SpvFPFastMathModeMask_ = 65536; +pub const SpvFPFastMathModeMask__SpvFPFastMathModeAllowContractFastINTELMask: + SpvFPFastMathModeMask_ = 65536; +pub const SpvFPFastMathModeMask__SpvFPFastMathModeAllowReassocMask: SpvFPFastMathModeMask_ = 131072; +pub const SpvFPFastMathModeMask__SpvFPFastMathModeAllowReassocINTELMask: SpvFPFastMathModeMask_ = + 131072; +pub const SpvFPFastMathModeMask__SpvFPFastMathModeAllowTransformMask: SpvFPFastMathModeMask_ = + 262144; +pub type SpvFPFastMathModeMask_ = ::std::os::raw::c_int; +pub use self::SpvFPFastMathModeMask_ as SpvFPFastMathModeMask; +pub const SpvFPRoundingMode__SpvFPRoundingModeRTE: SpvFPRoundingMode_ = 0; +pub const SpvFPRoundingMode__SpvFPRoundingModeRTZ: SpvFPRoundingMode_ = 1; +pub const SpvFPRoundingMode__SpvFPRoundingModeRTP: SpvFPRoundingMode_ = 2; +pub const SpvFPRoundingMode__SpvFPRoundingModeRTN: SpvFPRoundingMode_ = 3; +pub const SpvFPRoundingMode__SpvFPRoundingModeMax: SpvFPRoundingMode_ = 2147483647; +pub type SpvFPRoundingMode_ = ::std::os::raw::c_int; +pub use self::SpvFPRoundingMode_ as SpvFPRoundingMode; +pub const SpvLinkageType__SpvLinkageTypeExport: SpvLinkageType_ = 0; +pub const SpvLinkageType__SpvLinkageTypeImport: SpvLinkageType_ = 1; +pub const SpvLinkageType__SpvLinkageTypeLinkOnceODR: SpvLinkageType_ = 2; +pub const SpvLinkageType__SpvLinkageTypeMax: SpvLinkageType_ = 2147483647; +pub type SpvLinkageType_ = ::std::os::raw::c_int; +pub use self::SpvLinkageType_ as SpvLinkageType; +pub const SpvAccessQualifier__SpvAccessQualifierReadOnly: SpvAccessQualifier_ = 0; +pub const SpvAccessQualifier__SpvAccessQualifierWriteOnly: SpvAccessQualifier_ = 1; +pub const SpvAccessQualifier__SpvAccessQualifierReadWrite: SpvAccessQualifier_ = 2; +pub const SpvAccessQualifier__SpvAccessQualifierMax: SpvAccessQualifier_ = 2147483647; +pub type SpvAccessQualifier_ = ::std::os::raw::c_int; +pub use self::SpvAccessQualifier_ as SpvAccessQualifier; +pub const SpvFunctionParameterAttribute__SpvFunctionParameterAttributeZext: + SpvFunctionParameterAttribute_ = 0; +pub const SpvFunctionParameterAttribute__SpvFunctionParameterAttributeSext: + SpvFunctionParameterAttribute_ = 1; +pub const SpvFunctionParameterAttribute__SpvFunctionParameterAttributeByVal: + SpvFunctionParameterAttribute_ = 2; +pub const SpvFunctionParameterAttribute__SpvFunctionParameterAttributeSret: + SpvFunctionParameterAttribute_ = 3; +pub const SpvFunctionParameterAttribute__SpvFunctionParameterAttributeNoAlias: + SpvFunctionParameterAttribute_ = 4; +pub const SpvFunctionParameterAttribute__SpvFunctionParameterAttributeNoCapture: + SpvFunctionParameterAttribute_ = 5; +pub const SpvFunctionParameterAttribute__SpvFunctionParameterAttributeNoWrite: + SpvFunctionParameterAttribute_ = 6; +pub const SpvFunctionParameterAttribute__SpvFunctionParameterAttributeNoReadWrite: + SpvFunctionParameterAttribute_ = 7; +pub const SpvFunctionParameterAttribute__SpvFunctionParameterAttributeRuntimeAlignedINTEL: + SpvFunctionParameterAttribute_ = 5940; +pub const SpvFunctionParameterAttribute__SpvFunctionParameterAttributeMax: + SpvFunctionParameterAttribute_ = 2147483647; +pub type SpvFunctionParameterAttribute_ = ::std::os::raw::c_int; +pub use self::SpvFunctionParameterAttribute_ as SpvFunctionParameterAttribute; +pub const SpvDecoration__SpvDecorationRelaxedPrecision: SpvDecoration_ = 0; +pub const SpvDecoration__SpvDecorationSpecId: SpvDecoration_ = 1; +pub const SpvDecoration__SpvDecorationBlock: SpvDecoration_ = 2; +pub const SpvDecoration__SpvDecorationBufferBlock: SpvDecoration_ = 3; +pub const SpvDecoration__SpvDecorationRowMajor: SpvDecoration_ = 4; +pub const SpvDecoration__SpvDecorationColMajor: SpvDecoration_ = 5; +pub const SpvDecoration__SpvDecorationArrayStride: SpvDecoration_ = 6; +pub const SpvDecoration__SpvDecorationMatrixStride: SpvDecoration_ = 7; +pub const SpvDecoration__SpvDecorationGLSLShared: SpvDecoration_ = 8; +pub const SpvDecoration__SpvDecorationGLSLPacked: SpvDecoration_ = 9; +pub const SpvDecoration__SpvDecorationCPacked: SpvDecoration_ = 10; +pub const SpvDecoration__SpvDecorationBuiltIn: SpvDecoration_ = 11; +pub const SpvDecoration__SpvDecorationNoPerspective: SpvDecoration_ = 13; +pub const SpvDecoration__SpvDecorationFlat: SpvDecoration_ = 14; +pub const SpvDecoration__SpvDecorationPatch: SpvDecoration_ = 15; +pub const SpvDecoration__SpvDecorationCentroid: SpvDecoration_ = 16; +pub const SpvDecoration__SpvDecorationSample: SpvDecoration_ = 17; +pub const SpvDecoration__SpvDecorationInvariant: SpvDecoration_ = 18; +pub const SpvDecoration__SpvDecorationRestrict: SpvDecoration_ = 19; +pub const SpvDecoration__SpvDecorationAliased: SpvDecoration_ = 20; +pub const SpvDecoration__SpvDecorationVolatile: SpvDecoration_ = 21; +pub const SpvDecoration__SpvDecorationConstant: SpvDecoration_ = 22; +pub const SpvDecoration__SpvDecorationCoherent: SpvDecoration_ = 23; +pub const SpvDecoration__SpvDecorationNonWritable: SpvDecoration_ = 24; +pub const SpvDecoration__SpvDecorationNonReadable: SpvDecoration_ = 25; +pub const SpvDecoration__SpvDecorationUniform: SpvDecoration_ = 26; +pub const SpvDecoration__SpvDecorationUniformId: SpvDecoration_ = 27; +pub const SpvDecoration__SpvDecorationSaturatedConversion: SpvDecoration_ = 28; +pub const SpvDecoration__SpvDecorationStream: SpvDecoration_ = 29; +pub const SpvDecoration__SpvDecorationLocation: SpvDecoration_ = 30; +pub const SpvDecoration__SpvDecorationComponent: SpvDecoration_ = 31; +pub const SpvDecoration__SpvDecorationIndex: SpvDecoration_ = 32; +pub const SpvDecoration__SpvDecorationBinding: SpvDecoration_ = 33; +pub const SpvDecoration__SpvDecorationDescriptorSet: SpvDecoration_ = 34; +pub const SpvDecoration__SpvDecorationOffset: SpvDecoration_ = 35; +pub const SpvDecoration__SpvDecorationXfbBuffer: SpvDecoration_ = 36; +pub const SpvDecoration__SpvDecorationXfbStride: SpvDecoration_ = 37; +pub const SpvDecoration__SpvDecorationFuncParamAttr: SpvDecoration_ = 38; +pub const SpvDecoration__SpvDecorationFPRoundingMode: SpvDecoration_ = 39; +pub const SpvDecoration__SpvDecorationFPFastMathMode: SpvDecoration_ = 40; +pub const SpvDecoration__SpvDecorationLinkageAttributes: SpvDecoration_ = 41; +pub const SpvDecoration__SpvDecorationNoContraction: SpvDecoration_ = 42; +pub const SpvDecoration__SpvDecorationInputAttachmentIndex: SpvDecoration_ = 43; +pub const SpvDecoration__SpvDecorationAlignment: SpvDecoration_ = 44; +pub const SpvDecoration__SpvDecorationMaxByteOffset: SpvDecoration_ = 45; +pub const SpvDecoration__SpvDecorationAlignmentId: SpvDecoration_ = 46; +pub const SpvDecoration__SpvDecorationMaxByteOffsetId: SpvDecoration_ = 47; +pub const SpvDecoration__SpvDecorationSaturatedToLargestFloat8NormalConversionEXT: SpvDecoration_ = + 4216; +pub const SpvDecoration__SpvDecorationNoSignedWrap: SpvDecoration_ = 4469; +pub const SpvDecoration__SpvDecorationNoUnsignedWrap: SpvDecoration_ = 4470; +pub const SpvDecoration__SpvDecorationWeightTextureQCOM: SpvDecoration_ = 4487; +pub const SpvDecoration__SpvDecorationBlockMatchTextureQCOM: SpvDecoration_ = 4488; +pub const SpvDecoration__SpvDecorationBlockMatchSamplerQCOM: SpvDecoration_ = 4499; +pub const SpvDecoration__SpvDecorationExplicitInterpAMD: SpvDecoration_ = 4999; +pub const SpvDecoration__SpvDecorationNodeSharesPayloadLimitsWithAMDX: SpvDecoration_ = 5019; +pub const SpvDecoration__SpvDecorationNodeMaxPayloadsAMDX: SpvDecoration_ = 5020; +pub const SpvDecoration__SpvDecorationTrackFinishWritingAMDX: SpvDecoration_ = 5078; +pub const SpvDecoration__SpvDecorationPayloadNodeNameAMDX: SpvDecoration_ = 5091; +pub const SpvDecoration__SpvDecorationPayloadNodeBaseIndexAMDX: SpvDecoration_ = 5098; +pub const SpvDecoration__SpvDecorationPayloadNodeSparseArrayAMDX: SpvDecoration_ = 5099; +pub const SpvDecoration__SpvDecorationPayloadNodeArraySizeAMDX: SpvDecoration_ = 5100; +pub const SpvDecoration__SpvDecorationPayloadDispatchIndirectAMDX: SpvDecoration_ = 5105; +pub const SpvDecoration__SpvDecorationOverrideCoverageNV: SpvDecoration_ = 5248; +pub const SpvDecoration__SpvDecorationPassthroughNV: SpvDecoration_ = 5250; +pub const SpvDecoration__SpvDecorationViewportRelativeNV: SpvDecoration_ = 5252; +pub const SpvDecoration__SpvDecorationSecondaryViewportRelativeNV: SpvDecoration_ = 5256; +pub const SpvDecoration__SpvDecorationPerPrimitiveEXT: SpvDecoration_ = 5271; +pub const SpvDecoration__SpvDecorationPerPrimitiveNV: SpvDecoration_ = 5271; +pub const SpvDecoration__SpvDecorationPerViewNV: SpvDecoration_ = 5272; +pub const SpvDecoration__SpvDecorationPerTaskNV: SpvDecoration_ = 5273; +pub const SpvDecoration__SpvDecorationPerVertexKHR: SpvDecoration_ = 5285; +pub const SpvDecoration__SpvDecorationPerVertexNV: SpvDecoration_ = 5285; +pub const SpvDecoration__SpvDecorationNonUniform: SpvDecoration_ = 5300; +pub const SpvDecoration__SpvDecorationNonUniformEXT: SpvDecoration_ = 5300; +pub const SpvDecoration__SpvDecorationRestrictPointer: SpvDecoration_ = 5355; +pub const SpvDecoration__SpvDecorationRestrictPointerEXT: SpvDecoration_ = 5355; +pub const SpvDecoration__SpvDecorationAliasedPointer: SpvDecoration_ = 5356; +pub const SpvDecoration__SpvDecorationAliasedPointerEXT: SpvDecoration_ = 5356; +pub const SpvDecoration__SpvDecorationHitObjectShaderRecordBufferNV: SpvDecoration_ = 5386; +pub const SpvDecoration__SpvDecorationBindlessSamplerNV: SpvDecoration_ = 5398; +pub const SpvDecoration__SpvDecorationBindlessImageNV: SpvDecoration_ = 5399; +pub const SpvDecoration__SpvDecorationBoundSamplerNV: SpvDecoration_ = 5400; +pub const SpvDecoration__SpvDecorationBoundImageNV: SpvDecoration_ = 5401; +pub const SpvDecoration__SpvDecorationSIMTCallINTEL: SpvDecoration_ = 5599; +pub const SpvDecoration__SpvDecorationReferencedIndirectlyINTEL: SpvDecoration_ = 5602; +pub const SpvDecoration__SpvDecorationClobberINTEL: SpvDecoration_ = 5607; +pub const SpvDecoration__SpvDecorationSideEffectsINTEL: SpvDecoration_ = 5608; +pub const SpvDecoration__SpvDecorationVectorComputeVariableINTEL: SpvDecoration_ = 5624; +pub const SpvDecoration__SpvDecorationFuncParamIOKindINTEL: SpvDecoration_ = 5625; +pub const SpvDecoration__SpvDecorationVectorComputeFunctionINTEL: SpvDecoration_ = 5626; +pub const SpvDecoration__SpvDecorationStackCallINTEL: SpvDecoration_ = 5627; +pub const SpvDecoration__SpvDecorationGlobalVariableOffsetINTEL: SpvDecoration_ = 5628; +pub const SpvDecoration__SpvDecorationCounterBuffer: SpvDecoration_ = 5634; +pub const SpvDecoration__SpvDecorationHlslCounterBufferGOOGLE: SpvDecoration_ = 5634; +pub const SpvDecoration__SpvDecorationHlslSemanticGOOGLE: SpvDecoration_ = 5635; +pub const SpvDecoration__SpvDecorationUserSemantic: SpvDecoration_ = 5635; +pub const SpvDecoration__SpvDecorationUserTypeGOOGLE: SpvDecoration_ = 5636; +pub const SpvDecoration__SpvDecorationFunctionRoundingModeINTEL: SpvDecoration_ = 5822; +pub const SpvDecoration__SpvDecorationFunctionDenormModeINTEL: SpvDecoration_ = 5823; +pub const SpvDecoration__SpvDecorationRegisterINTEL: SpvDecoration_ = 5825; +pub const SpvDecoration__SpvDecorationMemoryINTEL: SpvDecoration_ = 5826; +pub const SpvDecoration__SpvDecorationNumbanksINTEL: SpvDecoration_ = 5827; +pub const SpvDecoration__SpvDecorationBankwidthINTEL: SpvDecoration_ = 5828; +pub const SpvDecoration__SpvDecorationMaxPrivateCopiesINTEL: SpvDecoration_ = 5829; +pub const SpvDecoration__SpvDecorationSinglepumpINTEL: SpvDecoration_ = 5830; +pub const SpvDecoration__SpvDecorationDoublepumpINTEL: SpvDecoration_ = 5831; +pub const SpvDecoration__SpvDecorationMaxReplicatesINTEL: SpvDecoration_ = 5832; +pub const SpvDecoration__SpvDecorationSimpleDualPortINTEL: SpvDecoration_ = 5833; +pub const SpvDecoration__SpvDecorationMergeINTEL: SpvDecoration_ = 5834; +pub const SpvDecoration__SpvDecorationBankBitsINTEL: SpvDecoration_ = 5835; +pub const SpvDecoration__SpvDecorationForcePow2DepthINTEL: SpvDecoration_ = 5836; +pub const SpvDecoration__SpvDecorationStridesizeINTEL: SpvDecoration_ = 5883; +pub const SpvDecoration__SpvDecorationWordsizeINTEL: SpvDecoration_ = 5884; +pub const SpvDecoration__SpvDecorationTrueDualPortINTEL: SpvDecoration_ = 5885; +pub const SpvDecoration__SpvDecorationBurstCoalesceINTEL: SpvDecoration_ = 5899; +pub const SpvDecoration__SpvDecorationCacheSizeINTEL: SpvDecoration_ = 5900; +pub const SpvDecoration__SpvDecorationDontStaticallyCoalesceINTEL: SpvDecoration_ = 5901; +pub const SpvDecoration__SpvDecorationPrefetchINTEL: SpvDecoration_ = 5902; +pub const SpvDecoration__SpvDecorationStallEnableINTEL: SpvDecoration_ = 5905; +pub const SpvDecoration__SpvDecorationFuseLoopsInFunctionINTEL: SpvDecoration_ = 5907; +pub const SpvDecoration__SpvDecorationMathOpDSPModeINTEL: SpvDecoration_ = 5909; +pub const SpvDecoration__SpvDecorationAliasScopeINTEL: SpvDecoration_ = 5914; +pub const SpvDecoration__SpvDecorationNoAliasINTEL: SpvDecoration_ = 5915; +pub const SpvDecoration__SpvDecorationInitiationIntervalINTEL: SpvDecoration_ = 5917; +pub const SpvDecoration__SpvDecorationMaxConcurrencyINTEL: SpvDecoration_ = 5918; +pub const SpvDecoration__SpvDecorationPipelineEnableINTEL: SpvDecoration_ = 5919; +pub const SpvDecoration__SpvDecorationBufferLocationINTEL: SpvDecoration_ = 5921; +pub const SpvDecoration__SpvDecorationIOPipeStorageINTEL: SpvDecoration_ = 5944; +pub const SpvDecoration__SpvDecorationFunctionFloatingPointModeINTEL: SpvDecoration_ = 6080; +pub const SpvDecoration__SpvDecorationSingleElementVectorINTEL: SpvDecoration_ = 6085; +pub const SpvDecoration__SpvDecorationVectorComputeCallableFunctionINTEL: SpvDecoration_ = 6087; +pub const SpvDecoration__SpvDecorationMediaBlockIOINTEL: SpvDecoration_ = 6140; +pub const SpvDecoration__SpvDecorationStallFreeINTEL: SpvDecoration_ = 6151; +pub const SpvDecoration__SpvDecorationFPMaxErrorDecorationINTEL: SpvDecoration_ = 6170; +pub const SpvDecoration__SpvDecorationLatencyControlLabelINTEL: SpvDecoration_ = 6172; +pub const SpvDecoration__SpvDecorationLatencyControlConstraintINTEL: SpvDecoration_ = 6173; +pub const SpvDecoration__SpvDecorationConduitKernelArgumentINTEL: SpvDecoration_ = 6175; +pub const SpvDecoration__SpvDecorationRegisterMapKernelArgumentINTEL: SpvDecoration_ = 6176; +pub const SpvDecoration__SpvDecorationMMHostInterfaceAddressWidthINTEL: SpvDecoration_ = 6177; +pub const SpvDecoration__SpvDecorationMMHostInterfaceDataWidthINTEL: SpvDecoration_ = 6178; +pub const SpvDecoration__SpvDecorationMMHostInterfaceLatencyINTEL: SpvDecoration_ = 6179; +pub const SpvDecoration__SpvDecorationMMHostInterfaceReadWriteModeINTEL: SpvDecoration_ = 6180; +pub const SpvDecoration__SpvDecorationMMHostInterfaceMaxBurstINTEL: SpvDecoration_ = 6181; +pub const SpvDecoration__SpvDecorationMMHostInterfaceWaitRequestINTEL: SpvDecoration_ = 6182; +pub const SpvDecoration__SpvDecorationStableKernelArgumentINTEL: SpvDecoration_ = 6183; +pub const SpvDecoration__SpvDecorationHostAccessINTEL: SpvDecoration_ = 6188; +pub const SpvDecoration__SpvDecorationInitModeINTEL: SpvDecoration_ = 6190; +pub const SpvDecoration__SpvDecorationImplementInRegisterMapINTEL: SpvDecoration_ = 6191; +pub const SpvDecoration__SpvDecorationConditionalINTEL: SpvDecoration_ = 6247; +pub const SpvDecoration__SpvDecorationCacheControlLoadINTEL: SpvDecoration_ = 6442; +pub const SpvDecoration__SpvDecorationCacheControlStoreINTEL: SpvDecoration_ = 6443; +pub const SpvDecoration__SpvDecorationMax: SpvDecoration_ = 2147483647; +pub type SpvDecoration_ = ::std::os::raw::c_int; +pub use self::SpvDecoration_ as SpvDecoration; +pub const SpvBuiltIn__SpvBuiltInPosition: SpvBuiltIn_ = 0; +pub const SpvBuiltIn__SpvBuiltInPointSize: SpvBuiltIn_ = 1; +pub const SpvBuiltIn__SpvBuiltInClipDistance: SpvBuiltIn_ = 3; +pub const SpvBuiltIn__SpvBuiltInCullDistance: SpvBuiltIn_ = 4; +pub const SpvBuiltIn__SpvBuiltInVertexId: SpvBuiltIn_ = 5; +pub const SpvBuiltIn__SpvBuiltInInstanceId: SpvBuiltIn_ = 6; +pub const SpvBuiltIn__SpvBuiltInPrimitiveId: SpvBuiltIn_ = 7; +pub const SpvBuiltIn__SpvBuiltInInvocationId: SpvBuiltIn_ = 8; +pub const SpvBuiltIn__SpvBuiltInLayer: SpvBuiltIn_ = 9; +pub const SpvBuiltIn__SpvBuiltInViewportIndex: SpvBuiltIn_ = 10; +pub const SpvBuiltIn__SpvBuiltInTessLevelOuter: SpvBuiltIn_ = 11; +pub const SpvBuiltIn__SpvBuiltInTessLevelInner: SpvBuiltIn_ = 12; +pub const SpvBuiltIn__SpvBuiltInTessCoord: SpvBuiltIn_ = 13; +pub const SpvBuiltIn__SpvBuiltInPatchVertices: SpvBuiltIn_ = 14; +pub const SpvBuiltIn__SpvBuiltInFragCoord: SpvBuiltIn_ = 15; +pub const SpvBuiltIn__SpvBuiltInPointCoord: SpvBuiltIn_ = 16; +pub const SpvBuiltIn__SpvBuiltInFrontFacing: SpvBuiltIn_ = 17; +pub const SpvBuiltIn__SpvBuiltInSampleId: SpvBuiltIn_ = 18; +pub const SpvBuiltIn__SpvBuiltInSamplePosition: SpvBuiltIn_ = 19; +pub const SpvBuiltIn__SpvBuiltInSampleMask: SpvBuiltIn_ = 20; +pub const SpvBuiltIn__SpvBuiltInFragDepth: SpvBuiltIn_ = 22; +pub const SpvBuiltIn__SpvBuiltInHelperInvocation: SpvBuiltIn_ = 23; +pub const SpvBuiltIn__SpvBuiltInNumWorkgroups: SpvBuiltIn_ = 24; +pub const SpvBuiltIn__SpvBuiltInWorkgroupSize: SpvBuiltIn_ = 25; +pub const SpvBuiltIn__SpvBuiltInWorkgroupId: SpvBuiltIn_ = 26; +pub const SpvBuiltIn__SpvBuiltInLocalInvocationId: SpvBuiltIn_ = 27; +pub const SpvBuiltIn__SpvBuiltInGlobalInvocationId: SpvBuiltIn_ = 28; +pub const SpvBuiltIn__SpvBuiltInLocalInvocationIndex: SpvBuiltIn_ = 29; +pub const SpvBuiltIn__SpvBuiltInWorkDim: SpvBuiltIn_ = 30; +pub const SpvBuiltIn__SpvBuiltInGlobalSize: SpvBuiltIn_ = 31; +pub const SpvBuiltIn__SpvBuiltInEnqueuedWorkgroupSize: SpvBuiltIn_ = 32; +pub const SpvBuiltIn__SpvBuiltInGlobalOffset: SpvBuiltIn_ = 33; +pub const SpvBuiltIn__SpvBuiltInGlobalLinearId: SpvBuiltIn_ = 34; +pub const SpvBuiltIn__SpvBuiltInSubgroupSize: SpvBuiltIn_ = 36; +pub const SpvBuiltIn__SpvBuiltInSubgroupMaxSize: SpvBuiltIn_ = 37; +pub const SpvBuiltIn__SpvBuiltInNumSubgroups: SpvBuiltIn_ = 38; +pub const SpvBuiltIn__SpvBuiltInNumEnqueuedSubgroups: SpvBuiltIn_ = 39; +pub const SpvBuiltIn__SpvBuiltInSubgroupId: SpvBuiltIn_ = 40; +pub const SpvBuiltIn__SpvBuiltInSubgroupLocalInvocationId: SpvBuiltIn_ = 41; +pub const SpvBuiltIn__SpvBuiltInVertexIndex: SpvBuiltIn_ = 42; +pub const SpvBuiltIn__SpvBuiltInInstanceIndex: SpvBuiltIn_ = 43; +pub const SpvBuiltIn__SpvBuiltInCoreIDARM: SpvBuiltIn_ = 4160; +pub const SpvBuiltIn__SpvBuiltInCoreCountARM: SpvBuiltIn_ = 4161; +pub const SpvBuiltIn__SpvBuiltInCoreMaxIDARM: SpvBuiltIn_ = 4162; +pub const SpvBuiltIn__SpvBuiltInWarpIDARM: SpvBuiltIn_ = 4163; +pub const SpvBuiltIn__SpvBuiltInWarpMaxIDARM: SpvBuiltIn_ = 4164; +pub const SpvBuiltIn__SpvBuiltInSubgroupEqMask: SpvBuiltIn_ = 4416; +pub const SpvBuiltIn__SpvBuiltInSubgroupEqMaskKHR: SpvBuiltIn_ = 4416; +pub const SpvBuiltIn__SpvBuiltInSubgroupGeMask: SpvBuiltIn_ = 4417; +pub const SpvBuiltIn__SpvBuiltInSubgroupGeMaskKHR: SpvBuiltIn_ = 4417; +pub const SpvBuiltIn__SpvBuiltInSubgroupGtMask: SpvBuiltIn_ = 4418; +pub const SpvBuiltIn__SpvBuiltInSubgroupGtMaskKHR: SpvBuiltIn_ = 4418; +pub const SpvBuiltIn__SpvBuiltInSubgroupLeMask: SpvBuiltIn_ = 4419; +pub const SpvBuiltIn__SpvBuiltInSubgroupLeMaskKHR: SpvBuiltIn_ = 4419; +pub const SpvBuiltIn__SpvBuiltInSubgroupLtMask: SpvBuiltIn_ = 4420; +pub const SpvBuiltIn__SpvBuiltInSubgroupLtMaskKHR: SpvBuiltIn_ = 4420; +pub const SpvBuiltIn__SpvBuiltInBaseVertex: SpvBuiltIn_ = 4424; +pub const SpvBuiltIn__SpvBuiltInBaseInstance: SpvBuiltIn_ = 4425; +pub const SpvBuiltIn__SpvBuiltInDrawIndex: SpvBuiltIn_ = 4426; +pub const SpvBuiltIn__SpvBuiltInPrimitiveShadingRateKHR: SpvBuiltIn_ = 4432; +pub const SpvBuiltIn__SpvBuiltInDeviceIndex: SpvBuiltIn_ = 4438; +pub const SpvBuiltIn__SpvBuiltInViewIndex: SpvBuiltIn_ = 4440; +pub const SpvBuiltIn__SpvBuiltInShadingRateKHR: SpvBuiltIn_ = 4444; +pub const SpvBuiltIn__SpvBuiltInTileOffsetQCOM: SpvBuiltIn_ = 4492; +pub const SpvBuiltIn__SpvBuiltInTileDimensionQCOM: SpvBuiltIn_ = 4493; +pub const SpvBuiltIn__SpvBuiltInTileApronSizeQCOM: SpvBuiltIn_ = 4494; +pub const SpvBuiltIn__SpvBuiltInBaryCoordNoPerspAMD: SpvBuiltIn_ = 4992; +pub const SpvBuiltIn__SpvBuiltInBaryCoordNoPerspCentroidAMD: SpvBuiltIn_ = 4993; +pub const SpvBuiltIn__SpvBuiltInBaryCoordNoPerspSampleAMD: SpvBuiltIn_ = 4994; +pub const SpvBuiltIn__SpvBuiltInBaryCoordSmoothAMD: SpvBuiltIn_ = 4995; +pub const SpvBuiltIn__SpvBuiltInBaryCoordSmoothCentroidAMD: SpvBuiltIn_ = 4996; +pub const SpvBuiltIn__SpvBuiltInBaryCoordSmoothSampleAMD: SpvBuiltIn_ = 4997; +pub const SpvBuiltIn__SpvBuiltInBaryCoordPullModelAMD: SpvBuiltIn_ = 4998; +pub const SpvBuiltIn__SpvBuiltInFragStencilRefEXT: SpvBuiltIn_ = 5014; +pub const SpvBuiltIn__SpvBuiltInRemainingRecursionLevelsAMDX: SpvBuiltIn_ = 5021; +pub const SpvBuiltIn__SpvBuiltInShaderIndexAMDX: SpvBuiltIn_ = 5073; +pub const SpvBuiltIn__SpvBuiltInViewportMaskNV: SpvBuiltIn_ = 5253; +pub const SpvBuiltIn__SpvBuiltInSecondaryPositionNV: SpvBuiltIn_ = 5257; +pub const SpvBuiltIn__SpvBuiltInSecondaryViewportMaskNV: SpvBuiltIn_ = 5258; +pub const SpvBuiltIn__SpvBuiltInPositionPerViewNV: SpvBuiltIn_ = 5261; +pub const SpvBuiltIn__SpvBuiltInViewportMaskPerViewNV: SpvBuiltIn_ = 5262; +pub const SpvBuiltIn__SpvBuiltInFullyCoveredEXT: SpvBuiltIn_ = 5264; +pub const SpvBuiltIn__SpvBuiltInTaskCountNV: SpvBuiltIn_ = 5274; +pub const SpvBuiltIn__SpvBuiltInPrimitiveCountNV: SpvBuiltIn_ = 5275; +pub const SpvBuiltIn__SpvBuiltInPrimitiveIndicesNV: SpvBuiltIn_ = 5276; +pub const SpvBuiltIn__SpvBuiltInClipDistancePerViewNV: SpvBuiltIn_ = 5277; +pub const SpvBuiltIn__SpvBuiltInCullDistancePerViewNV: SpvBuiltIn_ = 5278; +pub const SpvBuiltIn__SpvBuiltInLayerPerViewNV: SpvBuiltIn_ = 5279; +pub const SpvBuiltIn__SpvBuiltInMeshViewCountNV: SpvBuiltIn_ = 5280; +pub const SpvBuiltIn__SpvBuiltInMeshViewIndicesNV: SpvBuiltIn_ = 5281; +pub const SpvBuiltIn__SpvBuiltInBaryCoordKHR: SpvBuiltIn_ = 5286; +pub const SpvBuiltIn__SpvBuiltInBaryCoordNV: SpvBuiltIn_ = 5286; +pub const SpvBuiltIn__SpvBuiltInBaryCoordNoPerspKHR: SpvBuiltIn_ = 5287; +pub const SpvBuiltIn__SpvBuiltInBaryCoordNoPerspNV: SpvBuiltIn_ = 5287; +pub const SpvBuiltIn__SpvBuiltInFragSizeEXT: SpvBuiltIn_ = 5292; +pub const SpvBuiltIn__SpvBuiltInFragmentSizeNV: SpvBuiltIn_ = 5292; +pub const SpvBuiltIn__SpvBuiltInFragInvocationCountEXT: SpvBuiltIn_ = 5293; +pub const SpvBuiltIn__SpvBuiltInInvocationsPerPixelNV: SpvBuiltIn_ = 5293; +pub const SpvBuiltIn__SpvBuiltInPrimitivePointIndicesEXT: SpvBuiltIn_ = 5294; +pub const SpvBuiltIn__SpvBuiltInPrimitiveLineIndicesEXT: SpvBuiltIn_ = 5295; +pub const SpvBuiltIn__SpvBuiltInPrimitiveTriangleIndicesEXT: SpvBuiltIn_ = 5296; +pub const SpvBuiltIn__SpvBuiltInCullPrimitiveEXT: SpvBuiltIn_ = 5299; +pub const SpvBuiltIn__SpvBuiltInLaunchIdKHR: SpvBuiltIn_ = 5319; +pub const SpvBuiltIn__SpvBuiltInLaunchIdNV: SpvBuiltIn_ = 5319; +pub const SpvBuiltIn__SpvBuiltInLaunchSizeKHR: SpvBuiltIn_ = 5320; +pub const SpvBuiltIn__SpvBuiltInLaunchSizeNV: SpvBuiltIn_ = 5320; +pub const SpvBuiltIn__SpvBuiltInWorldRayOriginKHR: SpvBuiltIn_ = 5321; +pub const SpvBuiltIn__SpvBuiltInWorldRayOriginNV: SpvBuiltIn_ = 5321; +pub const SpvBuiltIn__SpvBuiltInWorldRayDirectionKHR: SpvBuiltIn_ = 5322; +pub const SpvBuiltIn__SpvBuiltInWorldRayDirectionNV: SpvBuiltIn_ = 5322; +pub const SpvBuiltIn__SpvBuiltInObjectRayOriginKHR: SpvBuiltIn_ = 5323; +pub const SpvBuiltIn__SpvBuiltInObjectRayOriginNV: SpvBuiltIn_ = 5323; +pub const SpvBuiltIn__SpvBuiltInObjectRayDirectionKHR: SpvBuiltIn_ = 5324; +pub const SpvBuiltIn__SpvBuiltInObjectRayDirectionNV: SpvBuiltIn_ = 5324; +pub const SpvBuiltIn__SpvBuiltInRayTminKHR: SpvBuiltIn_ = 5325; +pub const SpvBuiltIn__SpvBuiltInRayTminNV: SpvBuiltIn_ = 5325; +pub const SpvBuiltIn__SpvBuiltInRayTmaxKHR: SpvBuiltIn_ = 5326; +pub const SpvBuiltIn__SpvBuiltInRayTmaxNV: SpvBuiltIn_ = 5326; +pub const SpvBuiltIn__SpvBuiltInInstanceCustomIndexKHR: SpvBuiltIn_ = 5327; +pub const SpvBuiltIn__SpvBuiltInInstanceCustomIndexNV: SpvBuiltIn_ = 5327; +pub const SpvBuiltIn__SpvBuiltInObjectToWorldKHR: SpvBuiltIn_ = 5330; +pub const SpvBuiltIn__SpvBuiltInObjectToWorldNV: SpvBuiltIn_ = 5330; +pub const SpvBuiltIn__SpvBuiltInWorldToObjectKHR: SpvBuiltIn_ = 5331; +pub const SpvBuiltIn__SpvBuiltInWorldToObjectNV: SpvBuiltIn_ = 5331; +pub const SpvBuiltIn__SpvBuiltInHitTNV: SpvBuiltIn_ = 5332; +pub const SpvBuiltIn__SpvBuiltInHitKindKHR: SpvBuiltIn_ = 5333; +pub const SpvBuiltIn__SpvBuiltInHitKindNV: SpvBuiltIn_ = 5333; +pub const SpvBuiltIn__SpvBuiltInCurrentRayTimeNV: SpvBuiltIn_ = 5334; +pub const SpvBuiltIn__SpvBuiltInHitTriangleVertexPositionsKHR: SpvBuiltIn_ = 5335; +pub const SpvBuiltIn__SpvBuiltInHitMicroTriangleVertexPositionsNV: SpvBuiltIn_ = 5337; +pub const SpvBuiltIn__SpvBuiltInHitMicroTriangleVertexBarycentricsNV: SpvBuiltIn_ = 5344; +pub const SpvBuiltIn__SpvBuiltInIncomingRayFlagsKHR: SpvBuiltIn_ = 5351; +pub const SpvBuiltIn__SpvBuiltInIncomingRayFlagsNV: SpvBuiltIn_ = 5351; +pub const SpvBuiltIn__SpvBuiltInRayGeometryIndexKHR: SpvBuiltIn_ = 5352; +pub const SpvBuiltIn__SpvBuiltInHitIsSphereNV: SpvBuiltIn_ = 5359; +pub const SpvBuiltIn__SpvBuiltInHitIsLSSNV: SpvBuiltIn_ = 5360; +pub const SpvBuiltIn__SpvBuiltInHitSpherePositionNV: SpvBuiltIn_ = 5361; +pub const SpvBuiltIn__SpvBuiltInWarpsPerSMNV: SpvBuiltIn_ = 5374; +pub const SpvBuiltIn__SpvBuiltInSMCountNV: SpvBuiltIn_ = 5375; +pub const SpvBuiltIn__SpvBuiltInWarpIDNV: SpvBuiltIn_ = 5376; +pub const SpvBuiltIn__SpvBuiltInSMIDNV: SpvBuiltIn_ = 5377; +pub const SpvBuiltIn__SpvBuiltInHitLSSPositionsNV: SpvBuiltIn_ = 5396; +pub const SpvBuiltIn__SpvBuiltInHitKindFrontFacingMicroTriangleNV: SpvBuiltIn_ = 5405; +pub const SpvBuiltIn__SpvBuiltInHitKindBackFacingMicroTriangleNV: SpvBuiltIn_ = 5406; +pub const SpvBuiltIn__SpvBuiltInHitSphereRadiusNV: SpvBuiltIn_ = 5420; +pub const SpvBuiltIn__SpvBuiltInHitLSSRadiiNV: SpvBuiltIn_ = 5421; +pub const SpvBuiltIn__SpvBuiltInClusterIDNV: SpvBuiltIn_ = 5436; +pub const SpvBuiltIn__SpvBuiltInCullMaskKHR: SpvBuiltIn_ = 6021; +pub const SpvBuiltIn__SpvBuiltInMax: SpvBuiltIn_ = 2147483647; +pub type SpvBuiltIn_ = ::std::os::raw::c_int; +pub use self::SpvBuiltIn_ as SpvBuiltIn; +pub const SpvSelectionControlShift__SpvSelectionControlFlattenShift: SpvSelectionControlShift_ = 0; +pub const SpvSelectionControlShift__SpvSelectionControlDontFlattenShift: SpvSelectionControlShift_ = + 1; +pub const SpvSelectionControlShift__SpvSelectionControlMax: SpvSelectionControlShift_ = 2147483647; +pub type SpvSelectionControlShift_ = ::std::os::raw::c_int; +pub use self::SpvSelectionControlShift_ as SpvSelectionControlShift; +pub const SpvSelectionControlMask__SpvSelectionControlMaskNone: SpvSelectionControlMask_ = 0; +pub const SpvSelectionControlMask__SpvSelectionControlFlattenMask: SpvSelectionControlMask_ = 1; +pub const SpvSelectionControlMask__SpvSelectionControlDontFlattenMask: SpvSelectionControlMask_ = 2; +pub type SpvSelectionControlMask_ = ::std::os::raw::c_int; +pub use self::SpvSelectionControlMask_ as SpvSelectionControlMask; +pub const SpvLoopControlShift__SpvLoopControlUnrollShift: SpvLoopControlShift_ = 0; +pub const SpvLoopControlShift__SpvLoopControlDontUnrollShift: SpvLoopControlShift_ = 1; +pub const SpvLoopControlShift__SpvLoopControlDependencyInfiniteShift: SpvLoopControlShift_ = 2; +pub const SpvLoopControlShift__SpvLoopControlDependencyLengthShift: SpvLoopControlShift_ = 3; +pub const SpvLoopControlShift__SpvLoopControlMinIterationsShift: SpvLoopControlShift_ = 4; +pub const SpvLoopControlShift__SpvLoopControlMaxIterationsShift: SpvLoopControlShift_ = 5; +pub const SpvLoopControlShift__SpvLoopControlIterationMultipleShift: SpvLoopControlShift_ = 6; +pub const SpvLoopControlShift__SpvLoopControlPeelCountShift: SpvLoopControlShift_ = 7; +pub const SpvLoopControlShift__SpvLoopControlPartialCountShift: SpvLoopControlShift_ = 8; +pub const SpvLoopControlShift__SpvLoopControlInitiationIntervalINTELShift: SpvLoopControlShift_ = + 16; +pub const SpvLoopControlShift__SpvLoopControlMaxConcurrencyINTELShift: SpvLoopControlShift_ = 17; +pub const SpvLoopControlShift__SpvLoopControlDependencyArrayINTELShift: SpvLoopControlShift_ = 18; +pub const SpvLoopControlShift__SpvLoopControlPipelineEnableINTELShift: SpvLoopControlShift_ = 19; +pub const SpvLoopControlShift__SpvLoopControlLoopCoalesceINTELShift: SpvLoopControlShift_ = 20; +pub const SpvLoopControlShift__SpvLoopControlMaxInterleavingINTELShift: SpvLoopControlShift_ = 21; +pub const SpvLoopControlShift__SpvLoopControlSpeculatedIterationsINTELShift: SpvLoopControlShift_ = + 22; +pub const SpvLoopControlShift__SpvLoopControlNoFusionINTELShift: SpvLoopControlShift_ = 23; +pub const SpvLoopControlShift__SpvLoopControlLoopCountINTELShift: SpvLoopControlShift_ = 24; +pub const SpvLoopControlShift__SpvLoopControlMaxReinvocationDelayINTELShift: SpvLoopControlShift_ = + 25; +pub const SpvLoopControlShift__SpvLoopControlMax: SpvLoopControlShift_ = 2147483647; +pub type SpvLoopControlShift_ = ::std::os::raw::c_int; +pub use self::SpvLoopControlShift_ as SpvLoopControlShift; +pub const SpvLoopControlMask__SpvLoopControlMaskNone: SpvLoopControlMask_ = 0; +pub const SpvLoopControlMask__SpvLoopControlUnrollMask: SpvLoopControlMask_ = 1; +pub const SpvLoopControlMask__SpvLoopControlDontUnrollMask: SpvLoopControlMask_ = 2; +pub const SpvLoopControlMask__SpvLoopControlDependencyInfiniteMask: SpvLoopControlMask_ = 4; +pub const SpvLoopControlMask__SpvLoopControlDependencyLengthMask: SpvLoopControlMask_ = 8; +pub const SpvLoopControlMask__SpvLoopControlMinIterationsMask: SpvLoopControlMask_ = 16; +pub const SpvLoopControlMask__SpvLoopControlMaxIterationsMask: SpvLoopControlMask_ = 32; +pub const SpvLoopControlMask__SpvLoopControlIterationMultipleMask: SpvLoopControlMask_ = 64; +pub const SpvLoopControlMask__SpvLoopControlPeelCountMask: SpvLoopControlMask_ = 128; +pub const SpvLoopControlMask__SpvLoopControlPartialCountMask: SpvLoopControlMask_ = 256; +pub const SpvLoopControlMask__SpvLoopControlInitiationIntervalINTELMask: SpvLoopControlMask_ = + 65536; +pub const SpvLoopControlMask__SpvLoopControlMaxConcurrencyINTELMask: SpvLoopControlMask_ = 131072; +pub const SpvLoopControlMask__SpvLoopControlDependencyArrayINTELMask: SpvLoopControlMask_ = 262144; +pub const SpvLoopControlMask__SpvLoopControlPipelineEnableINTELMask: SpvLoopControlMask_ = 524288; +pub const SpvLoopControlMask__SpvLoopControlLoopCoalesceINTELMask: SpvLoopControlMask_ = 1048576; +pub const SpvLoopControlMask__SpvLoopControlMaxInterleavingINTELMask: SpvLoopControlMask_ = 2097152; +pub const SpvLoopControlMask__SpvLoopControlSpeculatedIterationsINTELMask: SpvLoopControlMask_ = + 4194304; +pub const SpvLoopControlMask__SpvLoopControlNoFusionINTELMask: SpvLoopControlMask_ = 8388608; +pub const SpvLoopControlMask__SpvLoopControlLoopCountINTELMask: SpvLoopControlMask_ = 16777216; +pub const SpvLoopControlMask__SpvLoopControlMaxReinvocationDelayINTELMask: SpvLoopControlMask_ = + 33554432; +pub type SpvLoopControlMask_ = ::std::os::raw::c_int; +pub use self::SpvLoopControlMask_ as SpvLoopControlMask; +pub const SpvFunctionControlShift__SpvFunctionControlInlineShift: SpvFunctionControlShift_ = 0; +pub const SpvFunctionControlShift__SpvFunctionControlDontInlineShift: SpvFunctionControlShift_ = 1; +pub const SpvFunctionControlShift__SpvFunctionControlPureShift: SpvFunctionControlShift_ = 2; +pub const SpvFunctionControlShift__SpvFunctionControlConstShift: SpvFunctionControlShift_ = 3; +pub const SpvFunctionControlShift__SpvFunctionControlOptNoneEXTShift: SpvFunctionControlShift_ = 16; +pub const SpvFunctionControlShift__SpvFunctionControlOptNoneINTELShift: SpvFunctionControlShift_ = + 16; +pub const SpvFunctionControlShift__SpvFunctionControlMax: SpvFunctionControlShift_ = 2147483647; +pub type SpvFunctionControlShift_ = ::std::os::raw::c_int; +pub use self::SpvFunctionControlShift_ as SpvFunctionControlShift; +pub const SpvFunctionControlMask__SpvFunctionControlMaskNone: SpvFunctionControlMask_ = 0; +pub const SpvFunctionControlMask__SpvFunctionControlInlineMask: SpvFunctionControlMask_ = 1; +pub const SpvFunctionControlMask__SpvFunctionControlDontInlineMask: SpvFunctionControlMask_ = 2; +pub const SpvFunctionControlMask__SpvFunctionControlPureMask: SpvFunctionControlMask_ = 4; +pub const SpvFunctionControlMask__SpvFunctionControlConstMask: SpvFunctionControlMask_ = 8; +pub const SpvFunctionControlMask__SpvFunctionControlOptNoneEXTMask: SpvFunctionControlMask_ = 65536; +pub const SpvFunctionControlMask__SpvFunctionControlOptNoneINTELMask: SpvFunctionControlMask_ = + 65536; +pub type SpvFunctionControlMask_ = ::std::os::raw::c_int; +pub use self::SpvFunctionControlMask_ as SpvFunctionControlMask; +pub const SpvMemorySemanticsShift__SpvMemorySemanticsAcquireShift: SpvMemorySemanticsShift_ = 1; +pub const SpvMemorySemanticsShift__SpvMemorySemanticsReleaseShift: SpvMemorySemanticsShift_ = 2; +pub const SpvMemorySemanticsShift__SpvMemorySemanticsAcquireReleaseShift: SpvMemorySemanticsShift_ = + 3; +pub const SpvMemorySemanticsShift__SpvMemorySemanticsSequentiallyConsistentShift: + SpvMemorySemanticsShift_ = 4; +pub const SpvMemorySemanticsShift__SpvMemorySemanticsUniformMemoryShift: SpvMemorySemanticsShift_ = + 6; +pub const SpvMemorySemanticsShift__SpvMemorySemanticsSubgroupMemoryShift: SpvMemorySemanticsShift_ = + 7; +pub const SpvMemorySemanticsShift__SpvMemorySemanticsWorkgroupMemoryShift: + SpvMemorySemanticsShift_ = 8; +pub const SpvMemorySemanticsShift__SpvMemorySemanticsCrossWorkgroupMemoryShift: + SpvMemorySemanticsShift_ = 9; +pub const SpvMemorySemanticsShift__SpvMemorySemanticsAtomicCounterMemoryShift: + SpvMemorySemanticsShift_ = 10; +pub const SpvMemorySemanticsShift__SpvMemorySemanticsImageMemoryShift: SpvMemorySemanticsShift_ = + 11; +pub const SpvMemorySemanticsShift__SpvMemorySemanticsOutputMemoryShift: SpvMemorySemanticsShift_ = + 12; +pub const SpvMemorySemanticsShift__SpvMemorySemanticsOutputMemoryKHRShift: + SpvMemorySemanticsShift_ = 12; +pub const SpvMemorySemanticsShift__SpvMemorySemanticsMakeAvailableShift: SpvMemorySemanticsShift_ = + 13; +pub const SpvMemorySemanticsShift__SpvMemorySemanticsMakeAvailableKHRShift: + SpvMemorySemanticsShift_ = 13; +pub const SpvMemorySemanticsShift__SpvMemorySemanticsMakeVisibleShift: SpvMemorySemanticsShift_ = + 14; +pub const SpvMemorySemanticsShift__SpvMemorySemanticsMakeVisibleKHRShift: SpvMemorySemanticsShift_ = + 14; +pub const SpvMemorySemanticsShift__SpvMemorySemanticsVolatileShift: SpvMemorySemanticsShift_ = 15; +pub const SpvMemorySemanticsShift__SpvMemorySemanticsMax: SpvMemorySemanticsShift_ = 2147483647; +pub type SpvMemorySemanticsShift_ = ::std::os::raw::c_int; +pub use self::SpvMemorySemanticsShift_ as SpvMemorySemanticsShift; +pub const SpvMemorySemanticsMask__SpvMemorySemanticsMaskNone: SpvMemorySemanticsMask_ = 0; +pub const SpvMemorySemanticsMask__SpvMemorySemanticsAcquireMask: SpvMemorySemanticsMask_ = 2; +pub const SpvMemorySemanticsMask__SpvMemorySemanticsReleaseMask: SpvMemorySemanticsMask_ = 4; +pub const SpvMemorySemanticsMask__SpvMemorySemanticsAcquireReleaseMask: SpvMemorySemanticsMask_ = 8; +pub const SpvMemorySemanticsMask__SpvMemorySemanticsSequentiallyConsistentMask: + SpvMemorySemanticsMask_ = 16; +pub const SpvMemorySemanticsMask__SpvMemorySemanticsUniformMemoryMask: SpvMemorySemanticsMask_ = 64; +pub const SpvMemorySemanticsMask__SpvMemorySemanticsSubgroupMemoryMask: SpvMemorySemanticsMask_ = + 128; +pub const SpvMemorySemanticsMask__SpvMemorySemanticsWorkgroupMemoryMask: SpvMemorySemanticsMask_ = + 256; +pub const SpvMemorySemanticsMask__SpvMemorySemanticsCrossWorkgroupMemoryMask: + SpvMemorySemanticsMask_ = 512; +pub const SpvMemorySemanticsMask__SpvMemorySemanticsAtomicCounterMemoryMask: + SpvMemorySemanticsMask_ = 1024; +pub const SpvMemorySemanticsMask__SpvMemorySemanticsImageMemoryMask: SpvMemorySemanticsMask_ = 2048; +pub const SpvMemorySemanticsMask__SpvMemorySemanticsOutputMemoryMask: SpvMemorySemanticsMask_ = + 4096; +pub const SpvMemorySemanticsMask__SpvMemorySemanticsOutputMemoryKHRMask: SpvMemorySemanticsMask_ = + 4096; +pub const SpvMemorySemanticsMask__SpvMemorySemanticsMakeAvailableMask: SpvMemorySemanticsMask_ = + 8192; +pub const SpvMemorySemanticsMask__SpvMemorySemanticsMakeAvailableKHRMask: SpvMemorySemanticsMask_ = + 8192; +pub const SpvMemorySemanticsMask__SpvMemorySemanticsMakeVisibleMask: SpvMemorySemanticsMask_ = + 16384; +pub const SpvMemorySemanticsMask__SpvMemorySemanticsMakeVisibleKHRMask: SpvMemorySemanticsMask_ = + 16384; +pub const SpvMemorySemanticsMask__SpvMemorySemanticsVolatileMask: SpvMemorySemanticsMask_ = 32768; +pub type SpvMemorySemanticsMask_ = ::std::os::raw::c_int; +pub use self::SpvMemorySemanticsMask_ as SpvMemorySemanticsMask; +pub const SpvMemoryAccessShift__SpvMemoryAccessVolatileShift: SpvMemoryAccessShift_ = 0; +pub const SpvMemoryAccessShift__SpvMemoryAccessAlignedShift: SpvMemoryAccessShift_ = 1; +pub const SpvMemoryAccessShift__SpvMemoryAccessNontemporalShift: SpvMemoryAccessShift_ = 2; +pub const SpvMemoryAccessShift__SpvMemoryAccessMakePointerAvailableShift: SpvMemoryAccessShift_ = 3; +pub const SpvMemoryAccessShift__SpvMemoryAccessMakePointerAvailableKHRShift: SpvMemoryAccessShift_ = + 3; +pub const SpvMemoryAccessShift__SpvMemoryAccessMakePointerVisibleShift: SpvMemoryAccessShift_ = 4; +pub const SpvMemoryAccessShift__SpvMemoryAccessMakePointerVisibleKHRShift: SpvMemoryAccessShift_ = + 4; +pub const SpvMemoryAccessShift__SpvMemoryAccessNonPrivatePointerShift: SpvMemoryAccessShift_ = 5; +pub const SpvMemoryAccessShift__SpvMemoryAccessNonPrivatePointerKHRShift: SpvMemoryAccessShift_ = 5; +pub const SpvMemoryAccessShift__SpvMemoryAccessAliasScopeINTELMaskShift: SpvMemoryAccessShift_ = 16; +pub const SpvMemoryAccessShift__SpvMemoryAccessNoAliasINTELMaskShift: SpvMemoryAccessShift_ = 17; +pub const SpvMemoryAccessShift__SpvMemoryAccessMax: SpvMemoryAccessShift_ = 2147483647; +pub type SpvMemoryAccessShift_ = ::std::os::raw::c_int; +pub use self::SpvMemoryAccessShift_ as SpvMemoryAccessShift; +pub const SpvMemoryAccessMask__SpvMemoryAccessMaskNone: SpvMemoryAccessMask_ = 0; +pub const SpvMemoryAccessMask__SpvMemoryAccessVolatileMask: SpvMemoryAccessMask_ = 1; +pub const SpvMemoryAccessMask__SpvMemoryAccessAlignedMask: SpvMemoryAccessMask_ = 2; +pub const SpvMemoryAccessMask__SpvMemoryAccessNontemporalMask: SpvMemoryAccessMask_ = 4; +pub const SpvMemoryAccessMask__SpvMemoryAccessMakePointerAvailableMask: SpvMemoryAccessMask_ = 8; +pub const SpvMemoryAccessMask__SpvMemoryAccessMakePointerAvailableKHRMask: SpvMemoryAccessMask_ = 8; +pub const SpvMemoryAccessMask__SpvMemoryAccessMakePointerVisibleMask: SpvMemoryAccessMask_ = 16; +pub const SpvMemoryAccessMask__SpvMemoryAccessMakePointerVisibleKHRMask: SpvMemoryAccessMask_ = 16; +pub const SpvMemoryAccessMask__SpvMemoryAccessNonPrivatePointerMask: SpvMemoryAccessMask_ = 32; +pub const SpvMemoryAccessMask__SpvMemoryAccessNonPrivatePointerKHRMask: SpvMemoryAccessMask_ = 32; +pub const SpvMemoryAccessMask__SpvMemoryAccessAliasScopeINTELMaskMask: SpvMemoryAccessMask_ = 65536; +pub const SpvMemoryAccessMask__SpvMemoryAccessNoAliasINTELMaskMask: SpvMemoryAccessMask_ = 131072; +pub type SpvMemoryAccessMask_ = ::std::os::raw::c_int; +pub use self::SpvMemoryAccessMask_ as SpvMemoryAccessMask; +pub const SpvScope__SpvScopeCrossDevice: SpvScope_ = 0; +pub const SpvScope__SpvScopeDevice: SpvScope_ = 1; +pub const SpvScope__SpvScopeWorkgroup: SpvScope_ = 2; +pub const SpvScope__SpvScopeSubgroup: SpvScope_ = 3; +pub const SpvScope__SpvScopeInvocation: SpvScope_ = 4; +pub const SpvScope__SpvScopeQueueFamily: SpvScope_ = 5; +pub const SpvScope__SpvScopeQueueFamilyKHR: SpvScope_ = 5; +pub const SpvScope__SpvScopeShaderCallKHR: SpvScope_ = 6; +pub const SpvScope__SpvScopeMax: SpvScope_ = 2147483647; +pub type SpvScope_ = ::std::os::raw::c_int; +pub use self::SpvScope_ as SpvScope; +pub const SpvGroupOperation__SpvGroupOperationReduce: SpvGroupOperation_ = 0; +pub const SpvGroupOperation__SpvGroupOperationInclusiveScan: SpvGroupOperation_ = 1; +pub const SpvGroupOperation__SpvGroupOperationExclusiveScan: SpvGroupOperation_ = 2; +pub const SpvGroupOperation__SpvGroupOperationClusteredReduce: SpvGroupOperation_ = 3; +pub const SpvGroupOperation__SpvGroupOperationPartitionedReduceNV: SpvGroupOperation_ = 6; +pub const SpvGroupOperation__SpvGroupOperationPartitionedInclusiveScanNV: SpvGroupOperation_ = 7; +pub const SpvGroupOperation__SpvGroupOperationPartitionedExclusiveScanNV: SpvGroupOperation_ = 8; +pub const SpvGroupOperation__SpvGroupOperationMax: SpvGroupOperation_ = 2147483647; +pub type SpvGroupOperation_ = ::std::os::raw::c_int; +pub use self::SpvGroupOperation_ as SpvGroupOperation; +pub const SpvKernelEnqueueFlags__SpvKernelEnqueueFlagsNoWait: SpvKernelEnqueueFlags_ = 0; +pub const SpvKernelEnqueueFlags__SpvKernelEnqueueFlagsWaitKernel: SpvKernelEnqueueFlags_ = 1; +pub const SpvKernelEnqueueFlags__SpvKernelEnqueueFlagsWaitWorkGroup: SpvKernelEnqueueFlags_ = 2; +pub const SpvKernelEnqueueFlags__SpvKernelEnqueueFlagsMax: SpvKernelEnqueueFlags_ = 2147483647; +pub type SpvKernelEnqueueFlags_ = ::std::os::raw::c_int; +pub use self::SpvKernelEnqueueFlags_ as SpvKernelEnqueueFlags; +pub const SpvKernelProfilingInfoShift__SpvKernelProfilingInfoCmdExecTimeShift: + SpvKernelProfilingInfoShift_ = 0; +pub const SpvKernelProfilingInfoShift__SpvKernelProfilingInfoMax: SpvKernelProfilingInfoShift_ = + 2147483647; +pub type SpvKernelProfilingInfoShift_ = ::std::os::raw::c_int; +pub use self::SpvKernelProfilingInfoShift_ as SpvKernelProfilingInfoShift; +pub const SpvKernelProfilingInfoMask__SpvKernelProfilingInfoMaskNone: SpvKernelProfilingInfoMask_ = + 0; +pub const SpvKernelProfilingInfoMask__SpvKernelProfilingInfoCmdExecTimeMask: + SpvKernelProfilingInfoMask_ = 1; +pub type SpvKernelProfilingInfoMask_ = ::std::os::raw::c_int; +pub use self::SpvKernelProfilingInfoMask_ as SpvKernelProfilingInfoMask; +pub const SpvCapability__SpvCapabilityMatrix: SpvCapability_ = 0; +pub const SpvCapability__SpvCapabilityShader: SpvCapability_ = 1; +pub const SpvCapability__SpvCapabilityGeometry: SpvCapability_ = 2; +pub const SpvCapability__SpvCapabilityTessellation: SpvCapability_ = 3; +pub const SpvCapability__SpvCapabilityAddresses: SpvCapability_ = 4; +pub const SpvCapability__SpvCapabilityLinkage: SpvCapability_ = 5; +pub const SpvCapability__SpvCapabilityKernel: SpvCapability_ = 6; +pub const SpvCapability__SpvCapabilityVector16: SpvCapability_ = 7; +pub const SpvCapability__SpvCapabilityFloat16Buffer: SpvCapability_ = 8; +pub const SpvCapability__SpvCapabilityFloat16: SpvCapability_ = 9; +pub const SpvCapability__SpvCapabilityFloat64: SpvCapability_ = 10; +pub const SpvCapability__SpvCapabilityInt64: SpvCapability_ = 11; +pub const SpvCapability__SpvCapabilityInt64Atomics: SpvCapability_ = 12; +pub const SpvCapability__SpvCapabilityImageBasic: SpvCapability_ = 13; +pub const SpvCapability__SpvCapabilityImageReadWrite: SpvCapability_ = 14; +pub const SpvCapability__SpvCapabilityImageMipmap: SpvCapability_ = 15; +pub const SpvCapability__SpvCapabilityPipes: SpvCapability_ = 17; +pub const SpvCapability__SpvCapabilityGroups: SpvCapability_ = 18; +pub const SpvCapability__SpvCapabilityDeviceEnqueue: SpvCapability_ = 19; +pub const SpvCapability__SpvCapabilityLiteralSampler: SpvCapability_ = 20; +pub const SpvCapability__SpvCapabilityAtomicStorage: SpvCapability_ = 21; +pub const SpvCapability__SpvCapabilityInt16: SpvCapability_ = 22; +pub const SpvCapability__SpvCapabilityTessellationPointSize: SpvCapability_ = 23; +pub const SpvCapability__SpvCapabilityGeometryPointSize: SpvCapability_ = 24; +pub const SpvCapability__SpvCapabilityImageGatherExtended: SpvCapability_ = 25; +pub const SpvCapability__SpvCapabilityStorageImageMultisample: SpvCapability_ = 27; +pub const SpvCapability__SpvCapabilityUniformBufferArrayDynamicIndexing: SpvCapability_ = 28; +pub const SpvCapability__SpvCapabilitySampledImageArrayDynamicIndexing: SpvCapability_ = 29; +pub const SpvCapability__SpvCapabilityStorageBufferArrayDynamicIndexing: SpvCapability_ = 30; +pub const SpvCapability__SpvCapabilityStorageImageArrayDynamicIndexing: SpvCapability_ = 31; +pub const SpvCapability__SpvCapabilityClipDistance: SpvCapability_ = 32; +pub const SpvCapability__SpvCapabilityCullDistance: SpvCapability_ = 33; +pub const SpvCapability__SpvCapabilityImageCubeArray: SpvCapability_ = 34; +pub const SpvCapability__SpvCapabilitySampleRateShading: SpvCapability_ = 35; +pub const SpvCapability__SpvCapabilityImageRect: SpvCapability_ = 36; +pub const SpvCapability__SpvCapabilitySampledRect: SpvCapability_ = 37; +pub const SpvCapability__SpvCapabilityGenericPointer: SpvCapability_ = 38; +pub const SpvCapability__SpvCapabilityInt8: SpvCapability_ = 39; +pub const SpvCapability__SpvCapabilityInputAttachment: SpvCapability_ = 40; +pub const SpvCapability__SpvCapabilitySparseResidency: SpvCapability_ = 41; +pub const SpvCapability__SpvCapabilityMinLod: SpvCapability_ = 42; +pub const SpvCapability__SpvCapabilitySampled1D: SpvCapability_ = 43; +pub const SpvCapability__SpvCapabilityImage1D: SpvCapability_ = 44; +pub const SpvCapability__SpvCapabilitySampledCubeArray: SpvCapability_ = 45; +pub const SpvCapability__SpvCapabilitySampledBuffer: SpvCapability_ = 46; +pub const SpvCapability__SpvCapabilityImageBuffer: SpvCapability_ = 47; +pub const SpvCapability__SpvCapabilityImageMSArray: SpvCapability_ = 48; +pub const SpvCapability__SpvCapabilityStorageImageExtendedFormats: SpvCapability_ = 49; +pub const SpvCapability__SpvCapabilityImageQuery: SpvCapability_ = 50; +pub const SpvCapability__SpvCapabilityDerivativeControl: SpvCapability_ = 51; +pub const SpvCapability__SpvCapabilityInterpolationFunction: SpvCapability_ = 52; +pub const SpvCapability__SpvCapabilityTransformFeedback: SpvCapability_ = 53; +pub const SpvCapability__SpvCapabilityGeometryStreams: SpvCapability_ = 54; +pub const SpvCapability__SpvCapabilityStorageImageReadWithoutFormat: SpvCapability_ = 55; +pub const SpvCapability__SpvCapabilityStorageImageWriteWithoutFormat: SpvCapability_ = 56; +pub const SpvCapability__SpvCapabilityMultiViewport: SpvCapability_ = 57; +pub const SpvCapability__SpvCapabilitySubgroupDispatch: SpvCapability_ = 58; +pub const SpvCapability__SpvCapabilityNamedBarrier: SpvCapability_ = 59; +pub const SpvCapability__SpvCapabilityPipeStorage: SpvCapability_ = 60; +pub const SpvCapability__SpvCapabilityGroupNonUniform: SpvCapability_ = 61; +pub const SpvCapability__SpvCapabilityGroupNonUniformVote: SpvCapability_ = 62; +pub const SpvCapability__SpvCapabilityGroupNonUniformArithmetic: SpvCapability_ = 63; +pub const SpvCapability__SpvCapabilityGroupNonUniformBallot: SpvCapability_ = 64; +pub const SpvCapability__SpvCapabilityGroupNonUniformShuffle: SpvCapability_ = 65; +pub const SpvCapability__SpvCapabilityGroupNonUniformShuffleRelative: SpvCapability_ = 66; +pub const SpvCapability__SpvCapabilityGroupNonUniformClustered: SpvCapability_ = 67; +pub const SpvCapability__SpvCapabilityGroupNonUniformQuad: SpvCapability_ = 68; +pub const SpvCapability__SpvCapabilityShaderLayer: SpvCapability_ = 69; +pub const SpvCapability__SpvCapabilityShaderViewportIndex: SpvCapability_ = 70; +pub const SpvCapability__SpvCapabilityUniformDecoration: SpvCapability_ = 71; +pub const SpvCapability__SpvCapabilityCoreBuiltinsARM: SpvCapability_ = 4165; +pub const SpvCapability__SpvCapabilityTileImageColorReadAccessEXT: SpvCapability_ = 4166; +pub const SpvCapability__SpvCapabilityTileImageDepthReadAccessEXT: SpvCapability_ = 4167; +pub const SpvCapability__SpvCapabilityTileImageStencilReadAccessEXT: SpvCapability_ = 4168; +pub const SpvCapability__SpvCapabilityTensorsARM: SpvCapability_ = 4174; +pub const SpvCapability__SpvCapabilityStorageTensorArrayDynamicIndexingARM: SpvCapability_ = 4175; +pub const SpvCapability__SpvCapabilityStorageTensorArrayNonUniformIndexingARM: SpvCapability_ = + 4176; +pub const SpvCapability__SpvCapabilityGraphARM: SpvCapability_ = 4191; +pub const SpvCapability__SpvCapabilityCooperativeMatrixLayoutsARM: SpvCapability_ = 4201; +pub const SpvCapability__SpvCapabilityFloat8EXT: SpvCapability_ = 4212; +pub const SpvCapability__SpvCapabilityFloat8CooperativeMatrixEXT: SpvCapability_ = 4213; +pub const SpvCapability__SpvCapabilityFragmentShadingRateKHR: SpvCapability_ = 4422; +pub const SpvCapability__SpvCapabilitySubgroupBallotKHR: SpvCapability_ = 4423; +pub const SpvCapability__SpvCapabilityDrawParameters: SpvCapability_ = 4427; +pub const SpvCapability__SpvCapabilityWorkgroupMemoryExplicitLayoutKHR: SpvCapability_ = 4428; +pub const SpvCapability__SpvCapabilityWorkgroupMemoryExplicitLayout8BitAccessKHR: SpvCapability_ = + 4429; +pub const SpvCapability__SpvCapabilityWorkgroupMemoryExplicitLayout16BitAccessKHR: SpvCapability_ = + 4430; +pub const SpvCapability__SpvCapabilitySubgroupVoteKHR: SpvCapability_ = 4431; +pub const SpvCapability__SpvCapabilityStorageBuffer16BitAccess: SpvCapability_ = 4433; +pub const SpvCapability__SpvCapabilityStorageUniformBufferBlock16: SpvCapability_ = 4433; +pub const SpvCapability__SpvCapabilityStorageUniform16: SpvCapability_ = 4434; +pub const SpvCapability__SpvCapabilityUniformAndStorageBuffer16BitAccess: SpvCapability_ = 4434; +pub const SpvCapability__SpvCapabilityStoragePushConstant16: SpvCapability_ = 4435; +pub const SpvCapability__SpvCapabilityStorageInputOutput16: SpvCapability_ = 4436; +pub const SpvCapability__SpvCapabilityDeviceGroup: SpvCapability_ = 4437; +pub const SpvCapability__SpvCapabilityMultiView: SpvCapability_ = 4439; +pub const SpvCapability__SpvCapabilityVariablePointersStorageBuffer: SpvCapability_ = 4441; +pub const SpvCapability__SpvCapabilityVariablePointers: SpvCapability_ = 4442; +pub const SpvCapability__SpvCapabilityAtomicStorageOps: SpvCapability_ = 4445; +pub const SpvCapability__SpvCapabilitySampleMaskPostDepthCoverage: SpvCapability_ = 4447; +pub const SpvCapability__SpvCapabilityStorageBuffer8BitAccess: SpvCapability_ = 4448; +pub const SpvCapability__SpvCapabilityUniformAndStorageBuffer8BitAccess: SpvCapability_ = 4449; +pub const SpvCapability__SpvCapabilityStoragePushConstant8: SpvCapability_ = 4450; +pub const SpvCapability__SpvCapabilityDenormPreserve: SpvCapability_ = 4464; +pub const SpvCapability__SpvCapabilityDenormFlushToZero: SpvCapability_ = 4465; +pub const SpvCapability__SpvCapabilitySignedZeroInfNanPreserve: SpvCapability_ = 4466; +pub const SpvCapability__SpvCapabilityRoundingModeRTE: SpvCapability_ = 4467; +pub const SpvCapability__SpvCapabilityRoundingModeRTZ: SpvCapability_ = 4468; +pub const SpvCapability__SpvCapabilityRayQueryProvisionalKHR: SpvCapability_ = 4471; +pub const SpvCapability__SpvCapabilityRayQueryKHR: SpvCapability_ = 4472; +pub const SpvCapability__SpvCapabilityUntypedPointersKHR: SpvCapability_ = 4473; +pub const SpvCapability__SpvCapabilityRayTraversalPrimitiveCullingKHR: SpvCapability_ = 4478; +pub const SpvCapability__SpvCapabilityRayTracingKHR: SpvCapability_ = 4479; +pub const SpvCapability__SpvCapabilityTextureSampleWeightedQCOM: SpvCapability_ = 4484; +pub const SpvCapability__SpvCapabilityTextureBoxFilterQCOM: SpvCapability_ = 4485; +pub const SpvCapability__SpvCapabilityTextureBlockMatchQCOM: SpvCapability_ = 4486; +pub const SpvCapability__SpvCapabilityTileShadingQCOM: SpvCapability_ = 4495; +pub const SpvCapability__SpvCapabilityCooperativeMatrixConversionQCOM: SpvCapability_ = 4496; +pub const SpvCapability__SpvCapabilityTextureBlockMatch2QCOM: SpvCapability_ = 4498; +pub const SpvCapability__SpvCapabilityFloat16ImageAMD: SpvCapability_ = 5008; +pub const SpvCapability__SpvCapabilityImageGatherBiasLodAMD: SpvCapability_ = 5009; +pub const SpvCapability__SpvCapabilityFragmentMaskAMD: SpvCapability_ = 5010; +pub const SpvCapability__SpvCapabilityStencilExportEXT: SpvCapability_ = 5013; +pub const SpvCapability__SpvCapabilityImageReadWriteLodAMD: SpvCapability_ = 5015; +pub const SpvCapability__SpvCapabilityInt64ImageEXT: SpvCapability_ = 5016; +pub const SpvCapability__SpvCapabilityShaderClockKHR: SpvCapability_ = 5055; +pub const SpvCapability__SpvCapabilityShaderEnqueueAMDX: SpvCapability_ = 5067; +pub const SpvCapability__SpvCapabilityQuadControlKHR: SpvCapability_ = 5087; +pub const SpvCapability__SpvCapabilityInt4TypeINTEL: SpvCapability_ = 5112; +pub const SpvCapability__SpvCapabilityInt4CooperativeMatrixINTEL: SpvCapability_ = 5114; +pub const SpvCapability__SpvCapabilityBFloat16TypeKHR: SpvCapability_ = 5116; +pub const SpvCapability__SpvCapabilityBFloat16DotProductKHR: SpvCapability_ = 5117; +pub const SpvCapability__SpvCapabilityBFloat16CooperativeMatrixKHR: SpvCapability_ = 5118; +pub const SpvCapability__SpvCapabilitySampleMaskOverrideCoverageNV: SpvCapability_ = 5249; +pub const SpvCapability__SpvCapabilityGeometryShaderPassthroughNV: SpvCapability_ = 5251; +pub const SpvCapability__SpvCapabilityShaderViewportIndexLayerEXT: SpvCapability_ = 5254; +pub const SpvCapability__SpvCapabilityShaderViewportIndexLayerNV: SpvCapability_ = 5254; +pub const SpvCapability__SpvCapabilityShaderViewportMaskNV: SpvCapability_ = 5255; +pub const SpvCapability__SpvCapabilityShaderStereoViewNV: SpvCapability_ = 5259; +pub const SpvCapability__SpvCapabilityPerViewAttributesNV: SpvCapability_ = 5260; +pub const SpvCapability__SpvCapabilityFragmentFullyCoveredEXT: SpvCapability_ = 5265; +pub const SpvCapability__SpvCapabilityMeshShadingNV: SpvCapability_ = 5266; +pub const SpvCapability__SpvCapabilityImageFootprintNV: SpvCapability_ = 5282; +pub const SpvCapability__SpvCapabilityMeshShadingEXT: SpvCapability_ = 5283; +pub const SpvCapability__SpvCapabilityFragmentBarycentricKHR: SpvCapability_ = 5284; +pub const SpvCapability__SpvCapabilityFragmentBarycentricNV: SpvCapability_ = 5284; +pub const SpvCapability__SpvCapabilityComputeDerivativeGroupQuadsKHR: SpvCapability_ = 5288; +pub const SpvCapability__SpvCapabilityComputeDerivativeGroupQuadsNV: SpvCapability_ = 5288; +pub const SpvCapability__SpvCapabilityFragmentDensityEXT: SpvCapability_ = 5291; +pub const SpvCapability__SpvCapabilityShadingRateNV: SpvCapability_ = 5291; +pub const SpvCapability__SpvCapabilityGroupNonUniformPartitionedNV: SpvCapability_ = 5297; +pub const SpvCapability__SpvCapabilityShaderNonUniform: SpvCapability_ = 5301; +pub const SpvCapability__SpvCapabilityShaderNonUniformEXT: SpvCapability_ = 5301; +pub const SpvCapability__SpvCapabilityRuntimeDescriptorArray: SpvCapability_ = 5302; +pub const SpvCapability__SpvCapabilityRuntimeDescriptorArrayEXT: SpvCapability_ = 5302; +pub const SpvCapability__SpvCapabilityInputAttachmentArrayDynamicIndexing: SpvCapability_ = 5303; +pub const SpvCapability__SpvCapabilityInputAttachmentArrayDynamicIndexingEXT: SpvCapability_ = 5303; +pub const SpvCapability__SpvCapabilityUniformTexelBufferArrayDynamicIndexing: SpvCapability_ = 5304; +pub const SpvCapability__SpvCapabilityUniformTexelBufferArrayDynamicIndexingEXT: SpvCapability_ = + 5304; +pub const SpvCapability__SpvCapabilityStorageTexelBufferArrayDynamicIndexing: SpvCapability_ = 5305; +pub const SpvCapability__SpvCapabilityStorageTexelBufferArrayDynamicIndexingEXT: SpvCapability_ = + 5305; +pub const SpvCapability__SpvCapabilityUniformBufferArrayNonUniformIndexing: SpvCapability_ = 5306; +pub const SpvCapability__SpvCapabilityUniformBufferArrayNonUniformIndexingEXT: SpvCapability_ = + 5306; +pub const SpvCapability__SpvCapabilitySampledImageArrayNonUniformIndexing: SpvCapability_ = 5307; +pub const SpvCapability__SpvCapabilitySampledImageArrayNonUniformIndexingEXT: SpvCapability_ = 5307; +pub const SpvCapability__SpvCapabilityStorageBufferArrayNonUniformIndexing: SpvCapability_ = 5308; +pub const SpvCapability__SpvCapabilityStorageBufferArrayNonUniformIndexingEXT: SpvCapability_ = + 5308; +pub const SpvCapability__SpvCapabilityStorageImageArrayNonUniformIndexing: SpvCapability_ = 5309; +pub const SpvCapability__SpvCapabilityStorageImageArrayNonUniformIndexingEXT: SpvCapability_ = 5309; +pub const SpvCapability__SpvCapabilityInputAttachmentArrayNonUniformIndexing: SpvCapability_ = 5310; +pub const SpvCapability__SpvCapabilityInputAttachmentArrayNonUniformIndexingEXT: SpvCapability_ = + 5310; +pub const SpvCapability__SpvCapabilityUniformTexelBufferArrayNonUniformIndexing: SpvCapability_ = + 5311; +pub const SpvCapability__SpvCapabilityUniformTexelBufferArrayNonUniformIndexingEXT: SpvCapability_ = + 5311; +pub const SpvCapability__SpvCapabilityStorageTexelBufferArrayNonUniformIndexing: SpvCapability_ = + 5312; +pub const SpvCapability__SpvCapabilityStorageTexelBufferArrayNonUniformIndexingEXT: SpvCapability_ = + 5312; +pub const SpvCapability__SpvCapabilityRayTracingPositionFetchKHR: SpvCapability_ = 5336; +pub const SpvCapability__SpvCapabilityRayTracingNV: SpvCapability_ = 5340; +pub const SpvCapability__SpvCapabilityRayTracingMotionBlurNV: SpvCapability_ = 5341; +pub const SpvCapability__SpvCapabilityVulkanMemoryModel: SpvCapability_ = 5345; +pub const SpvCapability__SpvCapabilityVulkanMemoryModelKHR: SpvCapability_ = 5345; +pub const SpvCapability__SpvCapabilityVulkanMemoryModelDeviceScope: SpvCapability_ = 5346; +pub const SpvCapability__SpvCapabilityVulkanMemoryModelDeviceScopeKHR: SpvCapability_ = 5346; +pub const SpvCapability__SpvCapabilityPhysicalStorageBufferAddresses: SpvCapability_ = 5347; +pub const SpvCapability__SpvCapabilityPhysicalStorageBufferAddressesEXT: SpvCapability_ = 5347; +pub const SpvCapability__SpvCapabilityComputeDerivativeGroupLinearKHR: SpvCapability_ = 5350; +pub const SpvCapability__SpvCapabilityComputeDerivativeGroupLinearNV: SpvCapability_ = 5350; +pub const SpvCapability__SpvCapabilityRayTracingProvisionalKHR: SpvCapability_ = 5353; +pub const SpvCapability__SpvCapabilityCooperativeMatrixNV: SpvCapability_ = 5357; +pub const SpvCapability__SpvCapabilityFragmentShaderSampleInterlockEXT: SpvCapability_ = 5363; +pub const SpvCapability__SpvCapabilityFragmentShaderShadingRateInterlockEXT: SpvCapability_ = 5372; +pub const SpvCapability__SpvCapabilityShaderSMBuiltinsNV: SpvCapability_ = 5373; +pub const SpvCapability__SpvCapabilityFragmentShaderPixelInterlockEXT: SpvCapability_ = 5378; +pub const SpvCapability__SpvCapabilityDemoteToHelperInvocation: SpvCapability_ = 5379; +pub const SpvCapability__SpvCapabilityDemoteToHelperInvocationEXT: SpvCapability_ = 5379; +pub const SpvCapability__SpvCapabilityDisplacementMicromapNV: SpvCapability_ = 5380; +pub const SpvCapability__SpvCapabilityRayTracingOpacityMicromapEXT: SpvCapability_ = 5381; +pub const SpvCapability__SpvCapabilityShaderInvocationReorderNV: SpvCapability_ = 5383; +pub const SpvCapability__SpvCapabilityBindlessTextureNV: SpvCapability_ = 5390; +pub const SpvCapability__SpvCapabilityRayQueryPositionFetchKHR: SpvCapability_ = 5391; +pub const SpvCapability__SpvCapabilityCooperativeVectorNV: SpvCapability_ = 5394; +pub const SpvCapability__SpvCapabilityAtomicFloat16VectorNV: SpvCapability_ = 5404; +pub const SpvCapability__SpvCapabilityRayTracingDisplacementMicromapNV: SpvCapability_ = 5409; +pub const SpvCapability__SpvCapabilityRawAccessChainsNV: SpvCapability_ = 5414; +pub const SpvCapability__SpvCapabilityRayTracingSpheresGeometryNV: SpvCapability_ = 5418; +pub const SpvCapability__SpvCapabilityRayTracingLinearSweptSpheresGeometryNV: SpvCapability_ = 5419; +pub const SpvCapability__SpvCapabilityCooperativeMatrixReductionsNV: SpvCapability_ = 5430; +pub const SpvCapability__SpvCapabilityCooperativeMatrixConversionsNV: SpvCapability_ = 5431; +pub const SpvCapability__SpvCapabilityCooperativeMatrixPerElementOperationsNV: SpvCapability_ = + 5432; +pub const SpvCapability__SpvCapabilityCooperativeMatrixTensorAddressingNV: SpvCapability_ = 5433; +pub const SpvCapability__SpvCapabilityCooperativeMatrixBlockLoadsNV: SpvCapability_ = 5434; +pub const SpvCapability__SpvCapabilityCooperativeVectorTrainingNV: SpvCapability_ = 5435; +pub const SpvCapability__SpvCapabilityRayTracingClusterAccelerationStructureNV: SpvCapability_ = + 5437; +pub const SpvCapability__SpvCapabilityTensorAddressingNV: SpvCapability_ = 5439; +pub const SpvCapability__SpvCapabilitySubgroupShuffleINTEL: SpvCapability_ = 5568; +pub const SpvCapability__SpvCapabilitySubgroupBufferBlockIOINTEL: SpvCapability_ = 5569; +pub const SpvCapability__SpvCapabilitySubgroupImageBlockIOINTEL: SpvCapability_ = 5570; +pub const SpvCapability__SpvCapabilitySubgroupImageMediaBlockIOINTEL: SpvCapability_ = 5579; +pub const SpvCapability__SpvCapabilityRoundToInfinityINTEL: SpvCapability_ = 5582; +pub const SpvCapability__SpvCapabilityFloatingPointModeINTEL: SpvCapability_ = 5583; +pub const SpvCapability__SpvCapabilityIntegerFunctions2INTEL: SpvCapability_ = 5584; +pub const SpvCapability__SpvCapabilityFunctionPointersINTEL: SpvCapability_ = 5603; +pub const SpvCapability__SpvCapabilityIndirectReferencesINTEL: SpvCapability_ = 5604; +pub const SpvCapability__SpvCapabilityAsmINTEL: SpvCapability_ = 5606; +pub const SpvCapability__SpvCapabilityAtomicFloat32MinMaxEXT: SpvCapability_ = 5612; +pub const SpvCapability__SpvCapabilityAtomicFloat64MinMaxEXT: SpvCapability_ = 5613; +pub const SpvCapability__SpvCapabilityAtomicFloat16MinMaxEXT: SpvCapability_ = 5616; +pub const SpvCapability__SpvCapabilityVectorComputeINTEL: SpvCapability_ = 5617; +pub const SpvCapability__SpvCapabilityVectorAnyINTEL: SpvCapability_ = 5619; +pub const SpvCapability__SpvCapabilityExpectAssumeKHR: SpvCapability_ = 5629; +pub const SpvCapability__SpvCapabilitySubgroupAvcMotionEstimationINTEL: SpvCapability_ = 5696; +pub const SpvCapability__SpvCapabilitySubgroupAvcMotionEstimationIntraINTEL: SpvCapability_ = 5697; +pub const SpvCapability__SpvCapabilitySubgroupAvcMotionEstimationChromaINTEL: SpvCapability_ = 5698; +pub const SpvCapability__SpvCapabilityVariableLengthArrayINTEL: SpvCapability_ = 5817; +pub const SpvCapability__SpvCapabilityFunctionFloatControlINTEL: SpvCapability_ = 5821; +pub const SpvCapability__SpvCapabilityFPGAMemoryAttributesINTEL: SpvCapability_ = 5824; +pub const SpvCapability__SpvCapabilityFPFastMathModeINTEL: SpvCapability_ = 5837; +pub const SpvCapability__SpvCapabilityArbitraryPrecisionIntegersINTEL: SpvCapability_ = 5844; +pub const SpvCapability__SpvCapabilityArbitraryPrecisionFloatingPointINTEL: SpvCapability_ = 5845; +pub const SpvCapability__SpvCapabilityUnstructuredLoopControlsINTEL: SpvCapability_ = 5886; +pub const SpvCapability__SpvCapabilityFPGALoopControlsINTEL: SpvCapability_ = 5888; +pub const SpvCapability__SpvCapabilityKernelAttributesINTEL: SpvCapability_ = 5892; +pub const SpvCapability__SpvCapabilityFPGAKernelAttributesINTEL: SpvCapability_ = 5897; +pub const SpvCapability__SpvCapabilityFPGAMemoryAccessesINTEL: SpvCapability_ = 5898; +pub const SpvCapability__SpvCapabilityFPGAClusterAttributesINTEL: SpvCapability_ = 5904; +pub const SpvCapability__SpvCapabilityLoopFuseINTEL: SpvCapability_ = 5906; +pub const SpvCapability__SpvCapabilityFPGADSPControlINTEL: SpvCapability_ = 5908; +pub const SpvCapability__SpvCapabilityMemoryAccessAliasingINTEL: SpvCapability_ = 5910; +pub const SpvCapability__SpvCapabilityFPGAInvocationPipeliningAttributesINTEL: SpvCapability_ = + 5916; +pub const SpvCapability__SpvCapabilityFPGABufferLocationINTEL: SpvCapability_ = 5920; +pub const SpvCapability__SpvCapabilityArbitraryPrecisionFixedPointINTEL: SpvCapability_ = 5922; +pub const SpvCapability__SpvCapabilityUSMStorageClassesINTEL: SpvCapability_ = 5935; +pub const SpvCapability__SpvCapabilityRuntimeAlignedAttributeINTEL: SpvCapability_ = 5939; +pub const SpvCapability__SpvCapabilityIOPipesINTEL: SpvCapability_ = 5943; +pub const SpvCapability__SpvCapabilityBlockingPipesINTEL: SpvCapability_ = 5945; +pub const SpvCapability__SpvCapabilityFPGARegINTEL: SpvCapability_ = 5948; +pub const SpvCapability__SpvCapabilityDotProductInputAll: SpvCapability_ = 6016; +pub const SpvCapability__SpvCapabilityDotProductInputAllKHR: SpvCapability_ = 6016; +pub const SpvCapability__SpvCapabilityDotProductInput4x8Bit: SpvCapability_ = 6017; +pub const SpvCapability__SpvCapabilityDotProductInput4x8BitKHR: SpvCapability_ = 6017; +pub const SpvCapability__SpvCapabilityDotProductInput4x8BitPacked: SpvCapability_ = 6018; +pub const SpvCapability__SpvCapabilityDotProductInput4x8BitPackedKHR: SpvCapability_ = 6018; +pub const SpvCapability__SpvCapabilityDotProduct: SpvCapability_ = 6019; +pub const SpvCapability__SpvCapabilityDotProductKHR: SpvCapability_ = 6019; +pub const SpvCapability__SpvCapabilityRayCullMaskKHR: SpvCapability_ = 6020; +pub const SpvCapability__SpvCapabilityCooperativeMatrixKHR: SpvCapability_ = 6022; +pub const SpvCapability__SpvCapabilityReplicatedCompositesEXT: SpvCapability_ = 6024; +pub const SpvCapability__SpvCapabilityBitInstructions: SpvCapability_ = 6025; +pub const SpvCapability__SpvCapabilityGroupNonUniformRotateKHR: SpvCapability_ = 6026; +pub const SpvCapability__SpvCapabilityFloatControls2: SpvCapability_ = 6029; +pub const SpvCapability__SpvCapabilityFMAKHR: SpvCapability_ = 6030; +pub const SpvCapability__SpvCapabilityAtomicFloat32AddEXT: SpvCapability_ = 6033; +pub const SpvCapability__SpvCapabilityAtomicFloat64AddEXT: SpvCapability_ = 6034; +pub const SpvCapability__SpvCapabilityLongCompositesINTEL: SpvCapability_ = 6089; +pub const SpvCapability__SpvCapabilityOptNoneEXT: SpvCapability_ = 6094; +pub const SpvCapability__SpvCapabilityOptNoneINTEL: SpvCapability_ = 6094; +pub const SpvCapability__SpvCapabilityAtomicFloat16AddEXT: SpvCapability_ = 6095; +pub const SpvCapability__SpvCapabilityDebugInfoModuleINTEL: SpvCapability_ = 6114; +pub const SpvCapability__SpvCapabilityBFloat16ConversionINTEL: SpvCapability_ = 6115; +pub const SpvCapability__SpvCapabilitySplitBarrierINTEL: SpvCapability_ = 6141; +pub const SpvCapability__SpvCapabilityArithmeticFenceEXT: SpvCapability_ = 6144; +pub const SpvCapability__SpvCapabilityFPGAClusterAttributesV2INTEL: SpvCapability_ = 6150; +pub const SpvCapability__SpvCapabilityFPGAKernelAttributesv2INTEL: SpvCapability_ = 6161; +pub const SpvCapability__SpvCapabilityTaskSequenceINTEL: SpvCapability_ = 6162; +pub const SpvCapability__SpvCapabilityFPMaxErrorINTEL: SpvCapability_ = 6169; +pub const SpvCapability__SpvCapabilityFPGALatencyControlINTEL: SpvCapability_ = 6171; +pub const SpvCapability__SpvCapabilityFPGAArgumentInterfacesINTEL: SpvCapability_ = 6174; +pub const SpvCapability__SpvCapabilityGlobalVariableHostAccessINTEL: SpvCapability_ = 6187; +pub const SpvCapability__SpvCapabilityGlobalVariableFPGADecorationsINTEL: SpvCapability_ = 6189; +pub const SpvCapability__SpvCapabilitySubgroupBufferPrefetchINTEL: SpvCapability_ = 6220; +pub const SpvCapability__SpvCapabilitySubgroup2DBlockIOINTEL: SpvCapability_ = 6228; +pub const SpvCapability__SpvCapabilitySubgroup2DBlockTransformINTEL: SpvCapability_ = 6229; +pub const SpvCapability__SpvCapabilitySubgroup2DBlockTransposeINTEL: SpvCapability_ = 6230; +pub const SpvCapability__SpvCapabilitySubgroupMatrixMultiplyAccumulateINTEL: SpvCapability_ = 6236; +pub const SpvCapability__SpvCapabilityTernaryBitwiseFunctionINTEL: SpvCapability_ = 6241; +pub const SpvCapability__SpvCapabilityUntypedVariableLengthArrayINTEL: SpvCapability_ = 6243; +pub const SpvCapability__SpvCapabilitySpecConditionalINTEL: SpvCapability_ = 6245; +pub const SpvCapability__SpvCapabilityFunctionVariantsINTEL: SpvCapability_ = 6246; +pub const SpvCapability__SpvCapabilityGroupUniformArithmeticKHR: SpvCapability_ = 6400; +pub const SpvCapability__SpvCapabilityTensorFloat32RoundingINTEL: SpvCapability_ = 6425; +pub const SpvCapability__SpvCapabilityMaskedGatherScatterINTEL: SpvCapability_ = 6427; +pub const SpvCapability__SpvCapabilityCacheControlsINTEL: SpvCapability_ = 6441; +pub const SpvCapability__SpvCapabilityRegisterLimitsINTEL: SpvCapability_ = 6460; +pub const SpvCapability__SpvCapabilityBindlessImagesINTEL: SpvCapability_ = 6528; +pub const SpvCapability__SpvCapabilityMax: SpvCapability_ = 2147483647; +pub type SpvCapability_ = ::std::os::raw::c_int; +pub use self::SpvCapability_ as SpvCapability; +pub const SpvRayFlagsShift__SpvRayFlagsOpaqueKHRShift: SpvRayFlagsShift_ = 0; +pub const SpvRayFlagsShift__SpvRayFlagsNoOpaqueKHRShift: SpvRayFlagsShift_ = 1; +pub const SpvRayFlagsShift__SpvRayFlagsTerminateOnFirstHitKHRShift: SpvRayFlagsShift_ = 2; +pub const SpvRayFlagsShift__SpvRayFlagsSkipClosestHitShaderKHRShift: SpvRayFlagsShift_ = 3; +pub const SpvRayFlagsShift__SpvRayFlagsCullBackFacingTrianglesKHRShift: SpvRayFlagsShift_ = 4; +pub const SpvRayFlagsShift__SpvRayFlagsCullFrontFacingTrianglesKHRShift: SpvRayFlagsShift_ = 5; +pub const SpvRayFlagsShift__SpvRayFlagsCullOpaqueKHRShift: SpvRayFlagsShift_ = 6; +pub const SpvRayFlagsShift__SpvRayFlagsCullNoOpaqueKHRShift: SpvRayFlagsShift_ = 7; +pub const SpvRayFlagsShift__SpvRayFlagsSkipBuiltinPrimitivesNVShift: SpvRayFlagsShift_ = 8; +pub const SpvRayFlagsShift__SpvRayFlagsSkipTrianglesKHRShift: SpvRayFlagsShift_ = 8; +pub const SpvRayFlagsShift__SpvRayFlagsSkipAABBsKHRShift: SpvRayFlagsShift_ = 9; +pub const SpvRayFlagsShift__SpvRayFlagsForceOpacityMicromap2StateEXTShift: SpvRayFlagsShift_ = 10; +pub const SpvRayFlagsShift__SpvRayFlagsMax: SpvRayFlagsShift_ = 2147483647; +pub type SpvRayFlagsShift_ = ::std::os::raw::c_int; +pub use self::SpvRayFlagsShift_ as SpvRayFlagsShift; +pub const SpvRayFlagsMask__SpvRayFlagsMaskNone: SpvRayFlagsMask_ = 0; +pub const SpvRayFlagsMask__SpvRayFlagsOpaqueKHRMask: SpvRayFlagsMask_ = 1; +pub const SpvRayFlagsMask__SpvRayFlagsNoOpaqueKHRMask: SpvRayFlagsMask_ = 2; +pub const SpvRayFlagsMask__SpvRayFlagsTerminateOnFirstHitKHRMask: SpvRayFlagsMask_ = 4; +pub const SpvRayFlagsMask__SpvRayFlagsSkipClosestHitShaderKHRMask: SpvRayFlagsMask_ = 8; +pub const SpvRayFlagsMask__SpvRayFlagsCullBackFacingTrianglesKHRMask: SpvRayFlagsMask_ = 16; +pub const SpvRayFlagsMask__SpvRayFlagsCullFrontFacingTrianglesKHRMask: SpvRayFlagsMask_ = 32; +pub const SpvRayFlagsMask__SpvRayFlagsCullOpaqueKHRMask: SpvRayFlagsMask_ = 64; +pub const SpvRayFlagsMask__SpvRayFlagsCullNoOpaqueKHRMask: SpvRayFlagsMask_ = 128; +pub const SpvRayFlagsMask__SpvRayFlagsSkipBuiltinPrimitivesNVMask: SpvRayFlagsMask_ = 256; +pub const SpvRayFlagsMask__SpvRayFlagsSkipTrianglesKHRMask: SpvRayFlagsMask_ = 256; +pub const SpvRayFlagsMask__SpvRayFlagsSkipAABBsKHRMask: SpvRayFlagsMask_ = 512; +pub const SpvRayFlagsMask__SpvRayFlagsForceOpacityMicromap2StateEXTMask: SpvRayFlagsMask_ = 1024; +pub type SpvRayFlagsMask_ = ::std::os::raw::c_int; +pub use self::SpvRayFlagsMask_ as SpvRayFlagsMask; +pub const SpvRayQueryIntersection__SpvRayQueryIntersectionRayQueryCandidateIntersectionKHR: + SpvRayQueryIntersection_ = 0; +pub const SpvRayQueryIntersection__SpvRayQueryIntersectionRayQueryCommittedIntersectionKHR: + SpvRayQueryIntersection_ = 1; +pub const SpvRayQueryIntersection__SpvRayQueryIntersectionMax: SpvRayQueryIntersection_ = + 2147483647; +pub type SpvRayQueryIntersection_ = ::std::os::raw::c_int; +pub use self::SpvRayQueryIntersection_ as SpvRayQueryIntersection; +pub const SpvRayQueryCommittedIntersectionType__SpvRayQueryCommittedIntersectionTypeRayQueryCommittedIntersectionNoneKHR : SpvRayQueryCommittedIntersectionType_ = 0 ; +pub const SpvRayQueryCommittedIntersectionType__SpvRayQueryCommittedIntersectionTypeRayQueryCommittedIntersectionTriangleKHR : SpvRayQueryCommittedIntersectionType_ = 1 ; +pub const SpvRayQueryCommittedIntersectionType__SpvRayQueryCommittedIntersectionTypeRayQueryCommittedIntersectionGeneratedKHR : SpvRayQueryCommittedIntersectionType_ = 2 ; +pub const SpvRayQueryCommittedIntersectionType__SpvRayQueryCommittedIntersectionTypeMax: + SpvRayQueryCommittedIntersectionType_ = 2147483647; +pub type SpvRayQueryCommittedIntersectionType_ = ::std::os::raw::c_int; +pub use self::SpvRayQueryCommittedIntersectionType_ as SpvRayQueryCommittedIntersectionType; +pub const SpvRayQueryCandidateIntersectionType__SpvRayQueryCandidateIntersectionTypeRayQueryCandidateIntersectionTriangleKHR : SpvRayQueryCandidateIntersectionType_ = 0 ; +pub const SpvRayQueryCandidateIntersectionType__SpvRayQueryCandidateIntersectionTypeRayQueryCandidateIntersectionAABBKHR : SpvRayQueryCandidateIntersectionType_ = 1 ; +pub const SpvRayQueryCandidateIntersectionType__SpvRayQueryCandidateIntersectionTypeMax: + SpvRayQueryCandidateIntersectionType_ = 2147483647; +pub type SpvRayQueryCandidateIntersectionType_ = ::std::os::raw::c_int; +pub use self::SpvRayQueryCandidateIntersectionType_ as SpvRayQueryCandidateIntersectionType; +pub const SpvFragmentShadingRateShift__SpvFragmentShadingRateVertical2PixelsShift: + SpvFragmentShadingRateShift_ = 0; +pub const SpvFragmentShadingRateShift__SpvFragmentShadingRateVertical4PixelsShift: + SpvFragmentShadingRateShift_ = 1; +pub const SpvFragmentShadingRateShift__SpvFragmentShadingRateHorizontal2PixelsShift: + SpvFragmentShadingRateShift_ = 2; +pub const SpvFragmentShadingRateShift__SpvFragmentShadingRateHorizontal4PixelsShift: + SpvFragmentShadingRateShift_ = 3; +pub const SpvFragmentShadingRateShift__SpvFragmentShadingRateMax: SpvFragmentShadingRateShift_ = + 2147483647; +pub type SpvFragmentShadingRateShift_ = ::std::os::raw::c_int; +pub use self::SpvFragmentShadingRateShift_ as SpvFragmentShadingRateShift; +pub const SpvFragmentShadingRateMask__SpvFragmentShadingRateMaskNone: SpvFragmentShadingRateMask_ = + 0; +pub const SpvFragmentShadingRateMask__SpvFragmentShadingRateVertical2PixelsMask: + SpvFragmentShadingRateMask_ = 1; +pub const SpvFragmentShadingRateMask__SpvFragmentShadingRateVertical4PixelsMask: + SpvFragmentShadingRateMask_ = 2; +pub const SpvFragmentShadingRateMask__SpvFragmentShadingRateHorizontal2PixelsMask: + SpvFragmentShadingRateMask_ = 4; +pub const SpvFragmentShadingRateMask__SpvFragmentShadingRateHorizontal4PixelsMask: + SpvFragmentShadingRateMask_ = 8; +pub type SpvFragmentShadingRateMask_ = ::std::os::raw::c_int; +pub use self::SpvFragmentShadingRateMask_ as SpvFragmentShadingRateMask; +pub const SpvFPDenormMode__SpvFPDenormModePreserve: SpvFPDenormMode_ = 0; +pub const SpvFPDenormMode__SpvFPDenormModeFlushToZero: SpvFPDenormMode_ = 1; +pub const SpvFPDenormMode__SpvFPDenormModeMax: SpvFPDenormMode_ = 2147483647; +pub type SpvFPDenormMode_ = ::std::os::raw::c_int; +pub use self::SpvFPDenormMode_ as SpvFPDenormMode; +pub const SpvFPOperationMode__SpvFPOperationModeIEEE: SpvFPOperationMode_ = 0; +pub const SpvFPOperationMode__SpvFPOperationModeALT: SpvFPOperationMode_ = 1; +pub const SpvFPOperationMode__SpvFPOperationModeMax: SpvFPOperationMode_ = 2147483647; +pub type SpvFPOperationMode_ = ::std::os::raw::c_int; +pub use self::SpvFPOperationMode_ as SpvFPOperationMode; +pub const SpvQuantizationModes__SpvQuantizationModesTRN: SpvQuantizationModes_ = 0; +pub const SpvQuantizationModes__SpvQuantizationModesTRN_ZERO: SpvQuantizationModes_ = 1; +pub const SpvQuantizationModes__SpvQuantizationModesRND: SpvQuantizationModes_ = 2; +pub const SpvQuantizationModes__SpvQuantizationModesRND_ZERO: SpvQuantizationModes_ = 3; +pub const SpvQuantizationModes__SpvQuantizationModesRND_INF: SpvQuantizationModes_ = 4; +pub const SpvQuantizationModes__SpvQuantizationModesRND_MIN_INF: SpvQuantizationModes_ = 5; +pub const SpvQuantizationModes__SpvQuantizationModesRND_CONV: SpvQuantizationModes_ = 6; +pub const SpvQuantizationModes__SpvQuantizationModesRND_CONV_ODD: SpvQuantizationModes_ = 7; +pub const SpvQuantizationModes__SpvQuantizationModesMax: SpvQuantizationModes_ = 2147483647; +pub type SpvQuantizationModes_ = ::std::os::raw::c_int; +pub use self::SpvQuantizationModes_ as SpvQuantizationModes; +pub const SpvOverflowModes__SpvOverflowModesWRAP: SpvOverflowModes_ = 0; +pub const SpvOverflowModes__SpvOverflowModesSAT: SpvOverflowModes_ = 1; +pub const SpvOverflowModes__SpvOverflowModesSAT_ZERO: SpvOverflowModes_ = 2; +pub const SpvOverflowModes__SpvOverflowModesSAT_SYM: SpvOverflowModes_ = 3; +pub const SpvOverflowModes__SpvOverflowModesMax: SpvOverflowModes_ = 2147483647; +pub type SpvOverflowModes_ = ::std::os::raw::c_int; +pub use self::SpvOverflowModes_ as SpvOverflowModes; +pub const SpvPackedVectorFormat__SpvPackedVectorFormatPackedVectorFormat4x8Bit: + SpvPackedVectorFormat_ = 0; +pub const SpvPackedVectorFormat__SpvPackedVectorFormatPackedVectorFormat4x8BitKHR: + SpvPackedVectorFormat_ = 0; +pub const SpvPackedVectorFormat__SpvPackedVectorFormatMax: SpvPackedVectorFormat_ = 2147483647; +pub type SpvPackedVectorFormat_ = ::std::os::raw::c_int; +pub use self::SpvPackedVectorFormat_ as SpvPackedVectorFormat; +pub const SpvCooperativeMatrixOperandsShift__SpvCooperativeMatrixOperandsMatrixASignedComponentsKHRShift : SpvCooperativeMatrixOperandsShift_ = 0 ; +pub const SpvCooperativeMatrixOperandsShift__SpvCooperativeMatrixOperandsMatrixBSignedComponentsKHRShift : SpvCooperativeMatrixOperandsShift_ = 1 ; +pub const SpvCooperativeMatrixOperandsShift__SpvCooperativeMatrixOperandsMatrixCSignedComponentsKHRShift : SpvCooperativeMatrixOperandsShift_ = 2 ; +pub const SpvCooperativeMatrixOperandsShift__SpvCooperativeMatrixOperandsMatrixResultSignedComponentsKHRShift : SpvCooperativeMatrixOperandsShift_ = 3 ; +pub const SpvCooperativeMatrixOperandsShift__SpvCooperativeMatrixOperandsSaturatingAccumulationKHRShift : SpvCooperativeMatrixOperandsShift_ = 4 ; +pub const SpvCooperativeMatrixOperandsShift__SpvCooperativeMatrixOperandsMax: + SpvCooperativeMatrixOperandsShift_ = 2147483647; +pub type SpvCooperativeMatrixOperandsShift_ = ::std::os::raw::c_int; +pub use self::SpvCooperativeMatrixOperandsShift_ as SpvCooperativeMatrixOperandsShift; +pub const SpvCooperativeMatrixOperandsMask__SpvCooperativeMatrixOperandsMaskNone: + SpvCooperativeMatrixOperandsMask_ = 0; +pub const SpvCooperativeMatrixOperandsMask__SpvCooperativeMatrixOperandsMatrixASignedComponentsKHRMask : SpvCooperativeMatrixOperandsMask_ = 1 ; +pub const SpvCooperativeMatrixOperandsMask__SpvCooperativeMatrixOperandsMatrixBSignedComponentsKHRMask : SpvCooperativeMatrixOperandsMask_ = 2 ; +pub const SpvCooperativeMatrixOperandsMask__SpvCooperativeMatrixOperandsMatrixCSignedComponentsKHRMask : SpvCooperativeMatrixOperandsMask_ = 4 ; +pub const SpvCooperativeMatrixOperandsMask__SpvCooperativeMatrixOperandsMatrixResultSignedComponentsKHRMask : SpvCooperativeMatrixOperandsMask_ = 8 ; +pub const SpvCooperativeMatrixOperandsMask__SpvCooperativeMatrixOperandsSaturatingAccumulationKHRMask : SpvCooperativeMatrixOperandsMask_ = 16 ; +pub type SpvCooperativeMatrixOperandsMask_ = ::std::os::raw::c_int; +pub use self::SpvCooperativeMatrixOperandsMask_ as SpvCooperativeMatrixOperandsMask; +pub const SpvCooperativeMatrixLayout__SpvCooperativeMatrixLayoutRowMajorKHR: + SpvCooperativeMatrixLayout_ = 0; +pub const SpvCooperativeMatrixLayout__SpvCooperativeMatrixLayoutColumnMajorKHR: + SpvCooperativeMatrixLayout_ = 1; +pub const SpvCooperativeMatrixLayout__SpvCooperativeMatrixLayoutRowBlockedInterleavedARM: + SpvCooperativeMatrixLayout_ = 4202; +pub const SpvCooperativeMatrixLayout__SpvCooperativeMatrixLayoutColumnBlockedInterleavedARM: + SpvCooperativeMatrixLayout_ = 4203; +pub const SpvCooperativeMatrixLayout__SpvCooperativeMatrixLayoutMax: SpvCooperativeMatrixLayout_ = + 2147483647; +pub type SpvCooperativeMatrixLayout_ = ::std::os::raw::c_int; +pub use self::SpvCooperativeMatrixLayout_ as SpvCooperativeMatrixLayout; +pub const SpvCooperativeMatrixUse__SpvCooperativeMatrixUseMatrixAKHR: SpvCooperativeMatrixUse_ = 0; +pub const SpvCooperativeMatrixUse__SpvCooperativeMatrixUseMatrixBKHR: SpvCooperativeMatrixUse_ = 1; +pub const SpvCooperativeMatrixUse__SpvCooperativeMatrixUseMatrixAccumulatorKHR: + SpvCooperativeMatrixUse_ = 2; +pub const SpvCooperativeMatrixUse__SpvCooperativeMatrixUseMax: SpvCooperativeMatrixUse_ = + 2147483647; +pub type SpvCooperativeMatrixUse_ = ::std::os::raw::c_int; +pub use self::SpvCooperativeMatrixUse_ as SpvCooperativeMatrixUse; +pub const SpvCooperativeMatrixReduceShift__SpvCooperativeMatrixReduceRowShift: + SpvCooperativeMatrixReduceShift_ = 0; +pub const SpvCooperativeMatrixReduceShift__SpvCooperativeMatrixReduceColumnShift: + SpvCooperativeMatrixReduceShift_ = 1; +pub const SpvCooperativeMatrixReduceShift__SpvCooperativeMatrixReduce2x2Shift: + SpvCooperativeMatrixReduceShift_ = 2; +pub const SpvCooperativeMatrixReduceShift__SpvCooperativeMatrixReduceMax: + SpvCooperativeMatrixReduceShift_ = 2147483647; +pub type SpvCooperativeMatrixReduceShift_ = ::std::os::raw::c_int; +pub use self::SpvCooperativeMatrixReduceShift_ as SpvCooperativeMatrixReduceShift; +pub const SpvCooperativeMatrixReduceMask__SpvCooperativeMatrixReduceMaskNone: + SpvCooperativeMatrixReduceMask_ = 0; +pub const SpvCooperativeMatrixReduceMask__SpvCooperativeMatrixReduceRowMask: + SpvCooperativeMatrixReduceMask_ = 1; +pub const SpvCooperativeMatrixReduceMask__SpvCooperativeMatrixReduceColumnMask: + SpvCooperativeMatrixReduceMask_ = 2; +pub const SpvCooperativeMatrixReduceMask__SpvCooperativeMatrixReduce2x2Mask: + SpvCooperativeMatrixReduceMask_ = 4; +pub type SpvCooperativeMatrixReduceMask_ = ::std::os::raw::c_int; +pub use self::SpvCooperativeMatrixReduceMask_ as SpvCooperativeMatrixReduceMask; +pub const SpvTensorClampMode__SpvTensorClampModeUndefined: SpvTensorClampMode_ = 0; +pub const SpvTensorClampMode__SpvTensorClampModeConstant: SpvTensorClampMode_ = 1; +pub const SpvTensorClampMode__SpvTensorClampModeClampToEdge: SpvTensorClampMode_ = 2; +pub const SpvTensorClampMode__SpvTensorClampModeRepeat: SpvTensorClampMode_ = 3; +pub const SpvTensorClampMode__SpvTensorClampModeRepeatMirrored: SpvTensorClampMode_ = 4; +pub const SpvTensorClampMode__SpvTensorClampModeMax: SpvTensorClampMode_ = 2147483647; +pub type SpvTensorClampMode_ = ::std::os::raw::c_int; +pub use self::SpvTensorClampMode_ as SpvTensorClampMode; +pub const SpvTensorAddressingOperandsShift__SpvTensorAddressingOperandsTensorViewShift: + SpvTensorAddressingOperandsShift_ = 0; +pub const SpvTensorAddressingOperandsShift__SpvTensorAddressingOperandsDecodeFuncShift: + SpvTensorAddressingOperandsShift_ = 1; +pub const SpvTensorAddressingOperandsShift__SpvTensorAddressingOperandsMax: + SpvTensorAddressingOperandsShift_ = 2147483647; +pub type SpvTensorAddressingOperandsShift_ = ::std::os::raw::c_int; +pub use self::SpvTensorAddressingOperandsShift_ as SpvTensorAddressingOperandsShift; +pub const SpvTensorAddressingOperandsMask__SpvTensorAddressingOperandsMaskNone: + SpvTensorAddressingOperandsMask_ = 0; +pub const SpvTensorAddressingOperandsMask__SpvTensorAddressingOperandsTensorViewMask: + SpvTensorAddressingOperandsMask_ = 1; +pub const SpvTensorAddressingOperandsMask__SpvTensorAddressingOperandsDecodeFuncMask: + SpvTensorAddressingOperandsMask_ = 2; +pub type SpvTensorAddressingOperandsMask_ = ::std::os::raw::c_int; +pub use self::SpvTensorAddressingOperandsMask_ as SpvTensorAddressingOperandsMask; +pub const SpvTensorOperandsShift__SpvTensorOperandsNontemporalARMShift: SpvTensorOperandsShift_ = 0; +pub const SpvTensorOperandsShift__SpvTensorOperandsOutOfBoundsValueARMShift: + SpvTensorOperandsShift_ = 1; +pub const SpvTensorOperandsShift__SpvTensorOperandsMakeElementAvailableARMShift: + SpvTensorOperandsShift_ = 2; +pub const SpvTensorOperandsShift__SpvTensorOperandsMakeElementVisibleARMShift: + SpvTensorOperandsShift_ = 3; +pub const SpvTensorOperandsShift__SpvTensorOperandsNonPrivateElementARMShift: + SpvTensorOperandsShift_ = 4; +pub const SpvTensorOperandsShift__SpvTensorOperandsMax: SpvTensorOperandsShift_ = 2147483647; +pub type SpvTensorOperandsShift_ = ::std::os::raw::c_int; +pub use self::SpvTensorOperandsShift_ as SpvTensorOperandsShift; +pub const SpvTensorOperandsMask__SpvTensorOperandsMaskNone: SpvTensorOperandsMask_ = 0; +pub const SpvTensorOperandsMask__SpvTensorOperandsNontemporalARMMask: SpvTensorOperandsMask_ = 1; +pub const SpvTensorOperandsMask__SpvTensorOperandsOutOfBoundsValueARMMask: SpvTensorOperandsMask_ = + 2; +pub const SpvTensorOperandsMask__SpvTensorOperandsMakeElementAvailableARMMask: + SpvTensorOperandsMask_ = 4; +pub const SpvTensorOperandsMask__SpvTensorOperandsMakeElementVisibleARMMask: + SpvTensorOperandsMask_ = 8; +pub const SpvTensorOperandsMask__SpvTensorOperandsNonPrivateElementARMMask: SpvTensorOperandsMask_ = + 16; +pub type SpvTensorOperandsMask_ = ::std::os::raw::c_int; +pub use self::SpvTensorOperandsMask_ as SpvTensorOperandsMask; +pub const SpvInitializationModeQualifier__SpvInitializationModeQualifierInitOnDeviceReprogramINTEL : SpvInitializationModeQualifier_ = 0 ; +pub const SpvInitializationModeQualifier__SpvInitializationModeQualifierInitOnDeviceResetINTEL: + SpvInitializationModeQualifier_ = 1; +pub const SpvInitializationModeQualifier__SpvInitializationModeQualifierMax: + SpvInitializationModeQualifier_ = 2147483647; +pub type SpvInitializationModeQualifier_ = ::std::os::raw::c_int; +pub use self::SpvInitializationModeQualifier_ as SpvInitializationModeQualifier; +pub const SpvHostAccessQualifier__SpvHostAccessQualifierNoneINTEL: SpvHostAccessQualifier_ = 0; +pub const SpvHostAccessQualifier__SpvHostAccessQualifierReadINTEL: SpvHostAccessQualifier_ = 1; +pub const SpvHostAccessQualifier__SpvHostAccessQualifierWriteINTEL: SpvHostAccessQualifier_ = 2; +pub const SpvHostAccessQualifier__SpvHostAccessQualifierReadWriteINTEL: SpvHostAccessQualifier_ = 3; +pub const SpvHostAccessQualifier__SpvHostAccessQualifierMax: SpvHostAccessQualifier_ = 2147483647; +pub type SpvHostAccessQualifier_ = ::std::os::raw::c_int; +pub use self::SpvHostAccessQualifier_ as SpvHostAccessQualifier; +pub const SpvLoadCacheControl__SpvLoadCacheControlUncachedINTEL: SpvLoadCacheControl_ = 0; +pub const SpvLoadCacheControl__SpvLoadCacheControlCachedINTEL: SpvLoadCacheControl_ = 1; +pub const SpvLoadCacheControl__SpvLoadCacheControlStreamingINTEL: SpvLoadCacheControl_ = 2; +pub const SpvLoadCacheControl__SpvLoadCacheControlInvalidateAfterReadINTEL: SpvLoadCacheControl_ = + 3; +pub const SpvLoadCacheControl__SpvLoadCacheControlConstCachedINTEL: SpvLoadCacheControl_ = 4; +pub const SpvLoadCacheControl__SpvLoadCacheControlMax: SpvLoadCacheControl_ = 2147483647; +pub type SpvLoadCacheControl_ = ::std::os::raw::c_int; +pub use self::SpvLoadCacheControl_ as SpvLoadCacheControl; +pub const SpvStoreCacheControl__SpvStoreCacheControlUncachedINTEL: SpvStoreCacheControl_ = 0; +pub const SpvStoreCacheControl__SpvStoreCacheControlWriteThroughINTEL: SpvStoreCacheControl_ = 1; +pub const SpvStoreCacheControl__SpvStoreCacheControlWriteBackINTEL: SpvStoreCacheControl_ = 2; +pub const SpvStoreCacheControl__SpvStoreCacheControlStreamingINTEL: SpvStoreCacheControl_ = 3; +pub const SpvStoreCacheControl__SpvStoreCacheControlMax: SpvStoreCacheControl_ = 2147483647; +pub type SpvStoreCacheControl_ = ::std::os::raw::c_int; +pub use self::SpvStoreCacheControl_ as SpvStoreCacheControl; +pub const SpvNamedMaximumNumberOfRegisters__SpvNamedMaximumNumberOfRegistersAutoINTEL: + SpvNamedMaximumNumberOfRegisters_ = 0; +pub const SpvNamedMaximumNumberOfRegisters__SpvNamedMaximumNumberOfRegistersMax: + SpvNamedMaximumNumberOfRegisters_ = 2147483647; +pub type SpvNamedMaximumNumberOfRegisters_ = ::std::os::raw::c_int; +pub use self::SpvNamedMaximumNumberOfRegisters_ as SpvNamedMaximumNumberOfRegisters; +pub const SpvMatrixMultiplyAccumulateOperandsShift__SpvMatrixMultiplyAccumulateOperandsMatrixASignedComponentsINTELShift : SpvMatrixMultiplyAccumulateOperandsShift_ = 0 ; +pub const SpvMatrixMultiplyAccumulateOperandsShift__SpvMatrixMultiplyAccumulateOperandsMatrixBSignedComponentsINTELShift : SpvMatrixMultiplyAccumulateOperandsShift_ = 1 ; +pub const SpvMatrixMultiplyAccumulateOperandsShift__SpvMatrixMultiplyAccumulateOperandsMatrixCBFloat16INTELShift : SpvMatrixMultiplyAccumulateOperandsShift_ = 2 ; +pub const SpvMatrixMultiplyAccumulateOperandsShift__SpvMatrixMultiplyAccumulateOperandsMatrixResultBFloat16INTELShift : SpvMatrixMultiplyAccumulateOperandsShift_ = 3 ; +pub const SpvMatrixMultiplyAccumulateOperandsShift__SpvMatrixMultiplyAccumulateOperandsMatrixAPackedInt8INTELShift : SpvMatrixMultiplyAccumulateOperandsShift_ = 4 ; +pub const SpvMatrixMultiplyAccumulateOperandsShift__SpvMatrixMultiplyAccumulateOperandsMatrixBPackedInt8INTELShift : SpvMatrixMultiplyAccumulateOperandsShift_ = 5 ; +pub const SpvMatrixMultiplyAccumulateOperandsShift__SpvMatrixMultiplyAccumulateOperandsMatrixAPackedInt4INTELShift : SpvMatrixMultiplyAccumulateOperandsShift_ = 6 ; +pub const SpvMatrixMultiplyAccumulateOperandsShift__SpvMatrixMultiplyAccumulateOperandsMatrixBPackedInt4INTELShift : SpvMatrixMultiplyAccumulateOperandsShift_ = 7 ; +pub const SpvMatrixMultiplyAccumulateOperandsShift__SpvMatrixMultiplyAccumulateOperandsMatrixATF32INTELShift : SpvMatrixMultiplyAccumulateOperandsShift_ = 8 ; +pub const SpvMatrixMultiplyAccumulateOperandsShift__SpvMatrixMultiplyAccumulateOperandsMatrixBTF32INTELShift : SpvMatrixMultiplyAccumulateOperandsShift_ = 9 ; +pub const SpvMatrixMultiplyAccumulateOperandsShift__SpvMatrixMultiplyAccumulateOperandsMatrixAPackedFloat16INTELShift : SpvMatrixMultiplyAccumulateOperandsShift_ = 10 ; +pub const SpvMatrixMultiplyAccumulateOperandsShift__SpvMatrixMultiplyAccumulateOperandsMatrixBPackedFloat16INTELShift : SpvMatrixMultiplyAccumulateOperandsShift_ = 11 ; +pub const SpvMatrixMultiplyAccumulateOperandsShift__SpvMatrixMultiplyAccumulateOperandsMatrixAPackedBFloat16INTELShift : SpvMatrixMultiplyAccumulateOperandsShift_ = 12 ; +pub const SpvMatrixMultiplyAccumulateOperandsShift__SpvMatrixMultiplyAccumulateOperandsMatrixBPackedBFloat16INTELShift : SpvMatrixMultiplyAccumulateOperandsShift_ = 13 ; +pub const SpvMatrixMultiplyAccumulateOperandsShift__SpvMatrixMultiplyAccumulateOperandsMax: + SpvMatrixMultiplyAccumulateOperandsShift_ = 2147483647; +pub type SpvMatrixMultiplyAccumulateOperandsShift_ = ::std::os::raw::c_int; +pub use self::SpvMatrixMultiplyAccumulateOperandsShift_ as SpvMatrixMultiplyAccumulateOperandsShift; +pub const SpvMatrixMultiplyAccumulateOperandsMask__SpvMatrixMultiplyAccumulateOperandsMaskNone: + SpvMatrixMultiplyAccumulateOperandsMask_ = 0; +pub const SpvMatrixMultiplyAccumulateOperandsMask__SpvMatrixMultiplyAccumulateOperandsMatrixASignedComponentsINTELMask : SpvMatrixMultiplyAccumulateOperandsMask_ = 1 ; +pub const SpvMatrixMultiplyAccumulateOperandsMask__SpvMatrixMultiplyAccumulateOperandsMatrixBSignedComponentsINTELMask : SpvMatrixMultiplyAccumulateOperandsMask_ = 2 ; +pub const SpvMatrixMultiplyAccumulateOperandsMask__SpvMatrixMultiplyAccumulateOperandsMatrixCBFloat16INTELMask : SpvMatrixMultiplyAccumulateOperandsMask_ = 4 ; +pub const SpvMatrixMultiplyAccumulateOperandsMask__SpvMatrixMultiplyAccumulateOperandsMatrixResultBFloat16INTELMask : SpvMatrixMultiplyAccumulateOperandsMask_ = 8 ; +pub const SpvMatrixMultiplyAccumulateOperandsMask__SpvMatrixMultiplyAccumulateOperandsMatrixAPackedInt8INTELMask : SpvMatrixMultiplyAccumulateOperandsMask_ = 16 ; +pub const SpvMatrixMultiplyAccumulateOperandsMask__SpvMatrixMultiplyAccumulateOperandsMatrixBPackedInt8INTELMask : SpvMatrixMultiplyAccumulateOperandsMask_ = 32 ; +pub const SpvMatrixMultiplyAccumulateOperandsMask__SpvMatrixMultiplyAccumulateOperandsMatrixAPackedInt4INTELMask : SpvMatrixMultiplyAccumulateOperandsMask_ = 64 ; +pub const SpvMatrixMultiplyAccumulateOperandsMask__SpvMatrixMultiplyAccumulateOperandsMatrixBPackedInt4INTELMask : SpvMatrixMultiplyAccumulateOperandsMask_ = 128 ; +pub const SpvMatrixMultiplyAccumulateOperandsMask__SpvMatrixMultiplyAccumulateOperandsMatrixATF32INTELMask : SpvMatrixMultiplyAccumulateOperandsMask_ = 256 ; +pub const SpvMatrixMultiplyAccumulateOperandsMask__SpvMatrixMultiplyAccumulateOperandsMatrixBTF32INTELMask : SpvMatrixMultiplyAccumulateOperandsMask_ = 512 ; +pub const SpvMatrixMultiplyAccumulateOperandsMask__SpvMatrixMultiplyAccumulateOperandsMatrixAPackedFloat16INTELMask : SpvMatrixMultiplyAccumulateOperandsMask_ = 1024 ; +pub const SpvMatrixMultiplyAccumulateOperandsMask__SpvMatrixMultiplyAccumulateOperandsMatrixBPackedFloat16INTELMask : SpvMatrixMultiplyAccumulateOperandsMask_ = 2048 ; +pub const SpvMatrixMultiplyAccumulateOperandsMask__SpvMatrixMultiplyAccumulateOperandsMatrixAPackedBFloat16INTELMask : SpvMatrixMultiplyAccumulateOperandsMask_ = 4096 ; +pub const SpvMatrixMultiplyAccumulateOperandsMask__SpvMatrixMultiplyAccumulateOperandsMatrixBPackedBFloat16INTELMask : SpvMatrixMultiplyAccumulateOperandsMask_ = 8192 ; +pub type SpvMatrixMultiplyAccumulateOperandsMask_ = ::std::os::raw::c_int; +pub use self::SpvMatrixMultiplyAccumulateOperandsMask_ as SpvMatrixMultiplyAccumulateOperandsMask; +pub const SpvRawAccessChainOperandsShift__SpvRawAccessChainOperandsRobustnessPerComponentNVShift: + SpvRawAccessChainOperandsShift_ = 0; +pub const SpvRawAccessChainOperandsShift__SpvRawAccessChainOperandsRobustnessPerElementNVShift: + SpvRawAccessChainOperandsShift_ = 1; +pub const SpvRawAccessChainOperandsShift__SpvRawAccessChainOperandsMax: + SpvRawAccessChainOperandsShift_ = 2147483647; +pub type SpvRawAccessChainOperandsShift_ = ::std::os::raw::c_int; +pub use self::SpvRawAccessChainOperandsShift_ as SpvRawAccessChainOperandsShift; +pub const SpvRawAccessChainOperandsMask__SpvRawAccessChainOperandsMaskNone: + SpvRawAccessChainOperandsMask_ = 0; +pub const SpvRawAccessChainOperandsMask__SpvRawAccessChainOperandsRobustnessPerComponentNVMask: + SpvRawAccessChainOperandsMask_ = 1; +pub const SpvRawAccessChainOperandsMask__SpvRawAccessChainOperandsRobustnessPerElementNVMask: + SpvRawAccessChainOperandsMask_ = 2; +pub type SpvRawAccessChainOperandsMask_ = ::std::os::raw::c_int; +pub use self::SpvRawAccessChainOperandsMask_ as SpvRawAccessChainOperandsMask; +pub const SpvFPEncoding__SpvFPEncodingBFloat16KHR: SpvFPEncoding_ = 0; +pub const SpvFPEncoding__SpvFPEncodingFloat8E4M3EXT: SpvFPEncoding_ = 4214; +pub const SpvFPEncoding__SpvFPEncodingFloat8E5M2EXT: SpvFPEncoding_ = 4215; +pub const SpvFPEncoding__SpvFPEncodingMax: SpvFPEncoding_ = 2147483647; +pub type SpvFPEncoding_ = ::std::os::raw::c_int; +pub use self::SpvFPEncoding_ as SpvFPEncoding; +pub const SpvCooperativeVectorMatrixLayout__SpvCooperativeVectorMatrixLayoutRowMajorNV: + SpvCooperativeVectorMatrixLayout_ = 0; +pub const SpvCooperativeVectorMatrixLayout__SpvCooperativeVectorMatrixLayoutColumnMajorNV: + SpvCooperativeVectorMatrixLayout_ = 1; +pub const SpvCooperativeVectorMatrixLayout__SpvCooperativeVectorMatrixLayoutInferencingOptimalNV: + SpvCooperativeVectorMatrixLayout_ = 2; +pub const SpvCooperativeVectorMatrixLayout__SpvCooperativeVectorMatrixLayoutTrainingOptimalNV: + SpvCooperativeVectorMatrixLayout_ = 3; +pub const SpvCooperativeVectorMatrixLayout__SpvCooperativeVectorMatrixLayoutMax: + SpvCooperativeVectorMatrixLayout_ = 2147483647; +pub type SpvCooperativeVectorMatrixLayout_ = ::std::os::raw::c_int; +pub use self::SpvCooperativeVectorMatrixLayout_ as SpvCooperativeVectorMatrixLayout; +pub const SpvComponentType__SpvComponentTypeFloat16NV: SpvComponentType_ = 0; +pub const SpvComponentType__SpvComponentTypeFloat32NV: SpvComponentType_ = 1; +pub const SpvComponentType__SpvComponentTypeFloat64NV: SpvComponentType_ = 2; +pub const SpvComponentType__SpvComponentTypeSignedInt8NV: SpvComponentType_ = 3; +pub const SpvComponentType__SpvComponentTypeSignedInt16NV: SpvComponentType_ = 4; +pub const SpvComponentType__SpvComponentTypeSignedInt32NV: SpvComponentType_ = 5; +pub const SpvComponentType__SpvComponentTypeSignedInt64NV: SpvComponentType_ = 6; +pub const SpvComponentType__SpvComponentTypeUnsignedInt8NV: SpvComponentType_ = 7; +pub const SpvComponentType__SpvComponentTypeUnsignedInt16NV: SpvComponentType_ = 8; +pub const SpvComponentType__SpvComponentTypeUnsignedInt32NV: SpvComponentType_ = 9; +pub const SpvComponentType__SpvComponentTypeUnsignedInt64NV: SpvComponentType_ = 10; +pub const SpvComponentType__SpvComponentTypeSignedInt8PackedNV: SpvComponentType_ = 1000491000; +pub const SpvComponentType__SpvComponentTypeUnsignedInt8PackedNV: SpvComponentType_ = 1000491001; +pub const SpvComponentType__SpvComponentTypeFloatE4M3NV: SpvComponentType_ = 1000491002; +pub const SpvComponentType__SpvComponentTypeFloatE5M2NV: SpvComponentType_ = 1000491003; +pub const SpvComponentType__SpvComponentTypeMax: SpvComponentType_ = 2147483647; +pub type SpvComponentType_ = ::std::os::raw::c_int; +pub use self::SpvComponentType_ as SpvComponentType; +pub const SpvOp__SpvOpNop: SpvOp_ = 0; +pub const SpvOp__SpvOpUndef: SpvOp_ = 1; +pub const SpvOp__SpvOpSourceContinued: SpvOp_ = 2; +pub const SpvOp__SpvOpSource: SpvOp_ = 3; +pub const SpvOp__SpvOpSourceExtension: SpvOp_ = 4; +pub const SpvOp__SpvOpName: SpvOp_ = 5; +pub const SpvOp__SpvOpMemberName: SpvOp_ = 6; +pub const SpvOp__SpvOpString: SpvOp_ = 7; +pub const SpvOp__SpvOpLine: SpvOp_ = 8; +pub const SpvOp__SpvOpExtension: SpvOp_ = 10; +pub const SpvOp__SpvOpExtInstImport: SpvOp_ = 11; +pub const SpvOp__SpvOpExtInst: SpvOp_ = 12; +pub const SpvOp__SpvOpMemoryModel: SpvOp_ = 14; +pub const SpvOp__SpvOpEntryPoint: SpvOp_ = 15; +pub const SpvOp__SpvOpExecutionMode: SpvOp_ = 16; +pub const SpvOp__SpvOpCapability: SpvOp_ = 17; +pub const SpvOp__SpvOpTypeVoid: SpvOp_ = 19; +pub const SpvOp__SpvOpTypeBool: SpvOp_ = 20; +pub const SpvOp__SpvOpTypeInt: SpvOp_ = 21; +pub const SpvOp__SpvOpTypeFloat: SpvOp_ = 22; +pub const SpvOp__SpvOpTypeVector: SpvOp_ = 23; +pub const SpvOp__SpvOpTypeMatrix: SpvOp_ = 24; +pub const SpvOp__SpvOpTypeImage: SpvOp_ = 25; +pub const SpvOp__SpvOpTypeSampler: SpvOp_ = 26; +pub const SpvOp__SpvOpTypeSampledImage: SpvOp_ = 27; +pub const SpvOp__SpvOpTypeArray: SpvOp_ = 28; +pub const SpvOp__SpvOpTypeRuntimeArray: SpvOp_ = 29; +pub const SpvOp__SpvOpTypeStruct: SpvOp_ = 30; +pub const SpvOp__SpvOpTypeOpaque: SpvOp_ = 31; +pub const SpvOp__SpvOpTypePointer: SpvOp_ = 32; +pub const SpvOp__SpvOpTypeFunction: SpvOp_ = 33; +pub const SpvOp__SpvOpTypeEvent: SpvOp_ = 34; +pub const SpvOp__SpvOpTypeDeviceEvent: SpvOp_ = 35; +pub const SpvOp__SpvOpTypeReserveId: SpvOp_ = 36; +pub const SpvOp__SpvOpTypeQueue: SpvOp_ = 37; +pub const SpvOp__SpvOpTypePipe: SpvOp_ = 38; +pub const SpvOp__SpvOpTypeForwardPointer: SpvOp_ = 39; +pub const SpvOp__SpvOpConstantTrue: SpvOp_ = 41; +pub const SpvOp__SpvOpConstantFalse: SpvOp_ = 42; +pub const SpvOp__SpvOpConstant: SpvOp_ = 43; +pub const SpvOp__SpvOpConstantComposite: SpvOp_ = 44; +pub const SpvOp__SpvOpConstantSampler: SpvOp_ = 45; +pub const SpvOp__SpvOpConstantNull: SpvOp_ = 46; +pub const SpvOp__SpvOpSpecConstantTrue: SpvOp_ = 48; +pub const SpvOp__SpvOpSpecConstantFalse: SpvOp_ = 49; +pub const SpvOp__SpvOpSpecConstant: SpvOp_ = 50; +pub const SpvOp__SpvOpSpecConstantComposite: SpvOp_ = 51; +pub const SpvOp__SpvOpSpecConstantOp: SpvOp_ = 52; +pub const SpvOp__SpvOpFunction: SpvOp_ = 54; +pub const SpvOp__SpvOpFunctionParameter: SpvOp_ = 55; +pub const SpvOp__SpvOpFunctionEnd: SpvOp_ = 56; +pub const SpvOp__SpvOpFunctionCall: SpvOp_ = 57; +pub const SpvOp__SpvOpVariable: SpvOp_ = 59; +pub const SpvOp__SpvOpImageTexelPointer: SpvOp_ = 60; +pub const SpvOp__SpvOpLoad: SpvOp_ = 61; +pub const SpvOp__SpvOpStore: SpvOp_ = 62; +pub const SpvOp__SpvOpCopyMemory: SpvOp_ = 63; +pub const SpvOp__SpvOpCopyMemorySized: SpvOp_ = 64; +pub const SpvOp__SpvOpAccessChain: SpvOp_ = 65; +pub const SpvOp__SpvOpInBoundsAccessChain: SpvOp_ = 66; +pub const SpvOp__SpvOpPtrAccessChain: SpvOp_ = 67; +pub const SpvOp__SpvOpArrayLength: SpvOp_ = 68; +pub const SpvOp__SpvOpGenericPtrMemSemantics: SpvOp_ = 69; +pub const SpvOp__SpvOpInBoundsPtrAccessChain: SpvOp_ = 70; +pub const SpvOp__SpvOpDecorate: SpvOp_ = 71; +pub const SpvOp__SpvOpMemberDecorate: SpvOp_ = 72; +pub const SpvOp__SpvOpDecorationGroup: SpvOp_ = 73; +pub const SpvOp__SpvOpGroupDecorate: SpvOp_ = 74; +pub const SpvOp__SpvOpGroupMemberDecorate: SpvOp_ = 75; +pub const SpvOp__SpvOpVectorExtractDynamic: SpvOp_ = 77; +pub const SpvOp__SpvOpVectorInsertDynamic: SpvOp_ = 78; +pub const SpvOp__SpvOpVectorShuffle: SpvOp_ = 79; +pub const SpvOp__SpvOpCompositeConstruct: SpvOp_ = 80; +pub const SpvOp__SpvOpCompositeExtract: SpvOp_ = 81; +pub const SpvOp__SpvOpCompositeInsert: SpvOp_ = 82; +pub const SpvOp__SpvOpCopyObject: SpvOp_ = 83; +pub const SpvOp__SpvOpTranspose: SpvOp_ = 84; +pub const SpvOp__SpvOpSampledImage: SpvOp_ = 86; +pub const SpvOp__SpvOpImageSampleImplicitLod: SpvOp_ = 87; +pub const SpvOp__SpvOpImageSampleExplicitLod: SpvOp_ = 88; +pub const SpvOp__SpvOpImageSampleDrefImplicitLod: SpvOp_ = 89; +pub const SpvOp__SpvOpImageSampleDrefExplicitLod: SpvOp_ = 90; +pub const SpvOp__SpvOpImageSampleProjImplicitLod: SpvOp_ = 91; +pub const SpvOp__SpvOpImageSampleProjExplicitLod: SpvOp_ = 92; +pub const SpvOp__SpvOpImageSampleProjDrefImplicitLod: SpvOp_ = 93; +pub const SpvOp__SpvOpImageSampleProjDrefExplicitLod: SpvOp_ = 94; +pub const SpvOp__SpvOpImageFetch: SpvOp_ = 95; +pub const SpvOp__SpvOpImageGather: SpvOp_ = 96; +pub const SpvOp__SpvOpImageDrefGather: SpvOp_ = 97; +pub const SpvOp__SpvOpImageRead: SpvOp_ = 98; +pub const SpvOp__SpvOpImageWrite: SpvOp_ = 99; +pub const SpvOp__SpvOpImage: SpvOp_ = 100; +pub const SpvOp__SpvOpImageQueryFormat: SpvOp_ = 101; +pub const SpvOp__SpvOpImageQueryOrder: SpvOp_ = 102; +pub const SpvOp__SpvOpImageQuerySizeLod: SpvOp_ = 103; +pub const SpvOp__SpvOpImageQuerySize: SpvOp_ = 104; +pub const SpvOp__SpvOpImageQueryLod: SpvOp_ = 105; +pub const SpvOp__SpvOpImageQueryLevels: SpvOp_ = 106; +pub const SpvOp__SpvOpImageQuerySamples: SpvOp_ = 107; +pub const SpvOp__SpvOpConvertFToU: SpvOp_ = 109; +pub const SpvOp__SpvOpConvertFToS: SpvOp_ = 110; +pub const SpvOp__SpvOpConvertSToF: SpvOp_ = 111; +pub const SpvOp__SpvOpConvertUToF: SpvOp_ = 112; +pub const SpvOp__SpvOpUConvert: SpvOp_ = 113; +pub const SpvOp__SpvOpSConvert: SpvOp_ = 114; +pub const SpvOp__SpvOpFConvert: SpvOp_ = 115; +pub const SpvOp__SpvOpQuantizeToF16: SpvOp_ = 116; +pub const SpvOp__SpvOpConvertPtrToU: SpvOp_ = 117; +pub const SpvOp__SpvOpSatConvertSToU: SpvOp_ = 118; +pub const SpvOp__SpvOpSatConvertUToS: SpvOp_ = 119; +pub const SpvOp__SpvOpConvertUToPtr: SpvOp_ = 120; +pub const SpvOp__SpvOpPtrCastToGeneric: SpvOp_ = 121; +pub const SpvOp__SpvOpGenericCastToPtr: SpvOp_ = 122; +pub const SpvOp__SpvOpGenericCastToPtrExplicit: SpvOp_ = 123; +pub const SpvOp__SpvOpBitcast: SpvOp_ = 124; +pub const SpvOp__SpvOpSNegate: SpvOp_ = 126; +pub const SpvOp__SpvOpFNegate: SpvOp_ = 127; +pub const SpvOp__SpvOpIAdd: SpvOp_ = 128; +pub const SpvOp__SpvOpFAdd: SpvOp_ = 129; +pub const SpvOp__SpvOpISub: SpvOp_ = 130; +pub const SpvOp__SpvOpFSub: SpvOp_ = 131; +pub const SpvOp__SpvOpIMul: SpvOp_ = 132; +pub const SpvOp__SpvOpFMul: SpvOp_ = 133; +pub const SpvOp__SpvOpUDiv: SpvOp_ = 134; +pub const SpvOp__SpvOpSDiv: SpvOp_ = 135; +pub const SpvOp__SpvOpFDiv: SpvOp_ = 136; +pub const SpvOp__SpvOpUMod: SpvOp_ = 137; +pub const SpvOp__SpvOpSRem: SpvOp_ = 138; +pub const SpvOp__SpvOpSMod: SpvOp_ = 139; +pub const SpvOp__SpvOpFRem: SpvOp_ = 140; +pub const SpvOp__SpvOpFMod: SpvOp_ = 141; +pub const SpvOp__SpvOpVectorTimesScalar: SpvOp_ = 142; +pub const SpvOp__SpvOpMatrixTimesScalar: SpvOp_ = 143; +pub const SpvOp__SpvOpVectorTimesMatrix: SpvOp_ = 144; +pub const SpvOp__SpvOpMatrixTimesVector: SpvOp_ = 145; +pub const SpvOp__SpvOpMatrixTimesMatrix: SpvOp_ = 146; +pub const SpvOp__SpvOpOuterProduct: SpvOp_ = 147; +pub const SpvOp__SpvOpDot: SpvOp_ = 148; +pub const SpvOp__SpvOpIAddCarry: SpvOp_ = 149; +pub const SpvOp__SpvOpISubBorrow: SpvOp_ = 150; +pub const SpvOp__SpvOpUMulExtended: SpvOp_ = 151; +pub const SpvOp__SpvOpSMulExtended: SpvOp_ = 152; +pub const SpvOp__SpvOpAny: SpvOp_ = 154; +pub const SpvOp__SpvOpAll: SpvOp_ = 155; +pub const SpvOp__SpvOpIsNan: SpvOp_ = 156; +pub const SpvOp__SpvOpIsInf: SpvOp_ = 157; +pub const SpvOp__SpvOpIsFinite: SpvOp_ = 158; +pub const SpvOp__SpvOpIsNormal: SpvOp_ = 159; +pub const SpvOp__SpvOpSignBitSet: SpvOp_ = 160; +pub const SpvOp__SpvOpLessOrGreater: SpvOp_ = 161; +pub const SpvOp__SpvOpOrdered: SpvOp_ = 162; +pub const SpvOp__SpvOpUnordered: SpvOp_ = 163; +pub const SpvOp__SpvOpLogicalEqual: SpvOp_ = 164; +pub const SpvOp__SpvOpLogicalNotEqual: SpvOp_ = 165; +pub const SpvOp__SpvOpLogicalOr: SpvOp_ = 166; +pub const SpvOp__SpvOpLogicalAnd: SpvOp_ = 167; +pub const SpvOp__SpvOpLogicalNot: SpvOp_ = 168; +pub const SpvOp__SpvOpSelect: SpvOp_ = 169; +pub const SpvOp__SpvOpIEqual: SpvOp_ = 170; +pub const SpvOp__SpvOpINotEqual: SpvOp_ = 171; +pub const SpvOp__SpvOpUGreaterThan: SpvOp_ = 172; +pub const SpvOp__SpvOpSGreaterThan: SpvOp_ = 173; +pub const SpvOp__SpvOpUGreaterThanEqual: SpvOp_ = 174; +pub const SpvOp__SpvOpSGreaterThanEqual: SpvOp_ = 175; +pub const SpvOp__SpvOpULessThan: SpvOp_ = 176; +pub const SpvOp__SpvOpSLessThan: SpvOp_ = 177; +pub const SpvOp__SpvOpULessThanEqual: SpvOp_ = 178; +pub const SpvOp__SpvOpSLessThanEqual: SpvOp_ = 179; +pub const SpvOp__SpvOpFOrdEqual: SpvOp_ = 180; +pub const SpvOp__SpvOpFUnordEqual: SpvOp_ = 181; +pub const SpvOp__SpvOpFOrdNotEqual: SpvOp_ = 182; +pub const SpvOp__SpvOpFUnordNotEqual: SpvOp_ = 183; +pub const SpvOp__SpvOpFOrdLessThan: SpvOp_ = 184; +pub const SpvOp__SpvOpFUnordLessThan: SpvOp_ = 185; +pub const SpvOp__SpvOpFOrdGreaterThan: SpvOp_ = 186; +pub const SpvOp__SpvOpFUnordGreaterThan: SpvOp_ = 187; +pub const SpvOp__SpvOpFOrdLessThanEqual: SpvOp_ = 188; +pub const SpvOp__SpvOpFUnordLessThanEqual: SpvOp_ = 189; +pub const SpvOp__SpvOpFOrdGreaterThanEqual: SpvOp_ = 190; +pub const SpvOp__SpvOpFUnordGreaterThanEqual: SpvOp_ = 191; +pub const SpvOp__SpvOpShiftRightLogical: SpvOp_ = 194; +pub const SpvOp__SpvOpShiftRightArithmetic: SpvOp_ = 195; +pub const SpvOp__SpvOpShiftLeftLogical: SpvOp_ = 196; +pub const SpvOp__SpvOpBitwiseOr: SpvOp_ = 197; +pub const SpvOp__SpvOpBitwiseXor: SpvOp_ = 198; +pub const SpvOp__SpvOpBitwiseAnd: SpvOp_ = 199; +pub const SpvOp__SpvOpNot: SpvOp_ = 200; +pub const SpvOp__SpvOpBitFieldInsert: SpvOp_ = 201; +pub const SpvOp__SpvOpBitFieldSExtract: SpvOp_ = 202; +pub const SpvOp__SpvOpBitFieldUExtract: SpvOp_ = 203; +pub const SpvOp__SpvOpBitReverse: SpvOp_ = 204; +pub const SpvOp__SpvOpBitCount: SpvOp_ = 205; +pub const SpvOp__SpvOpDPdx: SpvOp_ = 207; +pub const SpvOp__SpvOpDPdy: SpvOp_ = 208; +pub const SpvOp__SpvOpFwidth: SpvOp_ = 209; +pub const SpvOp__SpvOpDPdxFine: SpvOp_ = 210; +pub const SpvOp__SpvOpDPdyFine: SpvOp_ = 211; +pub const SpvOp__SpvOpFwidthFine: SpvOp_ = 212; +pub const SpvOp__SpvOpDPdxCoarse: SpvOp_ = 213; +pub const SpvOp__SpvOpDPdyCoarse: SpvOp_ = 214; +pub const SpvOp__SpvOpFwidthCoarse: SpvOp_ = 215; +pub const SpvOp__SpvOpEmitVertex: SpvOp_ = 218; +pub const SpvOp__SpvOpEndPrimitive: SpvOp_ = 219; +pub const SpvOp__SpvOpEmitStreamVertex: SpvOp_ = 220; +pub const SpvOp__SpvOpEndStreamPrimitive: SpvOp_ = 221; +pub const SpvOp__SpvOpControlBarrier: SpvOp_ = 224; +pub const SpvOp__SpvOpMemoryBarrier: SpvOp_ = 225; +pub const SpvOp__SpvOpAtomicLoad: SpvOp_ = 227; +pub const SpvOp__SpvOpAtomicStore: SpvOp_ = 228; +pub const SpvOp__SpvOpAtomicExchange: SpvOp_ = 229; +pub const SpvOp__SpvOpAtomicCompareExchange: SpvOp_ = 230; +pub const SpvOp__SpvOpAtomicCompareExchangeWeak: SpvOp_ = 231; +pub const SpvOp__SpvOpAtomicIIncrement: SpvOp_ = 232; +pub const SpvOp__SpvOpAtomicIDecrement: SpvOp_ = 233; +pub const SpvOp__SpvOpAtomicIAdd: SpvOp_ = 234; +pub const SpvOp__SpvOpAtomicISub: SpvOp_ = 235; +pub const SpvOp__SpvOpAtomicSMin: SpvOp_ = 236; +pub const SpvOp__SpvOpAtomicUMin: SpvOp_ = 237; +pub const SpvOp__SpvOpAtomicSMax: SpvOp_ = 238; +pub const SpvOp__SpvOpAtomicUMax: SpvOp_ = 239; +pub const SpvOp__SpvOpAtomicAnd: SpvOp_ = 240; +pub const SpvOp__SpvOpAtomicOr: SpvOp_ = 241; +pub const SpvOp__SpvOpAtomicXor: SpvOp_ = 242; +pub const SpvOp__SpvOpPhi: SpvOp_ = 245; +pub const SpvOp__SpvOpLoopMerge: SpvOp_ = 246; +pub const SpvOp__SpvOpSelectionMerge: SpvOp_ = 247; +pub const SpvOp__SpvOpLabel: SpvOp_ = 248; +pub const SpvOp__SpvOpBranch: SpvOp_ = 249; +pub const SpvOp__SpvOpBranchConditional: SpvOp_ = 250; +pub const SpvOp__SpvOpSwitch: SpvOp_ = 251; +pub const SpvOp__SpvOpKill: SpvOp_ = 252; +pub const SpvOp__SpvOpReturn: SpvOp_ = 253; +pub const SpvOp__SpvOpReturnValue: SpvOp_ = 254; +pub const SpvOp__SpvOpUnreachable: SpvOp_ = 255; +pub const SpvOp__SpvOpLifetimeStart: SpvOp_ = 256; +pub const SpvOp__SpvOpLifetimeStop: SpvOp_ = 257; +pub const SpvOp__SpvOpGroupAsyncCopy: SpvOp_ = 259; +pub const SpvOp__SpvOpGroupWaitEvents: SpvOp_ = 260; +pub const SpvOp__SpvOpGroupAll: SpvOp_ = 261; +pub const SpvOp__SpvOpGroupAny: SpvOp_ = 262; +pub const SpvOp__SpvOpGroupBroadcast: SpvOp_ = 263; +pub const SpvOp__SpvOpGroupIAdd: SpvOp_ = 264; +pub const SpvOp__SpvOpGroupFAdd: SpvOp_ = 265; +pub const SpvOp__SpvOpGroupFMin: SpvOp_ = 266; +pub const SpvOp__SpvOpGroupUMin: SpvOp_ = 267; +pub const SpvOp__SpvOpGroupSMin: SpvOp_ = 268; +pub const SpvOp__SpvOpGroupFMax: SpvOp_ = 269; +pub const SpvOp__SpvOpGroupUMax: SpvOp_ = 270; +pub const SpvOp__SpvOpGroupSMax: SpvOp_ = 271; +pub const SpvOp__SpvOpReadPipe: SpvOp_ = 274; +pub const SpvOp__SpvOpWritePipe: SpvOp_ = 275; +pub const SpvOp__SpvOpReservedReadPipe: SpvOp_ = 276; +pub const SpvOp__SpvOpReservedWritePipe: SpvOp_ = 277; +pub const SpvOp__SpvOpReserveReadPipePackets: SpvOp_ = 278; +pub const SpvOp__SpvOpReserveWritePipePackets: SpvOp_ = 279; +pub const SpvOp__SpvOpCommitReadPipe: SpvOp_ = 280; +pub const SpvOp__SpvOpCommitWritePipe: SpvOp_ = 281; +pub const SpvOp__SpvOpIsValidReserveId: SpvOp_ = 282; +pub const SpvOp__SpvOpGetNumPipePackets: SpvOp_ = 283; +pub const SpvOp__SpvOpGetMaxPipePackets: SpvOp_ = 284; +pub const SpvOp__SpvOpGroupReserveReadPipePackets: SpvOp_ = 285; +pub const SpvOp__SpvOpGroupReserveWritePipePackets: SpvOp_ = 286; +pub const SpvOp__SpvOpGroupCommitReadPipe: SpvOp_ = 287; +pub const SpvOp__SpvOpGroupCommitWritePipe: SpvOp_ = 288; +pub const SpvOp__SpvOpEnqueueMarker: SpvOp_ = 291; +pub const SpvOp__SpvOpEnqueueKernel: SpvOp_ = 292; +pub const SpvOp__SpvOpGetKernelNDrangeSubGroupCount: SpvOp_ = 293; +pub const SpvOp__SpvOpGetKernelNDrangeMaxSubGroupSize: SpvOp_ = 294; +pub const SpvOp__SpvOpGetKernelWorkGroupSize: SpvOp_ = 295; +pub const SpvOp__SpvOpGetKernelPreferredWorkGroupSizeMultiple: SpvOp_ = 296; +pub const SpvOp__SpvOpRetainEvent: SpvOp_ = 297; +pub const SpvOp__SpvOpReleaseEvent: SpvOp_ = 298; +pub const SpvOp__SpvOpCreateUserEvent: SpvOp_ = 299; +pub const SpvOp__SpvOpIsValidEvent: SpvOp_ = 300; +pub const SpvOp__SpvOpSetUserEventStatus: SpvOp_ = 301; +pub const SpvOp__SpvOpCaptureEventProfilingInfo: SpvOp_ = 302; +pub const SpvOp__SpvOpGetDefaultQueue: SpvOp_ = 303; +pub const SpvOp__SpvOpBuildNDRange: SpvOp_ = 304; +pub const SpvOp__SpvOpImageSparseSampleImplicitLod: SpvOp_ = 305; +pub const SpvOp__SpvOpImageSparseSampleExplicitLod: SpvOp_ = 306; +pub const SpvOp__SpvOpImageSparseSampleDrefImplicitLod: SpvOp_ = 307; +pub const SpvOp__SpvOpImageSparseSampleDrefExplicitLod: SpvOp_ = 308; +pub const SpvOp__SpvOpImageSparseSampleProjImplicitLod: SpvOp_ = 309; +pub const SpvOp__SpvOpImageSparseSampleProjExplicitLod: SpvOp_ = 310; +pub const SpvOp__SpvOpImageSparseSampleProjDrefImplicitLod: SpvOp_ = 311; +pub const SpvOp__SpvOpImageSparseSampleProjDrefExplicitLod: SpvOp_ = 312; +pub const SpvOp__SpvOpImageSparseFetch: SpvOp_ = 313; +pub const SpvOp__SpvOpImageSparseGather: SpvOp_ = 314; +pub const SpvOp__SpvOpImageSparseDrefGather: SpvOp_ = 315; +pub const SpvOp__SpvOpImageSparseTexelsResident: SpvOp_ = 316; +pub const SpvOp__SpvOpNoLine: SpvOp_ = 317; +pub const SpvOp__SpvOpAtomicFlagTestAndSet: SpvOp_ = 318; +pub const SpvOp__SpvOpAtomicFlagClear: SpvOp_ = 319; +pub const SpvOp__SpvOpImageSparseRead: SpvOp_ = 320; +pub const SpvOp__SpvOpSizeOf: SpvOp_ = 321; +pub const SpvOp__SpvOpTypePipeStorage: SpvOp_ = 322; +pub const SpvOp__SpvOpConstantPipeStorage: SpvOp_ = 323; +pub const SpvOp__SpvOpCreatePipeFromPipeStorage: SpvOp_ = 324; +pub const SpvOp__SpvOpGetKernelLocalSizeForSubgroupCount: SpvOp_ = 325; +pub const SpvOp__SpvOpGetKernelMaxNumSubgroups: SpvOp_ = 326; +pub const SpvOp__SpvOpTypeNamedBarrier: SpvOp_ = 327; +pub const SpvOp__SpvOpNamedBarrierInitialize: SpvOp_ = 328; +pub const SpvOp__SpvOpMemoryNamedBarrier: SpvOp_ = 329; +pub const SpvOp__SpvOpModuleProcessed: SpvOp_ = 330; +pub const SpvOp__SpvOpExecutionModeId: SpvOp_ = 331; +pub const SpvOp__SpvOpDecorateId: SpvOp_ = 332; +pub const SpvOp__SpvOpGroupNonUniformElect: SpvOp_ = 333; +pub const SpvOp__SpvOpGroupNonUniformAll: SpvOp_ = 334; +pub const SpvOp__SpvOpGroupNonUniformAny: SpvOp_ = 335; +pub const SpvOp__SpvOpGroupNonUniformAllEqual: SpvOp_ = 336; +pub const SpvOp__SpvOpGroupNonUniformBroadcast: SpvOp_ = 337; +pub const SpvOp__SpvOpGroupNonUniformBroadcastFirst: SpvOp_ = 338; +pub const SpvOp__SpvOpGroupNonUniformBallot: SpvOp_ = 339; +pub const SpvOp__SpvOpGroupNonUniformInverseBallot: SpvOp_ = 340; +pub const SpvOp__SpvOpGroupNonUniformBallotBitExtract: SpvOp_ = 341; +pub const SpvOp__SpvOpGroupNonUniformBallotBitCount: SpvOp_ = 342; +pub const SpvOp__SpvOpGroupNonUniformBallotFindLSB: SpvOp_ = 343; +pub const SpvOp__SpvOpGroupNonUniformBallotFindMSB: SpvOp_ = 344; +pub const SpvOp__SpvOpGroupNonUniformShuffle: SpvOp_ = 345; +pub const SpvOp__SpvOpGroupNonUniformShuffleXor: SpvOp_ = 346; +pub const SpvOp__SpvOpGroupNonUniformShuffleUp: SpvOp_ = 347; +pub const SpvOp__SpvOpGroupNonUniformShuffleDown: SpvOp_ = 348; +pub const SpvOp__SpvOpGroupNonUniformIAdd: SpvOp_ = 349; +pub const SpvOp__SpvOpGroupNonUniformFAdd: SpvOp_ = 350; +pub const SpvOp__SpvOpGroupNonUniformIMul: SpvOp_ = 351; +pub const SpvOp__SpvOpGroupNonUniformFMul: SpvOp_ = 352; +pub const SpvOp__SpvOpGroupNonUniformSMin: SpvOp_ = 353; +pub const SpvOp__SpvOpGroupNonUniformUMin: SpvOp_ = 354; +pub const SpvOp__SpvOpGroupNonUniformFMin: SpvOp_ = 355; +pub const SpvOp__SpvOpGroupNonUniformSMax: SpvOp_ = 356; +pub const SpvOp__SpvOpGroupNonUniformUMax: SpvOp_ = 357; +pub const SpvOp__SpvOpGroupNonUniformFMax: SpvOp_ = 358; +pub const SpvOp__SpvOpGroupNonUniformBitwiseAnd: SpvOp_ = 359; +pub const SpvOp__SpvOpGroupNonUniformBitwiseOr: SpvOp_ = 360; +pub const SpvOp__SpvOpGroupNonUniformBitwiseXor: SpvOp_ = 361; +pub const SpvOp__SpvOpGroupNonUniformLogicalAnd: SpvOp_ = 362; +pub const SpvOp__SpvOpGroupNonUniformLogicalOr: SpvOp_ = 363; +pub const SpvOp__SpvOpGroupNonUniformLogicalXor: SpvOp_ = 364; +pub const SpvOp__SpvOpGroupNonUniformQuadBroadcast: SpvOp_ = 365; +pub const SpvOp__SpvOpGroupNonUniformQuadSwap: SpvOp_ = 366; +pub const SpvOp__SpvOpCopyLogical: SpvOp_ = 400; +pub const SpvOp__SpvOpPtrEqual: SpvOp_ = 401; +pub const SpvOp__SpvOpPtrNotEqual: SpvOp_ = 402; +pub const SpvOp__SpvOpPtrDiff: SpvOp_ = 403; +pub const SpvOp__SpvOpColorAttachmentReadEXT: SpvOp_ = 4160; +pub const SpvOp__SpvOpDepthAttachmentReadEXT: SpvOp_ = 4161; +pub const SpvOp__SpvOpStencilAttachmentReadEXT: SpvOp_ = 4162; +pub const SpvOp__SpvOpTypeTensorARM: SpvOp_ = 4163; +pub const SpvOp__SpvOpTensorReadARM: SpvOp_ = 4164; +pub const SpvOp__SpvOpTensorWriteARM: SpvOp_ = 4165; +pub const SpvOp__SpvOpTensorQuerySizeARM: SpvOp_ = 4166; +pub const SpvOp__SpvOpGraphConstantARM: SpvOp_ = 4181; +pub const SpvOp__SpvOpGraphEntryPointARM: SpvOp_ = 4182; +pub const SpvOp__SpvOpGraphARM: SpvOp_ = 4183; +pub const SpvOp__SpvOpGraphInputARM: SpvOp_ = 4184; +pub const SpvOp__SpvOpGraphSetOutputARM: SpvOp_ = 4185; +pub const SpvOp__SpvOpGraphEndARM: SpvOp_ = 4186; +pub const SpvOp__SpvOpTypeGraphARM: SpvOp_ = 4190; +pub const SpvOp__SpvOpTerminateInvocation: SpvOp_ = 4416; +pub const SpvOp__SpvOpTypeUntypedPointerKHR: SpvOp_ = 4417; +pub const SpvOp__SpvOpUntypedVariableKHR: SpvOp_ = 4418; +pub const SpvOp__SpvOpUntypedAccessChainKHR: SpvOp_ = 4419; +pub const SpvOp__SpvOpUntypedInBoundsAccessChainKHR: SpvOp_ = 4420; +pub const SpvOp__SpvOpSubgroupBallotKHR: SpvOp_ = 4421; +pub const SpvOp__SpvOpSubgroupFirstInvocationKHR: SpvOp_ = 4422; +pub const SpvOp__SpvOpUntypedPtrAccessChainKHR: SpvOp_ = 4423; +pub const SpvOp__SpvOpUntypedInBoundsPtrAccessChainKHR: SpvOp_ = 4424; +pub const SpvOp__SpvOpUntypedArrayLengthKHR: SpvOp_ = 4425; +pub const SpvOp__SpvOpUntypedPrefetchKHR: SpvOp_ = 4426; +pub const SpvOp__SpvOpFmaKHR: SpvOp_ = 4427; +pub const SpvOp__SpvOpSubgroupAllKHR: SpvOp_ = 4428; +pub const SpvOp__SpvOpSubgroupAnyKHR: SpvOp_ = 4429; +pub const SpvOp__SpvOpSubgroupAllEqualKHR: SpvOp_ = 4430; +pub const SpvOp__SpvOpGroupNonUniformRotateKHR: SpvOp_ = 4431; +pub const SpvOp__SpvOpSubgroupReadInvocationKHR: SpvOp_ = 4432; +pub const SpvOp__SpvOpExtInstWithForwardRefsKHR: SpvOp_ = 4433; +pub const SpvOp__SpvOpUntypedGroupAsyncCopyKHR: SpvOp_ = 4434; +pub const SpvOp__SpvOpTraceRayKHR: SpvOp_ = 4445; +pub const SpvOp__SpvOpExecuteCallableKHR: SpvOp_ = 4446; +pub const SpvOp__SpvOpConvertUToAccelerationStructureKHR: SpvOp_ = 4447; +pub const SpvOp__SpvOpIgnoreIntersectionKHR: SpvOp_ = 4448; +pub const SpvOp__SpvOpTerminateRayKHR: SpvOp_ = 4449; +pub const SpvOp__SpvOpSDot: SpvOp_ = 4450; +pub const SpvOp__SpvOpSDotKHR: SpvOp_ = 4450; +pub const SpvOp__SpvOpUDot: SpvOp_ = 4451; +pub const SpvOp__SpvOpUDotKHR: SpvOp_ = 4451; +pub const SpvOp__SpvOpSUDot: SpvOp_ = 4452; +pub const SpvOp__SpvOpSUDotKHR: SpvOp_ = 4452; +pub const SpvOp__SpvOpSDotAccSat: SpvOp_ = 4453; +pub const SpvOp__SpvOpSDotAccSatKHR: SpvOp_ = 4453; +pub const SpvOp__SpvOpUDotAccSat: SpvOp_ = 4454; +pub const SpvOp__SpvOpUDotAccSatKHR: SpvOp_ = 4454; +pub const SpvOp__SpvOpSUDotAccSat: SpvOp_ = 4455; +pub const SpvOp__SpvOpSUDotAccSatKHR: SpvOp_ = 4455; +pub const SpvOp__SpvOpTypeCooperativeMatrixKHR: SpvOp_ = 4456; +pub const SpvOp__SpvOpCooperativeMatrixLoadKHR: SpvOp_ = 4457; +pub const SpvOp__SpvOpCooperativeMatrixStoreKHR: SpvOp_ = 4458; +pub const SpvOp__SpvOpCooperativeMatrixMulAddKHR: SpvOp_ = 4459; +pub const SpvOp__SpvOpCooperativeMatrixLengthKHR: SpvOp_ = 4460; +pub const SpvOp__SpvOpConstantCompositeReplicateEXT: SpvOp_ = 4461; +pub const SpvOp__SpvOpSpecConstantCompositeReplicateEXT: SpvOp_ = 4462; +pub const SpvOp__SpvOpCompositeConstructReplicateEXT: SpvOp_ = 4463; +pub const SpvOp__SpvOpTypeRayQueryKHR: SpvOp_ = 4472; +pub const SpvOp__SpvOpRayQueryInitializeKHR: SpvOp_ = 4473; +pub const SpvOp__SpvOpRayQueryTerminateKHR: SpvOp_ = 4474; +pub const SpvOp__SpvOpRayQueryGenerateIntersectionKHR: SpvOp_ = 4475; +pub const SpvOp__SpvOpRayQueryConfirmIntersectionKHR: SpvOp_ = 4476; +pub const SpvOp__SpvOpRayQueryProceedKHR: SpvOp_ = 4477; +pub const SpvOp__SpvOpRayQueryGetIntersectionTypeKHR: SpvOp_ = 4479; +pub const SpvOp__SpvOpImageSampleWeightedQCOM: SpvOp_ = 4480; +pub const SpvOp__SpvOpImageBoxFilterQCOM: SpvOp_ = 4481; +pub const SpvOp__SpvOpImageBlockMatchSSDQCOM: SpvOp_ = 4482; +pub const SpvOp__SpvOpImageBlockMatchSADQCOM: SpvOp_ = 4483; +pub const SpvOp__SpvOpBitCastArrayQCOM: SpvOp_ = 4497; +pub const SpvOp__SpvOpImageBlockMatchWindowSSDQCOM: SpvOp_ = 4500; +pub const SpvOp__SpvOpImageBlockMatchWindowSADQCOM: SpvOp_ = 4501; +pub const SpvOp__SpvOpImageBlockMatchGatherSSDQCOM: SpvOp_ = 4502; +pub const SpvOp__SpvOpImageBlockMatchGatherSADQCOM: SpvOp_ = 4503; +pub const SpvOp__SpvOpCompositeConstructCoopMatQCOM: SpvOp_ = 4540; +pub const SpvOp__SpvOpCompositeExtractCoopMatQCOM: SpvOp_ = 4541; +pub const SpvOp__SpvOpExtractSubArrayQCOM: SpvOp_ = 4542; +pub const SpvOp__SpvOpGroupIAddNonUniformAMD: SpvOp_ = 5000; +pub const SpvOp__SpvOpGroupFAddNonUniformAMD: SpvOp_ = 5001; +pub const SpvOp__SpvOpGroupFMinNonUniformAMD: SpvOp_ = 5002; +pub const SpvOp__SpvOpGroupUMinNonUniformAMD: SpvOp_ = 5003; +pub const SpvOp__SpvOpGroupSMinNonUniformAMD: SpvOp_ = 5004; +pub const SpvOp__SpvOpGroupFMaxNonUniformAMD: SpvOp_ = 5005; +pub const SpvOp__SpvOpGroupUMaxNonUniformAMD: SpvOp_ = 5006; +pub const SpvOp__SpvOpGroupSMaxNonUniformAMD: SpvOp_ = 5007; +pub const SpvOp__SpvOpFragmentMaskFetchAMD: SpvOp_ = 5011; +pub const SpvOp__SpvOpFragmentFetchAMD: SpvOp_ = 5012; +pub const SpvOp__SpvOpReadClockKHR: SpvOp_ = 5056; +pub const SpvOp__SpvOpAllocateNodePayloadsAMDX: SpvOp_ = 5074; +pub const SpvOp__SpvOpEnqueueNodePayloadsAMDX: SpvOp_ = 5075; +pub const SpvOp__SpvOpTypeNodePayloadArrayAMDX: SpvOp_ = 5076; +pub const SpvOp__SpvOpFinishWritingNodePayloadAMDX: SpvOp_ = 5078; +pub const SpvOp__SpvOpNodePayloadArrayLengthAMDX: SpvOp_ = 5090; +pub const SpvOp__SpvOpIsNodePayloadValidAMDX: SpvOp_ = 5101; +pub const SpvOp__SpvOpConstantStringAMDX: SpvOp_ = 5103; +pub const SpvOp__SpvOpSpecConstantStringAMDX: SpvOp_ = 5104; +pub const SpvOp__SpvOpGroupNonUniformQuadAllKHR: SpvOp_ = 5110; +pub const SpvOp__SpvOpGroupNonUniformQuadAnyKHR: SpvOp_ = 5111; +pub const SpvOp__SpvOpHitObjectRecordHitMotionNV: SpvOp_ = 5249; +pub const SpvOp__SpvOpHitObjectRecordHitWithIndexMotionNV: SpvOp_ = 5250; +pub const SpvOp__SpvOpHitObjectRecordMissMotionNV: SpvOp_ = 5251; +pub const SpvOp__SpvOpHitObjectGetWorldToObjectNV: SpvOp_ = 5252; +pub const SpvOp__SpvOpHitObjectGetObjectToWorldNV: SpvOp_ = 5253; +pub const SpvOp__SpvOpHitObjectGetObjectRayDirectionNV: SpvOp_ = 5254; +pub const SpvOp__SpvOpHitObjectGetObjectRayOriginNV: SpvOp_ = 5255; +pub const SpvOp__SpvOpHitObjectTraceRayMotionNV: SpvOp_ = 5256; +pub const SpvOp__SpvOpHitObjectGetShaderRecordBufferHandleNV: SpvOp_ = 5257; +pub const SpvOp__SpvOpHitObjectGetShaderBindingTableRecordIndexNV: SpvOp_ = 5258; +pub const SpvOp__SpvOpHitObjectRecordEmptyNV: SpvOp_ = 5259; +pub const SpvOp__SpvOpHitObjectTraceRayNV: SpvOp_ = 5260; +pub const SpvOp__SpvOpHitObjectRecordHitNV: SpvOp_ = 5261; +pub const SpvOp__SpvOpHitObjectRecordHitWithIndexNV: SpvOp_ = 5262; +pub const SpvOp__SpvOpHitObjectRecordMissNV: SpvOp_ = 5263; +pub const SpvOp__SpvOpHitObjectExecuteShaderNV: SpvOp_ = 5264; +pub const SpvOp__SpvOpHitObjectGetCurrentTimeNV: SpvOp_ = 5265; +pub const SpvOp__SpvOpHitObjectGetAttributesNV: SpvOp_ = 5266; +pub const SpvOp__SpvOpHitObjectGetHitKindNV: SpvOp_ = 5267; +pub const SpvOp__SpvOpHitObjectGetPrimitiveIndexNV: SpvOp_ = 5268; +pub const SpvOp__SpvOpHitObjectGetGeometryIndexNV: SpvOp_ = 5269; +pub const SpvOp__SpvOpHitObjectGetInstanceIdNV: SpvOp_ = 5270; +pub const SpvOp__SpvOpHitObjectGetInstanceCustomIndexNV: SpvOp_ = 5271; +pub const SpvOp__SpvOpHitObjectGetWorldRayDirectionNV: SpvOp_ = 5272; +pub const SpvOp__SpvOpHitObjectGetWorldRayOriginNV: SpvOp_ = 5273; +pub const SpvOp__SpvOpHitObjectGetRayTMaxNV: SpvOp_ = 5274; +pub const SpvOp__SpvOpHitObjectGetRayTMinNV: SpvOp_ = 5275; +pub const SpvOp__SpvOpHitObjectIsEmptyNV: SpvOp_ = 5276; +pub const SpvOp__SpvOpHitObjectIsHitNV: SpvOp_ = 5277; +pub const SpvOp__SpvOpHitObjectIsMissNV: SpvOp_ = 5278; +pub const SpvOp__SpvOpReorderThreadWithHitObjectNV: SpvOp_ = 5279; +pub const SpvOp__SpvOpReorderThreadWithHintNV: SpvOp_ = 5280; +pub const SpvOp__SpvOpTypeHitObjectNV: SpvOp_ = 5281; +pub const SpvOp__SpvOpImageSampleFootprintNV: SpvOp_ = 5283; +pub const SpvOp__SpvOpTypeCooperativeVectorNV: SpvOp_ = 5288; +pub const SpvOp__SpvOpCooperativeVectorMatrixMulNV: SpvOp_ = 5289; +pub const SpvOp__SpvOpCooperativeVectorOuterProductAccumulateNV: SpvOp_ = 5290; +pub const SpvOp__SpvOpCooperativeVectorReduceSumAccumulateNV: SpvOp_ = 5291; +pub const SpvOp__SpvOpCooperativeVectorMatrixMulAddNV: SpvOp_ = 5292; +pub const SpvOp__SpvOpCooperativeMatrixConvertNV: SpvOp_ = 5293; +pub const SpvOp__SpvOpEmitMeshTasksEXT: SpvOp_ = 5294; +pub const SpvOp__SpvOpSetMeshOutputsEXT: SpvOp_ = 5295; +pub const SpvOp__SpvOpGroupNonUniformPartitionNV: SpvOp_ = 5296; +pub const SpvOp__SpvOpWritePackedPrimitiveIndices4x8NV: SpvOp_ = 5299; +pub const SpvOp__SpvOpFetchMicroTriangleVertexPositionNV: SpvOp_ = 5300; +pub const SpvOp__SpvOpFetchMicroTriangleVertexBarycentricNV: SpvOp_ = 5301; +pub const SpvOp__SpvOpCooperativeVectorLoadNV: SpvOp_ = 5302; +pub const SpvOp__SpvOpCooperativeVectorStoreNV: SpvOp_ = 5303; +pub const SpvOp__SpvOpReportIntersectionKHR: SpvOp_ = 5334; +pub const SpvOp__SpvOpReportIntersectionNV: SpvOp_ = 5334; +pub const SpvOp__SpvOpIgnoreIntersectionNV: SpvOp_ = 5335; +pub const SpvOp__SpvOpTerminateRayNV: SpvOp_ = 5336; +pub const SpvOp__SpvOpTraceNV: SpvOp_ = 5337; +pub const SpvOp__SpvOpTraceMotionNV: SpvOp_ = 5338; +pub const SpvOp__SpvOpTraceRayMotionNV: SpvOp_ = 5339; +pub const SpvOp__SpvOpRayQueryGetIntersectionTriangleVertexPositionsKHR: SpvOp_ = 5340; +pub const SpvOp__SpvOpTypeAccelerationStructureKHR: SpvOp_ = 5341; +pub const SpvOp__SpvOpTypeAccelerationStructureNV: SpvOp_ = 5341; +pub const SpvOp__SpvOpExecuteCallableNV: SpvOp_ = 5344; +pub const SpvOp__SpvOpRayQueryGetClusterIdNV: SpvOp_ = 5345; +pub const SpvOp__SpvOpRayQueryGetIntersectionClusterIdNV: SpvOp_ = 5345; +pub const SpvOp__SpvOpHitObjectGetClusterIdNV: SpvOp_ = 5346; +pub const SpvOp__SpvOpTypeCooperativeMatrixNV: SpvOp_ = 5358; +pub const SpvOp__SpvOpCooperativeMatrixLoadNV: SpvOp_ = 5359; +pub const SpvOp__SpvOpCooperativeMatrixStoreNV: SpvOp_ = 5360; +pub const SpvOp__SpvOpCooperativeMatrixMulAddNV: SpvOp_ = 5361; +pub const SpvOp__SpvOpCooperativeMatrixLengthNV: SpvOp_ = 5362; +pub const SpvOp__SpvOpBeginInvocationInterlockEXT: SpvOp_ = 5364; +pub const SpvOp__SpvOpEndInvocationInterlockEXT: SpvOp_ = 5365; +pub const SpvOp__SpvOpCooperativeMatrixReduceNV: SpvOp_ = 5366; +pub const SpvOp__SpvOpCooperativeMatrixLoadTensorNV: SpvOp_ = 5367; +pub const SpvOp__SpvOpCooperativeMatrixStoreTensorNV: SpvOp_ = 5368; +pub const SpvOp__SpvOpCooperativeMatrixPerElementOpNV: SpvOp_ = 5369; +pub const SpvOp__SpvOpTypeTensorLayoutNV: SpvOp_ = 5370; +pub const SpvOp__SpvOpTypeTensorViewNV: SpvOp_ = 5371; +pub const SpvOp__SpvOpCreateTensorLayoutNV: SpvOp_ = 5372; +pub const SpvOp__SpvOpTensorLayoutSetDimensionNV: SpvOp_ = 5373; +pub const SpvOp__SpvOpTensorLayoutSetStrideNV: SpvOp_ = 5374; +pub const SpvOp__SpvOpTensorLayoutSliceNV: SpvOp_ = 5375; +pub const SpvOp__SpvOpTensorLayoutSetClampValueNV: SpvOp_ = 5376; +pub const SpvOp__SpvOpCreateTensorViewNV: SpvOp_ = 5377; +pub const SpvOp__SpvOpTensorViewSetDimensionNV: SpvOp_ = 5378; +pub const SpvOp__SpvOpTensorViewSetStrideNV: SpvOp_ = 5379; +pub const SpvOp__SpvOpDemoteToHelperInvocation: SpvOp_ = 5380; +pub const SpvOp__SpvOpDemoteToHelperInvocationEXT: SpvOp_ = 5380; +pub const SpvOp__SpvOpIsHelperInvocationEXT: SpvOp_ = 5381; +pub const SpvOp__SpvOpTensorViewSetClipNV: SpvOp_ = 5382; +pub const SpvOp__SpvOpTensorLayoutSetBlockSizeNV: SpvOp_ = 5384; +pub const SpvOp__SpvOpCooperativeMatrixTransposeNV: SpvOp_ = 5390; +pub const SpvOp__SpvOpConvertUToImageNV: SpvOp_ = 5391; +pub const SpvOp__SpvOpConvertUToSamplerNV: SpvOp_ = 5392; +pub const SpvOp__SpvOpConvertImageToUNV: SpvOp_ = 5393; +pub const SpvOp__SpvOpConvertSamplerToUNV: SpvOp_ = 5394; +pub const SpvOp__SpvOpConvertUToSampledImageNV: SpvOp_ = 5395; +pub const SpvOp__SpvOpConvertSampledImageToUNV: SpvOp_ = 5396; +pub const SpvOp__SpvOpSamplerImageAddressingModeNV: SpvOp_ = 5397; +pub const SpvOp__SpvOpRawAccessChainNV: SpvOp_ = 5398; +pub const SpvOp__SpvOpRayQueryGetIntersectionSpherePositionNV: SpvOp_ = 5427; +pub const SpvOp__SpvOpRayQueryGetIntersectionSphereRadiusNV: SpvOp_ = 5428; +pub const SpvOp__SpvOpRayQueryGetIntersectionLSSPositionsNV: SpvOp_ = 5429; +pub const SpvOp__SpvOpRayQueryGetIntersectionLSSRadiiNV: SpvOp_ = 5430; +pub const SpvOp__SpvOpRayQueryGetIntersectionLSSHitValueNV: SpvOp_ = 5431; +pub const SpvOp__SpvOpHitObjectGetSpherePositionNV: SpvOp_ = 5432; +pub const SpvOp__SpvOpHitObjectGetSphereRadiusNV: SpvOp_ = 5433; +pub const SpvOp__SpvOpHitObjectGetLSSPositionsNV: SpvOp_ = 5434; +pub const SpvOp__SpvOpHitObjectGetLSSRadiiNV: SpvOp_ = 5435; +pub const SpvOp__SpvOpHitObjectIsSphereHitNV: SpvOp_ = 5436; +pub const SpvOp__SpvOpHitObjectIsLSSHitNV: SpvOp_ = 5437; +pub const SpvOp__SpvOpRayQueryIsSphereHitNV: SpvOp_ = 5438; +pub const SpvOp__SpvOpRayQueryIsLSSHitNV: SpvOp_ = 5439; +pub const SpvOp__SpvOpSubgroupShuffleINTEL: SpvOp_ = 5571; +pub const SpvOp__SpvOpSubgroupShuffleDownINTEL: SpvOp_ = 5572; +pub const SpvOp__SpvOpSubgroupShuffleUpINTEL: SpvOp_ = 5573; +pub const SpvOp__SpvOpSubgroupShuffleXorINTEL: SpvOp_ = 5574; +pub const SpvOp__SpvOpSubgroupBlockReadINTEL: SpvOp_ = 5575; +pub const SpvOp__SpvOpSubgroupBlockWriteINTEL: SpvOp_ = 5576; +pub const SpvOp__SpvOpSubgroupImageBlockReadINTEL: SpvOp_ = 5577; +pub const SpvOp__SpvOpSubgroupImageBlockWriteINTEL: SpvOp_ = 5578; +pub const SpvOp__SpvOpSubgroupImageMediaBlockReadINTEL: SpvOp_ = 5580; +pub const SpvOp__SpvOpSubgroupImageMediaBlockWriteINTEL: SpvOp_ = 5581; +pub const SpvOp__SpvOpUCountLeadingZerosINTEL: SpvOp_ = 5585; +pub const SpvOp__SpvOpUCountTrailingZerosINTEL: SpvOp_ = 5586; +pub const SpvOp__SpvOpAbsISubINTEL: SpvOp_ = 5587; +pub const SpvOp__SpvOpAbsUSubINTEL: SpvOp_ = 5588; +pub const SpvOp__SpvOpIAddSatINTEL: SpvOp_ = 5589; +pub const SpvOp__SpvOpUAddSatINTEL: SpvOp_ = 5590; +pub const SpvOp__SpvOpIAverageINTEL: SpvOp_ = 5591; +pub const SpvOp__SpvOpUAverageINTEL: SpvOp_ = 5592; +pub const SpvOp__SpvOpIAverageRoundedINTEL: SpvOp_ = 5593; +pub const SpvOp__SpvOpUAverageRoundedINTEL: SpvOp_ = 5594; +pub const SpvOp__SpvOpISubSatINTEL: SpvOp_ = 5595; +pub const SpvOp__SpvOpUSubSatINTEL: SpvOp_ = 5596; +pub const SpvOp__SpvOpIMul32x16INTEL: SpvOp_ = 5597; +pub const SpvOp__SpvOpUMul32x16INTEL: SpvOp_ = 5598; +pub const SpvOp__SpvOpConstantFunctionPointerINTEL: SpvOp_ = 5600; +pub const SpvOp__SpvOpFunctionPointerCallINTEL: SpvOp_ = 5601; +pub const SpvOp__SpvOpAsmTargetINTEL: SpvOp_ = 5609; +pub const SpvOp__SpvOpAsmINTEL: SpvOp_ = 5610; +pub const SpvOp__SpvOpAsmCallINTEL: SpvOp_ = 5611; +pub const SpvOp__SpvOpAtomicFMinEXT: SpvOp_ = 5614; +pub const SpvOp__SpvOpAtomicFMaxEXT: SpvOp_ = 5615; +pub const SpvOp__SpvOpAssumeTrueKHR: SpvOp_ = 5630; +pub const SpvOp__SpvOpExpectKHR: SpvOp_ = 5631; +pub const SpvOp__SpvOpDecorateString: SpvOp_ = 5632; +pub const SpvOp__SpvOpDecorateStringGOOGLE: SpvOp_ = 5632; +pub const SpvOp__SpvOpMemberDecorateString: SpvOp_ = 5633; +pub const SpvOp__SpvOpMemberDecorateStringGOOGLE: SpvOp_ = 5633; +pub const SpvOp__SpvOpVmeImageINTEL: SpvOp_ = 5699; +pub const SpvOp__SpvOpTypeVmeImageINTEL: SpvOp_ = 5700; +pub const SpvOp__SpvOpTypeAvcImePayloadINTEL: SpvOp_ = 5701; +pub const SpvOp__SpvOpTypeAvcRefPayloadINTEL: SpvOp_ = 5702; +pub const SpvOp__SpvOpTypeAvcSicPayloadINTEL: SpvOp_ = 5703; +pub const SpvOp__SpvOpTypeAvcMcePayloadINTEL: SpvOp_ = 5704; +pub const SpvOp__SpvOpTypeAvcMceResultINTEL: SpvOp_ = 5705; +pub const SpvOp__SpvOpTypeAvcImeResultINTEL: SpvOp_ = 5706; +pub const SpvOp__SpvOpTypeAvcImeResultSingleReferenceStreamoutINTEL: SpvOp_ = 5707; +pub const SpvOp__SpvOpTypeAvcImeResultDualReferenceStreamoutINTEL: SpvOp_ = 5708; +pub const SpvOp__SpvOpTypeAvcImeSingleReferenceStreaminINTEL: SpvOp_ = 5709; +pub const SpvOp__SpvOpTypeAvcImeDualReferenceStreaminINTEL: SpvOp_ = 5710; +pub const SpvOp__SpvOpTypeAvcRefResultINTEL: SpvOp_ = 5711; +pub const SpvOp__SpvOpTypeAvcSicResultINTEL: SpvOp_ = 5712; +pub const SpvOp__SpvOpSubgroupAvcMceGetDefaultInterBaseMultiReferencePenaltyINTEL: SpvOp_ = 5713; +pub const SpvOp__SpvOpSubgroupAvcMceSetInterBaseMultiReferencePenaltyINTEL: SpvOp_ = 5714; +pub const SpvOp__SpvOpSubgroupAvcMceGetDefaultInterShapePenaltyINTEL: SpvOp_ = 5715; +pub const SpvOp__SpvOpSubgroupAvcMceSetInterShapePenaltyINTEL: SpvOp_ = 5716; +pub const SpvOp__SpvOpSubgroupAvcMceGetDefaultInterDirectionPenaltyINTEL: SpvOp_ = 5717; +pub const SpvOp__SpvOpSubgroupAvcMceSetInterDirectionPenaltyINTEL: SpvOp_ = 5718; +pub const SpvOp__SpvOpSubgroupAvcMceGetDefaultIntraLumaShapePenaltyINTEL: SpvOp_ = 5719; +pub const SpvOp__SpvOpSubgroupAvcMceGetDefaultInterMotionVectorCostTableINTEL: SpvOp_ = 5720; +pub const SpvOp__SpvOpSubgroupAvcMceGetDefaultHighPenaltyCostTableINTEL: SpvOp_ = 5721; +pub const SpvOp__SpvOpSubgroupAvcMceGetDefaultMediumPenaltyCostTableINTEL: SpvOp_ = 5722; +pub const SpvOp__SpvOpSubgroupAvcMceGetDefaultLowPenaltyCostTableINTEL: SpvOp_ = 5723; +pub const SpvOp__SpvOpSubgroupAvcMceSetMotionVectorCostFunctionINTEL: SpvOp_ = 5724; +pub const SpvOp__SpvOpSubgroupAvcMceGetDefaultIntraLumaModePenaltyINTEL: SpvOp_ = 5725; +pub const SpvOp__SpvOpSubgroupAvcMceGetDefaultNonDcLumaIntraPenaltyINTEL: SpvOp_ = 5726; +pub const SpvOp__SpvOpSubgroupAvcMceGetDefaultIntraChromaModeBasePenaltyINTEL: SpvOp_ = 5727; +pub const SpvOp__SpvOpSubgroupAvcMceSetAcOnlyHaarINTEL: SpvOp_ = 5728; +pub const SpvOp__SpvOpSubgroupAvcMceSetSourceInterlacedFieldPolarityINTEL: SpvOp_ = 5729; +pub const SpvOp__SpvOpSubgroupAvcMceSetSingleReferenceInterlacedFieldPolarityINTEL: SpvOp_ = 5730; +pub const SpvOp__SpvOpSubgroupAvcMceSetDualReferenceInterlacedFieldPolaritiesINTEL: SpvOp_ = 5731; +pub const SpvOp__SpvOpSubgroupAvcMceConvertToImePayloadINTEL: SpvOp_ = 5732; +pub const SpvOp__SpvOpSubgroupAvcMceConvertToImeResultINTEL: SpvOp_ = 5733; +pub const SpvOp__SpvOpSubgroupAvcMceConvertToRefPayloadINTEL: SpvOp_ = 5734; +pub const SpvOp__SpvOpSubgroupAvcMceConvertToRefResultINTEL: SpvOp_ = 5735; +pub const SpvOp__SpvOpSubgroupAvcMceConvertToSicPayloadINTEL: SpvOp_ = 5736; +pub const SpvOp__SpvOpSubgroupAvcMceConvertToSicResultINTEL: SpvOp_ = 5737; +pub const SpvOp__SpvOpSubgroupAvcMceGetMotionVectorsINTEL: SpvOp_ = 5738; +pub const SpvOp__SpvOpSubgroupAvcMceGetInterDistortionsINTEL: SpvOp_ = 5739; +pub const SpvOp__SpvOpSubgroupAvcMceGetBestInterDistortionsINTEL: SpvOp_ = 5740; +pub const SpvOp__SpvOpSubgroupAvcMceGetInterMajorShapeINTEL: SpvOp_ = 5741; +pub const SpvOp__SpvOpSubgroupAvcMceGetInterMinorShapeINTEL: SpvOp_ = 5742; +pub const SpvOp__SpvOpSubgroupAvcMceGetInterDirectionsINTEL: SpvOp_ = 5743; +pub const SpvOp__SpvOpSubgroupAvcMceGetInterMotionVectorCountINTEL: SpvOp_ = 5744; +pub const SpvOp__SpvOpSubgroupAvcMceGetInterReferenceIdsINTEL: SpvOp_ = 5745; +pub const SpvOp__SpvOpSubgroupAvcMceGetInterReferenceInterlacedFieldPolaritiesINTEL: SpvOp_ = 5746; +pub const SpvOp__SpvOpSubgroupAvcImeInitializeINTEL: SpvOp_ = 5747; +pub const SpvOp__SpvOpSubgroupAvcImeSetSingleReferenceINTEL: SpvOp_ = 5748; +pub const SpvOp__SpvOpSubgroupAvcImeSetDualReferenceINTEL: SpvOp_ = 5749; +pub const SpvOp__SpvOpSubgroupAvcImeRefWindowSizeINTEL: SpvOp_ = 5750; +pub const SpvOp__SpvOpSubgroupAvcImeAdjustRefOffsetINTEL: SpvOp_ = 5751; +pub const SpvOp__SpvOpSubgroupAvcImeConvertToMcePayloadINTEL: SpvOp_ = 5752; +pub const SpvOp__SpvOpSubgroupAvcImeSetMaxMotionVectorCountINTEL: SpvOp_ = 5753; +pub const SpvOp__SpvOpSubgroupAvcImeSetUnidirectionalMixDisableINTEL: SpvOp_ = 5754; +pub const SpvOp__SpvOpSubgroupAvcImeSetEarlySearchTerminationThresholdINTEL: SpvOp_ = 5755; +pub const SpvOp__SpvOpSubgroupAvcImeSetWeightedSadINTEL: SpvOp_ = 5756; +pub const SpvOp__SpvOpSubgroupAvcImeEvaluateWithSingleReferenceINTEL: SpvOp_ = 5757; +pub const SpvOp__SpvOpSubgroupAvcImeEvaluateWithDualReferenceINTEL: SpvOp_ = 5758; +pub const SpvOp__SpvOpSubgroupAvcImeEvaluateWithSingleReferenceStreaminINTEL: SpvOp_ = 5759; +pub const SpvOp__SpvOpSubgroupAvcImeEvaluateWithDualReferenceStreaminINTEL: SpvOp_ = 5760; +pub const SpvOp__SpvOpSubgroupAvcImeEvaluateWithSingleReferenceStreamoutINTEL: SpvOp_ = 5761; +pub const SpvOp__SpvOpSubgroupAvcImeEvaluateWithDualReferenceStreamoutINTEL: SpvOp_ = 5762; +pub const SpvOp__SpvOpSubgroupAvcImeEvaluateWithSingleReferenceStreaminoutINTEL: SpvOp_ = 5763; +pub const SpvOp__SpvOpSubgroupAvcImeEvaluateWithDualReferenceStreaminoutINTEL: SpvOp_ = 5764; +pub const SpvOp__SpvOpSubgroupAvcImeConvertToMceResultINTEL: SpvOp_ = 5765; +pub const SpvOp__SpvOpSubgroupAvcImeGetSingleReferenceStreaminINTEL: SpvOp_ = 5766; +pub const SpvOp__SpvOpSubgroupAvcImeGetDualReferenceStreaminINTEL: SpvOp_ = 5767; +pub const SpvOp__SpvOpSubgroupAvcImeStripSingleReferenceStreamoutINTEL: SpvOp_ = 5768; +pub const SpvOp__SpvOpSubgroupAvcImeStripDualReferenceStreamoutINTEL: SpvOp_ = 5769; +pub const SpvOp__SpvOpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeMotionVectorsINTEL: + SpvOp_ = 5770; +pub const SpvOp__SpvOpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeDistortionsINTEL: SpvOp_ = + 5771; +pub const SpvOp__SpvOpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeReferenceIdsINTEL: SpvOp_ = + 5772; +pub const SpvOp__SpvOpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeMotionVectorsINTEL: SpvOp_ = + 5773; +pub const SpvOp__SpvOpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeDistortionsINTEL: SpvOp_ = + 5774; +pub const SpvOp__SpvOpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeReferenceIdsINTEL: SpvOp_ = + 5775; +pub const SpvOp__SpvOpSubgroupAvcImeGetBorderReachedINTEL: SpvOp_ = 5776; +pub const SpvOp__SpvOpSubgroupAvcImeGetTruncatedSearchIndicationINTEL: SpvOp_ = 5777; +pub const SpvOp__SpvOpSubgroupAvcImeGetUnidirectionalEarlySearchTerminationINTEL: SpvOp_ = 5778; +pub const SpvOp__SpvOpSubgroupAvcImeGetWeightingPatternMinimumMotionVectorINTEL: SpvOp_ = 5779; +pub const SpvOp__SpvOpSubgroupAvcImeGetWeightingPatternMinimumDistortionINTEL: SpvOp_ = 5780; +pub const SpvOp__SpvOpSubgroupAvcFmeInitializeINTEL: SpvOp_ = 5781; +pub const SpvOp__SpvOpSubgroupAvcBmeInitializeINTEL: SpvOp_ = 5782; +pub const SpvOp__SpvOpSubgroupAvcRefConvertToMcePayloadINTEL: SpvOp_ = 5783; +pub const SpvOp__SpvOpSubgroupAvcRefSetBidirectionalMixDisableINTEL: SpvOp_ = 5784; +pub const SpvOp__SpvOpSubgroupAvcRefSetBilinearFilterEnableINTEL: SpvOp_ = 5785; +pub const SpvOp__SpvOpSubgroupAvcRefEvaluateWithSingleReferenceINTEL: SpvOp_ = 5786; +pub const SpvOp__SpvOpSubgroupAvcRefEvaluateWithDualReferenceINTEL: SpvOp_ = 5787; +pub const SpvOp__SpvOpSubgroupAvcRefEvaluateWithMultiReferenceINTEL: SpvOp_ = 5788; +pub const SpvOp__SpvOpSubgroupAvcRefEvaluateWithMultiReferenceInterlacedINTEL: SpvOp_ = 5789; +pub const SpvOp__SpvOpSubgroupAvcRefConvertToMceResultINTEL: SpvOp_ = 5790; +pub const SpvOp__SpvOpSubgroupAvcSicInitializeINTEL: SpvOp_ = 5791; +pub const SpvOp__SpvOpSubgroupAvcSicConfigureSkcINTEL: SpvOp_ = 5792; +pub const SpvOp__SpvOpSubgroupAvcSicConfigureIpeLumaINTEL: SpvOp_ = 5793; +pub const SpvOp__SpvOpSubgroupAvcSicConfigureIpeLumaChromaINTEL: SpvOp_ = 5794; +pub const SpvOp__SpvOpSubgroupAvcSicGetMotionVectorMaskINTEL: SpvOp_ = 5795; +pub const SpvOp__SpvOpSubgroupAvcSicConvertToMcePayloadINTEL: SpvOp_ = 5796; +pub const SpvOp__SpvOpSubgroupAvcSicSetIntraLumaShapePenaltyINTEL: SpvOp_ = 5797; +pub const SpvOp__SpvOpSubgroupAvcSicSetIntraLumaModeCostFunctionINTEL: SpvOp_ = 5798; +pub const SpvOp__SpvOpSubgroupAvcSicSetIntraChromaModeCostFunctionINTEL: SpvOp_ = 5799; +pub const SpvOp__SpvOpSubgroupAvcSicSetBilinearFilterEnableINTEL: SpvOp_ = 5800; +pub const SpvOp__SpvOpSubgroupAvcSicSetSkcForwardTransformEnableINTEL: SpvOp_ = 5801; +pub const SpvOp__SpvOpSubgroupAvcSicSetBlockBasedRawSkipSadINTEL: SpvOp_ = 5802; +pub const SpvOp__SpvOpSubgroupAvcSicEvaluateIpeINTEL: SpvOp_ = 5803; +pub const SpvOp__SpvOpSubgroupAvcSicEvaluateWithSingleReferenceINTEL: SpvOp_ = 5804; +pub const SpvOp__SpvOpSubgroupAvcSicEvaluateWithDualReferenceINTEL: SpvOp_ = 5805; +pub const SpvOp__SpvOpSubgroupAvcSicEvaluateWithMultiReferenceINTEL: SpvOp_ = 5806; +pub const SpvOp__SpvOpSubgroupAvcSicEvaluateWithMultiReferenceInterlacedINTEL: SpvOp_ = 5807; +pub const SpvOp__SpvOpSubgroupAvcSicConvertToMceResultINTEL: SpvOp_ = 5808; +pub const SpvOp__SpvOpSubgroupAvcSicGetIpeLumaShapeINTEL: SpvOp_ = 5809; +pub const SpvOp__SpvOpSubgroupAvcSicGetBestIpeLumaDistortionINTEL: SpvOp_ = 5810; +pub const SpvOp__SpvOpSubgroupAvcSicGetBestIpeChromaDistortionINTEL: SpvOp_ = 5811; +pub const SpvOp__SpvOpSubgroupAvcSicGetPackedIpeLumaModesINTEL: SpvOp_ = 5812; +pub const SpvOp__SpvOpSubgroupAvcSicGetIpeChromaModeINTEL: SpvOp_ = 5813; +pub const SpvOp__SpvOpSubgroupAvcSicGetPackedSkcLumaCountThresholdINTEL: SpvOp_ = 5814; +pub const SpvOp__SpvOpSubgroupAvcSicGetPackedSkcLumaSumThresholdINTEL: SpvOp_ = 5815; +pub const SpvOp__SpvOpSubgroupAvcSicGetInterRawSadsINTEL: SpvOp_ = 5816; +pub const SpvOp__SpvOpVariableLengthArrayINTEL: SpvOp_ = 5818; +pub const SpvOp__SpvOpSaveMemoryINTEL: SpvOp_ = 5819; +pub const SpvOp__SpvOpRestoreMemoryINTEL: SpvOp_ = 5820; +pub const SpvOp__SpvOpArbitraryFloatSinCosPiINTEL: SpvOp_ = 5840; +pub const SpvOp__SpvOpArbitraryFloatCastINTEL: SpvOp_ = 5841; +pub const SpvOp__SpvOpArbitraryFloatCastFromIntINTEL: SpvOp_ = 5842; +pub const SpvOp__SpvOpArbitraryFloatCastToIntINTEL: SpvOp_ = 5843; +pub const SpvOp__SpvOpArbitraryFloatAddINTEL: SpvOp_ = 5846; +pub const SpvOp__SpvOpArbitraryFloatSubINTEL: SpvOp_ = 5847; +pub const SpvOp__SpvOpArbitraryFloatMulINTEL: SpvOp_ = 5848; +pub const SpvOp__SpvOpArbitraryFloatDivINTEL: SpvOp_ = 5849; +pub const SpvOp__SpvOpArbitraryFloatGTINTEL: SpvOp_ = 5850; +pub const SpvOp__SpvOpArbitraryFloatGEINTEL: SpvOp_ = 5851; +pub const SpvOp__SpvOpArbitraryFloatLTINTEL: SpvOp_ = 5852; +pub const SpvOp__SpvOpArbitraryFloatLEINTEL: SpvOp_ = 5853; +pub const SpvOp__SpvOpArbitraryFloatEQINTEL: SpvOp_ = 5854; +pub const SpvOp__SpvOpArbitraryFloatRecipINTEL: SpvOp_ = 5855; +pub const SpvOp__SpvOpArbitraryFloatRSqrtINTEL: SpvOp_ = 5856; +pub const SpvOp__SpvOpArbitraryFloatCbrtINTEL: SpvOp_ = 5857; +pub const SpvOp__SpvOpArbitraryFloatHypotINTEL: SpvOp_ = 5858; +pub const SpvOp__SpvOpArbitraryFloatSqrtINTEL: SpvOp_ = 5859; +pub const SpvOp__SpvOpArbitraryFloatLogINTEL: SpvOp_ = 5860; +pub const SpvOp__SpvOpArbitraryFloatLog2INTEL: SpvOp_ = 5861; +pub const SpvOp__SpvOpArbitraryFloatLog10INTEL: SpvOp_ = 5862; +pub const SpvOp__SpvOpArbitraryFloatLog1pINTEL: SpvOp_ = 5863; +pub const SpvOp__SpvOpArbitraryFloatExpINTEL: SpvOp_ = 5864; +pub const SpvOp__SpvOpArbitraryFloatExp2INTEL: SpvOp_ = 5865; +pub const SpvOp__SpvOpArbitraryFloatExp10INTEL: SpvOp_ = 5866; +pub const SpvOp__SpvOpArbitraryFloatExpm1INTEL: SpvOp_ = 5867; +pub const SpvOp__SpvOpArbitraryFloatSinINTEL: SpvOp_ = 5868; +pub const SpvOp__SpvOpArbitraryFloatCosINTEL: SpvOp_ = 5869; +pub const SpvOp__SpvOpArbitraryFloatSinCosINTEL: SpvOp_ = 5870; +pub const SpvOp__SpvOpArbitraryFloatSinPiINTEL: SpvOp_ = 5871; +pub const SpvOp__SpvOpArbitraryFloatCosPiINTEL: SpvOp_ = 5872; +pub const SpvOp__SpvOpArbitraryFloatASinINTEL: SpvOp_ = 5873; +pub const SpvOp__SpvOpArbitraryFloatASinPiINTEL: SpvOp_ = 5874; +pub const SpvOp__SpvOpArbitraryFloatACosINTEL: SpvOp_ = 5875; +pub const SpvOp__SpvOpArbitraryFloatACosPiINTEL: SpvOp_ = 5876; +pub const SpvOp__SpvOpArbitraryFloatATanINTEL: SpvOp_ = 5877; +pub const SpvOp__SpvOpArbitraryFloatATanPiINTEL: SpvOp_ = 5878; +pub const SpvOp__SpvOpArbitraryFloatATan2INTEL: SpvOp_ = 5879; +pub const SpvOp__SpvOpArbitraryFloatPowINTEL: SpvOp_ = 5880; +pub const SpvOp__SpvOpArbitraryFloatPowRINTEL: SpvOp_ = 5881; +pub const SpvOp__SpvOpArbitraryFloatPowNINTEL: SpvOp_ = 5882; +pub const SpvOp__SpvOpLoopControlINTEL: SpvOp_ = 5887; +pub const SpvOp__SpvOpAliasDomainDeclINTEL: SpvOp_ = 5911; +pub const SpvOp__SpvOpAliasScopeDeclINTEL: SpvOp_ = 5912; +pub const SpvOp__SpvOpAliasScopeListDeclINTEL: SpvOp_ = 5913; +pub const SpvOp__SpvOpFixedSqrtINTEL: SpvOp_ = 5923; +pub const SpvOp__SpvOpFixedRecipINTEL: SpvOp_ = 5924; +pub const SpvOp__SpvOpFixedRsqrtINTEL: SpvOp_ = 5925; +pub const SpvOp__SpvOpFixedSinINTEL: SpvOp_ = 5926; +pub const SpvOp__SpvOpFixedCosINTEL: SpvOp_ = 5927; +pub const SpvOp__SpvOpFixedSinCosINTEL: SpvOp_ = 5928; +pub const SpvOp__SpvOpFixedSinPiINTEL: SpvOp_ = 5929; +pub const SpvOp__SpvOpFixedCosPiINTEL: SpvOp_ = 5930; +pub const SpvOp__SpvOpFixedSinCosPiINTEL: SpvOp_ = 5931; +pub const SpvOp__SpvOpFixedLogINTEL: SpvOp_ = 5932; +pub const SpvOp__SpvOpFixedExpINTEL: SpvOp_ = 5933; +pub const SpvOp__SpvOpPtrCastToCrossWorkgroupINTEL: SpvOp_ = 5934; +pub const SpvOp__SpvOpCrossWorkgroupCastToPtrINTEL: SpvOp_ = 5938; +pub const SpvOp__SpvOpReadPipeBlockingINTEL: SpvOp_ = 5946; +pub const SpvOp__SpvOpWritePipeBlockingINTEL: SpvOp_ = 5947; +pub const SpvOp__SpvOpFPGARegINTEL: SpvOp_ = 5949; +pub const SpvOp__SpvOpRayQueryGetRayTMinKHR: SpvOp_ = 6016; +pub const SpvOp__SpvOpRayQueryGetRayFlagsKHR: SpvOp_ = 6017; +pub const SpvOp__SpvOpRayQueryGetIntersectionTKHR: SpvOp_ = 6018; +pub const SpvOp__SpvOpRayQueryGetIntersectionInstanceCustomIndexKHR: SpvOp_ = 6019; +pub const SpvOp__SpvOpRayQueryGetIntersectionInstanceIdKHR: SpvOp_ = 6020; +pub const SpvOp__SpvOpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR: SpvOp_ = + 6021; +pub const SpvOp__SpvOpRayQueryGetIntersectionGeometryIndexKHR: SpvOp_ = 6022; +pub const SpvOp__SpvOpRayQueryGetIntersectionPrimitiveIndexKHR: SpvOp_ = 6023; +pub const SpvOp__SpvOpRayQueryGetIntersectionBarycentricsKHR: SpvOp_ = 6024; +pub const SpvOp__SpvOpRayQueryGetIntersectionFrontFaceKHR: SpvOp_ = 6025; +pub const SpvOp__SpvOpRayQueryGetIntersectionCandidateAABBOpaqueKHR: SpvOp_ = 6026; +pub const SpvOp__SpvOpRayQueryGetIntersectionObjectRayDirectionKHR: SpvOp_ = 6027; +pub const SpvOp__SpvOpRayQueryGetIntersectionObjectRayOriginKHR: SpvOp_ = 6028; +pub const SpvOp__SpvOpRayQueryGetWorldRayDirectionKHR: SpvOp_ = 6029; +pub const SpvOp__SpvOpRayQueryGetWorldRayOriginKHR: SpvOp_ = 6030; +pub const SpvOp__SpvOpRayQueryGetIntersectionObjectToWorldKHR: SpvOp_ = 6031; +pub const SpvOp__SpvOpRayQueryGetIntersectionWorldToObjectKHR: SpvOp_ = 6032; +pub const SpvOp__SpvOpAtomicFAddEXT: SpvOp_ = 6035; +pub const SpvOp__SpvOpTypeBufferSurfaceINTEL: SpvOp_ = 6086; +pub const SpvOp__SpvOpTypeStructContinuedINTEL: SpvOp_ = 6090; +pub const SpvOp__SpvOpConstantCompositeContinuedINTEL: SpvOp_ = 6091; +pub const SpvOp__SpvOpSpecConstantCompositeContinuedINTEL: SpvOp_ = 6092; +pub const SpvOp__SpvOpCompositeConstructContinuedINTEL: SpvOp_ = 6096; +pub const SpvOp__SpvOpConvertFToBF16INTEL: SpvOp_ = 6116; +pub const SpvOp__SpvOpConvertBF16ToFINTEL: SpvOp_ = 6117; +pub const SpvOp__SpvOpControlBarrierArriveINTEL: SpvOp_ = 6142; +pub const SpvOp__SpvOpControlBarrierWaitINTEL: SpvOp_ = 6143; +pub const SpvOp__SpvOpArithmeticFenceEXT: SpvOp_ = 6145; +pub const SpvOp__SpvOpTaskSequenceCreateINTEL: SpvOp_ = 6163; +pub const SpvOp__SpvOpTaskSequenceAsyncINTEL: SpvOp_ = 6164; +pub const SpvOp__SpvOpTaskSequenceGetINTEL: SpvOp_ = 6165; +pub const SpvOp__SpvOpTaskSequenceReleaseINTEL: SpvOp_ = 6166; +pub const SpvOp__SpvOpTypeTaskSequenceINTEL: SpvOp_ = 6199; +pub const SpvOp__SpvOpSubgroupBlockPrefetchINTEL: SpvOp_ = 6221; +pub const SpvOp__SpvOpSubgroup2DBlockLoadINTEL: SpvOp_ = 6231; +pub const SpvOp__SpvOpSubgroup2DBlockLoadTransformINTEL: SpvOp_ = 6232; +pub const SpvOp__SpvOpSubgroup2DBlockLoadTransposeINTEL: SpvOp_ = 6233; +pub const SpvOp__SpvOpSubgroup2DBlockPrefetchINTEL: SpvOp_ = 6234; +pub const SpvOp__SpvOpSubgroup2DBlockStoreINTEL: SpvOp_ = 6235; +pub const SpvOp__SpvOpSubgroupMatrixMultiplyAccumulateINTEL: SpvOp_ = 6237; +pub const SpvOp__SpvOpBitwiseFunctionINTEL: SpvOp_ = 6242; +pub const SpvOp__SpvOpUntypedVariableLengthArrayINTEL: SpvOp_ = 6244; +pub const SpvOp__SpvOpConditionalExtensionINTEL: SpvOp_ = 6248; +pub const SpvOp__SpvOpConditionalEntryPointINTEL: SpvOp_ = 6249; +pub const SpvOp__SpvOpConditionalCapabilityINTEL: SpvOp_ = 6250; +pub const SpvOp__SpvOpSpecConstantTargetINTEL: SpvOp_ = 6251; +pub const SpvOp__SpvOpSpecConstantArchitectureINTEL: SpvOp_ = 6252; +pub const SpvOp__SpvOpSpecConstantCapabilitiesINTEL: SpvOp_ = 6253; +pub const SpvOp__SpvOpConditionalCopyObjectINTEL: SpvOp_ = 6254; +pub const SpvOp__SpvOpGroupIMulKHR: SpvOp_ = 6401; +pub const SpvOp__SpvOpGroupFMulKHR: SpvOp_ = 6402; +pub const SpvOp__SpvOpGroupBitwiseAndKHR: SpvOp_ = 6403; +pub const SpvOp__SpvOpGroupBitwiseOrKHR: SpvOp_ = 6404; +pub const SpvOp__SpvOpGroupBitwiseXorKHR: SpvOp_ = 6405; +pub const SpvOp__SpvOpGroupLogicalAndKHR: SpvOp_ = 6406; +pub const SpvOp__SpvOpGroupLogicalOrKHR: SpvOp_ = 6407; +pub const SpvOp__SpvOpGroupLogicalXorKHR: SpvOp_ = 6408; +pub const SpvOp__SpvOpRoundFToTF32INTEL: SpvOp_ = 6426; +pub const SpvOp__SpvOpMaskedGatherINTEL: SpvOp_ = 6428; +pub const SpvOp__SpvOpMaskedScatterINTEL: SpvOp_ = 6429; +pub const SpvOp__SpvOpConvertHandleToImageINTEL: SpvOp_ = 6529; +pub const SpvOp__SpvOpConvertHandleToSamplerINTEL: SpvOp_ = 6530; +pub const SpvOp__SpvOpConvertHandleToSampledImageINTEL: SpvOp_ = 6531; +pub const SpvOp__SpvOpMax: SpvOp_ = 2147483647; +pub type SpvOp_ = ::std::os::raw::c_int; +pub use self::SpvOp_ as SpvOp; +extern "C" { + pub fn spvc_get_version( + major: *mut ::std::os::raw::c_uint, + minor: *mut ::std::os::raw::c_uint, + patch: *mut ::std::os::raw::c_uint, + ); +} +extern "C" { + pub fn spvc_get_commit_revision_and_timestamp() -> *const ::std::os::raw::c_char; +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct spvc_context_s { + _unused: [u8; 0], +} +pub type spvc_context = *mut spvc_context_s; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct spvc_parsed_ir_s { + _unused: [u8; 0], +} +pub type spvc_parsed_ir = *mut spvc_parsed_ir_s; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct spvc_compiler_s { + _unused: [u8; 0], +} +pub type spvc_compiler = *mut spvc_compiler_s; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct spvc_compiler_options_s { + _unused: [u8; 0], +} +pub type spvc_compiler_options = *mut spvc_compiler_options_s; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct spvc_resources_s { + _unused: [u8; 0], +} +pub type spvc_resources = *mut spvc_resources_s; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct spvc_type_s { + _unused: [u8; 0], +} +pub type spvc_type = *const spvc_type_s; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct spvc_constant_s { + _unused: [u8; 0], +} +pub type spvc_constant = *mut spvc_constant_s; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct spvc_set_s { + _unused: [u8; 0], +} +pub type spvc_set = *const spvc_set_s; +pub type spvc_type_id = SpvId; +pub type spvc_variable_id = SpvId; +pub type spvc_constant_id = SpvId; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct spvc_reflected_resource { + pub id: spvc_variable_id, + pub base_type_id: spvc_type_id, + pub type_id: spvc_type_id, + pub name: *const ::std::os::raw::c_char, +} +#[test] +fn bindgen_test_layout_spvc_reflected_resource() { + const UNINIT: ::std::mem::MaybeUninit = + ::std::mem::MaybeUninit::uninit(); + let ptr = UNINIT.as_ptr(); + assert_eq!( + ::std::mem::size_of::(), + 24usize, + concat!("Size of: ", stringify!(spvc_reflected_resource)) + ); + assert_eq!( + ::std::mem::align_of::(), + 8usize, + concat!("Alignment of ", stringify!(spvc_reflected_resource)) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).id) as usize - ptr as usize }, + 0usize, + concat!( + "Offset of field: ", + stringify!(spvc_reflected_resource), + "::", + stringify!(id) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).base_type_id) as usize - ptr as usize }, + 4usize, + concat!( + "Offset of field: ", + stringify!(spvc_reflected_resource), + "::", + stringify!(base_type_id) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).type_id) as usize - ptr as usize }, + 8usize, + concat!( + "Offset of field: ", + stringify!(spvc_reflected_resource), + "::", + stringify!(type_id) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).name) as usize - ptr as usize }, + 16usize, + concat!( + "Offset of field: ", + stringify!(spvc_reflected_resource), + "::", + stringify!(name) + ) + ); +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct spvc_reflected_builtin_resource { + pub builtin: SpvBuiltIn, + pub value_type_id: spvc_type_id, + pub resource: spvc_reflected_resource, +} +#[test] +fn bindgen_test_layout_spvc_reflected_builtin_resource() { + const UNINIT: ::std::mem::MaybeUninit = + ::std::mem::MaybeUninit::uninit(); + let ptr = UNINIT.as_ptr(); + assert_eq!( + ::std::mem::size_of::(), + 32usize, + concat!("Size of: ", stringify!(spvc_reflected_builtin_resource)) + ); + assert_eq!( + ::std::mem::align_of::(), + 8usize, + concat!("Alignment of ", stringify!(spvc_reflected_builtin_resource)) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).builtin) as usize - ptr as usize }, + 0usize, + concat!( + "Offset of field: ", + stringify!(spvc_reflected_builtin_resource), + "::", + stringify!(builtin) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).value_type_id) as usize - ptr as usize }, + 4usize, + concat!( + "Offset of field: ", + stringify!(spvc_reflected_builtin_resource), + "::", + stringify!(value_type_id) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).resource) as usize - ptr as usize }, + 8usize, + concat!( + "Offset of field: ", + stringify!(spvc_reflected_builtin_resource), + "::", + stringify!(resource) + ) + ); +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct spvc_entry_point { + pub execution_model: SpvExecutionModel, + pub name: *const ::std::os::raw::c_char, +} +#[test] +fn bindgen_test_layout_spvc_entry_point() { + const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); + let ptr = UNINIT.as_ptr(); + assert_eq!( + ::std::mem::size_of::(), + 16usize, + concat!("Size of: ", stringify!(spvc_entry_point)) + ); + assert_eq!( + ::std::mem::align_of::(), + 8usize, + concat!("Alignment of ", stringify!(spvc_entry_point)) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).execution_model) as usize - ptr as usize }, + 0usize, + concat!( + "Offset of field: ", + stringify!(spvc_entry_point), + "::", + stringify!(execution_model) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).name) as usize - ptr as usize }, + 8usize, + concat!( + "Offset of field: ", + stringify!(spvc_entry_point), + "::", + stringify!(name) + ) + ); +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct spvc_combined_image_sampler { + pub combined_id: spvc_variable_id, + pub image_id: spvc_variable_id, + pub sampler_id: spvc_variable_id, +} +#[test] +fn bindgen_test_layout_spvc_combined_image_sampler() { + const UNINIT: ::std::mem::MaybeUninit = + ::std::mem::MaybeUninit::uninit(); + let ptr = UNINIT.as_ptr(); + assert_eq!( + ::std::mem::size_of::(), + 12usize, + concat!("Size of: ", stringify!(spvc_combined_image_sampler)) + ); + assert_eq!( + ::std::mem::align_of::(), + 4usize, + concat!("Alignment of ", stringify!(spvc_combined_image_sampler)) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).combined_id) as usize - ptr as usize }, + 0usize, + concat!( + "Offset of field: ", + stringify!(spvc_combined_image_sampler), + "::", + stringify!(combined_id) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).image_id) as usize - ptr as usize }, + 4usize, + concat!( + "Offset of field: ", + stringify!(spvc_combined_image_sampler), + "::", + stringify!(image_id) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).sampler_id) as usize - ptr as usize }, + 8usize, + concat!( + "Offset of field: ", + stringify!(spvc_combined_image_sampler), + "::", + stringify!(sampler_id) + ) + ); +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct spvc_specialization_constant { + pub id: spvc_constant_id, + pub constant_id: ::std::os::raw::c_uint, +} +#[test] +fn bindgen_test_layout_spvc_specialization_constant() { + const UNINIT: ::std::mem::MaybeUninit = + ::std::mem::MaybeUninit::uninit(); + let ptr = UNINIT.as_ptr(); + assert_eq!( + ::std::mem::size_of::(), + 8usize, + concat!("Size of: ", stringify!(spvc_specialization_constant)) + ); + assert_eq!( + ::std::mem::align_of::(), + 4usize, + concat!("Alignment of ", stringify!(spvc_specialization_constant)) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).id) as usize - ptr as usize }, + 0usize, + concat!( + "Offset of field: ", + stringify!(spvc_specialization_constant), + "::", + stringify!(id) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).constant_id) as usize - ptr as usize }, + 4usize, + concat!( + "Offset of field: ", + stringify!(spvc_specialization_constant), + "::", + stringify!(constant_id) + ) + ); +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct spvc_buffer_range { + pub index: ::std::os::raw::c_uint, + pub offset: usize, + pub range: usize, +} +#[test] +fn bindgen_test_layout_spvc_buffer_range() { + const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); + let ptr = UNINIT.as_ptr(); + assert_eq!( + ::std::mem::size_of::(), + 24usize, + concat!("Size of: ", stringify!(spvc_buffer_range)) + ); + assert_eq!( + ::std::mem::align_of::(), + 8usize, + concat!("Alignment of ", stringify!(spvc_buffer_range)) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).index) as usize - ptr as usize }, + 0usize, + concat!( + "Offset of field: ", + stringify!(spvc_buffer_range), + "::", + stringify!(index) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).offset) as usize - ptr as usize }, + 8usize, + concat!( + "Offset of field: ", + stringify!(spvc_buffer_range), + "::", + stringify!(offset) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).range) as usize - ptr as usize }, + 16usize, + concat!( + "Offset of field: ", + stringify!(spvc_buffer_range), + "::", + stringify!(range) + ) + ); +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct spvc_hlsl_root_constants { + pub start: ::std::os::raw::c_uint, + pub end: ::std::os::raw::c_uint, + pub binding: ::std::os::raw::c_uint, + pub space: ::std::os::raw::c_uint, +} +#[test] +fn bindgen_test_layout_spvc_hlsl_root_constants() { + const UNINIT: ::std::mem::MaybeUninit = + ::std::mem::MaybeUninit::uninit(); + let ptr = UNINIT.as_ptr(); + assert_eq!( + ::std::mem::size_of::(), + 16usize, + concat!("Size of: ", stringify!(spvc_hlsl_root_constants)) + ); + assert_eq!( + ::std::mem::align_of::(), + 4usize, + concat!("Alignment of ", stringify!(spvc_hlsl_root_constants)) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).start) as usize - ptr as usize }, + 0usize, + concat!( + "Offset of field: ", + stringify!(spvc_hlsl_root_constants), + "::", + stringify!(start) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).end) as usize - ptr as usize }, + 4usize, + concat!( + "Offset of field: ", + stringify!(spvc_hlsl_root_constants), + "::", + stringify!(end) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).binding) as usize - ptr as usize }, + 8usize, + concat!( + "Offset of field: ", + stringify!(spvc_hlsl_root_constants), + "::", + stringify!(binding) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).space) as usize - ptr as usize }, + 12usize, + concat!( + "Offset of field: ", + stringify!(spvc_hlsl_root_constants), + "::", + stringify!(space) + ) + ); +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct spvc_hlsl_vertex_attribute_remap { + pub location: ::std::os::raw::c_uint, + pub semantic: *const ::std::os::raw::c_char, +} +#[test] +fn bindgen_test_layout_spvc_hlsl_vertex_attribute_remap() { + const UNINIT: ::std::mem::MaybeUninit = + ::std::mem::MaybeUninit::uninit(); + let ptr = UNINIT.as_ptr(); + assert_eq!( + ::std::mem::size_of::(), + 16usize, + concat!("Size of: ", stringify!(spvc_hlsl_vertex_attribute_remap)) + ); + assert_eq!( + ::std::mem::align_of::(), + 8usize, + concat!( + "Alignment of ", + stringify!(spvc_hlsl_vertex_attribute_remap) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).location) as usize - ptr as usize }, + 0usize, + concat!( + "Offset of field: ", + stringify!(spvc_hlsl_vertex_attribute_remap), + "::", + stringify!(location) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).semantic) as usize - ptr as usize }, + 8usize, + concat!( + "Offset of field: ", + stringify!(spvc_hlsl_vertex_attribute_remap), + "::", + stringify!(semantic) + ) + ); +} +pub type spvc_bool = ::std::os::raw::c_uchar; +pub const spvc_result_SPVC_SUCCESS: spvc_result = 0; +pub const spvc_result_SPVC_ERROR_INVALID_SPIRV: spvc_result = -1; +pub const spvc_result_SPVC_ERROR_UNSUPPORTED_SPIRV: spvc_result = -2; +pub const spvc_result_SPVC_ERROR_OUT_OF_MEMORY: spvc_result = -3; +pub const spvc_result_SPVC_ERROR_INVALID_ARGUMENT: spvc_result = -4; +pub const spvc_result_SPVC_ERROR_INT_MAX: spvc_result = 2147483647; +pub type spvc_result = ::std::os::raw::c_int; +pub const spvc_capture_mode_SPVC_CAPTURE_MODE_COPY: spvc_capture_mode = 0; +pub const spvc_capture_mode_SPVC_CAPTURE_MODE_TAKE_OWNERSHIP: spvc_capture_mode = 1; +pub const spvc_capture_mode_SPVC_CAPTURE_MODE_INT_MAX: spvc_capture_mode = 2147483647; +pub type spvc_capture_mode = ::std::os::raw::c_int; +pub const spvc_backend_SPVC_BACKEND_NONE: spvc_backend = 0; +pub const spvc_backend_SPVC_BACKEND_GLSL: spvc_backend = 1; +pub const spvc_backend_SPVC_BACKEND_HLSL: spvc_backend = 2; +pub const spvc_backend_SPVC_BACKEND_MSL: spvc_backend = 3; +pub const spvc_backend_SPVC_BACKEND_CPP: spvc_backend = 4; +pub const spvc_backend_SPVC_BACKEND_JSON: spvc_backend = 5; +pub const spvc_backend_SPVC_BACKEND_INT_MAX: spvc_backend = 2147483647; +pub type spvc_backend = ::std::os::raw::c_int; +pub const spvc_resource_type_SPVC_RESOURCE_TYPE_UNKNOWN: spvc_resource_type = 0; +pub const spvc_resource_type_SPVC_RESOURCE_TYPE_UNIFORM_BUFFER: spvc_resource_type = 1; +pub const spvc_resource_type_SPVC_RESOURCE_TYPE_STORAGE_BUFFER: spvc_resource_type = 2; +pub const spvc_resource_type_SPVC_RESOURCE_TYPE_STAGE_INPUT: spvc_resource_type = 3; +pub const spvc_resource_type_SPVC_RESOURCE_TYPE_STAGE_OUTPUT: spvc_resource_type = 4; +pub const spvc_resource_type_SPVC_RESOURCE_TYPE_SUBPASS_INPUT: spvc_resource_type = 5; +pub const spvc_resource_type_SPVC_RESOURCE_TYPE_STORAGE_IMAGE: spvc_resource_type = 6; +pub const spvc_resource_type_SPVC_RESOURCE_TYPE_SAMPLED_IMAGE: spvc_resource_type = 7; +pub const spvc_resource_type_SPVC_RESOURCE_TYPE_ATOMIC_COUNTER: spvc_resource_type = 8; +pub const spvc_resource_type_SPVC_RESOURCE_TYPE_PUSH_CONSTANT: spvc_resource_type = 9; +pub const spvc_resource_type_SPVC_RESOURCE_TYPE_SEPARATE_IMAGE: spvc_resource_type = 10; +pub const spvc_resource_type_SPVC_RESOURCE_TYPE_SEPARATE_SAMPLERS: spvc_resource_type = 11; +pub const spvc_resource_type_SPVC_RESOURCE_TYPE_ACCELERATION_STRUCTURE: spvc_resource_type = 12; +pub const spvc_resource_type_SPVC_RESOURCE_TYPE_RAY_QUERY: spvc_resource_type = 13; +pub const spvc_resource_type_SPVC_RESOURCE_TYPE_SHADER_RECORD_BUFFER: spvc_resource_type = 14; +pub const spvc_resource_type_SPVC_RESOURCE_TYPE_GL_PLAIN_UNIFORM: spvc_resource_type = 15; +pub const spvc_resource_type_SPVC_RESOURCE_TYPE_TENSOR: spvc_resource_type = 16; +pub const spvc_resource_type_SPVC_RESOURCE_TYPE_INT_MAX: spvc_resource_type = 2147483647; +pub type spvc_resource_type = ::std::os::raw::c_int; +pub const spvc_builtin_resource_type_SPVC_BUILTIN_RESOURCE_TYPE_UNKNOWN: + spvc_builtin_resource_type = 0; +pub const spvc_builtin_resource_type_SPVC_BUILTIN_RESOURCE_TYPE_STAGE_INPUT: + spvc_builtin_resource_type = 1; +pub const spvc_builtin_resource_type_SPVC_BUILTIN_RESOURCE_TYPE_STAGE_OUTPUT: + spvc_builtin_resource_type = 2; +pub const spvc_builtin_resource_type_SPVC_BUILTIN_RESOURCE_TYPE_INT_MAX: + spvc_builtin_resource_type = 2147483647; +pub type spvc_builtin_resource_type = ::std::os::raw::c_int; +pub const spvc_basetype_SPVC_BASETYPE_UNKNOWN: spvc_basetype = 0; +pub const spvc_basetype_SPVC_BASETYPE_VOID: spvc_basetype = 1; +pub const spvc_basetype_SPVC_BASETYPE_BOOLEAN: spvc_basetype = 2; +pub const spvc_basetype_SPVC_BASETYPE_INT8: spvc_basetype = 3; +pub const spvc_basetype_SPVC_BASETYPE_UINT8: spvc_basetype = 4; +pub const spvc_basetype_SPVC_BASETYPE_INT16: spvc_basetype = 5; +pub const spvc_basetype_SPVC_BASETYPE_UINT16: spvc_basetype = 6; +pub const spvc_basetype_SPVC_BASETYPE_INT32: spvc_basetype = 7; +pub const spvc_basetype_SPVC_BASETYPE_UINT32: spvc_basetype = 8; +pub const spvc_basetype_SPVC_BASETYPE_INT64: spvc_basetype = 9; +pub const spvc_basetype_SPVC_BASETYPE_UINT64: spvc_basetype = 10; +pub const spvc_basetype_SPVC_BASETYPE_ATOMIC_COUNTER: spvc_basetype = 11; +pub const spvc_basetype_SPVC_BASETYPE_FP16: spvc_basetype = 12; +pub const spvc_basetype_SPVC_BASETYPE_FP32: spvc_basetype = 13; +pub const spvc_basetype_SPVC_BASETYPE_FP64: spvc_basetype = 14; +pub const spvc_basetype_SPVC_BASETYPE_STRUCT: spvc_basetype = 15; +pub const spvc_basetype_SPVC_BASETYPE_IMAGE: spvc_basetype = 16; +pub const spvc_basetype_SPVC_BASETYPE_SAMPLED_IMAGE: spvc_basetype = 17; +pub const spvc_basetype_SPVC_BASETYPE_SAMPLER: spvc_basetype = 18; +pub const spvc_basetype_SPVC_BASETYPE_ACCELERATION_STRUCTURE: spvc_basetype = 19; +pub const spvc_basetype_SPVC_BASETYPE_INT_MAX: spvc_basetype = 2147483647; +pub type spvc_basetype = ::std::os::raw::c_int; +pub const spvc_msl_platform_SPVC_MSL_PLATFORM_IOS: spvc_msl_platform = 0; +pub const spvc_msl_platform_SPVC_MSL_PLATFORM_MACOS: spvc_msl_platform = 1; +pub const spvc_msl_platform_SPVC_MSL_PLATFORM_MAX_INT: spvc_msl_platform = 2147483647; +pub type spvc_msl_platform = ::std::os::raw::c_int; +pub const spvc_msl_index_type_SPVC_MSL_INDEX_TYPE_NONE: spvc_msl_index_type = 0; +pub const spvc_msl_index_type_SPVC_MSL_INDEX_TYPE_UINT16: spvc_msl_index_type = 1; +pub const spvc_msl_index_type_SPVC_MSL_INDEX_TYPE_UINT32: spvc_msl_index_type = 2; +pub const spvc_msl_index_type_SPVC_MSL_INDEX_TYPE_MAX_INT: spvc_msl_index_type = 2147483647; +pub type spvc_msl_index_type = ::std::os::raw::c_int; +pub const spvc_msl_shader_variable_format_SPVC_MSL_SHADER_VARIABLE_FORMAT_OTHER: + spvc_msl_shader_variable_format = 0; +pub const spvc_msl_shader_variable_format_SPVC_MSL_SHADER_VARIABLE_FORMAT_UINT8: + spvc_msl_shader_variable_format = 1; +pub const spvc_msl_shader_variable_format_SPVC_MSL_SHADER_VARIABLE_FORMAT_UINT16: + spvc_msl_shader_variable_format = 2; +pub const spvc_msl_shader_variable_format_SPVC_MSL_SHADER_VARIABLE_FORMAT_ANY16: + spvc_msl_shader_variable_format = 3; +pub const spvc_msl_shader_variable_format_SPVC_MSL_SHADER_VARIABLE_FORMAT_ANY32: + spvc_msl_shader_variable_format = 4; +pub const spvc_msl_shader_variable_format_SPVC_MSL_VERTEX_FORMAT_OTHER: + spvc_msl_shader_variable_format = 0; +pub const spvc_msl_shader_variable_format_SPVC_MSL_VERTEX_FORMAT_UINT8: + spvc_msl_shader_variable_format = 1; +pub const spvc_msl_shader_variable_format_SPVC_MSL_VERTEX_FORMAT_UINT16: + spvc_msl_shader_variable_format = 2; +pub const spvc_msl_shader_variable_format_SPVC_MSL_SHADER_INPUT_FORMAT_OTHER: + spvc_msl_shader_variable_format = 0; +pub const spvc_msl_shader_variable_format_SPVC_MSL_SHADER_INPUT_FORMAT_UINT8: + spvc_msl_shader_variable_format = 1; +pub const spvc_msl_shader_variable_format_SPVC_MSL_SHADER_INPUT_FORMAT_UINT16: + spvc_msl_shader_variable_format = 2; +pub const spvc_msl_shader_variable_format_SPVC_MSL_SHADER_INPUT_FORMAT_ANY16: + spvc_msl_shader_variable_format = 3; +pub const spvc_msl_shader_variable_format_SPVC_MSL_SHADER_INPUT_FORMAT_ANY32: + spvc_msl_shader_variable_format = 4; +pub const spvc_msl_shader_variable_format_SPVC_MSL_SHADER_INPUT_FORMAT_INT_MAX: + spvc_msl_shader_variable_format = 2147483647; +pub type spvc_msl_shader_variable_format = ::std::os::raw::c_int; +pub use self::spvc_msl_shader_variable_format as spvc_msl_shader_input_format; +pub use self::spvc_msl_shader_variable_format as spvc_msl_vertex_format; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct spvc_msl_vertex_attribute { + pub location: ::std::os::raw::c_uint, + pub msl_buffer: ::std::os::raw::c_uint, + pub msl_offset: ::std::os::raw::c_uint, + pub msl_stride: ::std::os::raw::c_uint, + pub per_instance: spvc_bool, + pub format: spvc_msl_vertex_format, + pub builtin: SpvBuiltIn, +} +#[test] +fn bindgen_test_layout_spvc_msl_vertex_attribute() { + const UNINIT: ::std::mem::MaybeUninit = + ::std::mem::MaybeUninit::uninit(); + let ptr = UNINIT.as_ptr(); + assert_eq!( + ::std::mem::size_of::(), + 28usize, + concat!("Size of: ", stringify!(spvc_msl_vertex_attribute)) + ); + assert_eq!( + ::std::mem::align_of::(), + 4usize, + concat!("Alignment of ", stringify!(spvc_msl_vertex_attribute)) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).location) as usize - ptr as usize }, + 0usize, + concat!( + "Offset of field: ", + stringify!(spvc_msl_vertex_attribute), + "::", + stringify!(location) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).msl_buffer) as usize - ptr as usize }, + 4usize, + concat!( + "Offset of field: ", + stringify!(spvc_msl_vertex_attribute), + "::", + stringify!(msl_buffer) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).msl_offset) as usize - ptr as usize }, + 8usize, + concat!( + "Offset of field: ", + stringify!(spvc_msl_vertex_attribute), + "::", + stringify!(msl_offset) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).msl_stride) as usize - ptr as usize }, + 12usize, + concat!( + "Offset of field: ", + stringify!(spvc_msl_vertex_attribute), + "::", + stringify!(msl_stride) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).per_instance) as usize - ptr as usize }, + 16usize, + concat!( + "Offset of field: ", + stringify!(spvc_msl_vertex_attribute), + "::", + stringify!(per_instance) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).format) as usize - ptr as usize }, + 20usize, + concat!( + "Offset of field: ", + stringify!(spvc_msl_vertex_attribute), + "::", + stringify!(format) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).builtin) as usize - ptr as usize }, + 24usize, + concat!( + "Offset of field: ", + stringify!(spvc_msl_vertex_attribute), + "::", + stringify!(builtin) + ) + ); +} +extern "C" { + pub fn spvc_msl_vertex_attribute_init(attr: *mut spvc_msl_vertex_attribute); +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct spvc_msl_shader_interface_var { + pub location: ::std::os::raw::c_uint, + pub format: spvc_msl_vertex_format, + pub builtin: SpvBuiltIn, + pub vecsize: ::std::os::raw::c_uint, +} +#[test] +fn bindgen_test_layout_spvc_msl_shader_interface_var() { + const UNINIT: ::std::mem::MaybeUninit = + ::std::mem::MaybeUninit::uninit(); + let ptr = UNINIT.as_ptr(); + assert_eq!( + ::std::mem::size_of::(), + 16usize, + concat!("Size of: ", stringify!(spvc_msl_shader_interface_var)) + ); + assert_eq!( + ::std::mem::align_of::(), + 4usize, + concat!("Alignment of ", stringify!(spvc_msl_shader_interface_var)) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).location) as usize - ptr as usize }, + 0usize, + concat!( + "Offset of field: ", + stringify!(spvc_msl_shader_interface_var), + "::", + stringify!(location) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).format) as usize - ptr as usize }, + 4usize, + concat!( + "Offset of field: ", + stringify!(spvc_msl_shader_interface_var), + "::", + stringify!(format) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).builtin) as usize - ptr as usize }, + 8usize, + concat!( + "Offset of field: ", + stringify!(spvc_msl_shader_interface_var), + "::", + stringify!(builtin) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).vecsize) as usize - ptr as usize }, + 12usize, + concat!( + "Offset of field: ", + stringify!(spvc_msl_shader_interface_var), + "::", + stringify!(vecsize) + ) + ); +} +pub type spvc_msl_shader_input = spvc_msl_shader_interface_var; +extern "C" { + pub fn spvc_msl_shader_interface_var_init(var: *mut spvc_msl_shader_interface_var); +} +extern "C" { + pub fn spvc_msl_shader_input_init(input: *mut spvc_msl_shader_input); +} +pub const spvc_msl_shader_variable_rate_SPVC_MSL_SHADER_VARIABLE_RATE_PER_VERTEX: + spvc_msl_shader_variable_rate = 0; +pub const spvc_msl_shader_variable_rate_SPVC_MSL_SHADER_VARIABLE_RATE_PER_PRIMITIVE: + spvc_msl_shader_variable_rate = 1; +pub const spvc_msl_shader_variable_rate_SPVC_MSL_SHADER_VARIABLE_RATE_PER_PATCH: + spvc_msl_shader_variable_rate = 2; +pub const spvc_msl_shader_variable_rate_SPVC_MSL_SHADER_VARIABLE_RATE_INT_MAX: + spvc_msl_shader_variable_rate = 2147483647; +pub type spvc_msl_shader_variable_rate = ::std::os::raw::c_int; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct spvc_msl_shader_interface_var_2 { + pub location: ::std::os::raw::c_uint, + pub format: spvc_msl_shader_variable_format, + pub builtin: SpvBuiltIn, + pub vecsize: ::std::os::raw::c_uint, + pub rate: spvc_msl_shader_variable_rate, +} +#[test] +fn bindgen_test_layout_spvc_msl_shader_interface_var_2() { + const UNINIT: ::std::mem::MaybeUninit = + ::std::mem::MaybeUninit::uninit(); + let ptr = UNINIT.as_ptr(); + assert_eq!( + ::std::mem::size_of::(), + 20usize, + concat!("Size of: ", stringify!(spvc_msl_shader_interface_var_2)) + ); + assert_eq!( + ::std::mem::align_of::(), + 4usize, + concat!("Alignment of ", stringify!(spvc_msl_shader_interface_var_2)) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).location) as usize - ptr as usize }, + 0usize, + concat!( + "Offset of field: ", + stringify!(spvc_msl_shader_interface_var_2), + "::", + stringify!(location) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).format) as usize - ptr as usize }, + 4usize, + concat!( + "Offset of field: ", + stringify!(spvc_msl_shader_interface_var_2), + "::", + stringify!(format) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).builtin) as usize - ptr as usize }, + 8usize, + concat!( + "Offset of field: ", + stringify!(spvc_msl_shader_interface_var_2), + "::", + stringify!(builtin) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).vecsize) as usize - ptr as usize }, + 12usize, + concat!( + "Offset of field: ", + stringify!(spvc_msl_shader_interface_var_2), + "::", + stringify!(vecsize) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).rate) as usize - ptr as usize }, + 16usize, + concat!( + "Offset of field: ", + stringify!(spvc_msl_shader_interface_var_2), + "::", + stringify!(rate) + ) + ); +} +extern "C" { + pub fn spvc_msl_shader_interface_var_init_2(var: *mut spvc_msl_shader_interface_var_2); +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct spvc_msl_resource_binding { + pub stage: SpvExecutionModel, + pub desc_set: ::std::os::raw::c_uint, + pub binding: ::std::os::raw::c_uint, + pub msl_buffer: ::std::os::raw::c_uint, + pub msl_texture: ::std::os::raw::c_uint, + pub msl_sampler: ::std::os::raw::c_uint, +} +#[test] +fn bindgen_test_layout_spvc_msl_resource_binding() { + const UNINIT: ::std::mem::MaybeUninit = + ::std::mem::MaybeUninit::uninit(); + let ptr = UNINIT.as_ptr(); + assert_eq!( + ::std::mem::size_of::(), + 24usize, + concat!("Size of: ", stringify!(spvc_msl_resource_binding)) + ); + assert_eq!( + ::std::mem::align_of::(), + 4usize, + concat!("Alignment of ", stringify!(spvc_msl_resource_binding)) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).stage) as usize - ptr as usize }, + 0usize, + concat!( + "Offset of field: ", + stringify!(spvc_msl_resource_binding), + "::", + stringify!(stage) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).desc_set) as usize - ptr as usize }, + 4usize, + concat!( + "Offset of field: ", + stringify!(spvc_msl_resource_binding), + "::", + stringify!(desc_set) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).binding) as usize - ptr as usize }, + 8usize, + concat!( + "Offset of field: ", + stringify!(spvc_msl_resource_binding), + "::", + stringify!(binding) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).msl_buffer) as usize - ptr as usize }, + 12usize, + concat!( + "Offset of field: ", + stringify!(spvc_msl_resource_binding), + "::", + stringify!(msl_buffer) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).msl_texture) as usize - ptr as usize }, + 16usize, + concat!( + "Offset of field: ", + stringify!(spvc_msl_resource_binding), + "::", + stringify!(msl_texture) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).msl_sampler) as usize - ptr as usize }, + 20usize, + concat!( + "Offset of field: ", + stringify!(spvc_msl_resource_binding), + "::", + stringify!(msl_sampler) + ) + ); +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct spvc_msl_resource_binding_2 { + pub stage: SpvExecutionModel, + pub desc_set: ::std::os::raw::c_uint, + pub binding: ::std::os::raw::c_uint, + pub count: ::std::os::raw::c_uint, + pub msl_buffer: ::std::os::raw::c_uint, + pub msl_texture: ::std::os::raw::c_uint, + pub msl_sampler: ::std::os::raw::c_uint, +} +#[test] +fn bindgen_test_layout_spvc_msl_resource_binding_2() { + const UNINIT: ::std::mem::MaybeUninit = + ::std::mem::MaybeUninit::uninit(); + let ptr = UNINIT.as_ptr(); + assert_eq!( + ::std::mem::size_of::(), + 28usize, + concat!("Size of: ", stringify!(spvc_msl_resource_binding_2)) + ); + assert_eq!( + ::std::mem::align_of::(), + 4usize, + concat!("Alignment of ", stringify!(spvc_msl_resource_binding_2)) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).stage) as usize - ptr as usize }, + 0usize, + concat!( + "Offset of field: ", + stringify!(spvc_msl_resource_binding_2), + "::", + stringify!(stage) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).desc_set) as usize - ptr as usize }, + 4usize, + concat!( + "Offset of field: ", + stringify!(spvc_msl_resource_binding_2), + "::", + stringify!(desc_set) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).binding) as usize - ptr as usize }, + 8usize, + concat!( + "Offset of field: ", + stringify!(spvc_msl_resource_binding_2), + "::", + stringify!(binding) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).count) as usize - ptr as usize }, + 12usize, + concat!( + "Offset of field: ", + stringify!(spvc_msl_resource_binding_2), + "::", + stringify!(count) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).msl_buffer) as usize - ptr as usize }, + 16usize, + concat!( + "Offset of field: ", + stringify!(spvc_msl_resource_binding_2), + "::", + stringify!(msl_buffer) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).msl_texture) as usize - ptr as usize }, + 20usize, + concat!( + "Offset of field: ", + stringify!(spvc_msl_resource_binding_2), + "::", + stringify!(msl_texture) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).msl_sampler) as usize - ptr as usize }, + 24usize, + concat!( + "Offset of field: ", + stringify!(spvc_msl_resource_binding_2), + "::", + stringify!(msl_sampler) + ) + ); +} +extern "C" { + pub fn spvc_msl_resource_binding_init(binding: *mut spvc_msl_resource_binding); +} +extern "C" { + pub fn spvc_msl_resource_binding_init_2(binding: *mut spvc_msl_resource_binding_2); +} +extern "C" { + pub fn spvc_msl_get_aux_buffer_struct_version() -> ::std::os::raw::c_uint; +} +pub const spvc_msl_sampler_coord_SPVC_MSL_SAMPLER_COORD_NORMALIZED: spvc_msl_sampler_coord = 0; +pub const spvc_msl_sampler_coord_SPVC_MSL_SAMPLER_COORD_PIXEL: spvc_msl_sampler_coord = 1; +pub const spvc_msl_sampler_coord_SPVC_MSL_SAMPLER_INT_MAX: spvc_msl_sampler_coord = 2147483647; +pub type spvc_msl_sampler_coord = ::std::os::raw::c_int; +pub const spvc_msl_sampler_filter_SPVC_MSL_SAMPLER_FILTER_NEAREST: spvc_msl_sampler_filter = 0; +pub const spvc_msl_sampler_filter_SPVC_MSL_SAMPLER_FILTER_LINEAR: spvc_msl_sampler_filter = 1; +pub const spvc_msl_sampler_filter_SPVC_MSL_SAMPLER_FILTER_INT_MAX: spvc_msl_sampler_filter = + 2147483647; +pub type spvc_msl_sampler_filter = ::std::os::raw::c_int; +pub const spvc_msl_sampler_mip_filter_SPVC_MSL_SAMPLER_MIP_FILTER_NONE: + spvc_msl_sampler_mip_filter = 0; +pub const spvc_msl_sampler_mip_filter_SPVC_MSL_SAMPLER_MIP_FILTER_NEAREST: + spvc_msl_sampler_mip_filter = 1; +pub const spvc_msl_sampler_mip_filter_SPVC_MSL_SAMPLER_MIP_FILTER_LINEAR: + spvc_msl_sampler_mip_filter = 2; +pub const spvc_msl_sampler_mip_filter_SPVC_MSL_SAMPLER_MIP_FILTER_INT_MAX: + spvc_msl_sampler_mip_filter = 2147483647; +pub type spvc_msl_sampler_mip_filter = ::std::os::raw::c_int; +pub const spvc_msl_sampler_address_SPVC_MSL_SAMPLER_ADDRESS_CLAMP_TO_ZERO: + spvc_msl_sampler_address = 0; +pub const spvc_msl_sampler_address_SPVC_MSL_SAMPLER_ADDRESS_CLAMP_TO_EDGE: + spvc_msl_sampler_address = 1; +pub const spvc_msl_sampler_address_SPVC_MSL_SAMPLER_ADDRESS_CLAMP_TO_BORDER: + spvc_msl_sampler_address = 2; +pub const spvc_msl_sampler_address_SPVC_MSL_SAMPLER_ADDRESS_REPEAT: spvc_msl_sampler_address = 3; +pub const spvc_msl_sampler_address_SPVC_MSL_SAMPLER_ADDRESS_MIRRORED_REPEAT: + spvc_msl_sampler_address = 4; +pub const spvc_msl_sampler_address_SPVC_MSL_SAMPLER_ADDRESS_INT_MAX: spvc_msl_sampler_address = + 2147483647; +pub type spvc_msl_sampler_address = ::std::os::raw::c_int; +pub const spvc_msl_sampler_compare_func_SPVC_MSL_SAMPLER_COMPARE_FUNC_NEVER: + spvc_msl_sampler_compare_func = 0; +pub const spvc_msl_sampler_compare_func_SPVC_MSL_SAMPLER_COMPARE_FUNC_LESS: + spvc_msl_sampler_compare_func = 1; +pub const spvc_msl_sampler_compare_func_SPVC_MSL_SAMPLER_COMPARE_FUNC_LESS_EQUAL: + spvc_msl_sampler_compare_func = 2; +pub const spvc_msl_sampler_compare_func_SPVC_MSL_SAMPLER_COMPARE_FUNC_GREATER: + spvc_msl_sampler_compare_func = 3; +pub const spvc_msl_sampler_compare_func_SPVC_MSL_SAMPLER_COMPARE_FUNC_GREATER_EQUAL: + spvc_msl_sampler_compare_func = 4; +pub const spvc_msl_sampler_compare_func_SPVC_MSL_SAMPLER_COMPARE_FUNC_EQUAL: + spvc_msl_sampler_compare_func = 5; +pub const spvc_msl_sampler_compare_func_SPVC_MSL_SAMPLER_COMPARE_FUNC_NOT_EQUAL: + spvc_msl_sampler_compare_func = 6; +pub const spvc_msl_sampler_compare_func_SPVC_MSL_SAMPLER_COMPARE_FUNC_ALWAYS: + spvc_msl_sampler_compare_func = 7; +pub const spvc_msl_sampler_compare_func_SPVC_MSL_SAMPLER_COMPARE_FUNC_INT_MAX: + spvc_msl_sampler_compare_func = 2147483647; +pub type spvc_msl_sampler_compare_func = ::std::os::raw::c_int; +pub const spvc_msl_sampler_border_color_SPVC_MSL_SAMPLER_BORDER_COLOR_TRANSPARENT_BLACK: + spvc_msl_sampler_border_color = 0; +pub const spvc_msl_sampler_border_color_SPVC_MSL_SAMPLER_BORDER_COLOR_OPAQUE_BLACK: + spvc_msl_sampler_border_color = 1; +pub const spvc_msl_sampler_border_color_SPVC_MSL_SAMPLER_BORDER_COLOR_OPAQUE_WHITE: + spvc_msl_sampler_border_color = 2; +pub const spvc_msl_sampler_border_color_SPVC_MSL_SAMPLER_BORDER_COLOR_INT_MAX: + spvc_msl_sampler_border_color = 2147483647; +pub type spvc_msl_sampler_border_color = ::std::os::raw::c_int; +pub const spvc_msl_format_resolution_SPVC_MSL_FORMAT_RESOLUTION_444: spvc_msl_format_resolution = 0; +pub const spvc_msl_format_resolution_SPVC_MSL_FORMAT_RESOLUTION_422: spvc_msl_format_resolution = 1; +pub const spvc_msl_format_resolution_SPVC_MSL_FORMAT_RESOLUTION_420: spvc_msl_format_resolution = 2; +pub const spvc_msl_format_resolution_SPVC_MSL_FORMAT_RESOLUTION_INT_MAX: + spvc_msl_format_resolution = 2147483647; +pub type spvc_msl_format_resolution = ::std::os::raw::c_int; +pub const spvc_msl_chroma_location_SPVC_MSL_CHROMA_LOCATION_COSITED_EVEN: spvc_msl_chroma_location = + 0; +pub const spvc_msl_chroma_location_SPVC_MSL_CHROMA_LOCATION_MIDPOINT: spvc_msl_chroma_location = 1; +pub const spvc_msl_chroma_location_SPVC_MSL_CHROMA_LOCATION_INT_MAX: spvc_msl_chroma_location = + 2147483647; +pub type spvc_msl_chroma_location = ::std::os::raw::c_int; +pub const spvc_msl_component_swizzle_SPVC_MSL_COMPONENT_SWIZZLE_IDENTITY: + spvc_msl_component_swizzle = 0; +pub const spvc_msl_component_swizzle_SPVC_MSL_COMPONENT_SWIZZLE_ZERO: spvc_msl_component_swizzle = + 1; +pub const spvc_msl_component_swizzle_SPVC_MSL_COMPONENT_SWIZZLE_ONE: spvc_msl_component_swizzle = 2; +pub const spvc_msl_component_swizzle_SPVC_MSL_COMPONENT_SWIZZLE_R: spvc_msl_component_swizzle = 3; +pub const spvc_msl_component_swizzle_SPVC_MSL_COMPONENT_SWIZZLE_G: spvc_msl_component_swizzle = 4; +pub const spvc_msl_component_swizzle_SPVC_MSL_COMPONENT_SWIZZLE_B: spvc_msl_component_swizzle = 5; +pub const spvc_msl_component_swizzle_SPVC_MSL_COMPONENT_SWIZZLE_A: spvc_msl_component_swizzle = 6; +pub const spvc_msl_component_swizzle_SPVC_MSL_COMPONENT_SWIZZLE_INT_MAX: + spvc_msl_component_swizzle = 2147483647; +pub type spvc_msl_component_swizzle = ::std::os::raw::c_int; +pub const spvc_msl_sampler_ycbcr_model_conversion_SPVC_MSL_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY : spvc_msl_sampler_ycbcr_model_conversion = 0 ; +pub const spvc_msl_sampler_ycbcr_model_conversion_SPVC_MSL_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_IDENTITY : spvc_msl_sampler_ycbcr_model_conversion = 1 ; +pub const spvc_msl_sampler_ycbcr_model_conversion_SPVC_MSL_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_BT_709 : spvc_msl_sampler_ycbcr_model_conversion = 2 ; +pub const spvc_msl_sampler_ycbcr_model_conversion_SPVC_MSL_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_BT_601 : spvc_msl_sampler_ycbcr_model_conversion = 3 ; +pub const spvc_msl_sampler_ycbcr_model_conversion_SPVC_MSL_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_BT_2020 : spvc_msl_sampler_ycbcr_model_conversion = 4 ; +pub const spvc_msl_sampler_ycbcr_model_conversion_SPVC_MSL_SAMPLER_YCBCR_MODEL_CONVERSION_INT_MAX : spvc_msl_sampler_ycbcr_model_conversion = 2147483647 ; +pub type spvc_msl_sampler_ycbcr_model_conversion = ::std::os::raw::c_int; +pub const spvc_msl_sampler_ycbcr_range_SPVC_MSL_SAMPLER_YCBCR_RANGE_ITU_FULL: + spvc_msl_sampler_ycbcr_range = 0; +pub const spvc_msl_sampler_ycbcr_range_SPVC_MSL_SAMPLER_YCBCR_RANGE_ITU_NARROW: + spvc_msl_sampler_ycbcr_range = 1; +pub const spvc_msl_sampler_ycbcr_range_SPVC_MSL_SAMPLER_YCBCR_RANGE_INT_MAX: + spvc_msl_sampler_ycbcr_range = 2147483647; +pub type spvc_msl_sampler_ycbcr_range = ::std::os::raw::c_int; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct spvc_msl_constexpr_sampler { + pub coord: spvc_msl_sampler_coord, + pub min_filter: spvc_msl_sampler_filter, + pub mag_filter: spvc_msl_sampler_filter, + pub mip_filter: spvc_msl_sampler_mip_filter, + pub s_address: spvc_msl_sampler_address, + pub t_address: spvc_msl_sampler_address, + pub r_address: spvc_msl_sampler_address, + pub compare_func: spvc_msl_sampler_compare_func, + pub border_color: spvc_msl_sampler_border_color, + pub lod_clamp_min: f32, + pub lod_clamp_max: f32, + pub max_anisotropy: ::std::os::raw::c_int, + pub compare_enable: spvc_bool, + pub lod_clamp_enable: spvc_bool, + pub anisotropy_enable: spvc_bool, +} +#[test] +fn bindgen_test_layout_spvc_msl_constexpr_sampler() { + const UNINIT: ::std::mem::MaybeUninit = + ::std::mem::MaybeUninit::uninit(); + let ptr = UNINIT.as_ptr(); + assert_eq!( + ::std::mem::size_of::(), + 52usize, + concat!("Size of: ", stringify!(spvc_msl_constexpr_sampler)) + ); + assert_eq!( + ::std::mem::align_of::(), + 4usize, + concat!("Alignment of ", stringify!(spvc_msl_constexpr_sampler)) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).coord) as usize - ptr as usize }, + 0usize, + concat!( + "Offset of field: ", + stringify!(spvc_msl_constexpr_sampler), + "::", + stringify!(coord) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).min_filter) as usize - ptr as usize }, + 4usize, + concat!( + "Offset of field: ", + stringify!(spvc_msl_constexpr_sampler), + "::", + stringify!(min_filter) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).mag_filter) as usize - ptr as usize }, + 8usize, + concat!( + "Offset of field: ", + stringify!(spvc_msl_constexpr_sampler), + "::", + stringify!(mag_filter) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).mip_filter) as usize - ptr as usize }, + 12usize, + concat!( + "Offset of field: ", + stringify!(spvc_msl_constexpr_sampler), + "::", + stringify!(mip_filter) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).s_address) as usize - ptr as usize }, + 16usize, + concat!( + "Offset of field: ", + stringify!(spvc_msl_constexpr_sampler), + "::", + stringify!(s_address) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).t_address) as usize - ptr as usize }, + 20usize, + concat!( + "Offset of field: ", + stringify!(spvc_msl_constexpr_sampler), + "::", + stringify!(t_address) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).r_address) as usize - ptr as usize }, + 24usize, + concat!( + "Offset of field: ", + stringify!(spvc_msl_constexpr_sampler), + "::", + stringify!(r_address) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).compare_func) as usize - ptr as usize }, + 28usize, + concat!( + "Offset of field: ", + stringify!(spvc_msl_constexpr_sampler), + "::", + stringify!(compare_func) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).border_color) as usize - ptr as usize }, + 32usize, + concat!( + "Offset of field: ", + stringify!(spvc_msl_constexpr_sampler), + "::", + stringify!(border_color) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).lod_clamp_min) as usize - ptr as usize }, + 36usize, + concat!( + "Offset of field: ", + stringify!(spvc_msl_constexpr_sampler), + "::", + stringify!(lod_clamp_min) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).lod_clamp_max) as usize - ptr as usize }, + 40usize, + concat!( + "Offset of field: ", + stringify!(spvc_msl_constexpr_sampler), + "::", + stringify!(lod_clamp_max) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).max_anisotropy) as usize - ptr as usize }, + 44usize, + concat!( + "Offset of field: ", + stringify!(spvc_msl_constexpr_sampler), + "::", + stringify!(max_anisotropy) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).compare_enable) as usize - ptr as usize }, + 48usize, + concat!( + "Offset of field: ", + stringify!(spvc_msl_constexpr_sampler), + "::", + stringify!(compare_enable) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).lod_clamp_enable) as usize - ptr as usize }, + 49usize, + concat!( + "Offset of field: ", + stringify!(spvc_msl_constexpr_sampler), + "::", + stringify!(lod_clamp_enable) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).anisotropy_enable) as usize - ptr as usize }, + 50usize, + concat!( + "Offset of field: ", + stringify!(spvc_msl_constexpr_sampler), + "::", + stringify!(anisotropy_enable) + ) + ); +} +extern "C" { + pub fn spvc_msl_constexpr_sampler_init(sampler: *mut spvc_msl_constexpr_sampler); +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct spvc_msl_sampler_ycbcr_conversion { + pub planes: ::std::os::raw::c_uint, + pub resolution: spvc_msl_format_resolution, + pub chroma_filter: spvc_msl_sampler_filter, + pub x_chroma_offset: spvc_msl_chroma_location, + pub y_chroma_offset: spvc_msl_chroma_location, + pub swizzle: [spvc_msl_component_swizzle; 4usize], + pub ycbcr_model: spvc_msl_sampler_ycbcr_model_conversion, + pub ycbcr_range: spvc_msl_sampler_ycbcr_range, + pub bpc: ::std::os::raw::c_uint, +} +#[test] +fn bindgen_test_layout_spvc_msl_sampler_ycbcr_conversion() { + const UNINIT: ::std::mem::MaybeUninit = + ::std::mem::MaybeUninit::uninit(); + let ptr = UNINIT.as_ptr(); + assert_eq!( + ::std::mem::size_of::(), + 48usize, + concat!("Size of: ", stringify!(spvc_msl_sampler_ycbcr_conversion)) + ); + assert_eq!( + ::std::mem::align_of::(), + 4usize, + concat!( + "Alignment of ", + stringify!(spvc_msl_sampler_ycbcr_conversion) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).planes) as usize - ptr as usize }, + 0usize, + concat!( + "Offset of field: ", + stringify!(spvc_msl_sampler_ycbcr_conversion), + "::", + stringify!(planes) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).resolution) as usize - ptr as usize }, + 4usize, + concat!( + "Offset of field: ", + stringify!(spvc_msl_sampler_ycbcr_conversion), + "::", + stringify!(resolution) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).chroma_filter) as usize - ptr as usize }, + 8usize, + concat!( + "Offset of field: ", + stringify!(spvc_msl_sampler_ycbcr_conversion), + "::", + stringify!(chroma_filter) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).x_chroma_offset) as usize - ptr as usize }, + 12usize, + concat!( + "Offset of field: ", + stringify!(spvc_msl_sampler_ycbcr_conversion), + "::", + stringify!(x_chroma_offset) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).y_chroma_offset) as usize - ptr as usize }, + 16usize, + concat!( + "Offset of field: ", + stringify!(spvc_msl_sampler_ycbcr_conversion), + "::", + stringify!(y_chroma_offset) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).swizzle) as usize - ptr as usize }, + 20usize, + concat!( + "Offset of field: ", + stringify!(spvc_msl_sampler_ycbcr_conversion), + "::", + stringify!(swizzle) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).ycbcr_model) as usize - ptr as usize }, + 36usize, + concat!( + "Offset of field: ", + stringify!(spvc_msl_sampler_ycbcr_conversion), + "::", + stringify!(ycbcr_model) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).ycbcr_range) as usize - ptr as usize }, + 40usize, + concat!( + "Offset of field: ", + stringify!(spvc_msl_sampler_ycbcr_conversion), + "::", + stringify!(ycbcr_range) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).bpc) as usize - ptr as usize }, + 44usize, + concat!( + "Offset of field: ", + stringify!(spvc_msl_sampler_ycbcr_conversion), + "::", + stringify!(bpc) + ) + ); +} +extern "C" { + pub fn spvc_msl_sampler_ycbcr_conversion_init(conv: *mut spvc_msl_sampler_ycbcr_conversion); +} +pub const spvc_hlsl_binding_flag_bits_SPVC_HLSL_BINDING_AUTO_NONE_BIT: spvc_hlsl_binding_flag_bits = + 0; +pub const spvc_hlsl_binding_flag_bits_SPVC_HLSL_BINDING_AUTO_PUSH_CONSTANT_BIT: + spvc_hlsl_binding_flag_bits = 1; +pub const spvc_hlsl_binding_flag_bits_SPVC_HLSL_BINDING_AUTO_CBV_BIT: spvc_hlsl_binding_flag_bits = + 2; +pub const spvc_hlsl_binding_flag_bits_SPVC_HLSL_BINDING_AUTO_SRV_BIT: spvc_hlsl_binding_flag_bits = + 4; +pub const spvc_hlsl_binding_flag_bits_SPVC_HLSL_BINDING_AUTO_UAV_BIT: spvc_hlsl_binding_flag_bits = + 8; +pub const spvc_hlsl_binding_flag_bits_SPVC_HLSL_BINDING_AUTO_SAMPLER_BIT: + spvc_hlsl_binding_flag_bits = 16; +pub const spvc_hlsl_binding_flag_bits_SPVC_HLSL_BINDING_AUTO_ALL: spvc_hlsl_binding_flag_bits = + 2147483647; +pub type spvc_hlsl_binding_flag_bits = ::std::os::raw::c_int; +pub type spvc_hlsl_binding_flags = ::std::os::raw::c_uint; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct spvc_hlsl_resource_binding_mapping { + pub register_space: ::std::os::raw::c_uint, + pub register_binding: ::std::os::raw::c_uint, +} +#[test] +fn bindgen_test_layout_spvc_hlsl_resource_binding_mapping() { + const UNINIT: ::std::mem::MaybeUninit = + ::std::mem::MaybeUninit::uninit(); + let ptr = UNINIT.as_ptr(); + assert_eq!( + ::std::mem::size_of::(), + 8usize, + concat!("Size of: ", stringify!(spvc_hlsl_resource_binding_mapping)) + ); + assert_eq!( + ::std::mem::align_of::(), + 4usize, + concat!( + "Alignment of ", + stringify!(spvc_hlsl_resource_binding_mapping) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).register_space) as usize - ptr as usize }, + 0usize, + concat!( + "Offset of field: ", + stringify!(spvc_hlsl_resource_binding_mapping), + "::", + stringify!(register_space) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).register_binding) as usize - ptr as usize }, + 4usize, + concat!( + "Offset of field: ", + stringify!(spvc_hlsl_resource_binding_mapping), + "::", + stringify!(register_binding) + ) + ); +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct spvc_hlsl_resource_binding { + pub stage: SpvExecutionModel, + pub desc_set: ::std::os::raw::c_uint, + pub binding: ::std::os::raw::c_uint, + pub cbv: spvc_hlsl_resource_binding_mapping, + pub uav: spvc_hlsl_resource_binding_mapping, + pub srv: spvc_hlsl_resource_binding_mapping, + pub sampler: spvc_hlsl_resource_binding_mapping, +} +#[test] +fn bindgen_test_layout_spvc_hlsl_resource_binding() { + const UNINIT: ::std::mem::MaybeUninit = + ::std::mem::MaybeUninit::uninit(); + let ptr = UNINIT.as_ptr(); + assert_eq!( + ::std::mem::size_of::(), + 44usize, + concat!("Size of: ", stringify!(spvc_hlsl_resource_binding)) + ); + assert_eq!( + ::std::mem::align_of::(), + 4usize, + concat!("Alignment of ", stringify!(spvc_hlsl_resource_binding)) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).stage) as usize - ptr as usize }, + 0usize, + concat!( + "Offset of field: ", + stringify!(spvc_hlsl_resource_binding), + "::", + stringify!(stage) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).desc_set) as usize - ptr as usize }, + 4usize, + concat!( + "Offset of field: ", + stringify!(spvc_hlsl_resource_binding), + "::", + stringify!(desc_set) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).binding) as usize - ptr as usize }, + 8usize, + concat!( + "Offset of field: ", + stringify!(spvc_hlsl_resource_binding), + "::", + stringify!(binding) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).cbv) as usize - ptr as usize }, + 12usize, + concat!( + "Offset of field: ", + stringify!(spvc_hlsl_resource_binding), + "::", + stringify!(cbv) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).uav) as usize - ptr as usize }, + 20usize, + concat!( + "Offset of field: ", + stringify!(spvc_hlsl_resource_binding), + "::", + stringify!(uav) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).srv) as usize - ptr as usize }, + 28usize, + concat!( + "Offset of field: ", + stringify!(spvc_hlsl_resource_binding), + "::", + stringify!(srv) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).sampler) as usize - ptr as usize }, + 36usize, + concat!( + "Offset of field: ", + stringify!(spvc_hlsl_resource_binding), + "::", + stringify!(sampler) + ) + ); +} +extern "C" { + pub fn spvc_hlsl_resource_binding_init(binding: *mut spvc_hlsl_resource_binding); +} +pub const spvc_compiler_option_SPVC_COMPILER_OPTION_UNKNOWN: spvc_compiler_option = 0; +pub const spvc_compiler_option_SPVC_COMPILER_OPTION_FORCE_TEMPORARY: spvc_compiler_option = + 16777217; +pub const spvc_compiler_option_SPVC_COMPILER_OPTION_FLATTEN_MULTIDIMENSIONAL_ARRAYS: + spvc_compiler_option = 16777218; +pub const spvc_compiler_option_SPVC_COMPILER_OPTION_FIXUP_DEPTH_CONVENTION: spvc_compiler_option = + 16777219; +pub const spvc_compiler_option_SPVC_COMPILER_OPTION_FLIP_VERTEX_Y: spvc_compiler_option = 16777220; +pub const spvc_compiler_option_SPVC_COMPILER_OPTION_GLSL_SUPPORT_NONZERO_BASE_INSTANCE: + spvc_compiler_option = 33554437; +pub const spvc_compiler_option_SPVC_COMPILER_OPTION_GLSL_SEPARATE_SHADER_OBJECTS: + spvc_compiler_option = 33554438; +pub const spvc_compiler_option_SPVC_COMPILER_OPTION_GLSL_ENABLE_420PACK_EXTENSION: + spvc_compiler_option = 33554439; +pub const spvc_compiler_option_SPVC_COMPILER_OPTION_GLSL_VERSION: spvc_compiler_option = 33554440; +pub const spvc_compiler_option_SPVC_COMPILER_OPTION_GLSL_ES: spvc_compiler_option = 33554441; +pub const spvc_compiler_option_SPVC_COMPILER_OPTION_GLSL_VULKAN_SEMANTICS: spvc_compiler_option = + 33554442; +pub const spvc_compiler_option_SPVC_COMPILER_OPTION_GLSL_ES_DEFAULT_FLOAT_PRECISION_HIGHP: + spvc_compiler_option = 33554443; +pub const spvc_compiler_option_SPVC_COMPILER_OPTION_GLSL_ES_DEFAULT_INT_PRECISION_HIGHP: + spvc_compiler_option = 33554444; +pub const spvc_compiler_option_SPVC_COMPILER_OPTION_HLSL_SHADER_MODEL: spvc_compiler_option = + 67108877; +pub const spvc_compiler_option_SPVC_COMPILER_OPTION_HLSL_POINT_SIZE_COMPAT: spvc_compiler_option = + 67108878; +pub const spvc_compiler_option_SPVC_COMPILER_OPTION_HLSL_POINT_COORD_COMPAT: spvc_compiler_option = + 67108879; +pub const spvc_compiler_option_SPVC_COMPILER_OPTION_HLSL_SUPPORT_NONZERO_BASE_VERTEX_BASE_INSTANCE : spvc_compiler_option = 67108880 ; +pub const spvc_compiler_option_SPVC_COMPILER_OPTION_MSL_VERSION: spvc_compiler_option = 134217745; +pub const spvc_compiler_option_SPVC_COMPILER_OPTION_MSL_TEXEL_BUFFER_TEXTURE_WIDTH: + spvc_compiler_option = 134217746; +pub const spvc_compiler_option_SPVC_COMPILER_OPTION_MSL_AUX_BUFFER_INDEX: spvc_compiler_option = + 134217747; +pub const spvc_compiler_option_SPVC_COMPILER_OPTION_MSL_SWIZZLE_BUFFER_INDEX: spvc_compiler_option = + 134217747; +pub const spvc_compiler_option_SPVC_COMPILER_OPTION_MSL_INDIRECT_PARAMS_BUFFER_INDEX: + spvc_compiler_option = 134217748; +pub const spvc_compiler_option_SPVC_COMPILER_OPTION_MSL_SHADER_OUTPUT_BUFFER_INDEX: + spvc_compiler_option = 134217749; +pub const spvc_compiler_option_SPVC_COMPILER_OPTION_MSL_SHADER_PATCH_OUTPUT_BUFFER_INDEX: + spvc_compiler_option = 134217750; +pub const spvc_compiler_option_SPVC_COMPILER_OPTION_MSL_SHADER_TESS_FACTOR_OUTPUT_BUFFER_INDEX: + spvc_compiler_option = 134217751; +pub const spvc_compiler_option_SPVC_COMPILER_OPTION_MSL_SHADER_INPUT_WORKGROUP_INDEX: + spvc_compiler_option = 134217752; +pub const spvc_compiler_option_SPVC_COMPILER_OPTION_MSL_ENABLE_POINT_SIZE_BUILTIN: + spvc_compiler_option = 134217753; +pub const spvc_compiler_option_SPVC_COMPILER_OPTION_MSL_DISABLE_RASTERIZATION: + spvc_compiler_option = 134217754; +pub const spvc_compiler_option_SPVC_COMPILER_OPTION_MSL_CAPTURE_OUTPUT_TO_BUFFER: + spvc_compiler_option = 134217755; +pub const spvc_compiler_option_SPVC_COMPILER_OPTION_MSL_SWIZZLE_TEXTURE_SAMPLES: + spvc_compiler_option = 134217756; +pub const spvc_compiler_option_SPVC_COMPILER_OPTION_MSL_PAD_FRAGMENT_OUTPUT_COMPONENTS: + spvc_compiler_option = 134217757; +pub const spvc_compiler_option_SPVC_COMPILER_OPTION_MSL_TESS_DOMAIN_ORIGIN_LOWER_LEFT: + spvc_compiler_option = 134217758; +pub const spvc_compiler_option_SPVC_COMPILER_OPTION_MSL_PLATFORM: spvc_compiler_option = 134217759; +pub const spvc_compiler_option_SPVC_COMPILER_OPTION_MSL_ARGUMENT_BUFFERS: spvc_compiler_option = + 134217760; +pub const spvc_compiler_option_SPVC_COMPILER_OPTION_GLSL_EMIT_PUSH_CONSTANT_AS_UNIFORM_BUFFER: + spvc_compiler_option = 33554465; +pub const spvc_compiler_option_SPVC_COMPILER_OPTION_MSL_TEXTURE_BUFFER_NATIVE: + spvc_compiler_option = 134217762; +pub const spvc_compiler_option_SPVC_COMPILER_OPTION_GLSL_EMIT_UNIFORM_BUFFER_AS_PLAIN_UNIFORMS: + spvc_compiler_option = 33554467; +pub const spvc_compiler_option_SPVC_COMPILER_OPTION_MSL_BUFFER_SIZE_BUFFER_INDEX: + spvc_compiler_option = 134217764; +pub const spvc_compiler_option_SPVC_COMPILER_OPTION_EMIT_LINE_DIRECTIVES: spvc_compiler_option = + 16777253; +pub const spvc_compiler_option_SPVC_COMPILER_OPTION_MSL_MULTIVIEW: spvc_compiler_option = 134217766; +pub const spvc_compiler_option_SPVC_COMPILER_OPTION_MSL_VIEW_MASK_BUFFER_INDEX: + spvc_compiler_option = 134217767; +pub const spvc_compiler_option_SPVC_COMPILER_OPTION_MSL_DEVICE_INDEX: spvc_compiler_option = + 134217768; +pub const spvc_compiler_option_SPVC_COMPILER_OPTION_MSL_VIEW_INDEX_FROM_DEVICE_INDEX: + spvc_compiler_option = 134217769; +pub const spvc_compiler_option_SPVC_COMPILER_OPTION_MSL_DISPATCH_BASE: spvc_compiler_option = + 134217770; +pub const spvc_compiler_option_SPVC_COMPILER_OPTION_MSL_DYNAMIC_OFFSETS_BUFFER_INDEX: + spvc_compiler_option = 134217771; +pub const spvc_compiler_option_SPVC_COMPILER_OPTION_MSL_TEXTURE_1D_AS_2D: spvc_compiler_option = + 134217772; +pub const spvc_compiler_option_SPVC_COMPILER_OPTION_MSL_ENABLE_BASE_INDEX_ZERO: + spvc_compiler_option = 134217773; +pub const spvc_compiler_option_SPVC_COMPILER_OPTION_MSL_IOS_FRAMEBUFFER_FETCH_SUBPASS: + spvc_compiler_option = 134217774; +pub const spvc_compiler_option_SPVC_COMPILER_OPTION_MSL_FRAMEBUFFER_FETCH_SUBPASS: + spvc_compiler_option = 134217774; +pub const spvc_compiler_option_SPVC_COMPILER_OPTION_MSL_INVARIANT_FP_MATH: spvc_compiler_option = + 134217775; +pub const spvc_compiler_option_SPVC_COMPILER_OPTION_MSL_EMULATE_CUBEMAP_ARRAY: + spvc_compiler_option = 134217776; +pub const spvc_compiler_option_SPVC_COMPILER_OPTION_MSL_ENABLE_DECORATION_BINDING: + spvc_compiler_option = 134217777; +pub const spvc_compiler_option_SPVC_COMPILER_OPTION_MSL_FORCE_ACTIVE_ARGUMENT_BUFFER_RESOURCES: + spvc_compiler_option = 134217778; +pub const spvc_compiler_option_SPVC_COMPILER_OPTION_MSL_FORCE_NATIVE_ARRAYS: spvc_compiler_option = + 134217779; +pub const spvc_compiler_option_SPVC_COMPILER_OPTION_ENABLE_STORAGE_IMAGE_QUALIFIER_DEDUCTION: + spvc_compiler_option = 16777268; +pub const spvc_compiler_option_SPVC_COMPILER_OPTION_HLSL_FORCE_STORAGE_BUFFER_AS_UAV: + spvc_compiler_option = 67108917; +pub const spvc_compiler_option_SPVC_COMPILER_OPTION_FORCE_ZERO_INITIALIZED_VARIABLES: + spvc_compiler_option = 16777270; +pub const spvc_compiler_option_SPVC_COMPILER_OPTION_HLSL_NONWRITABLE_UAV_TEXTURE_AS_SRV: + spvc_compiler_option = 67108919; +pub const spvc_compiler_option_SPVC_COMPILER_OPTION_MSL_ENABLE_FRAG_OUTPUT_MASK: + spvc_compiler_option = 134217784; +pub const spvc_compiler_option_SPVC_COMPILER_OPTION_MSL_ENABLE_FRAG_DEPTH_BUILTIN: + spvc_compiler_option = 134217785; +pub const spvc_compiler_option_SPVC_COMPILER_OPTION_MSL_ENABLE_FRAG_STENCIL_REF_BUILTIN: + spvc_compiler_option = 134217786; +pub const spvc_compiler_option_SPVC_COMPILER_OPTION_MSL_ENABLE_CLIP_DISTANCE_USER_VARYING: + spvc_compiler_option = 134217787; +pub const spvc_compiler_option_SPVC_COMPILER_OPTION_HLSL_ENABLE_16BIT_TYPES: spvc_compiler_option = + 67108924; +pub const spvc_compiler_option_SPVC_COMPILER_OPTION_MSL_MULTI_PATCH_WORKGROUP: + spvc_compiler_option = 134217789; +pub const spvc_compiler_option_SPVC_COMPILER_OPTION_MSL_SHADER_INPUT_BUFFER_INDEX: + spvc_compiler_option = 134217790; +pub const spvc_compiler_option_SPVC_COMPILER_OPTION_MSL_SHADER_INDEX_BUFFER_INDEX: + spvc_compiler_option = 134217791; +pub const spvc_compiler_option_SPVC_COMPILER_OPTION_MSL_VERTEX_FOR_TESSELLATION: + spvc_compiler_option = 134217792; +pub const spvc_compiler_option_SPVC_COMPILER_OPTION_MSL_VERTEX_INDEX_TYPE: spvc_compiler_option = + 134217793; +pub const spvc_compiler_option_SPVC_COMPILER_OPTION_GLSL_FORCE_FLATTENED_IO_BLOCKS: + spvc_compiler_option = 33554498; +pub const spvc_compiler_option_SPVC_COMPILER_OPTION_MSL_MULTIVIEW_LAYERED_RENDERING: + spvc_compiler_option = 134217795; +pub const spvc_compiler_option_SPVC_COMPILER_OPTION_MSL_ARRAYED_SUBPASS_INPUT: + spvc_compiler_option = 134217796; +pub const spvc_compiler_option_SPVC_COMPILER_OPTION_MSL_R32UI_LINEAR_TEXTURE_ALIGNMENT: + spvc_compiler_option = 134217797; +pub const spvc_compiler_option_SPVC_COMPILER_OPTION_MSL_R32UI_ALIGNMENT_CONSTANT_ID: + spvc_compiler_option = 134217798; +pub const spvc_compiler_option_SPVC_COMPILER_OPTION_HLSL_FLATTEN_MATRIX_VERTEX_INPUT_SEMANTICS: + spvc_compiler_option = 67108935; +pub const spvc_compiler_option_SPVC_COMPILER_OPTION_MSL_IOS_USE_SIMDGROUP_FUNCTIONS: + spvc_compiler_option = 134217800; +pub const spvc_compiler_option_SPVC_COMPILER_OPTION_MSL_EMULATE_SUBGROUPS: spvc_compiler_option = + 134217801; +pub const spvc_compiler_option_SPVC_COMPILER_OPTION_MSL_FIXED_SUBGROUP_SIZE: spvc_compiler_option = + 134217802; +pub const spvc_compiler_option_SPVC_COMPILER_OPTION_MSL_FORCE_SAMPLE_RATE_SHADING: + spvc_compiler_option = 134217803; +pub const spvc_compiler_option_SPVC_COMPILER_OPTION_MSL_IOS_SUPPORT_BASE_VERTEX_INSTANCE: + spvc_compiler_option = 134217804; +pub const spvc_compiler_option_SPVC_COMPILER_OPTION_GLSL_OVR_MULTIVIEW_VIEW_COUNT: + spvc_compiler_option = 33554509; +pub const spvc_compiler_option_SPVC_COMPILER_OPTION_RELAX_NAN_CHECKS: spvc_compiler_option = + 16777294; +pub const spvc_compiler_option_SPVC_COMPILER_OPTION_MSL_RAW_BUFFER_TESE_INPUT: + spvc_compiler_option = 134217807; +pub const spvc_compiler_option_SPVC_COMPILER_OPTION_MSL_SHADER_PATCH_INPUT_BUFFER_INDEX: + spvc_compiler_option = 134217808; +pub const spvc_compiler_option_SPVC_COMPILER_OPTION_MSL_MANUAL_HELPER_INVOCATION_UPDATES: + spvc_compiler_option = 134217809; +pub const spvc_compiler_option_SPVC_COMPILER_OPTION_MSL_CHECK_DISCARDED_FRAG_STORES: + spvc_compiler_option = 134217810; +pub const spvc_compiler_option_SPVC_COMPILER_OPTION_GLSL_ENABLE_ROW_MAJOR_LOAD_WORKAROUND: + spvc_compiler_option = 33554515; +pub const spvc_compiler_option_SPVC_COMPILER_OPTION_MSL_ARGUMENT_BUFFERS_TIER: + spvc_compiler_option = 134217812; +pub const spvc_compiler_option_SPVC_COMPILER_OPTION_MSL_SAMPLE_DREF_LOD_ARRAY_AS_GRAD: + spvc_compiler_option = 134217813; +pub const spvc_compiler_option_SPVC_COMPILER_OPTION_MSL_READWRITE_TEXTURE_FENCES: + spvc_compiler_option = 134217814; +pub const spvc_compiler_option_SPVC_COMPILER_OPTION_MSL_REPLACE_RECURSIVE_INPUTS: + spvc_compiler_option = 134217815; +pub const spvc_compiler_option_SPVC_COMPILER_OPTION_MSL_AGX_MANUAL_CUBE_GRAD_FIXUP: + spvc_compiler_option = 134217816; +pub const spvc_compiler_option_SPVC_COMPILER_OPTION_MSL_FORCE_FRAGMENT_WITH_SIDE_EFFECTS_EXECUTION : spvc_compiler_option = 134217817 ; +pub const spvc_compiler_option_SPVC_COMPILER_OPTION_HLSL_USE_ENTRY_POINT_NAME: + spvc_compiler_option = 67108954; +pub const spvc_compiler_option_SPVC_COMPILER_OPTION_HLSL_PRESERVE_STRUCTURED_BUFFERS: + spvc_compiler_option = 67108955; +pub const spvc_compiler_option_SPVC_COMPILER_OPTION_MSL_AUTO_DISABLE_RASTERIZATION: + spvc_compiler_option = 134217820; +pub const spvc_compiler_option_SPVC_COMPILER_OPTION_MSL_ENABLE_POINT_SIZE_DEFAULT: + spvc_compiler_option = 134217821; +pub const spvc_compiler_option_SPVC_COMPILER_OPTION_INT_MAX: spvc_compiler_option = 2147483647; +pub type spvc_compiler_option = ::std::os::raw::c_int; +extern "C" { + pub fn spvc_context_create(context: *mut spvc_context) -> spvc_result; +} +extern "C" { + pub fn spvc_context_destroy(context: spvc_context); +} +extern "C" { + pub fn spvc_context_release_allocations(context: spvc_context); +} +extern "C" { + pub fn spvc_context_get_last_error_string( + context: spvc_context, + ) -> *const ::std::os::raw::c_char; +} +pub type spvc_error_callback = ::std::option::Option< + unsafe extern "C" fn( + userdata: *mut ::std::os::raw::c_void, + error: *const ::std::os::raw::c_char, + ), +>; +extern "C" { + pub fn spvc_context_set_error_callback( + context: spvc_context, + cb: spvc_error_callback, + userdata: *mut ::std::os::raw::c_void, + ); +} +extern "C" { + pub fn spvc_context_parse_spirv( + context: spvc_context, + spirv: *const SpvId, + word_count: usize, + parsed_ir: *mut spvc_parsed_ir, + ) -> spvc_result; +} +extern "C" { + pub fn spvc_context_create_compiler( + context: spvc_context, + backend: spvc_backend, + parsed_ir: spvc_parsed_ir, + mode: spvc_capture_mode, + compiler: *mut spvc_compiler, + ) -> spvc_result; +} +extern "C" { + pub fn spvc_compiler_get_current_id_bound(compiler: spvc_compiler) -> ::std::os::raw::c_uint; +} +extern "C" { + pub fn spvc_compiler_create_compiler_options( + compiler: spvc_compiler, + options: *mut spvc_compiler_options, + ) -> spvc_result; +} +extern "C" { + pub fn spvc_compiler_options_set_bool( + options: spvc_compiler_options, + option: spvc_compiler_option, + value: spvc_bool, + ) -> spvc_result; +} +extern "C" { + pub fn spvc_compiler_options_set_uint( + options: spvc_compiler_options, + option: spvc_compiler_option, + value: ::std::os::raw::c_uint, + ) -> spvc_result; +} +extern "C" { + pub fn spvc_compiler_install_compiler_options( + compiler: spvc_compiler, + options: spvc_compiler_options, + ) -> spvc_result; +} +extern "C" { + pub fn spvc_compiler_compile( + compiler: spvc_compiler, + source: *mut *const ::std::os::raw::c_char, + ) -> spvc_result; +} +extern "C" { + pub fn spvc_compiler_add_header_line( + compiler: spvc_compiler, + line: *const ::std::os::raw::c_char, + ) -> spvc_result; +} +extern "C" { + pub fn spvc_compiler_require_extension( + compiler: spvc_compiler, + ext: *const ::std::os::raw::c_char, + ) -> spvc_result; +} +extern "C" { + pub fn spvc_compiler_get_num_required_extensions(compiler: spvc_compiler) -> usize; +} +extern "C" { + pub fn spvc_compiler_get_required_extension( + compiler: spvc_compiler, + index: usize, + ) -> *const ::std::os::raw::c_char; +} +extern "C" { + pub fn spvc_compiler_flatten_buffer_block( + compiler: spvc_compiler, + id: spvc_variable_id, + ) -> spvc_result; +} +extern "C" { + pub fn spvc_compiler_variable_is_depth_or_compare( + compiler: spvc_compiler, + id: spvc_variable_id, + ) -> spvc_bool; +} +extern "C" { + pub fn spvc_compiler_mask_stage_output_by_location( + compiler: spvc_compiler, + location: ::std::os::raw::c_uint, + component: ::std::os::raw::c_uint, + ) -> spvc_result; +} +extern "C" { + pub fn spvc_compiler_mask_stage_output_by_builtin( + compiler: spvc_compiler, + builtin: SpvBuiltIn, + ) -> spvc_result; +} +extern "C" { + pub fn spvc_compiler_hlsl_set_root_constants_layout( + compiler: spvc_compiler, + constant_info: *const spvc_hlsl_root_constants, + count: usize, + ) -> spvc_result; +} +extern "C" { + pub fn spvc_compiler_hlsl_add_vertex_attribute_remap( + compiler: spvc_compiler, + remap: *const spvc_hlsl_vertex_attribute_remap, + remaps: usize, + ) -> spvc_result; +} +extern "C" { + pub fn spvc_compiler_hlsl_remap_num_workgroups_builtin( + compiler: spvc_compiler, + ) -> spvc_variable_id; +} +extern "C" { + pub fn spvc_compiler_hlsl_set_resource_binding_flags( + compiler: spvc_compiler, + flags: spvc_hlsl_binding_flags, + ) -> spvc_result; +} +extern "C" { + pub fn spvc_compiler_hlsl_add_resource_binding( + compiler: spvc_compiler, + binding: *const spvc_hlsl_resource_binding, + ) -> spvc_result; +} +extern "C" { + pub fn spvc_compiler_hlsl_is_resource_used( + compiler: spvc_compiler, + model: SpvExecutionModel, + set: ::std::os::raw::c_uint, + binding: ::std::os::raw::c_uint, + ) -> spvc_bool; +} +extern "C" { + pub fn spvc_compiler_msl_is_rasterization_disabled(compiler: spvc_compiler) -> spvc_bool; +} +extern "C" { + pub fn spvc_compiler_msl_needs_aux_buffer(compiler: spvc_compiler) -> spvc_bool; +} +extern "C" { + pub fn spvc_compiler_msl_needs_swizzle_buffer(compiler: spvc_compiler) -> spvc_bool; +} +extern "C" { + pub fn spvc_compiler_msl_needs_buffer_size_buffer(compiler: spvc_compiler) -> spvc_bool; +} +extern "C" { + pub fn spvc_compiler_msl_needs_output_buffer(compiler: spvc_compiler) -> spvc_bool; +} +extern "C" { + pub fn spvc_compiler_msl_needs_patch_output_buffer(compiler: spvc_compiler) -> spvc_bool; +} +extern "C" { + pub fn spvc_compiler_msl_needs_input_threadgroup_mem(compiler: spvc_compiler) -> spvc_bool; +} +extern "C" { + pub fn spvc_compiler_msl_add_vertex_attribute( + compiler: spvc_compiler, + attrs: *const spvc_msl_vertex_attribute, + ) -> spvc_result; +} +extern "C" { + pub fn spvc_compiler_msl_add_resource_binding( + compiler: spvc_compiler, + binding: *const spvc_msl_resource_binding, + ) -> spvc_result; +} +extern "C" { + pub fn spvc_compiler_msl_add_resource_binding_2( + compiler: spvc_compiler, + binding: *const spvc_msl_resource_binding_2, + ) -> spvc_result; +} +extern "C" { + pub fn spvc_compiler_msl_add_shader_input( + compiler: spvc_compiler, + input: *const spvc_msl_shader_interface_var, + ) -> spvc_result; +} +extern "C" { + pub fn spvc_compiler_msl_add_shader_input_2( + compiler: spvc_compiler, + input: *const spvc_msl_shader_interface_var_2, + ) -> spvc_result; +} +extern "C" { + pub fn spvc_compiler_msl_add_shader_output( + compiler: spvc_compiler, + output: *const spvc_msl_shader_interface_var, + ) -> spvc_result; +} +extern "C" { + pub fn spvc_compiler_msl_add_shader_output_2( + compiler: spvc_compiler, + output: *const spvc_msl_shader_interface_var_2, + ) -> spvc_result; +} +extern "C" { + pub fn spvc_compiler_msl_add_discrete_descriptor_set( + compiler: spvc_compiler, + desc_set: ::std::os::raw::c_uint, + ) -> spvc_result; +} +extern "C" { + pub fn spvc_compiler_msl_set_argument_buffer_device_address_space( + compiler: spvc_compiler, + desc_set: ::std::os::raw::c_uint, + device_address: spvc_bool, + ) -> spvc_result; +} +extern "C" { + pub fn spvc_compiler_msl_is_vertex_attribute_used( + compiler: spvc_compiler, + location: ::std::os::raw::c_uint, + ) -> spvc_bool; +} +extern "C" { + pub fn spvc_compiler_msl_is_shader_input_used( + compiler: spvc_compiler, + location: ::std::os::raw::c_uint, + ) -> spvc_bool; +} +extern "C" { + pub fn spvc_compiler_msl_is_shader_output_used( + compiler: spvc_compiler, + location: ::std::os::raw::c_uint, + ) -> spvc_bool; +} +extern "C" { + pub fn spvc_compiler_msl_is_resource_used( + compiler: spvc_compiler, + model: SpvExecutionModel, + set: ::std::os::raw::c_uint, + binding: ::std::os::raw::c_uint, + ) -> spvc_bool; +} +extern "C" { + pub fn spvc_compiler_msl_remap_constexpr_sampler( + compiler: spvc_compiler, + id: spvc_variable_id, + sampler: *const spvc_msl_constexpr_sampler, + ) -> spvc_result; +} +extern "C" { + pub fn spvc_compiler_msl_remap_constexpr_sampler_by_binding( + compiler: spvc_compiler, + desc_set: ::std::os::raw::c_uint, + binding: ::std::os::raw::c_uint, + sampler: *const spvc_msl_constexpr_sampler, + ) -> spvc_result; +} +extern "C" { + pub fn spvc_compiler_msl_remap_constexpr_sampler_ycbcr( + compiler: spvc_compiler, + id: spvc_variable_id, + sampler: *const spvc_msl_constexpr_sampler, + conv: *const spvc_msl_sampler_ycbcr_conversion, + ) -> spvc_result; +} +extern "C" { + pub fn spvc_compiler_msl_remap_constexpr_sampler_by_binding_ycbcr( + compiler: spvc_compiler, + desc_set: ::std::os::raw::c_uint, + binding: ::std::os::raw::c_uint, + sampler: *const spvc_msl_constexpr_sampler, + conv: *const spvc_msl_sampler_ycbcr_conversion, + ) -> spvc_result; +} +extern "C" { + pub fn spvc_compiler_msl_set_fragment_output_components( + compiler: spvc_compiler, + location: ::std::os::raw::c_uint, + components: ::std::os::raw::c_uint, + ) -> spvc_result; +} +extern "C" { + pub fn spvc_compiler_msl_get_automatic_resource_binding( + compiler: spvc_compiler, + id: spvc_variable_id, + ) -> ::std::os::raw::c_uint; +} +extern "C" { + pub fn spvc_compiler_msl_get_automatic_resource_binding_secondary( + compiler: spvc_compiler, + id: spvc_variable_id, + ) -> ::std::os::raw::c_uint; +} +extern "C" { + pub fn spvc_compiler_msl_add_dynamic_buffer( + compiler: spvc_compiler, + desc_set: ::std::os::raw::c_uint, + binding: ::std::os::raw::c_uint, + index: ::std::os::raw::c_uint, + ) -> spvc_result; +} +extern "C" { + pub fn spvc_compiler_msl_add_inline_uniform_block( + compiler: spvc_compiler, + desc_set: ::std::os::raw::c_uint, + binding: ::std::os::raw::c_uint, + ) -> spvc_result; +} +extern "C" { + pub fn spvc_compiler_msl_set_combined_sampler_suffix( + compiler: spvc_compiler, + suffix: *const ::std::os::raw::c_char, + ) -> spvc_result; +} +extern "C" { + pub fn spvc_compiler_msl_get_combined_sampler_suffix( + compiler: spvc_compiler, + ) -> *const ::std::os::raw::c_char; +} +extern "C" { + pub fn spvc_compiler_get_active_interface_variables( + compiler: spvc_compiler, + set: *mut spvc_set, + ) -> spvc_result; +} +extern "C" { + pub fn spvc_compiler_set_enabled_interface_variables( + compiler: spvc_compiler, + set: spvc_set, + ) -> spvc_result; +} +extern "C" { + pub fn spvc_compiler_create_shader_resources( + compiler: spvc_compiler, + resources: *mut spvc_resources, + ) -> spvc_result; +} +extern "C" { + pub fn spvc_compiler_create_shader_resources_for_active_variables( + compiler: spvc_compiler, + resources: *mut spvc_resources, + active: spvc_set, + ) -> spvc_result; +} +extern "C" { + pub fn spvc_resources_get_resource_list_for_type( + resources: spvc_resources, + type_: spvc_resource_type, + resource_list: *mut *const spvc_reflected_resource, + resource_size: *mut usize, + ) -> spvc_result; +} +extern "C" { + pub fn spvc_resources_get_builtin_resource_list_for_type( + resources: spvc_resources, + type_: spvc_builtin_resource_type, + resource_list: *mut *const spvc_reflected_builtin_resource, + resource_size: *mut usize, + ) -> spvc_result; +} +extern "C" { + pub fn spvc_compiler_set_decoration( + compiler: spvc_compiler, + id: SpvId, + decoration: SpvDecoration, + argument: ::std::os::raw::c_uint, + ); +} +extern "C" { + pub fn spvc_compiler_set_decoration_string( + compiler: spvc_compiler, + id: SpvId, + decoration: SpvDecoration, + argument: *const ::std::os::raw::c_char, + ); +} +extern "C" { + pub fn spvc_compiler_set_name( + compiler: spvc_compiler, + id: SpvId, + argument: *const ::std::os::raw::c_char, + ); +} +extern "C" { + pub fn spvc_compiler_set_member_decoration( + compiler: spvc_compiler, + id: spvc_type_id, + member_index: ::std::os::raw::c_uint, + decoration: SpvDecoration, + argument: ::std::os::raw::c_uint, + ); +} +extern "C" { + pub fn spvc_compiler_set_member_decoration_string( + compiler: spvc_compiler, + id: spvc_type_id, + member_index: ::std::os::raw::c_uint, + decoration: SpvDecoration, + argument: *const ::std::os::raw::c_char, + ); +} +extern "C" { + pub fn spvc_compiler_set_member_name( + compiler: spvc_compiler, + id: spvc_type_id, + member_index: ::std::os::raw::c_uint, + argument: *const ::std::os::raw::c_char, + ); +} +extern "C" { + pub fn spvc_compiler_unset_decoration( + compiler: spvc_compiler, + id: SpvId, + decoration: SpvDecoration, + ); +} +extern "C" { + pub fn spvc_compiler_unset_member_decoration( + compiler: spvc_compiler, + id: spvc_type_id, + member_index: ::std::os::raw::c_uint, + decoration: SpvDecoration, + ); +} +extern "C" { + pub fn spvc_compiler_has_decoration( + compiler: spvc_compiler, + id: SpvId, + decoration: SpvDecoration, + ) -> spvc_bool; +} +extern "C" { + pub fn spvc_compiler_has_member_decoration( + compiler: spvc_compiler, + id: spvc_type_id, + member_index: ::std::os::raw::c_uint, + decoration: SpvDecoration, + ) -> spvc_bool; +} +extern "C" { + pub fn spvc_compiler_get_name( + compiler: spvc_compiler, + id: SpvId, + ) -> *const ::std::os::raw::c_char; +} +extern "C" { + pub fn spvc_compiler_get_decoration( + compiler: spvc_compiler, + id: SpvId, + decoration: SpvDecoration, + ) -> ::std::os::raw::c_uint; +} +extern "C" { + pub fn spvc_compiler_get_decoration_string( + compiler: spvc_compiler, + id: SpvId, + decoration: SpvDecoration, + ) -> *const ::std::os::raw::c_char; +} +extern "C" { + pub fn spvc_compiler_get_member_decoration( + compiler: spvc_compiler, + id: spvc_type_id, + member_index: ::std::os::raw::c_uint, + decoration: SpvDecoration, + ) -> ::std::os::raw::c_uint; +} +extern "C" { + pub fn spvc_compiler_get_member_decoration_string( + compiler: spvc_compiler, + id: spvc_type_id, + member_index: ::std::os::raw::c_uint, + decoration: SpvDecoration, + ) -> *const ::std::os::raw::c_char; +} +extern "C" { + pub fn spvc_compiler_get_member_name( + compiler: spvc_compiler, + id: spvc_type_id, + member_index: ::std::os::raw::c_uint, + ) -> *const ::std::os::raw::c_char; +} +extern "C" { + pub fn spvc_compiler_get_entry_points( + compiler: spvc_compiler, + entry_points: *mut *const spvc_entry_point, + num_entry_points: *mut usize, + ) -> spvc_result; +} +extern "C" { + pub fn spvc_compiler_set_entry_point( + compiler: spvc_compiler, + name: *const ::std::os::raw::c_char, + model: SpvExecutionModel, + ) -> spvc_result; +} +extern "C" { + pub fn spvc_compiler_rename_entry_point( + compiler: spvc_compiler, + old_name: *const ::std::os::raw::c_char, + new_name: *const ::std::os::raw::c_char, + model: SpvExecutionModel, + ) -> spvc_result; +} +extern "C" { + pub fn spvc_compiler_get_cleansed_entry_point_name( + compiler: spvc_compiler, + name: *const ::std::os::raw::c_char, + model: SpvExecutionModel, + ) -> *const ::std::os::raw::c_char; +} +extern "C" { + pub fn spvc_compiler_set_execution_mode(compiler: spvc_compiler, mode: SpvExecutionMode); +} +extern "C" { + pub fn spvc_compiler_unset_execution_mode(compiler: spvc_compiler, mode: SpvExecutionMode); +} +extern "C" { + pub fn spvc_compiler_set_execution_mode_with_arguments( + compiler: spvc_compiler, + mode: SpvExecutionMode, + arg0: ::std::os::raw::c_uint, + arg1: ::std::os::raw::c_uint, + arg2: ::std::os::raw::c_uint, + ); +} +extern "C" { + pub fn spvc_compiler_get_execution_modes( + compiler: spvc_compiler, + modes: *mut *const SpvExecutionMode, + num_modes: *mut usize, + ) -> spvc_result; +} +extern "C" { + pub fn spvc_compiler_get_execution_mode_argument( + compiler: spvc_compiler, + mode: SpvExecutionMode, + ) -> ::std::os::raw::c_uint; +} +extern "C" { + pub fn spvc_compiler_get_execution_mode_argument_by_index( + compiler: spvc_compiler, + mode: SpvExecutionMode, + index: ::std::os::raw::c_uint, + ) -> ::std::os::raw::c_uint; +} +extern "C" { + pub fn spvc_compiler_get_execution_model(compiler: spvc_compiler) -> SpvExecutionModel; +} +extern "C" { + pub fn spvc_compiler_update_active_builtins(compiler: spvc_compiler); +} +extern "C" { + pub fn spvc_compiler_has_active_builtin( + compiler: spvc_compiler, + builtin: SpvBuiltIn, + storage: SpvStorageClass, + ) -> spvc_bool; +} +extern "C" { + pub fn spvc_compiler_get_type_handle(compiler: spvc_compiler, id: spvc_type_id) -> spvc_type; +} +extern "C" { + pub fn spvc_type_get_base_type_id(type_: spvc_type) -> spvc_type_id; +} +extern "C" { + pub fn spvc_type_get_basetype(type_: spvc_type) -> spvc_basetype; +} +extern "C" { + pub fn spvc_type_get_bit_width(type_: spvc_type) -> ::std::os::raw::c_uint; +} +extern "C" { + pub fn spvc_type_get_vector_size(type_: spvc_type) -> ::std::os::raw::c_uint; +} +extern "C" { + pub fn spvc_type_get_columns(type_: spvc_type) -> ::std::os::raw::c_uint; +} +extern "C" { + pub fn spvc_type_get_num_array_dimensions(type_: spvc_type) -> ::std::os::raw::c_uint; +} +extern "C" { + pub fn spvc_type_array_dimension_is_literal( + type_: spvc_type, + dimension: ::std::os::raw::c_uint, + ) -> spvc_bool; +} +extern "C" { + pub fn spvc_type_get_array_dimension( + type_: spvc_type, + dimension: ::std::os::raw::c_uint, + ) -> SpvId; +} +extern "C" { + pub fn spvc_type_get_num_member_types(type_: spvc_type) -> ::std::os::raw::c_uint; +} +extern "C" { + pub fn spvc_type_get_member_type( + type_: spvc_type, + index: ::std::os::raw::c_uint, + ) -> spvc_type_id; +} +extern "C" { + pub fn spvc_type_get_storage_class(type_: spvc_type) -> SpvStorageClass; +} +extern "C" { + pub fn spvc_type_get_image_sampled_type(type_: spvc_type) -> spvc_type_id; +} +extern "C" { + pub fn spvc_type_get_image_dimension(type_: spvc_type) -> SpvDim; +} +extern "C" { + pub fn spvc_type_get_image_is_depth(type_: spvc_type) -> spvc_bool; +} +extern "C" { + pub fn spvc_type_get_image_arrayed(type_: spvc_type) -> spvc_bool; +} +extern "C" { + pub fn spvc_type_get_image_multisampled(type_: spvc_type) -> spvc_bool; +} +extern "C" { + pub fn spvc_type_get_image_is_storage(type_: spvc_type) -> spvc_bool; +} +extern "C" { + pub fn spvc_type_get_image_storage_format(type_: spvc_type) -> SpvImageFormat; +} +extern "C" { + pub fn spvc_type_get_image_access_qualifier(type_: spvc_type) -> SpvAccessQualifier; +} +extern "C" { + pub fn spvc_compiler_get_declared_struct_size( + compiler: spvc_compiler, + struct_type: spvc_type, + size: *mut usize, + ) -> spvc_result; +} +extern "C" { + pub fn spvc_compiler_get_declared_struct_size_runtime_array( + compiler: spvc_compiler, + struct_type: spvc_type, + array_size: usize, + size: *mut usize, + ) -> spvc_result; +} +extern "C" { + pub fn spvc_compiler_get_declared_struct_member_size( + compiler: spvc_compiler, + type_: spvc_type, + index: ::std::os::raw::c_uint, + size: *mut usize, + ) -> spvc_result; +} +extern "C" { + pub fn spvc_compiler_type_struct_member_offset( + compiler: spvc_compiler, + type_: spvc_type, + index: ::std::os::raw::c_uint, + offset: *mut ::std::os::raw::c_uint, + ) -> spvc_result; +} +extern "C" { + pub fn spvc_compiler_type_struct_member_array_stride( + compiler: spvc_compiler, + type_: spvc_type, + index: ::std::os::raw::c_uint, + stride: *mut ::std::os::raw::c_uint, + ) -> spvc_result; +} +extern "C" { + pub fn spvc_compiler_type_struct_member_matrix_stride( + compiler: spvc_compiler, + type_: spvc_type, + index: ::std::os::raw::c_uint, + stride: *mut ::std::os::raw::c_uint, + ) -> spvc_result; +} +extern "C" { + pub fn spvc_compiler_build_dummy_sampler_for_combined_images( + compiler: spvc_compiler, + id: *mut spvc_variable_id, + ) -> spvc_result; +} +extern "C" { + pub fn spvc_compiler_build_combined_image_samplers(compiler: spvc_compiler) -> spvc_result; +} +extern "C" { + pub fn spvc_compiler_get_combined_image_samplers( + compiler: spvc_compiler, + samplers: *mut *const spvc_combined_image_sampler, + num_samplers: *mut usize, + ) -> spvc_result; +} +extern "C" { + pub fn spvc_compiler_get_specialization_constants( + compiler: spvc_compiler, + constants: *mut *const spvc_specialization_constant, + num_constants: *mut usize, + ) -> spvc_result; +} +extern "C" { + pub fn spvc_compiler_get_constant_handle( + compiler: spvc_compiler, + id: spvc_constant_id, + ) -> spvc_constant; +} +extern "C" { + pub fn spvc_compiler_get_work_group_size_specialization_constants( + compiler: spvc_compiler, + x: *mut spvc_specialization_constant, + y: *mut spvc_specialization_constant, + z: *mut spvc_specialization_constant, + ) -> spvc_constant_id; +} +extern "C" { + pub fn spvc_compiler_get_active_buffer_ranges( + compiler: spvc_compiler, + id: spvc_variable_id, + ranges: *mut *const spvc_buffer_range, + num_ranges: *mut usize, + ) -> spvc_result; +} +extern "C" { + pub fn spvc_constant_get_scalar_fp16( + constant: spvc_constant, + column: ::std::os::raw::c_uint, + row: ::std::os::raw::c_uint, + ) -> f32; +} +extern "C" { + pub fn spvc_constant_get_scalar_fp32( + constant: spvc_constant, + column: ::std::os::raw::c_uint, + row: ::std::os::raw::c_uint, + ) -> f32; +} +extern "C" { + pub fn spvc_constant_get_scalar_fp64( + constant: spvc_constant, + column: ::std::os::raw::c_uint, + row: ::std::os::raw::c_uint, + ) -> f64; +} +extern "C" { + pub fn spvc_constant_get_scalar_u32( + constant: spvc_constant, + column: ::std::os::raw::c_uint, + row: ::std::os::raw::c_uint, + ) -> ::std::os::raw::c_uint; +} +extern "C" { + pub fn spvc_constant_get_scalar_i32( + constant: spvc_constant, + column: ::std::os::raw::c_uint, + row: ::std::os::raw::c_uint, + ) -> ::std::os::raw::c_int; +} +extern "C" { + pub fn spvc_constant_get_scalar_u16( + constant: spvc_constant, + column: ::std::os::raw::c_uint, + row: ::std::os::raw::c_uint, + ) -> ::std::os::raw::c_uint; +} +extern "C" { + pub fn spvc_constant_get_scalar_i16( + constant: spvc_constant, + column: ::std::os::raw::c_uint, + row: ::std::os::raw::c_uint, + ) -> ::std::os::raw::c_int; +} +extern "C" { + pub fn spvc_constant_get_scalar_u8( + constant: spvc_constant, + column: ::std::os::raw::c_uint, + row: ::std::os::raw::c_uint, + ) -> ::std::os::raw::c_uint; +} +extern "C" { + pub fn spvc_constant_get_scalar_i8( + constant: spvc_constant, + column: ::std::os::raw::c_uint, + row: ::std::os::raw::c_uint, + ) -> ::std::os::raw::c_int; +} +extern "C" { + pub fn spvc_constant_get_subconstants( + constant: spvc_constant, + constituents: *mut *const spvc_constant_id, + count: *mut usize, + ); +} +extern "C" { + pub fn spvc_constant_get_scalar_u64( + constant: spvc_constant, + column: ::std::os::raw::c_uint, + row: ::std::os::raw::c_uint, + ) -> ::std::os::raw::c_ulonglong; +} +extern "C" { + pub fn spvc_constant_get_scalar_i64( + constant: spvc_constant, + column: ::std::os::raw::c_uint, + row: ::std::os::raw::c_uint, + ) -> ::std::os::raw::c_longlong; +} +extern "C" { + pub fn spvc_constant_get_type(constant: spvc_constant) -> spvc_type_id; +} +extern "C" { + pub fn spvc_constant_set_scalar_fp16( + constant: spvc_constant, + column: ::std::os::raw::c_uint, + row: ::std::os::raw::c_uint, + value: ::std::os::raw::c_ushort, + ); +} +extern "C" { + pub fn spvc_constant_set_scalar_fp32( + constant: spvc_constant, + column: ::std::os::raw::c_uint, + row: ::std::os::raw::c_uint, + value: f32, + ); +} +extern "C" { + pub fn spvc_constant_set_scalar_fp64( + constant: spvc_constant, + column: ::std::os::raw::c_uint, + row: ::std::os::raw::c_uint, + value: f64, + ); +} +extern "C" { + pub fn spvc_constant_set_scalar_u32( + constant: spvc_constant, + column: ::std::os::raw::c_uint, + row: ::std::os::raw::c_uint, + value: ::std::os::raw::c_uint, + ); +} +extern "C" { + pub fn spvc_constant_set_scalar_i32( + constant: spvc_constant, + column: ::std::os::raw::c_uint, + row: ::std::os::raw::c_uint, + value: ::std::os::raw::c_int, + ); +} +extern "C" { + pub fn spvc_constant_set_scalar_u64( + constant: spvc_constant, + column: ::std::os::raw::c_uint, + row: ::std::os::raw::c_uint, + value: ::std::os::raw::c_ulonglong, + ); +} +extern "C" { + pub fn spvc_constant_set_scalar_i64( + constant: spvc_constant, + column: ::std::os::raw::c_uint, + row: ::std::os::raw::c_uint, + value: ::std::os::raw::c_longlong, + ); +} +extern "C" { + pub fn spvc_constant_set_scalar_u16( + constant: spvc_constant, + column: ::std::os::raw::c_uint, + row: ::std::os::raw::c_uint, + value: ::std::os::raw::c_ushort, + ); +} +extern "C" { + pub fn spvc_constant_set_scalar_i16( + constant: spvc_constant, + column: ::std::os::raw::c_uint, + row: ::std::os::raw::c_uint, + value: ::std::os::raw::c_short, + ); +} +extern "C" { + pub fn spvc_constant_set_scalar_u8( + constant: spvc_constant, + column: ::std::os::raw::c_uint, + row: ::std::os::raw::c_uint, + value: ::std::os::raw::c_uchar, + ); +} +extern "C" { + pub fn spvc_constant_set_scalar_i8( + constant: spvc_constant, + column: ::std::os::raw::c_uint, + row: ::std::os::raw::c_uint, + value: ::std::os::raw::c_schar, + ); +} +extern "C" { + pub fn spvc_compiler_get_binary_offset_for_decoration( + compiler: spvc_compiler, + id: spvc_variable_id, + decoration: SpvDecoration, + word_offset: *mut ::std::os::raw::c_uint, + ) -> spvc_bool; +} +extern "C" { + pub fn spvc_compiler_buffer_is_hlsl_counter_buffer( + compiler: spvc_compiler, + id: spvc_variable_id, + ) -> spvc_bool; +} +extern "C" { + pub fn spvc_compiler_buffer_get_hlsl_counter_buffer( + compiler: spvc_compiler, + id: spvc_variable_id, + counter_id: *mut spvc_variable_id, + ) -> spvc_bool; +} +extern "C" { + pub fn spvc_compiler_get_declared_capabilities( + compiler: spvc_compiler, + capabilities: *mut *const SpvCapability, + num_capabilities: *mut usize, + ) -> spvc_result; +} +extern "C" { + pub fn spvc_compiler_get_declared_extensions( + compiler: spvc_compiler, + extensions: *mut *mut *const ::std::os::raw::c_char, + num_extensions: *mut usize, + ) -> spvc_result; +} +extern "C" { + pub fn spvc_compiler_get_remapped_declared_block_name( + compiler: spvc_compiler, + id: spvc_variable_id, + ) -> *const ::std::os::raw::c_char; +} +extern "C" { + pub fn spvc_compiler_get_buffer_block_decorations( + compiler: spvc_compiler, + id: spvc_variable_id, + decorations: *mut *const SpvDecoration, + num_decorations: *mut usize, + ) -> spvc_result; +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct __crt_locale_data { + pub _address: u8, +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct __crt_multibyte_data { + pub _address: u8, +} diff --git a/crates/htwv/third_party/SPIRV-Cross b/crates/htwv/third_party/SPIRV-Cross new file mode 160000 index 00000000..7bfcf72a --- /dev/null +++ b/crates/htwv/third_party/SPIRV-Cross @@ -0,0 +1 @@ +Subproject commit 7bfcf72ad28d1429deddff6c71b71c81b40b7063 diff --git a/crates/htwv/third_party/pmfx-shader b/crates/htwv/third_party/pmfx-shader new file mode 160000 index 00000000..a0a1e970 --- /dev/null +++ b/crates/htwv/third_party/pmfx-shader @@ -0,0 +1 @@ +Subproject commit a0a1e970d96deb5cd3b45f4c9450eff7adfe10bd From d0f6d6442a1fd131728e4c473e31097034fbafa1 Mon Sep 17 00:00:00 2001 From: polymonster Date: Fri, 27 Feb 2026 15:59:08 +0000 Subject: [PATCH 18/62] - client and plugins compiling, running and crashing --- .claude/settings.local.json | 5 +++- .vscode/launch.json | 12 ++++++-- build.rs | 1 - plugins/ecs_examples/src/claude.rs | 3 -- plugins/ecs_examples/src/lib.rs | 45 ++++++++++++++---------------- src/client.rs | 11 ++++++-- src/gfx/mtl.rs | 13 ++++++--- src/image.rs | 9 +++--- src/lib.rs | 3 ++ src/os/macos.rs | 2 +- 10 files changed, 61 insertions(+), 43 deletions(-) diff --git a/.claude/settings.local.json b/.claude/settings.local.json index a831cab5..bbe8b7b2 100644 --- a/.claude/settings.local.json +++ b/.claude/settings.local.json @@ -6,7 +6,10 @@ "Bash(cargo build:*)", "Bash(ls:*)", "Bash(python3:*)", - "Bash(cargo check:*)" + "Bash(cargo check:*)", + "Bash(cargo tree:*)", + "Bash(xargs:*)", + "Bash(cargo doc:*)" ] } } diff --git a/.vscode/launch.json b/.vscode/launch.json index 7465efd8..1598bec1 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -119,10 +119,18 @@ "program": "${workspaceFolder}/target/debug/examples/imgui_demo", "args": [], "stopAtEntry": false, - // "cwd": "${fileDirname}", "environment": [], "console": "externalTerminal", - // "preLaunchTask": "examples" + }, + { + "name": "client (macOS|Debug)", + "type": "lldb", + "request": "launch", + "program": "${workspaceFolder}/target/debug/client", + "args": [], + "stopAtEntry": false, + "environment": [], + "console": "externalTerminal", }, { "name": "imgui_demo (Win32|Debug)", diff --git a/build.rs b/build.rs index e3f65391..d8b515aa 100644 --- a/build.rs +++ b/build.rs @@ -39,7 +39,6 @@ fn main() { .unwrap_or(true); let pmbuild = "pmbuild"; - let status = Command::new(pmbuild) .args(["mac-data"]) .status() diff --git a/plugins/ecs_examples/src/claude.rs b/plugins/ecs_examples/src/claude.rs index c654f2c5..a6319a56 100644 --- a/plugins/ecs_examples/src/claude.rs +++ b/plugins/ecs_examples/src/claude.rs @@ -1,6 +1,3 @@ -// currently windows only because here we need a concrete gfx and os implementation -#![cfg(target_os = "windows")] - use crate::prelude::*; /// diff --git a/plugins/ecs_examples/src/lib.rs b/plugins/ecs_examples/src/lib.rs index bad6b22c..156d2201 100644 --- a/plugins/ecs_examples/src/lib.rs +++ b/plugins/ecs_examples/src/lib.rs @@ -1,6 +1,3 @@ -// currently windows only because here we need a concrete gfx and os implementation -#![cfg(target_os = "windows")] - /// Contains basic examples and unit tests of rendering and ecs functionality mod error_tests; mod draw; @@ -57,8 +54,8 @@ pub fn load_material( if !map_path.is_empty() { textures.push( image::load_texture_from_file( - device, - &format!("{}/{}", dir, map_path[0]), + device, + &format!("{}/{}", dir, map_path[0]), Some(&mut pmfx.shader_heap) ).unwrap() ); @@ -68,7 +65,7 @@ pub fn load_material( if textures.len() != 3 { return Err(hotline_rs::Error { msg: format!( - "hotline_rs::ecs:: error: material '{}' does not contain enough maps ({}/3)", + "hotline_rs::ecs:: error: material '{}' does not contain enough maps ({}/3)", dir, textures.len() ) @@ -207,8 +204,8 @@ const fn unit_aabb_corners() -> [Vec3f; 8] { pub fn batch_bindless_draw_data( mut pmfx: ResMut, draw_query: Query<(&WorldMatrix, &Extents)>) -> Result<(), hotline_rs::Error> { - - let world_buffers = pmfx.get_world_buffers_mut(); + + let world_buffers = pmfx.get_world_buffers_mut(); world_buffers.draw.clear(); world_buffers.extent.clear(); @@ -222,7 +219,7 @@ pub fn batch_bindless_draw_data( let emin = extents.aabb_min; let emax = extents.aabb_max; - + let transform_min = corners.iter().fold( Vec3f::max_value(), |acc, x| min(acc, world_matrix.0 * (emin + (emax - emin) * *x))); let transform_max = corners.iter().fold(-Vec3f::max_value(), |acc, x| max(acc, world_matrix.0 * (emin + (emax - emin) * *x))); @@ -249,7 +246,7 @@ pub fn render_meshes_bindless( Query<(&MeshComponent, &WorldMatrix), Without> ) ) -> Result<(), hotline_rs::Error> { - + let (instance_draw_query, single_draw_query) = queries; let pmfx = &pmfx; @@ -280,9 +277,9 @@ pub fn render_meshes_bindless( for i in 0..view.use_indices.len() { let num_constants = gfx::num_32bit_constants(&view.use_indices[i]); cmd_buf.push_compute_constants( - 0, - num_constants, - i as u32 * num_constants, + 0, + num_constants, + i as u32 * num_constants, gfx::as_u8_slice(&view.use_indices[i]) ); } @@ -325,7 +322,7 @@ pub fn render_meshes( Query<(&WorldMatrix, &MeshComponent), (With, Without)>, Query<(&WorldMatrix, &MeshComponent), With>, )) -> Result<(), hotline_rs::Error> { - + let fmt = view.pass.get_format_hash(); let pipeline = pmfx.get_render_pipeline_for_format(&view.view_pipeline, fmt)?; let camera = pmfx.get_camera_constants(&view.camera)?; @@ -399,7 +396,7 @@ pub fn render_debug( if session_info.debug_draw_flags.is_empty() { return Ok(()); } - + let fmt = view.pass.get_format_hash(); let pipeline = pmfx.get_render_pipeline_for_format("imdraw_3d", fmt)?; let camera = pmfx.get_camera_constants(&view.camera)?; @@ -421,7 +418,7 @@ pub fn render_debug( if i % 20 == 0 { tint *= 0.125; } - + imdraw.add_line_3d(Vec3f::new(offset, 0.0, -scale), Vec3f::new(offset, 0.0, scale), Vec4f::from(tint)); imdraw.add_line_3d(Vec3f::new(-scale, 0.0, offset), Vec3f::new(scale, 0.0, offset), Vec4f::from(tint)); } @@ -456,7 +453,7 @@ pub fn render_debug( imdraw.add_frustum(constants.view_projection_matrix, Vec4f::white()); } } - + // submit the buffers imdraw.submit(&mut device.0, bb as usize).unwrap(); @@ -475,7 +472,7 @@ pub fn blit( view: &pmfx::View, cmd_buf: &mut ::CmdBuf ) -> Result<(), hotline_rs::Error> { - + let pmfx = &pmfx; let fmt = view.pass.get_format_hash(); let pipeline = pmfx.get_render_pipeline_for_format("imdraw_blit", fmt)?; @@ -510,7 +507,7 @@ pub fn cubemap_clear( view: &pmfx::View, cmd_buf: &mut ::CmdBuf ) -> Result<(), hotline_rs::Error> { - + let pmfx = &pmfx; let fmt = view.pass.get_format_hash(); let pipeline = pmfx.get_render_pipeline_for_format("cubemap_clear", fmt)?; @@ -557,16 +554,16 @@ pub fn dispatch_compute( for i in 0..pass.use_indices.len() { let num_constants = gfx::num_32bit_constants(&pass.use_indices[i]); cmd_buf.push_compute_constants( - slot.index, - num_constants, - i as u32 * num_constants, + slot.index, + num_constants, + i as u32 * num_constants, gfx::as_u8_slice(&pass.use_indices[i]) ); } } cmd_buf.set_heap(pipeline, &pmfx.shader_heap); - + cmd_buf.dispatch( pass.group_count, pass.numthreads @@ -648,7 +645,7 @@ pub fn update_tlas( } ); } - + if let Some(tlas) = t.tlas.as_ref() { let instance_buffer = device.create_raytracing_instance_buffer(&instances)?; cmd_buf.update_raytracing_tlas(tlas, &instance_buffer, instances.len(), gfx::AccelerationStructureRebuildMode::Refit); diff --git a/src/client.rs b/src/client.rs index fca0fbda..c074a72b 100644 --- a/src/client.rs +++ b/src/client.rs @@ -547,8 +547,15 @@ impl Client where D: gfx::Device, A: os::App, D::RenderPipeline: gfx ], }; - if !std::path::Path::new(&lib_path).join(name.to_string() + ".dll").exists() { - println!("hotline_rs::client:: plugin not found: {}/{}", lib_path, name); + #[cfg(target_os = "windows")] + let lib_file = format!("{}.dll", name); + #[cfg(target_os = "macos")] + let lib_file = format!("lib{}.dylib", name); + #[cfg(target_os = "linux")] + let lib_file = format!("lib{}.so", name); + + if !std::path::Path::new(&lib_path).join(&lib_file).exists() { + println!("hotline_rs::client:: plugin not found: {}/{}", lib_path, lib_file); return; } diff --git a/src/gfx/mtl.rs b/src/gfx/mtl.rs index a8e490bb..5ebeb934 100644 --- a/src/gfx/mtl.rs +++ b/src/gfx/mtl.rs @@ -694,6 +694,7 @@ impl super::CmdBuf for CmdBuf { } } +#[derive(Clone)] pub struct Buffer { metal_buffer: metal::Buffer, element_stride: usize @@ -1332,9 +1333,11 @@ impl super::Device for Device { fn create_cmd_buf(&self, num_buffers: u32) -> CmdBuf { objc::rc::autoreleasepool(|| { + let cmd_queue = self.command_queue.clone(); + let cmd = cmd_queue.new_command_buffer().to_owned(); CmdBuf { - cmd_queue: self.command_queue.clone(), - cmd: None, + cmd_queue, + cmd: Some(cmd), render_encoder: None, compute_encoder: None, bound_index_buffer: None, @@ -1354,14 +1357,16 @@ impl super::Device for Device { if let Some(vs) = info.vs { unsafe { let lib = self.metal_device.new_library_with_data(std::slice::from_raw_parts(vs.data, vs.data_size))?; - let vvs = lib.get_function("vs_main", None).unwrap(); + let name = &lib.function_names()[0]; + let vvs = lib.get_function(name, None).unwrap(); pipeline_state_descriptor.set_vertex_function(Some(&vvs)); } }; if let Some(fs) = info.fs { unsafe { let lib = self.metal_device.new_library_with_data(std::slice::from_raw_parts(fs.data, fs.data_size))?; - let pps = lib.get_function("ps_main", None).unwrap(); + let name = &lib.function_names()[0]; + let pps = lib.get_function(name, None).unwrap(); pipeline_state_descriptor.set_fragment_function(Some(&pps)); } }; diff --git a/src/image.rs b/src/image.rs index a8316add..653ab206 100644 --- a/src/image.rs +++ b/src/image.rs @@ -29,7 +29,7 @@ pub fn load_from_file(filename: &str) -> Result { let mut f = fs::File::open(path).expect("hotline_rs::image:: File not found"); // dds file if filename.ends_with(".dds") { - let dds = DDS::read(f)?; + let dds = DDS::read(f)?; Ok(ImageData { info: TextureInfo { tex_type: to_gfx_texture_type(&dds), @@ -72,7 +72,7 @@ pub fn load_from_file(filename: &str) -> Result { let data_size_bytes = x * y * 4; data_out.resize(data_size_bytes as usize, 0); std::ptr::copy_nonoverlapping(img, data_out.as_mut_ptr(), data_size_bytes as usize); - + // cleanup stb_image_rust::c_runtime::free(img); @@ -96,14 +96,13 @@ pub fn load_from_file(filename: &str) -> Result { } /// Loads an image from file and creates a shader resource on the specified heap, or on the device heap if `heap.is_none()` -#[cfg(target_os = "windows")] pub fn load_texture_from_file( device: &mut crate::gfx_platform::Device, file: &str, heap: Option<&mut crate::gfx_platform::Heap>) -> Result { let image = load_from_file(file)?; device.create_texture_with_heaps( - &image.info, + &image.info, gfx::TextureHeapInfo { shader: heap, ..Default::default() @@ -391,7 +390,7 @@ fn to_gfx_format(dds: &DDS) -> gfx::Format { DxgiFormat::Y216 => panic!(), DxgiFormat::NV11 => panic!(), DxgiFormat::AI44 => panic!(), - DxgiFormat::IA44 => panic!(), + DxgiFormat::IA44 => panic!(), DxgiFormat::P8 => panic!(), DxgiFormat::A8P8 => panic!(), DxgiFormat::B4G4R4A4_UNorm => panic!(), diff --git a/src/lib.rs b/src/lib.rs index 84df5dba..8eb23049 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -242,8 +242,11 @@ pub mod prelude { // modules gfx, os, + client, + plugin, pmfx, imgui, + image, // platform specific gfx_platform, diff --git a/src/os/macos.rs b/src/os/macos.rs index dc89c1e1..7753259a 100644 --- a/src/os/macos.rs +++ b/src/os/macos.rs @@ -493,7 +493,7 @@ impl super::App for App { /// Sets the console window rect that belongs to this app fn set_console_window_rect(&self, rect: super::Rect) { - panic!(); + // stub } } From 2e380dd821a4b5796730ee9526f619a2f2d426e4 Mon Sep 17 00:00:00 2001 From: polymonster Date: Fri, 27 Feb 2026 16:58:16 +0000 Subject: [PATCH 19/62] draw.rs, almost --- plugins/ecs_examples/src/draw.rs | 7 +- src/gfx/mtl.rs | 127 +++++++++++++++++----- src/imgui.rs | 2 +- src/pmfx.rs | 178 +++++++++++++++---------------- 4 files changed, 195 insertions(+), 119 deletions(-) diff --git a/plugins/ecs_examples/src/draw.rs b/plugins/ecs_examples/src/draw.rs index 70efc887..9c1a9fa2 100644 --- a/plugins/ecs_examples/src/draw.rs +++ b/plugins/ecs_examples/src/draw.rs @@ -1,6 +1,6 @@ /// /// Draw -/// +/// use crate::prelude::*; @@ -80,7 +80,10 @@ pub fn draw_meshes( let camera = pmfx.get_camera_constants(&view.camera)?; cmd_buf.set_render_pipeline(pipeline); - cmd_buf.push_render_constants(0, 16, 0, gfx::as_u8_slice(&camera.view_projection_matrix)); + + if let Some(c0) = pipeline.get_pipeline_slot(0, 0, gfx::DescriptorType::PushConstants) { + cmd_buf.push_render_constants(c0.index, 16, 0, gfx::as_u8_slice(&camera.view_projection_matrix)); + } for (_, mesh) in &mesh_draw_query { cmd_buf.set_vertex_buffer(&mesh.0.vb, 0); diff --git a/src/gfx/mtl.rs b/src/gfx/mtl.rs index 5ebeb934..e034cdbc 100644 --- a/src/gfx/mtl.rs +++ b/src/gfx/mtl.rs @@ -140,6 +140,54 @@ fn to_mtl_texture_usage(usage: TextureUsage) -> MTLTextureUsage { mtl_usage } +fn to_mtl_pixel_format(format: super::Format) -> metal::MTLPixelFormat { + match format { + super::Format::Unknown => metal::MTLPixelFormat::Invalid, + super::Format::R16n => metal::MTLPixelFormat::R16Unorm, + super::Format::R16u => metal::MTLPixelFormat::R16Uint, + super::Format::R16i => metal::MTLPixelFormat::R16Sint, + super::Format::R16f => metal::MTLPixelFormat::R16Float, + super::Format::R32u => metal::MTLPixelFormat::R32Uint, + super::Format::R32i => metal::MTLPixelFormat::R32Sint, + super::Format::R32f => metal::MTLPixelFormat::R32Float, + super::Format::RG16f => metal::MTLPixelFormat::RG16Float, + super::Format::RG16u => metal::MTLPixelFormat::RG16Uint, + super::Format::RG16i => metal::MTLPixelFormat::RG16Sint, + super::Format::RG32u => metal::MTLPixelFormat::RG32Uint, + super::Format::RG32i => metal::MTLPixelFormat::RG32Sint, + super::Format::RG32f => metal::MTLPixelFormat::RG32Float, + super::Format::RGB32u | + super::Format::RGB32i | + super::Format::RGB32f => panic!("hotline_rs::gfx::mtl RGB32 formats not supported in Metal"), + super::Format::RGBA8nSRGB => metal::MTLPixelFormat::RGBA8Unorm_sRGB, + super::Format::RGBA8n => metal::MTLPixelFormat::RGBA8Unorm, + super::Format::RGBA8u => metal::MTLPixelFormat::RGBA8Uint, + super::Format::RGBA8i => metal::MTLPixelFormat::RGBA8Sint, + super::Format::BGRA8n => metal::MTLPixelFormat::BGRA8Unorm, + super::Format::BGRX8n => metal::MTLPixelFormat::BGRA8Unorm, + super::Format::BGRA8nSRGB => metal::MTLPixelFormat::BGRA8Unorm_sRGB, + super::Format::BGRX8nSRGB => metal::MTLPixelFormat::BGRA8Unorm_sRGB, + super::Format::RGBA16u => metal::MTLPixelFormat::RGBA16Uint, + super::Format::RGBA16i => metal::MTLPixelFormat::RGBA16Sint, + super::Format::RGBA16f => metal::MTLPixelFormat::RGBA16Float, + super::Format::RGBA32u => metal::MTLPixelFormat::RGBA32Uint, + super::Format::RGBA32i => metal::MTLPixelFormat::RGBA32Sint, + super::Format::RGBA32f => metal::MTLPixelFormat::RGBA32Float, + super::Format::D32fS8X24u => metal::MTLPixelFormat::Depth32Float_Stencil8, + super::Format::D32f => metal::MTLPixelFormat::Depth32Float, + super::Format::D24nS8u => metal::MTLPixelFormat::Depth32Float_Stencil8, // D24S8 not supported on Apple Silicon + super::Format::D16n => metal::MTLPixelFormat::Depth16Unorm, + super::Format::BC1n => metal::MTLPixelFormat::BC1_RGBA, + super::Format::BC1nSRGB => metal::MTLPixelFormat::BC1_RGBA_sRGB, + super::Format::BC2n => metal::MTLPixelFormat::BC2_RGBA, + super::Format::BC2nSRGB => metal::MTLPixelFormat::BC2_RGBA_sRGB, + super::Format::BC3n => metal::MTLPixelFormat::BC3_RGBA, + super::Format::BC3nSRGB => metal::MTLPixelFormat::BC3_RGBA_sRGB, + super::Format::BC4n => metal::MTLPixelFormat::BC4_RUnorm, + super::Format::BC5n => metal::MTLPixelFormat::BC5_RGUnorm, + } +} + fn to_mtl_data_type(resource_type: super::ResourceType) -> metal::MTLDataType { match resource_type { super::ResourceType::StructuredBuffer | @@ -199,6 +247,7 @@ impl super::SwapChain for SwapChain { self.backbuffer_texture = Texture { metal_texture: drawable.texture().to_owned(), srv_index: None, + uav_index: None, heap_id: None }; @@ -818,6 +867,7 @@ impl super::Pipeline for RenderPipeline { pub struct Texture { metal_texture: metal::Texture, srv_index: Option, + uav_index: Option, heap_id: Option } @@ -842,6 +892,7 @@ impl super::Texture for Texture { Texture { metal_texture: self.metal_texture.clone(), srv_index: self.srv_index, + uav_index: self.uav_index, heap_id: self.heap_id } } @@ -1255,7 +1306,7 @@ impl super::Device for Device { // feature info let tier = device.argument_buffers_support(); - assert_eq!(metal::MTLArgumentBuffersTier::Tier2, tier); //TODO: message + assert_eq!(metal::MTLArgumentBuffersTier::Tier2, tier); Device { command_queue: command_queue, @@ -1312,6 +1363,7 @@ impl super::Device for Device { let backbuffer_texture = Texture { metal_texture: drawable.texture().to_owned(), srv_index: None, + uav_index: None, heap_id: None }; let render_pass = self.create_render_pass_for_swap_chain(&backbuffer_texture, info.clear_colour); @@ -1614,7 +1666,8 @@ impl super::Device for Device { let opt = metal::MTLResourceOptions::CPUCacheModeDefaultCache | metal::MTLResourceOptions::StorageModeManaged; - let byte_len = size as NSUInteger; + // Metal doesn't allow zero-size buffers + let byte_len = size.max(1) as NSUInteger; let buf = self.metal_device.new_buffer(byte_len, opt); Ok(Buffer{ @@ -1629,27 +1682,41 @@ impl super::Device for Device { info: &super::TextureInfo, data: Option<&[T]>, ) -> result::Result { + self.create_texture_with_heaps( + info, + TextureHeapInfo::default(), + data, + ) + } + + fn create_texture_with_heaps( + &mut self, + info: &TextureInfo, + heaps: TextureHeapInfo, + data: Option<&[T]>, + ) -> result::Result { objc::rc::autoreleasepool(|| { let desc = TextureDescriptor::new(); // TODO: // tex_type - // format // initial_state // desc - desc.set_pixel_format(metal::MTLPixelFormat::RGBA8Unorm); // TODO: format - + desc.set_pixel_format(to_mtl_pixel_format(info.format)); desc.set_width(info.width as NSUInteger); desc.set_height(info.height as NSUInteger); desc.set_depth(info.depth as NSUInteger); desc.set_array_length(info.array_layers as NSUInteger); desc.set_mipmap_level_count(info.mip_levels as NSUInteger); - desc.set_sample_count(info.samples as NSUInteger); desc.set_usage(to_mtl_texture_usage(info.usage)); desc.set_storage_mode(metal::MTLStorageMode::Shared); desc.set_texture_type(metal::MTLTextureType::D2); + // TODO: multi sample + // desc.set_sample_count(info.samples as NSUInteger); + desc.set_sample_count(1); + // heap bindless let tex = self.shader_heap.mtl_heap.new_texture(&desc) .expect("hotline_rs::gfx::mtl failed to allocate texture in heap!"); @@ -1671,31 +1738,37 @@ impl super::Device for Device { ); } - // srv - let srv_index = self.shader_heap.allocate(); - self.shader_heap.texture_slots[srv_index] = Some(tex.to_owned()); + let shader_heap = if let Some(shader_heap) = heaps.shader { + shader_heap + } + else { + &mut self.shader_heap + }; - Ok(Texture{ - metal_texture: tex, - srv_index: Some(srv_index), - heap_id: Some(self.shader_heap.id) - }) - }) - } + // allocate on the heap + let alloc_index = shader_heap.allocate(); + shader_heap.texture_slots[alloc_index] = Some(tex.to_owned()); + + // assign srv or uav + let srv_index = if info.usage.contains(TextureUsage::SHADER_RESOURCE) { + Some(alloc_index) + } + else { + None + }; + + let uav_index = if info.usage.contains(TextureUsage::UNORDERED_ACCESS) { + Some(alloc_index) + } + else { + None + }; - fn create_texture_with_heaps( - &mut self, - info: &TextureInfo, - heaps: TextureHeapInfo, - data: Option<&[T]>, - ) -> result::Result { - objc::rc::autoreleasepool(|| { - let desc = TextureDescriptor::new(); - let tex = self.metal_device.new_texture(&desc); Ok(Texture{ metal_texture: tex, - srv_index: None, - heap_id: Some(self.shader_heap.id) + srv_index, + uav_index, + heap_id: Some(shader_heap.id) }) }) } diff --git a/src/imgui.rs b/src/imgui.rs index 68b61f28..798cbd94 100644 --- a/src/imgui.rs +++ b/src/imgui.rs @@ -496,7 +496,7 @@ fn render_draw_data( cmd.set_binding(pipeline, 0, 0, gfx::DescriptorType::ShaderResource, device.get_shader_heap(), srv); } else { - // bund srv in another heap + // bound srv in another heap for heap in image_heaps { if heap.get_heap_id() == heap_id { cmd.set_binding(pipeline, 0, 0, gfx::DescriptorType::ShaderResource, heap, srv); diff --git a/src/pmfx.rs b/src/pmfx.rs index 6bcec06e..ef4302c4 100644 --- a/src/pmfx.rs +++ b/src/pmfx.rs @@ -1,4 +1,4 @@ -#![allow(clippy::collapsible_if)] +#![allow(clippy::collapsible_if)] use crate::gfx::Buffer; use crate::gfx::PipelineStatistics; @@ -36,7 +36,7 @@ use std::hash::{Hash, Hasher}; pub struct ResourceUse { pub index: u32, pub dimension: Vec3u -} +} /// Everything you need to render a world view; command buffers will be automatically reset and submitted for you. pub struct View { @@ -121,7 +121,7 @@ struct TrackedTexture { _tex_type: gfx::TextureType, } -/// Information to track changes to +/// Information to track changes to struct PmfxTrackingInfo { /// Filepath to the data which the pmfx File was deserialised from filepath: std::path::PathBuf, @@ -132,7 +132,7 @@ struct PmfxTrackingInfo { // pipelines (name) > permutation (mask : u32) which is tuple (build_hash, pipeline) type FormatPipelineMap = HashMap>; -// hash of the view in .0, the view itself in .1 the source view name which was used to generate the instance is stored in .2, +// hash of the view in .0, the view itself in .1 the source view name which was used to generate the instance is stored in .2, type TrackedView = (PmfxHash, Arc>>, String); type TrackedComputePass = (PmfxHash, Arc>>); @@ -147,8 +147,8 @@ pub struct Pmfx { pmfx: File, /// Tracking info for check on data reloads, grouped by pmfx name pmfx_tracking: HashMap, - /// Folder paths for - pmfx_folders: HashMap, + /// Folder paths for + pmfx_folders: HashMap, /// Updated by calling 'update_window' this will cause any tracked textures to check for resizes and rebuild textures if necessary window_sizes: HashMap, /// Nested structure of: format (u64) > FormatPipelineMap @@ -203,7 +203,7 @@ pub struct TotalStats { pub gpu_start: f64, /// Time of the final submission in seconds pub gpu_end: f64, - /// Total pipeline statistics + /// Total pipeline statistics pub pipeline_stats: PipelineStatistics } @@ -237,7 +237,7 @@ impl PassStats where D: gfx::Device { pub fn new_query_buffer(device: &mut D, elem_size: usize, num_elems: usize) -> D::Buffer { device.create_read_back_buffer(elem_size * num_elems).unwrap() } - + pub fn new(device: &mut D, num_buffers: usize) -> Self { let mut timestamp_buffers = Vec::new(); let mut fences = Vec::new(); @@ -291,7 +291,7 @@ struct File { dependencies: Vec } -/// pmfx File serialisation, +/// pmfx File serialisation, impl File { /// creates a new empty pmfx fn new() -> Self { @@ -358,7 +358,7 @@ struct RaytracingShaderBindingTableInfo { callable_shaders: Vec } -/// Enum for possible pipeline types +/// Enum for possible pipeline types #[derive(Clone)] pub enum PipelineType { None, @@ -627,7 +627,7 @@ pub struct CameraConstants { #[derive(Clone)] pub struct DrawData { /// World matrix for transforming entity - pub world_matrix: Mat34f, + pub world_matrix: Mat34f, } /// GPU friendly struct containing single entity draw data @@ -637,10 +637,10 @@ pub struct ExtentData { /// Centre pos of aabb pub pos: Vec3f, /// Half extent of aabb - pub extent: Vec3f + pub extent: Vec3f } -/// GPU friendly structure containing lookup id's for bindless materials +/// GPU friendly structure containing lookup id's for bindless materials #[repr(C)] #[derive(Clone)] pub struct MaterialData { @@ -735,7 +735,7 @@ pub fn cubemap_camera_face(face: usize, pos: Vec3f, near: f32, far: f32) -> Came vec3f(1.0, 0.0, 0.0), //+x vec3f(-1.0, 0.0, 0.0), //-x vec3f(0.0, 1.0, 0.0), //+y - vec3f(0.0, -1.0, 0.0), //-y + vec3f(0.0, -1.0, 0.0), //-y vec3f(0.0, 0.0, 1.0), //+z vec3f(0.0, 0.0, -1.0) //-z ]; @@ -779,7 +779,7 @@ pub fn cubemap_camera_face(face: usize, pos: Vec3f, near: f32, far: f32) -> Came fn create_shader_from_file(device: &D, folder: &Path, file: Option) -> Result, super::Error> { if let Some(shader) = file { let shader_filepath = folder.join(shader); - let shader_data = fs::read(shader_filepath)?; + let shader_data = fs::read(shader_filepath)?; let shader_info = gfx::ShaderInfo { shader_type: gfx::ShaderType::Vertex, compile_info: None @@ -851,9 +851,9 @@ fn to_gfx_texture_info(pmfx_texture: &TextureInfo, ratio_size: (u64, u64)) -> gf let (width, height) = ratio_size; // infer texture type from dimensions - let tex_type = if pmfx_texture.cubemap { + let tex_type = if pmfx_texture.cubemap { gfx::TextureType::TextureCube - } + } else if pmfx_texture.depth > 1 { gfx::TextureType::Texture3D } @@ -1063,8 +1063,8 @@ impl Pmfx where D: gfx::Device { /// Load a pmfx from a folder, where the folder contains a pmfx info.json and shader binaries in separate files within the directory /// You can load multiple pmfx files which will be merged together, shaders are grouped by pmfx_name/ps_main.psc - /// Render graphs and pipleines must have unique names, if multiple pmfx name a pipeline the same name - pub fn load(&mut self, filepath: &str) -> Result<(), super::Error> { + /// Render graphs and pipleines must have unique names, if multiple pmfx name a pipeline the same name + pub fn load(&mut self, filepath: &str) -> Result<(), super::Error> { // get the name for indexing by pmfx name/folder let folder = Path::new(filepath); let pmfx_name = if let Some(name) = folder.file_name() { @@ -1081,19 +1081,19 @@ impl Pmfx where D: gfx::Device { let info_filepath = folder.join(format!("{}.json", pmfx_name)); let pmfx_data = fs::read(&info_filepath)?; let file : File = serde_json::from_slice(&pmfx_data)?; - + // create tracking info to check if the pmfx has been rebuilt let file_metadata = fs::metadata(&info_filepath)?; e.insert(PmfxTrackingInfo { modified_time: file_metadata.modified()?, filepath: info_filepath }); - + // add files from pmfx for tracking for dep in &file.dependencies { self.reloader.add_file(dep); } - + // merge into pmfx self.merge_pmfx(file, filepath); } @@ -1314,7 +1314,7 @@ impl Pmfx where D: gfx::Device { /// Retruns a vector of resource use indices specified in `pmfx` pass and based on `ResourceUsage` /// creates resources that do not yet exist fn get_resource_use_indices(&mut self, device: &mut D, info: &GraphPassInfo) -> Result, super::Error> { - // create textures we may use + // create textures we may use let mut use_indices = Vec::new(); if let Some(uses) = &info.uses { for (resource, usage) in uses { @@ -1371,15 +1371,15 @@ impl Pmfx where D: gfx::Device { } fn create_view_pass_inner( - &mut self, device: - &mut D, view_name: &str, - graph_pass_name: &str, + &mut self, device: + &mut D, view_name: &str, + graph_pass_name: &str, info: &GraphPassInfo, pmfx_view: &ViewInfo, array_slice: usize, cubemap: bool ) -> Result<(), super::Error> { - + // make a custom name for multi pass let graph_pass_multi_name = if array_slice > 0 { format!("{}_{}", graph_pass_name, array_slice) @@ -1515,7 +1515,7 @@ impl Pmfx where D: gfx::Device { self.pass_stats.insert(graph_pass_multi_name.to_string(), PassStats::new(device, 2)); Ok(()) - } + } /// Create a view pass from information specified in pmfx file fn create_view_pass(&mut self, device: &mut D, view_name: &str, graph_pass_name: &str, info: &GraphPassInfo) -> Result<(), super::Error> { @@ -1526,7 +1526,7 @@ impl Pmfx where D: gfx::Device { // create pass from targets let pmfx_view = self.pmfx.views[view_name].clone(); - // create textures for view + // create textures for view let mut cubemap = false; for name in &pmfx_view.render_target { self.create_texture(device, name)?; @@ -1635,7 +1635,7 @@ impl Pmfx where D: gfx::Device { let mut hash = DefaultHasher::new(); graph_pass_name.hash(&mut hash); let colour_hash : u32 = hash.finish() as u32 | 0xff000000; - + let pass = ComputePass { phantom_data: std::marker::PhantomData, pass_pipline: pass_pipeline, @@ -1745,9 +1745,9 @@ impl Pmfx where D: gfx::Device { fn create_resolve_transition( &mut self, device: &mut D, - texture_barriers: &mut HashMap, - view_name: &str, - texture_name: &str, + texture_barriers: &mut HashMap, + view_name: &str, + texture_name: &str, target_state: ResourceState) -> Result<(), super::Error> { if texture_barriers.contains_key(texture_name) { let state = texture_barriers[texture_name]; @@ -1780,7 +1780,7 @@ impl Pmfx where D: gfx::Device { }, Subresource::ResolveResource ); - + // perform the resolve cmd_buf.resolve_texture_subresource(tex, 0)?; @@ -1814,21 +1814,21 @@ impl Pmfx where D: gfx::Device { fn create_texture_transition_barrier( &mut self, device: &mut D, - texture_barriers: &mut HashMap, - view_name: &str, - texture_name: &str, + texture_barriers: &mut HashMap, + view_name: &str, + texture_name: &str, target_state: ResourceState) -> Result<(), super::Error> { if texture_barriers.contains_key(texture_name) { let state = texture_barriers[texture_name]; if state != target_state { // add barrier placeholder in the command_queue let barrier_name = format!("barrier_{}-{} ({:?})", view_name, texture_name, target_state); - self.command_queue.push(barrier_name.to_string()); + self.command_queue.push(barrier_name.to_string()); // create a command buffer let mut cmd_buf = device.create_cmd_buf(1); cmd_buf.begin_event( - 0xfff1b023, + 0xfff1b023, &format!("transition_barrier: {} ({} -> {})", &texture_name, state, target_state) ); cmd_buf.transition_barrier(&gfx::TransitionBarrier { @@ -1840,7 +1840,7 @@ impl Pmfx where D: gfx::Device { cmd_buf.end_event(); cmd_buf.close()?; self.barriers.insert(barrier_name, cmd_buf); - + // update track state texture_barriers.remove(texture_name); texture_barriers.insert(texture_name.to_string(), target_state); @@ -1857,8 +1857,8 @@ impl Pmfx where D: gfx::Device { } /// Create a render graph wih automatic resource barrier generation from info specified insie .pmfx file - pub fn create_render_graph(&mut self, device: &mut D, graph_name: &str) -> Result<(), super::Error> { - // go through the graph sequentially, as the command lists are executed in order but generated + pub fn create_render_graph(&mut self, device: &mut D, graph_name: &str) -> Result<(), super::Error> { + // go through the graph sequentially, as the command lists are executed in order but generated if self.pmfx.render_graphs.contains_key(graph_name) { // create views for any nodes in the graph @@ -1869,16 +1869,16 @@ impl Pmfx where D: gfx::Device { self.command_queue.clear(); let mut barriers = self.pmfx.textures.iter().filter(|tex|{ - tex.1.usage.contains(&ResourceState::ShaderResource) || + tex.1.usage.contains(&ResourceState::ShaderResource) || tex.1.usage.contains(&ResourceState::RenderTarget) || tex.1.usage.contains(&ResourceState::DepthStencil) }).map(|tex|{ - (tex.0.to_string(), ResourceState::ShaderResource) + (tex.0.to_string(), ResourceState::ShaderResource) }).collect::>(); // loop over the graph multiple times adding views in depends on order, until we add all the views let mut to_add = self.pmfx.render_graphs[graph_name].len(); - + let mut added = 0; let mut dependencies = HashSet::new(); while added < to_add { @@ -1893,12 +1893,12 @@ impl Pmfx where D: gfx::Device { continue; } } - + // already added this pass if dependencies.contains(graph_pass_name) { continue; } - + // wait for dependencies if let Some(depends_on) = &instance.depends_on { let mut passes = false; @@ -1906,7 +1906,7 @@ impl Pmfx where D: gfx::Device { for d in depends_on { if !pmfx_graph.contains_key(d) { passes = true; - println!("hotline_rs::pmfx:: [warning] graph pass {} missing dependency {}. ignoring", + println!("hotline_rs::pmfx:: [warning] graph pass {} missing dependency {}. ignoring", graph_pass_name, d); } else if dependencies.contains(d) { @@ -1962,21 +1962,21 @@ impl Pmfx where D: gfx::Device { // resolve and generate mips if resolve { self.create_resolve_transition( - device, - &mut barriers, - &graph_pass_name, + device, + &mut barriers, + &graph_pass_name, &u.0, ResourceState::ShaderResource, )?; } - + // generate mips on non msaa resources if gen_mips { // generate_mip_maps mips expects us to be in ShaderResource state self.create_texture_transition_barrier( - device, - &mut barriers, - &graph_pass_name, + device, + &mut barriers, + &graph_pass_name, &u.0, ResourceState::ShaderResource)?; @@ -1988,14 +1988,14 @@ impl Pmfx where D: gfx::Device { // transition to target state self.create_texture_transition_barrier( - device, - &mut barriers, - &graph_pass_name, + device, + &mut barriers, + &graph_pass_name, &u.0, res_state)?; } } - + if let Some(view) = &instance.view { // create transitions by inspecting view info let pmfx_view = self.pmfx.views[view].clone(); @@ -2004,14 +2004,14 @@ impl Pmfx where D: gfx::Device { for rt_name in pmfx_view.render_target { self.create_texture_transition_barrier( device, &mut barriers, view, &rt_name, ResourceState::RenderTarget)?; - + } - + // same for depth stencils for ds_name in pmfx_view.depth_stencil { self.create_texture_transition_barrier( device, &mut barriers, view, &ds_name, ResourceState::DepthStencil)?; - + } // create pipelines requested for this view instance with the pass format @@ -2052,7 +2052,7 @@ impl Pmfx where D: gfx::Device { dependencies.insert(graph_pass_name.to_string()); } } - + // finally all targets which are in the 'barriers' array are transitioned to shader resources (for debug views) let srvs = barriers.keys().map(|k|{ k.to_string() @@ -2061,7 +2061,7 @@ impl Pmfx where D: gfx::Device { for name in srvs { let result = self.create_resolve_transition( device, &mut barriers, "eof", &name, ResourceState::ShaderResource); - + if result.is_err() { // TODO: tell user without spewing out errors } @@ -2109,7 +2109,7 @@ impl Pmfx where D: gfx::Device { } /// Create a ComputePipeline instance for the combination of pmfx_pipeline settings - pub fn create_compute_pipeline(&mut self, device: &D, pipeline_name: &str) -> Result<(), super::Error> { + pub fn create_compute_pipeline(&mut self, device: &D, pipeline_name: &str) -> Result<(), super::Error> { if self.pmfx.pipelines.contains_key(pipeline_name) { // first create shaders if necessary let folder = self.pmfx_folders.get(pipeline_name) @@ -2119,7 +2119,7 @@ impl Pmfx where D: gfx::Device { self.create_shader(device, Path::new(&folder), &pipeline.cs)?; } - for (_, pipeline) in self.pmfx.pipelines[pipeline_name].clone() { + for (_, pipeline) in self.pmfx.pipelines[pipeline_name].clone() { let cs = self.get_shader(&pipeline.cs); if let Some(cs) = cs { let pso = device.create_compute_pipeline(&gfx::ComputePipelineInfo { @@ -2131,7 +2131,7 @@ impl Pmfx where D: gfx::Device { // TODO: permutations //let mask = permutation.parse().unwrap(); //permutations.insert(mask, (pipeline.hash, pso)); - + self.compute_pipelines.insert(pipeline_name.to_string(), (pipeline.hash, pso)); } } @@ -2146,27 +2146,27 @@ impl Pmfx where D: gfx::Device { } /// Create a RenderPipeline instance for the combination of pmfx_pipeline settings and an associated RenderPass - pub fn create_render_pipeline(&mut self, device: &D, pipeline_name: &str, pass: &D::RenderPass) -> Result<(), super::Error> { + pub fn create_render_pipeline(&mut self, device: &D, pipeline_name: &str, pass: &D::RenderPass) -> Result<(), super::Error> { if self.pmfx.pipelines.contains_key(pipeline_name) { // first create shaders if necessary let folder = self.pmfx_folders.get(pipeline_name) .unwrap_or_else(|| panic!("hotline_rs::pmfx:: expected to find pipeline {} in pmfx_folders", pipeline_name)).to_string(); - + for (_, pipeline) in self.pmfx.pipelines[pipeline_name].clone() { self.create_shader(device, Path::new(&folder), &pipeline.vs)?; self.create_shader(device, Path::new(&folder), &pipeline.ps)?; } - + // create entry for this format if it does not exist let fmt = pass.get_format_hash(); let format_pipeline = self.render_pipelines.entry(fmt).or_insert(HashMap::new()); - + // create entry for this pipeline permutation set if it does not exist if !format_pipeline.contains_key(pipeline_name) { println!("hotline_rs::pmfx:: creating pipeline: {}", pipeline_name); format_pipeline.insert(pipeline_name.to_string(), HashMap::new()); // we create a pipeline per-permutation - for (permutation, pipeline) in self.pmfx.pipelines[pipeline_name].clone() { + for (permutation, pipeline) in self.pmfx.pipelines[pipeline_name].clone() { let vertex_layout = pipeline.vertex_layout.as_ref().unwrap(); let pso = device.create_render_pipeline(&gfx::RenderPipelineInfo { vs: self.get_shader(&pipeline.vs), @@ -2182,10 +2182,10 @@ impl Pmfx where D: gfx::Device { pass: Some(pass), ..Default::default() })?; - + println!("hotline_rs::pmfx:: compiled render pipeline: {}", pipeline_name); let format_pipeline = self.render_pipelines.get_mut(&fmt).unwrap(); - let permutations = format_pipeline.get_mut(pipeline_name).unwrap(); + let permutations = format_pipeline.get_mut(pipeline_name).unwrap(); let mask = permutation.parse().unwrap(); permutations.insert(mask, (pipeline.hash, pso)); @@ -2215,9 +2215,9 @@ impl Pmfx where D: gfx::Device { self.create_shader(device, Path::new(&folder), &Some(shader))?; } } - + // for each permutation create a pipeline - for (_, pipeline) in self.pmfx.pipelines[pipeline_name].clone() { + for (_, pipeline) in self.pmfx.pipelines[pipeline_name].clone() { let shaders = pipeline.lib.expect("hotline_rs::pmfx:: ray tracing pipeline expects a lib member with a set of raytacing shaders") .iter() .map(|x| gfx::RaytracingShader { @@ -2262,7 +2262,7 @@ impl Pmfx where D: gfx::Device { self.get_render_pipeline_permutation_for_format(pipeline_name, 0, format_hash) } - /// Returns a pmfx pipline for a random / unknown render target format... prefer to use `get_render_pipeline_for_format` + /// Returns a pmfx pipline for a random / unknown render target format... prefer to use `get_render_pipeline_for_format` /// if you know the format the target you are rendering in to. pub fn get_render_pipeline<'stack>(&'stack self, pipeline_name: &str) -> Result<&'stack D::RenderPipeline, super::Error> { for format in self.render_pipelines.values() { @@ -2305,7 +2305,7 @@ impl Pmfx where D: gfx::Device { }) } } - + /// Fetch a prebuilt RaytracingPipelineBinding which is contains a RaytracingPipeline and RaytracingShaderBindingTable pub fn get_raytracing_pipeline<'stack>(&'stack self, pipeline_name: &str) -> Result<&'stack RaytracingPipelineBinding, super::Error> { if self.raytracing_pipelines.contains_key(pipeline_name) { @@ -2336,7 +2336,7 @@ impl Pmfx where D: gfx::Device { if !timestamps.is_empty() { stats.start_timestamp = timestamps[0]; min_frame_timestamp = min(stats.start_timestamp, min_frame_timestamp); - + } // end timestamp let timestamps = device.read_timestamps( @@ -2387,7 +2387,7 @@ impl Pmfx where D: gfx::Device { } /// Reload all active resources based on hashes - pub fn reload(&mut self, device: &mut D) -> Result<(), super::Error> { + pub fn reload(&mut self, device: &mut D) -> Result<(), super::Error> { let reload_paths = self.pmfx_tracking.iter_mut().filter(|(_, tracking)| { fs::metadata(&tracking.filepath).unwrap().modified().unwrap() > tracking.modified_time }).map(|tracking| { @@ -2399,7 +2399,7 @@ impl Pmfx where D: gfx::Device { if !reload_filepath.is_empty() { println!("hotline_rs::pmfx:: reload from {}", reload_filepath); let pmfx_data = fs::read(&reload_filepath).expect("hotline_rs::pmfx:: failed to read file"); - + let file : File = serde_json::from_slice(&pmfx_data)?; self.merge_pmfx(file, PathBuf::from(&reload_filepath).parent().unwrap().to_str().unwrap()); @@ -2474,11 +2474,11 @@ impl Pmfx where D: gfx::Device { println!("hotline::pmfx:: reloading shader: {}", shader); self.shaders.remove(shader); } - + // reload pipelines tuple = (format_hash, pipeline_name, permutation_mask) for pipeline in &reload_pipelines { println!("hotline::pmfx:: reloading pipeline: {}", pipeline.1); - + // TODO: here we could only remove affected permutations let format_pipelines = self.render_pipelines.get_mut(&pipeline.0).unwrap(); format_pipelines.remove(&pipeline.1); @@ -2507,7 +2507,7 @@ impl Pmfx where D: gfx::Device { }); } - // + // if rebuild_graph { self.create_render_graph(device, &self.active_render_graph.to_string())?; } @@ -2637,7 +2637,7 @@ impl Pmfx where D: gfx::Device { // view pipeline stats pass_stats.pipeline_stats_heap.reset(); pass_stats.pipeline_query_index = cmd_buf.begin_query( - &mut pass_stats.pipeline_stats_heap, + &mut pass_stats.pipeline_stats_heap, gfx::QueryType::PipelineStatistics ); } @@ -2651,7 +2651,7 @@ impl Pmfx where D: gfx::Device { if pass_stats.pipeline_query_index != usize::max_value() { let buf = &mut pass_stats.pipeline_stats_buffers[pass_stats.write_index]; cmd_buf.end_query( - &mut pass_stats.pipeline_stats_heap, + &mut pass_stats.pipeline_stats_heap, gfx::QueryType::PipelineStatistics, pass_stats.pipeline_query_index, buf, @@ -2758,7 +2758,7 @@ impl imgui::UserInterface for Pmfx where D: gfx::Device, A: os::A let mut imgui_open = open; if imgui.begin("textures", &mut imgui_open, imgui::WindowFlags::ALWAYS_HORIZONTAL_SCROLLBAR) { for texture in self.textures.values() { - + let thumb_size = 256.0; let aspect = texture.1.size.0 as f32 / texture.1.size.1 as f32; let w = thumb_size * aspect; @@ -2818,7 +2818,7 @@ impl imgui::UserInterface for Pmfx where D: gfx::Device, A: os::A imgui.end(); imgui_open - } + } else { false } @@ -2842,7 +2842,7 @@ impl PmfxReloadResponder { impl ReloadResponder for PmfxReloadResponder { fn add_file(&mut self, filepath: &str) { self.files.push(filepath.to_string()); - } + } fn get_files(&self) -> Vec { self.files.to_vec() From 30c62b8e2bf2a9422ee0088a099d253c7425b534 Mon Sep 17 00:00:00 2001 From: polymonster Date: Fri, 27 Feb 2026 17:19:52 +0000 Subject: [PATCH 20/62] - correctly setup use of different heaps --- src/gfx/mtl.rs | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/src/gfx/mtl.rs b/src/gfx/mtl.rs index e034cdbc..aef8773e 100644 --- a/src/gfx/mtl.rs +++ b/src/gfx/mtl.rs @@ -205,7 +205,8 @@ pub struct Device { metal_device: metal::Device, command_queue: metal::CommandQueue, shader_heap: Heap, - adapter_info: AdapterInfo + adapter_info: AdapterInfo, + heap_alloc_id: u16, } #[derive(Clone)] @@ -1316,7 +1317,8 @@ impl super::Device for Device { debug_name: Some("mtl device: shader heap".to_string()) }, 1), adapter_info: adapter_info, - metal_device: device + metal_device: device, + heap_alloc_id: 2 } }) } @@ -1326,7 +1328,9 @@ impl super::Device for Device { } fn create_heap(&mut self, info: &HeapInfo) -> Heap { - Self::create_heap_mtl(&self.metal_device, &info, 2) + let id = self.heap_alloc_id; + self.heap_alloc_id += 1; + Self::create_heap_mtl(&self.metal_device, &info, id) } fn create_query_heap(&self, info: &QueryHeapInfo) -> QueryHeap { @@ -1717,8 +1721,16 @@ impl super::Device for Device { // desc.set_sample_count(info.samples as NSUInteger); desc.set_sample_count(1); + // use supplied heap or fallback to the device default + let shader_heap = if let Some(shader_heap) = heaps.shader { + shader_heap + } + else { + &mut self.shader_heap + }; + // heap bindless - let tex = self.shader_heap.mtl_heap.new_texture(&desc) + let tex = shader_heap.mtl_heap.new_texture(&desc) .expect("hotline_rs::gfx::mtl failed to allocate texture in heap!"); // data @@ -1738,13 +1750,6 @@ impl super::Device for Device { ); } - let shader_heap = if let Some(shader_heap) = heaps.shader { - shader_heap - } - else { - &mut self.shader_heap - }; - // allocate on the heap let alloc_index = shader_heap.allocate(); shader_heap.texture_slots[alloc_index] = Some(tex.to_owned()); From 0b0481a88089ff9d702853e50b5b762d3bb71ac7 Mon Sep 17 00:00:00 2001 From: polymonster Date: Fri, 27 Feb 2026 18:52:39 +0000 Subject: [PATCH 21/62] - binding architecture --- src/gfx/mtl.rs | 344 ++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 282 insertions(+), 62 deletions(-) diff --git a/src/gfx/mtl.rs b/src/gfx/mtl.rs index aef8773e..93a76c7d 100644 --- a/src/gfx/mtl.rs +++ b/src/gfx/mtl.rs @@ -302,6 +302,19 @@ pub struct CmdBuf { bound_index_stride: usize, /// Raw pointer to bound render pipeline (valid during render pass) bound_render_pipeline: Option<*const RenderPipeline>, + /// Device reference for allocating transient buffers + metal_device: metal::Device, + /// Transient argument buffers allocated per frame (for bindful/push constants) + /// These are allocated on-the-fly and kept alive until the command buffer completes + transient_buffers: Vec, + /// Transient argument encoders (cached for reuse) + transient_texture_encoder: metal::ArgumentEncoder, + transient_buffer_encoder: metal::ArgumentEncoder, + transient_pointer_encoder: metal::ArgumentEncoder, + /// Argument buffers for bindful, keyed by (buffer_index, heap_id) + /// Accumulates multiple textures into one buffer per (slot, heap) pair + current_fragment_arg_buffers: HashMap<(u32, u16), (metal::Buffer, metal::ArgumentEncoder)>, + current_vertex_arg_buffers: HashMap<(u32, u16), (metal::Buffer, metal::ArgumentEncoder)>, } impl Clone for CmdBuf { @@ -314,6 +327,13 @@ impl Clone for CmdBuf { bound_index_buffer: self.bound_index_buffer.clone(), bound_index_stride: self.bound_index_stride, bound_render_pipeline: self.bound_render_pipeline, + metal_device: self.metal_device.clone(), + transient_buffers: self.transient_buffers.clone(), + transient_texture_encoder: self.transient_texture_encoder.clone(), + transient_buffer_encoder: self.transient_buffer_encoder.clone(), + transient_pointer_encoder: self.transient_pointer_encoder.clone(), + current_fragment_arg_buffers: self.current_fragment_arg_buffers.clone(), + current_vertex_arg_buffers: self.current_vertex_arg_buffers.clone(), } } } @@ -322,6 +342,11 @@ impl super::CmdBuf for CmdBuf { fn reset(&mut self, swap_chain: &SwapChain) { objc::rc::autoreleasepool(|| { self.cmd = Some(self.cmd_queue.new_command_buffer().to_owned()); + // Clear transient buffers from previous frame + self.transient_buffers.clear(); + // Clear argument buffer caches + self.current_fragment_arg_buffers.clear(); + self.current_vertex_arg_buffers.clear(); }); } @@ -473,67 +498,35 @@ impl super::CmdBuf for CmdBuf { // Cast pipeline to RenderPipeline to access slot_lookup let rp: &RenderPipeline = unsafe { std::mem::transmute(pipeline) }; - // Track which argument buffers we've already bound (they're shared across texture slots) + // Track which buffer indices we've already bound let mut bound_vertex_buffers: std::collections::HashSet = std::collections::HashSet::new(); let mut bound_fragment_buffers: std::collections::HashSet = std::collections::HashSet::new(); - // Encode resources and bind shared argument buffer - for ((_register, _space, _descriptor_type), slot) in &rp.slot_lookup { - // Skip push constants (they have data_buffer) + // Bind heap's pre-encoded argument buffers to the slots specified by the pipeline + for slot in rp.slot_lookup.values() { + // Skip push constants if slot.data_buffer.is_some() { continue; } - // Set up the argument buffer for encoding - slot.argument_encoder.set_argument_buffer(&slot.argument_buffer, 0); - - // Check if this is an array binding (bindless) or single resource (bindful) - let count = slot.info.count.unwrap_or(1) as usize; - - match slot.data_type { - Some(metal::MTLDataType::Pointer) => { - // Buffer binding - if count > 1 { - for i in 0..count.min(heap.buffer_slots.len()) { - if let Some(buffer) = heap.buffer_slots.get(i).and_then(|b| b.as_ref()) { - slot.argument_encoder.set_buffer(i as u64, buffer, 0); - } - } - } - else { - if let Some(buffer) = heap.buffer_slots.get(slot.binding_index as usize).and_then(|b| b.as_ref()) { - slot.argument_encoder.set_buffer(slot.binding_index as u64, buffer, 0); - } - } - }, - Some(metal::MTLDataType::Texture) => { - // Texture binding - if count > 1 { - for i in 0..count.min(heap.texture_slots.len()) { - if let Some(texture) = heap.texture_slots.get(i).and_then(|t| t.as_ref()) { - slot.argument_encoder.set_texture(i as u64, texture); - } - } - } else { - if let Some(texture) = heap.texture_slots.get(slot.binding_index as usize).and_then(|t| t.as_ref()) { - slot.argument_encoder.set_texture(slot.binding_index as u64, texture); - } - } - }, - _ => { - unimplemented!(); - } - } + // Get the appropriate heap argument buffer based on data type + let arg_buffer = match slot.data_type { + Some(metal::MTLDataType::Texture) => heap.get_texture_argument_buffer(), + Some(metal::MTLDataType::Pointer) => heap.get_buffer_argument_buffer(), + _ => continue, + }; - // Bind the argument buffer only once per stage (it's shared across all slots) + // Bind to vertex stage if needed (once per buffer index) if let Some(vertex_idx) = slot.vertex_buffer_index { if bound_vertex_buffers.insert(vertex_idx as u64) { - encoder.set_vertex_buffer(vertex_idx as u64, Some(&slot.argument_buffer), 0); + encoder.set_vertex_buffer(vertex_idx as u64, Some(arg_buffer), 0); } } + + // Bind to fragment stage if needed (once per buffer index) if let Some(fragment_idx) = slot.fragment_buffer_index { if bound_fragment_buffers.insert(fragment_idx as u64) { - encoder.set_fragment_buffer(fragment_idx as u64, Some(&slot.argument_buffer), 0); + encoder.set_fragment_buffer(fragment_idx as u64, Some(arg_buffer), 0); } } } @@ -550,26 +543,101 @@ impl super::CmdBuf for CmdBuf { let rp: &RenderPipeline = unsafe { std::mem::transmute(pipeline) }; // Look up the slot by (register, space, descriptor_type) - if let Some(slot) = rp.slot_lookup.get(&(register, space, descriptor_type)) { - slot.argument_encoder.set_argument_buffer(&slot.argument_buffer, 0); + let slot = rp.slot_lookup.get(&(register, space, descriptor_type))?; + let data_type = slot.data_type?; + + // Handle fragment stage binding + if let Some(frag_idx) = slot.fragment_buffer_index { + // Key by (buffer_index, heap_id) to support multi-heap while accumulating textures + let frag_key = (frag_idx, heap.id); + + // Get or create argument buffer for this (buffer_index, heap_id) + if !self.current_fragment_arg_buffers.contains_key(&frag_key) { + let space_info = rp.fragment_space_buffers.get(&frag_idx)?; + + let arg_desc = metal::ArgumentDescriptor::new(); + arg_desc.set_index(0); + arg_desc.set_data_type(space_info.data_type); + arg_desc.set_array_length(space_info.array_length); + arg_desc.set_access(metal::MTLArgumentAccess::ReadOnly); - // Set texture from heap at offset, using binding_index for position in shared buffer - if let Some(texture) = heap.texture_slots.get(offset).and_then(|t| t.as_ref()) { - slot.argument_encoder.set_texture(slot.binding_index as u64, texture); + let arg_encoder = self.metal_device.new_argument_encoder( + metal::Array::from_owned_slice(&[arg_desc.to_owned()]) + ); + let arg_buffer = self.metal_device.new_buffer( + arg_encoder.encoded_length(), + metal::MTLResourceOptions::StorageModeShared + ); + + // Keep buffer alive until command buffer completes + self.transient_buffers.push(arg_buffer.clone()); + self.current_fragment_arg_buffers.insert(frag_key, (arg_buffer, arg_encoder)); } - // Bind to appropriate stage(s) - if let Some(vertex_idx) = slot.vertex_buffer_index { - encoder.set_vertex_buffer(vertex_idx as u64, Some(&slot.argument_buffer), 0); + let (arg_buffer, arg_encoder) = self.current_fragment_arg_buffers.get(&frag_key)?; + + // Encode the resource at the correct id_offset (binding_index) + arg_encoder.set_argument_buffer(arg_buffer, 0); + match data_type { + metal::MTLDataType::Texture => { + let texture = heap.texture_slots.get(offset).and_then(|t| t.as_ref())?; + arg_encoder.set_texture(slot.binding_index as u64, texture); + }, + metal::MTLDataType::Pointer => { + let buffer = heap.buffer_slots.get(offset).and_then(|b| b.as_ref())?; + arg_encoder.set_buffer(slot.binding_index as u64, buffer, 0); + }, + _ => return None, } - if let Some(fragment_idx) = slot.fragment_buffer_index { - encoder.set_fragment_buffer(fragment_idx as u64, Some(&slot.argument_buffer), 0); + + // Bind the argument buffer + encoder.set_fragment_buffer(frag_idx as u64, Some(arg_buffer), 0); + } + + // Handle vertex stage binding (similar logic) + if let Some(vert_idx) = slot.vertex_buffer_index { + let vert_key = (vert_idx, heap.id); + + if !self.current_vertex_arg_buffers.contains_key(&vert_key) { + let space_info = rp.vertex_space_buffers.get(&vert_idx)?; + + let arg_desc = metal::ArgumentDescriptor::new(); + arg_desc.set_index(0); + arg_desc.set_data_type(space_info.data_type); + arg_desc.set_array_length(space_info.array_length); + arg_desc.set_access(metal::MTLArgumentAccess::ReadOnly); + + let arg_encoder = self.metal_device.new_argument_encoder( + metal::Array::from_owned_slice(&[arg_desc.to_owned()]) + ); + let arg_buffer = self.metal_device.new_buffer( + arg_encoder.encoded_length(), + metal::MTLResourceOptions::StorageModeShared + ); + + self.transient_buffers.push(arg_buffer.clone()); + self.current_vertex_arg_buffers.insert(vert_key, (arg_buffer, arg_encoder)); } - Some(()) - } else { - None + let (arg_buffer, arg_encoder) = self.current_vertex_arg_buffers.get(&vert_key)?; + + arg_encoder.set_argument_buffer(arg_buffer, 0); + match data_type { + metal::MTLDataType::Texture => { + let texture = heap.texture_slots.get(offset).and_then(|t| t.as_ref())?; + arg_encoder.set_texture(slot.binding_index as u64, texture); + }, + metal::MTLDataType::Pointer => { + let buffer = heap.buffer_slots.get(offset).and_then(|b| b.as_ref())?; + arg_encoder.set_buffer(slot.binding_index as u64, buffer, 0); + }, + _ => return None, + } + + encoder.set_vertex_buffer(vert_idx as u64, Some(arg_buffer), 0); } + + Some(()) } fn set_marker(&mut self, colour: u32, name: &str) { @@ -836,6 +904,16 @@ pub struct PipelineSlot { /// Key for slot lookup: (register, space, descriptor_type) type SlotKey = (u32, u32, DescriptorType); +/// Info about argument buffer requirements for a specific buffer index +/// Used for on-the-fly allocation in set_binding +#[derive(Clone)] +pub struct SpaceBufferInfo { + /// Number of elements in the argument buffer (max binding_index + 1) + pub array_length: u64, + /// Data type (Texture or Pointer) + pub data_type: metal::MTLDataType, +} + pub struct RenderPipeline { pipeline_state: metal::RenderPipelineState, static_samplers: Vec, @@ -846,6 +924,11 @@ pub struct RenderPipeline { sampler_argument_buffer: Option, /// Primitive topology for draw calls topology: Topology, + /// Info about argument buffer requirements per fragment buffer index + /// Used for on-the-fly allocation in set_binding + fragment_space_buffers: HashMap, + /// Info about argument buffer requirements per vertex buffer index + vertex_space_buffers: HashMap, } impl super::RenderPipeline for RenderPipeline {} @@ -977,7 +1060,15 @@ pub struct Heap { buffer_slots: Vec>, resource_type: Vec, offset: usize, - id: u16 + id: u16, + /// Argument encoder for bindless texture access (pre-encodes all textures) + texture_argument_encoder: metal::ArgumentEncoder, + /// Pre-encoded argument buffer containing all texture references + texture_argument_buffer: metal::Buffer, + /// Argument encoder for bindless buffer access + buffer_argument_encoder: metal::ArgumentEncoder, + /// Pre-encoded argument buffer containing all buffer references + buffer_argument_buffer: metal::Buffer, } impl Heap { @@ -991,6 +1082,28 @@ impl Heap { self.resource_type.resize(self.offset, HeapResourceType::None); srv } + + /// Encode a texture into the heap's argument buffer at the given index (for bindless) + fn encode_texture(&self, index: usize, texture: &metal::Texture) { + self.texture_argument_encoder.set_argument_buffer(&self.texture_argument_buffer, 0); + self.texture_argument_encoder.set_texture(index as u64, texture); + } + + /// Encode a buffer into the heap's argument buffer at the given index (for bindless) + fn encode_buffer(&self, index: usize, buffer: &metal::Buffer) { + self.buffer_argument_encoder.set_argument_buffer(&self.buffer_argument_buffer, 0); + self.buffer_argument_encoder.set_buffer(index as u64, buffer, 0); + } + + /// Get the pre-encoded texture argument buffer for binding + pub fn get_texture_argument_buffer(&self) -> &metal::Buffer { + &self.texture_argument_buffer + } + + /// Get the pre-encoded buffer argument buffer for binding + pub fn get_buffer_argument_buffer(&self) -> &metal::Buffer { + &self.buffer_argument_buffer + } } impl super::Heap for Heap { @@ -1076,13 +1189,48 @@ impl Device { let heap = mtl_device.new_heap(&heap_descriptor); + // Create texture argument encoder for bindless access + let max_resources = info.num_descriptors.max(1) as u64; + let tex_arg_desc = metal::ArgumentDescriptor::new(); + tex_arg_desc.set_index(0); + tex_arg_desc.set_data_type(metal::MTLDataType::Texture); + tex_arg_desc.set_array_length(max_resources); + tex_arg_desc.set_access(metal::MTLArgumentAccess::ReadOnly); + + let texture_argument_encoder = mtl_device.new_argument_encoder( + metal::Array::from_owned_slice(&[tex_arg_desc.to_owned()]) + ); + let texture_argument_buffer = mtl_device.new_buffer( + texture_argument_encoder.encoded_length(), + metal::MTLResourceOptions::StorageModeShared + ); + + // Create buffer argument encoder for bindless access + let buf_arg_desc = metal::ArgumentDescriptor::new(); + buf_arg_desc.set_index(0); + buf_arg_desc.set_data_type(metal::MTLDataType::Pointer); + buf_arg_desc.set_array_length(max_resources); + buf_arg_desc.set_access(metal::MTLArgumentAccess::ReadOnly); + + let buffer_argument_encoder = mtl_device.new_argument_encoder( + metal::Array::from_owned_slice(&[buf_arg_desc.to_owned()]) + ); + let buffer_argument_buffer = mtl_device.new_buffer( + buffer_argument_encoder.encoded_length(), + metal::MTLResourceOptions::StorageModeShared + ); + Heap { mtl_heap: heap, texture_slots: Vec::new(), buffer_slots: Vec::new(), resource_type: Vec::new(), offset: 0, - id + id, + texture_argument_encoder, + texture_argument_buffer, + buffer_argument_encoder, + buffer_argument_buffer, } } @@ -1391,6 +1539,37 @@ impl super::Device for Device { objc::rc::autoreleasepool(|| { let cmd_queue = self.command_queue.clone(); let cmd = cmd_queue.new_command_buffer().to_owned(); + + // Create transient encoders for on-the-fly argument buffer encoding + // Texture encoder (single texture at [[id(0)]]) + let tex_desc = metal::ArgumentDescriptor::new(); + tex_desc.set_index(0); + tex_desc.set_data_type(metal::MTLDataType::Texture); + tex_desc.set_array_length(1); + tex_desc.set_access(metal::MTLArgumentAccess::ReadOnly); + let transient_texture_encoder = self.metal_device.new_argument_encoder( + metal::Array::from_owned_slice(&[tex_desc.to_owned()]) + ); + + // Buffer encoder (single buffer at [[id(0)]]) + let buf_desc = metal::ArgumentDescriptor::new(); + buf_desc.set_index(0); + buf_desc.set_data_type(metal::MTLDataType::Pointer); + buf_desc.set_array_length(1); + buf_desc.set_access(metal::MTLArgumentAccess::ReadOnly); + let transient_buffer_encoder = self.metal_device.new_argument_encoder( + metal::Array::from_owned_slice(&[buf_desc.to_owned()]) + ); + + // Pointer encoder for push constants + let ptr_desc = metal::ArgumentDescriptor::new(); + ptr_desc.set_index(0); + ptr_desc.set_data_type(metal::MTLDataType::Pointer); + ptr_desc.set_access(metal::MTLArgumentAccess::ReadOnly); + let transient_pointer_encoder = self.metal_device.new_argument_encoder( + metal::Array::from_owned_slice(&[ptr_desc.to_owned()]) + ); + CmdBuf { cmd_queue, cmd: Some(cmd), @@ -1399,6 +1578,13 @@ impl super::Device for Device { bound_index_buffer: None, bound_index_stride: 0, bound_render_pipeline: None, + metal_device: self.metal_device.clone(), + transient_buffers: Vec::new(), + transient_texture_encoder, + transient_buffer_encoder, + transient_pointer_encoder, + current_fragment_arg_buffers: HashMap::new(), + current_vertex_arg_buffers: HashMap::new(), } }) } @@ -1540,6 +1726,35 @@ impl super::Device for Device { &info.pipeline_layout.push_constants, ); + // Compute space buffer info from slot_lookup + let mut fragment_space_buffers: HashMap = HashMap::new(); + let mut vertex_space_buffers: HashMap = HashMap::new(); + + for slot in slot_lookup.values() { + // Skip push constants (they have data_buffer) + if slot.data_buffer.is_some() { + continue; + } + + if let Some(data_type) = slot.data_type { + // Track max binding_index for each buffer index + if let Some(frag_idx) = slot.fragment_buffer_index { + let entry = fragment_space_buffers.entry(frag_idx).or_insert(SpaceBufferInfo { + array_length: 0, + data_type, + }); + entry.array_length = entry.array_length.max(slot.binding_index as u64 + 1); + } + if let Some(vert_idx) = slot.vertex_buffer_index { + let entry = vertex_space_buffers.entry(vert_idx).or_insert(SpaceBufferInfo { + array_length: 0, + data_type, + }); + entry.array_length = entry.array_length.max(slot.binding_index as u64 + 1); + } + } + } + let pipeline_state = self.metal_device.new_render_pipeline_state(&pipeline_state_descriptor)?; Ok(RenderPipeline { @@ -1549,6 +1764,8 @@ impl super::Device for Device { slot_lookup, sampler_argument_buffer, topology: info.topology, + fragment_space_buffers, + vertex_space_buffers, }) }) } @@ -1754,6 +1971,9 @@ impl super::Device for Device { let alloc_index = shader_heap.allocate(); shader_heap.texture_slots[alloc_index] = Some(tex.to_owned()); + // Encode texture into heap's argument buffer for bindless access + shader_heap.encode_texture(alloc_index, &tex); + // assign srv or uav let srv_index = if info.usage.contains(TextureUsage::SHADER_RESOURCE) { Some(alloc_index) From 08b1224ddb26cc318fc8fdfdc2d7bc87d4704b4f Mon Sep 17 00:00:00 2001 From: polymonster Date: Fri, 27 Feb 2026 19:06:30 +0000 Subject: [PATCH 22/62] - fix input issue in client macos --- shaders/imgui.hlsl | 4 +- src/os/macos.rs | 99 +++++++++++++++++++++------------------------- 2 files changed, 47 insertions(+), 56 deletions(-) diff --git a/shaders/imgui.hlsl b/shaders/imgui.hlsl index 120bdb27..814f314c 100644 --- a/shaders/imgui.hlsl +++ b/shaders/imgui.hlsl @@ -1,6 +1,6 @@ cbuffer proj_matrix : register(b0, space0) { - float4x4 ProjectionMatrix; + row_major float4x4 ProjectionMatrix; }; struct VS_INPUT @@ -21,7 +21,7 @@ struct PS_INPUT PS_INPUT vs_main(VS_INPUT input) { PS_INPUT output; - output.pos = mul(ProjectionMatrix, float4(input.pos.xy, 0.0, 1.0)); + output.pos = mul(float4(input.pos.xy, 0.0, 1.0), ProjectionMatrix); output.col = input.col; output.uv = input.uv; return output; diff --git a/src/os/macos.rs b/src/os/macos.rs index 7753259a..2fa48640 100644 --- a/src/os/macos.rs +++ b/src/os/macos.rs @@ -249,14 +249,12 @@ impl super::App for App { // Mouse cursor position (window-relative from winit) WindowEvent::CursorMoved { position, .. } => { - if state.mouse_enabled { - // winit gives us logical coordinates relative to window content area - state.mouse_client_pos = super::Point { - x: position.x as i32, - y: position.y as i32, - }; - state.hovered_window_id = Some(window_id); - } + // winit gives us logical coordinates relative to window content area + state.mouse_client_pos = super::Point { + x: position.x as i32, + y: position.y as i32, + }; + state.hovered_window_id = Some(window_id); } // Mouse enter/leave for hover tracking @@ -271,59 +269,53 @@ impl super::App for App { // Mouse buttons WindowEvent::MouseInput { state: element_state, button, .. } => { - if state.mouse_enabled { - let pressed = element_state == ElementState::Pressed; - // Map to MouseButton enum order: Left=0, Middle=1, Right=2, X1=3, X2=4 - let index = match button { - winit::event::MouseButton::Left => Some(super::MouseButton::Left as usize), - winit::event::MouseButton::Middle => Some(super::MouseButton::Middle as usize), - winit::event::MouseButton::Right => Some(super::MouseButton::Right as usize), - winit::event::MouseButton::Back => Some(super::MouseButton::X1 as usize), - winit::event::MouseButton::Forward => Some(super::MouseButton::X2 as usize), - winit::event::MouseButton::Other(_) => None, - }; - if let Some(idx) = index { - state.mouse_down[idx] = pressed; - } + let pressed = element_state == ElementState::Pressed; + // Map to MouseButton enum order: Left=0, Middle=1, Right=2, X1=3, X2=4 + let index = match button { + winit::event::MouseButton::Left => Some(super::MouseButton::Left as usize), + winit::event::MouseButton::Middle => Some(super::MouseButton::Middle as usize), + winit::event::MouseButton::Right => Some(super::MouseButton::Right as usize), + winit::event::MouseButton::Back => Some(super::MouseButton::X1 as usize), + winit::event::MouseButton::Forward => Some(super::MouseButton::X2 as usize), + winit::event::MouseButton::Other(_) => None, + }; + if let Some(idx) = index { + state.mouse_down[idx] = pressed; } } // Mouse wheel WindowEvent::MouseWheel { delta, .. } => { - if state.mouse_enabled { - match delta { - winit::event::MouseScrollDelta::LineDelta(h, v) => { - state.mouse_wheel += v; - state.mouse_hwheel += h; - } - winit::event::MouseScrollDelta::PixelDelta(pos) => { - // Convert pixel delta to line delta (approximate) - state.mouse_wheel += (pos.y / 20.0) as f32; - state.mouse_hwheel += (pos.x / 20.0) as f32; - } + match delta { + winit::event::MouseScrollDelta::LineDelta(h, v) => { + state.mouse_wheel += v; + state.mouse_hwheel += h; + } + winit::event::MouseScrollDelta::PixelDelta(pos) => { + // Convert pixel delta to line delta (approximate) + state.mouse_wheel += (pos.y / 20.0) as f32; + state.mouse_hwheel += (pos.x / 20.0) as f32; } } } // Keyboard input WindowEvent::KeyboardInput { event, .. } => { - if state.keyboard_enabled { - let pressed = event.state == ElementState::Pressed; - - // Get physical key code for key_down array - if let PhysicalKey::Code(key_code) = event.physical_key { - let code = key_code as usize; - if code < 256 { - state.key_down[code] = pressed; - } + let pressed = event.state == ElementState::Pressed; + + // Get physical key code for key_down array + if let PhysicalKey::Code(key_code) = event.physical_key { + let code = key_code as usize; + if code < 256 { + state.key_down[code] = pressed; } + } - // Handle text input from logical key - if pressed { - if let Key::Character(ref c) = event.logical_key { - for ch in c.encode_utf16() { - state.utf16_inputs.push(ch); - } + // Handle text input from logical key + if pressed { + if let Key::Character(ref c) = event.logical_key { + for ch in c.encode_utf16() { + state.utf16_inputs.push(ch); } } } @@ -331,12 +323,10 @@ impl super::App for App { // Modifier keys WindowEvent::ModifiersChanged(modifiers) => { - if state.keyboard_enabled { - let mods = modifiers.state(); - state.sys_key_down[super::SysKey::Ctrl as usize] = mods.control_key(); - state.sys_key_down[super::SysKey::Shift as usize] = mods.shift_key(); - state.sys_key_down[super::SysKey::Alt as usize] = mods.alt_key(); - } + let mods = modifiers.state(); + state.sys_key_down[super::SysKey::Ctrl as usize] = mods.control_key(); + state.sys_key_down[super::SysKey::Shift as usize] = mods.shift_key(); + state.sys_key_down[super::SysKey::Alt as usize] = mods.alt_key(); } _ => {} @@ -494,6 +484,7 @@ impl super::App for App { /// Sets the console window rect that belongs to this app fn set_console_window_rect(&self, rect: super::Rect) { // stub + } } From 0811c4a7ce6342de52c40ac0e26302c4c1007c1e Mon Sep 17 00:00:00 2001 From: polymonster Date: Sat, 28 Feb 2026 10:00:29 +0000 Subject: [PATCH 23/62] - fist couple of 3d samples working --- build.rs | 18 +++++------------ crates/htwv/third_party/pmfx-shader | 2 +- plugins/ecs_examples/src/draw_indexed.rs | 11 +++++++---- plugins/ecs_examples/src/draw_indirect.rs | 24 +++++++++++------------ shaders/draw.hlsl | 8 ++++---- shaders/ecs.hlsl | 8 ++++---- src/gfx/mtl.rs | 6 ++++-- 7 files changed, 37 insertions(+), 40 deletions(-) diff --git a/build.rs b/build.rs index d8b515aa..ac2ef215 100644 --- a/build.rs +++ b/build.rs @@ -26,18 +26,12 @@ fn main() { // Rerun when source shaders change println!("cargo:rerun-if-changed=shaders"); - // Rerun when output dir changes (including deletion) println!("cargo:rerun-if-changed=target/data/shaders"); + println!("cargo:rerun-if-changed=target/temp/shaders"); if std::env::var("CARGO_FEATURE_BUILD_DATA").is_ok() { let output_dir = Path::new("target/data/shaders"); - // Check if we actually need to rebuild - let needs_build = !output_dir.exists() - || std::fs::read_dir(output_dir) - .map(|mut d| d.next().is_none()) - .unwrap_or(true); - let pmbuild = "pmbuild"; let status = Command::new(pmbuild) .args(["mac-data"]) @@ -48,12 +42,10 @@ fn main() { panic!("pmbuild mac-data failed with status: {status}"); } - if needs_build { - println!("cargo:warning=Compiling shaders..."); - match htwv::compile_dir("shaders", "target/data/shaders") { - Ok(_) => println!("cargo:warning=Shader compilation succeeded"), - Err(e) => {} //panic!("Shader compilation failed: {e}"), - } + println!("cargo:warning=Compiling shaders..."); + match htwv::compile_dir("shaders", "target/data/shaders") { + Ok(_) => println!("cargo:warning=Shader compilation succeeded"), + Err(e) => {} //panic!("Shader compilation failed: {e}"), } } } \ No newline at end of file diff --git a/crates/htwv/third_party/pmfx-shader b/crates/htwv/third_party/pmfx-shader index a0a1e970..c0a93b8b 160000 --- a/crates/htwv/third_party/pmfx-shader +++ b/crates/htwv/third_party/pmfx-shader @@ -1 +1 @@ -Subproject commit a0a1e970d96deb5cd3b45f4c9450eff7adfe10bd +Subproject commit c0a93b8b10d706bddf1c01d6aaf51c37ca702216 diff --git a/plugins/ecs_examples/src/draw_indexed.rs b/plugins/ecs_examples/src/draw_indexed.rs index 0530971f..b105d446 100644 --- a/plugins/ecs_examples/src/draw_indexed.rs +++ b/plugins/ecs_examples/src/draw_indexed.rs @@ -2,7 +2,7 @@ /// Draw Indexed /// -use crate::prelude::*; +use crate::prelude::*; /// Sets up a single cube mesh to test draw indexed call with a single enity #[no_mangle] @@ -17,7 +17,7 @@ pub fn draw_indexed(client: &mut Client) } } -/// Set's up a single cube mesh. The draw all is made with `draw_meshes` in `draw.rs` +/// Set's up a single cube mesh. The draw all is made with `draw_meshes` in `draw.rs` #[export_update_fn] pub fn setup_draw_indexed( mut device: ResMut, @@ -44,13 +44,16 @@ pub fn draw_meshes_indexed( view: &pmfx::View, cmd_buf: &mut ::CmdBuf, mesh_draw_query: Query<(&WorldMatrix, &MeshComponent)>) -> Result<(), hotline_rs::Error> { - + let fmt = view.pass.get_format_hash(); let pipeline = pmfx.get_render_pipeline_for_format(&view.view_pipeline, fmt)?; let camera = pmfx.get_camera_constants(&view.camera)?; cmd_buf.set_render_pipeline(pipeline); - cmd_buf.push_render_constants(0, 16, 0, gfx::as_u8_slice(&camera.view_projection_matrix)); + + if let Some(c0) = pipeline.get_pipeline_slot(0, 0, gfx::DescriptorType::PushConstants) { + cmd_buf.push_render_constants(c0.index, 16, 0, gfx::as_u8_slice(&camera.view_projection_matrix)); + } for (_, mesh) in &mesh_draw_query { cmd_buf.set_vertex_buffer(&mesh.0.vb, 0); diff --git a/plugins/ecs_examples/src/draw_indirect.rs b/plugins/ecs_examples/src/draw_indirect.rs index 2bcf2810..4ed7b884 100644 --- a/plugins/ecs_examples/src/draw_indirect.rs +++ b/plugins/ecs_examples/src/draw_indirect.rs @@ -22,13 +22,13 @@ pub fn draw_indirect(client: &mut Client pub fn setup_draw_indirect( mut device: ResMut, mut commands: Commands) -> Result<(), hotline_rs::Error> { - + let scalar_scale = 10.0; let scale = Mat34f::from_scale(splat3f(scalar_scale)); // draw indirect let tri = hotline_rs::primitives::create_triangle_mesh(&mut device.0); - let pos = Mat34f::from_translation(vec3f(-scalar_scale, scalar_scale, 0.0)); + let pos = Mat34f::from_translation(vec3f(-scalar_scale, scalar_scale, 0.0)); let args = gfx::DrawArguments { vertex_count_per_instance: 3, @@ -50,7 +50,7 @@ pub fn setup_draw_indirect( vec![gfx::IndirectArgument{ argument_type: gfx::IndirectArgumentType::Draw, arguments: None - }], + }], None ).unwrap(); @@ -65,7 +65,7 @@ pub fn setup_draw_indirect( // draw indexed indirect let teapot = hotline_rs::primitives::create_teapot_mesh(&mut device.0, 8); - let pos = Mat34f::from_translation(vec3f(scalar_scale, scalar_scale, 0.0)); + let pos = Mat34f::from_translation(vec3f(scalar_scale, scalar_scale, 0.0)); let args = gfx::DrawIndexedArguments { index_count_per_instance: teapot.num_indices, @@ -88,7 +88,7 @@ pub fn setup_draw_indirect( vec![gfx::IndirectArgument{ argument_type: gfx::IndirectArgumentType::DrawIndexed, arguments: None - }], + }], None ).unwrap(); @@ -110,9 +110,9 @@ pub fn draw_meshes_indirect( pmfx: &Res, view: &pmfx::View, cmd_buf: &mut ::CmdBuf, - mesh_draw_indirect_query: Query<(&WorldMatrix, &MeshComponent, &CommandSignatureComponent, &BufferComponent)>) + mesh_draw_indirect_query: Query<(&WorldMatrix, &MeshComponent, &CommandSignatureComponent, &BufferComponent)>) -> Result<(), hotline_rs::Error> { - + let fmt = view.pass.get_format_hash(); let pipeline = pmfx.get_render_pipeline_for_format(&view.view_pipeline, fmt)?; let camera = pmfx.get_camera_constants(&view.camera)?; @@ -126,11 +126,11 @@ pub fn draw_meshes_indirect( cmd_buf.set_vertex_buffer(&mesh.0.vb, 0); cmd_buf.execute_indirect( - &command.0, - 1, - &args.0, - 0, - None, + &command.0, + 1, + &args.0, + 0, + None, 0 ); } diff --git a/shaders/draw.hlsl b/shaders/draw.hlsl index 19feca05..6c3773c3 100644 --- a/shaders/draw.hlsl +++ b/shaders/draw.hlsl @@ -19,7 +19,7 @@ vs_output vs_mesh_identity(vs_input_mesh input) { output.texcoord = float4(input.texcoord, 0.0, 0.0); output.colour = float4(1.0, 1.0, 1.0, 1.0); output.normal = input.normal.xyz; - + return output; } @@ -39,13 +39,13 @@ vs_output vs_mesh(vs_input_mesh input) { output.texcoord = float4(input.texcoord, 0.0, 0.0); output.colour = material_colour; output.normal = normalize(mul(rot, input.normal.xyz)); - + return output; } // // textureles checkboard shader -// +// float4 ps_checkerboard(vs_output input) : SV_Target { float4 output = float4(input.normal.xyz * 0.5 + 0.5, 1.0); @@ -73,7 +73,7 @@ float4 ps_checkerboard(vs_output input) : SV_Target { // debug switches // u gradient //colour.rgb = uv_gradient(u % 1.0); - + // v gradient //colour.rgb = uv_gradient(v % 1.0); diff --git a/shaders/ecs.hlsl b/shaders/ecs.hlsl index b79bb24d..55da224a 100644 --- a/shaders/ecs.hlsl +++ b/shaders/ecs.hlsl @@ -18,13 +18,13 @@ struct ps_output { // per view constants with basic camera transforms cbuffer view_push_constants : register(b0) { - float4x4 view_projection_matrix; + row_major float4x4 view_projection_matrix; float4 view_position; } // per entity draw constants used in CPU draw calls cbuffer draw_push_constants : register(b1) { - float3x4 world_matrix; + row_major float3x4 world_matrix; float4 material_colour; uint4 draw_indices; } @@ -61,7 +61,7 @@ ConstantBuffer resources: register(b0, space1); // bindless draw data for entites to look up by ID struct draw_data { - float3x4 world_matrix; + row_major float3x4 world_matrix; } // bindless material ID's which can be looked up into textures array @@ -118,7 +118,7 @@ struct directional_light_data { // camera data struct camera_data { - float4x4 view_projection_matrix; + row_major float4x4 view_projection_matrix; float4 view_position; float4 planes[6]; } diff --git a/src/gfx/mtl.rs b/src/gfx/mtl.rs index 93a76c7d..bea255ca 100644 --- a/src/gfx/mtl.rs +++ b/src/gfx/mtl.rs @@ -652,6 +652,8 @@ impl super::CmdBuf for CmdBuf { if let Some(pipeline_ptr) = self.bound_render_pipeline { let pipeline = unsafe { &*pipeline_ptr }; + let data_size_bytes = (num_values * 4) as usize; + // Find slot with matching buffer index for pipeline_slot in pipeline.slot_lookup.values() { if pipeline_slot.info.index == slot && pipeline_slot.data_buffer.is_some() { @@ -660,7 +662,7 @@ impl super::CmdBuf for CmdBuf { let data_bytes = unsafe { std::slice::from_raw_parts( data.as_ptr() as *const u8, - std::mem::size_of_val(data) + data_size_bytes ) }; let dest_ptr = data_buffer.contents() as *mut u8; @@ -669,7 +671,7 @@ impl super::CmdBuf for CmdBuf { std::ptr::copy_nonoverlapping( data_bytes.as_ptr(), dest_ptr.add(dest_offset_bytes), - data_bytes.len() + data_size_bytes ); } From a043c5531dc0eaf4b97f9be98a802f1b42e78b09 Mon Sep 17 00:00:00 2001 From: polymonster Date: Sat, 28 Feb 2026 10:13:22 +0000 Subject: [PATCH 24/62] - row major --- shaders/imdraw.hlsl | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/shaders/imdraw.hlsl b/shaders/imdraw.hlsl index bdba2069..135e3c16 100644 --- a/shaders/imdraw.hlsl +++ b/shaders/imdraw.hlsl @@ -28,7 +28,7 @@ struct ps_output { }; cbuffer view_push_constants : register(b0) { - float4x4 projection_matrix; + row_major float4x4 projection_matrix; }; struct vs_input_mesh { @@ -41,16 +41,16 @@ struct vs_input_mesh { vs_output vs_2d( vs_input_2d input ) { vs_output output; - + output.position = mul(projection_matrix, float4(input.position.xy, 0.0, 1.0)); output.colour = input.colour; - + return output; } ps_output ps_main( vs_output input ) { ps_output output; - + output.colour = input.colour; return output; @@ -63,7 +63,7 @@ vs_output vs_3d( vs_input_3d input ) float4 pos = float4(input.position.xyz, 1.0); output.position = mul(projection_matrix, pos); output.colour = input.colour; - + return output; } From 4c031aceee97eae7ebfceb2e16bfce57e4d89be4 Mon Sep 17 00:00:00 2001 From: polymonster Date: Sat, 28 Feb 2026 17:14:23 +0000 Subject: [PATCH 25/62] - refactoring binding encoding --- src/gfx.rs | 2 +- src/gfx/mtl.rs | 223 ++++++++++++++++++------------------------------- 2 files changed, 82 insertions(+), 143 deletions(-) diff --git a/src/gfx.rs b/src/gfx.rs index e78ddb39..c800daa8 100644 --- a/src/gfx.rs +++ b/src/gfx.rs @@ -436,7 +436,7 @@ pub struct ShaderCompileInfo { } /// The stage to which a shader will bind itself. -#[derive(Copy, Clone)] +#[derive(Copy, Clone, PartialEq, Eq, Hash)] pub enum ShaderType { Vertex, Fragment, diff --git a/src/gfx/mtl.rs b/src/gfx/mtl.rs index 98fce18f..58e55487 100644 --- a/src/gfx/mtl.rs +++ b/src/gfx/mtl.rs @@ -28,6 +28,8 @@ use core_graphics_types::geometry::CGSize; use std::path::Path; +type BindingEncoderKey = (super::ShaderType, u32, u16); + const MEGA_BYTE : usize = 1024 * 1024 * 1024; const fn to_mtl_vertex_format(format: super::Format) -> MTLVertexFormat { @@ -300,21 +302,10 @@ pub struct CmdBuf { compute_encoder: Option, bound_index_buffer: Option, bound_index_stride: usize, - /// Raw pointer to bound render pipeline (valid during render pass) bound_render_pipeline: Option<*const RenderPipeline>, - /// Device reference for allocating transient buffers metal_device: metal::Device, - /// Transient argument buffers allocated per frame (for bindful/push constants) - /// These are allocated on-the-fly and kept alive until the command buffer completes transient_buffers: Vec, - /// Transient argument encoders (cached for reuse) - transient_texture_encoder: metal::ArgumentEncoder, - transient_buffer_encoder: metal::ArgumentEncoder, - transient_pointer_encoder: metal::ArgumentEncoder, - /// Argument buffers for bindful, keyed by (buffer_index, heap_id) - /// Accumulates multiple textures into one buffer per (slot, heap) pair - current_fragment_arg_buffers: HashMap<(u32, u16), (metal::Buffer, metal::ArgumentEncoder)>, - current_vertex_arg_buffers: HashMap<(u32, u16), (metal::Buffer, metal::ArgumentEncoder)>, + binding_encoders: HashMap, } impl Clone for CmdBuf { @@ -329,15 +320,70 @@ impl Clone for CmdBuf { bound_render_pipeline: self.bound_render_pipeline, metal_device: self.metal_device.clone(), transient_buffers: self.transient_buffers.clone(), - transient_texture_encoder: self.transient_texture_encoder.clone(), - transient_buffer_encoder: self.transient_buffer_encoder.clone(), - transient_pointer_encoder: self.transient_pointer_encoder.clone(), - current_fragment_arg_buffers: self.current_fragment_arg_buffers.clone(), - current_vertex_arg_buffers: self.current_vertex_arg_buffers.clone(), + binding_encoders: self.binding_encoders.clone() } } } +impl CmdBuf { + fn encode_binding(&mut self, stage: super::ShaderType, binding_index: u32, space_info: &SpaceBufferInfo, slot: &PipelineSlot, heap: &Heap, offset: usize) -> Option<()> { + let key = (stage, binding_index, heap.id); + if !self.binding_encoders.contains_key(&key) { + let arg_desc = metal::ArgumentDescriptor::new(); + arg_desc.set_index(0); + arg_desc.set_data_type(space_info.data_type); + arg_desc.set_array_length(space_info.array_length); + arg_desc.set_access(metal::MTLArgumentAccess::ReadOnly); + + let arg_encoder = self.metal_device.new_argument_encoder( + metal::Array::from_owned_slice(&[arg_desc.to_owned()]) + ); + let arg_buffer = self.metal_device.new_buffer( + arg_encoder.encoded_length(), + metal::MTLResourceOptions::StorageModeShared + ); + + // Keep buffer alive until command buffer completes + self.transient_buffers.push(arg_buffer.clone()); + self.binding_encoders.insert(key, (arg_buffer, arg_encoder)); + } + + let (arg_buffer, arg_encoder) = self.binding_encoders.get(&key)?; + + // Encode the resource at the correct id_offset (binding_index) + arg_encoder.set_argument_buffer(arg_buffer, 0); + match slot.data_type.unwrap() { + metal::MTLDataType::Texture => { + let texture = heap.texture_slots.get(offset).and_then(|t| t.as_ref())?; + arg_encoder.set_texture(slot.binding_index as u64, texture); + }, + metal::MTLDataType::Pointer => { + let buffer = heap.buffer_slots.get(offset).and_then(|b| b.as_ref())?; + arg_encoder.set_buffer(slot.binding_index as u64, buffer, 0); + }, + _ => {} + } + + match stage { + super::ShaderType::Vertex => { + let encoder = self.render_encoder.as_ref() + .expect("hotline_rs::gfx::metal expected a call to begin render pass before using render commands"); + encoder.set_vertex_buffer(binding_index as u64, Some(&arg_buffer), 0); + } + super::ShaderType::Fragment => { + let encoder = self.render_encoder.as_ref() + .expect("hotline_rs::gfx::metal expected a call to begin render pass before using render commands"); + encoder.set_fragment_buffer(binding_index as u64, Some(&arg_buffer), 0); + } + _ => { + unimplemented!() + } + } + + Some(()) + } +} + impl super::CmdBuf for CmdBuf { fn reset(&mut self, swap_chain: &SwapChain) { objc::rc::autoreleasepool(|| { @@ -345,8 +391,7 @@ impl super::CmdBuf for CmdBuf { // Clear transient buffers from previous frame self.transient_buffers.clear(); // Clear argument buffer caches - self.current_fragment_arg_buffers.clear(); - self.current_vertex_arg_buffers.clear(); + self.binding_encoders.clear(); }); } @@ -473,7 +518,14 @@ impl super::CmdBuf for CmdBuf { ); } - // Store pipeline pointer for push_render_constants + // clear the arg buffers + if let Some(current) = self.bound_render_pipeline { + if pipeline as *const RenderPipeline != current { + self.binding_encoders.clear(); + } + } + + // store pipeline pointer for push_render_constants self.bound_render_pipeline = Some(pipeline as *const RenderPipeline); }); } @@ -546,95 +598,17 @@ impl super::CmdBuf for CmdBuf { let slot = rp.slot_lookup.get(&(register, space, descriptor_type))?; let data_type = slot.data_type?; - // Handle fragment stage binding + // fragment stage binding if let Some(frag_idx) = slot.fragment_buffer_index { - // Key by (buffer_index, heap_id) to support multi-heap while accumulating textures - let frag_key = (frag_idx, heap.id); - - // Get or create argument buffer for this (buffer_index, heap_id) - if !self.current_fragment_arg_buffers.contains_key(&frag_key) { - let space_info = rp.fragment_space_buffers.get(&frag_idx)?; - - let arg_desc = metal::ArgumentDescriptor::new(); - arg_desc.set_index(0); - arg_desc.set_data_type(space_info.data_type); - arg_desc.set_array_length(space_info.array_length); - arg_desc.set_access(metal::MTLArgumentAccess::ReadOnly); - - let arg_encoder = self.metal_device.new_argument_encoder( - metal::Array::from_owned_slice(&[arg_desc.to_owned()]) - ); - let arg_buffer = self.metal_device.new_buffer( - arg_encoder.encoded_length(), - metal::MTLResourceOptions::StorageModeShared - ); - - // Keep buffer alive until command buffer completes - self.transient_buffers.push(arg_buffer.clone()); - self.current_fragment_arg_buffers.insert(frag_key, (arg_buffer, arg_encoder)); - } - - let (arg_buffer, arg_encoder) = self.current_fragment_arg_buffers.get(&frag_key)?; - - // Encode the resource at the correct id_offset (binding_index) - arg_encoder.set_argument_buffer(arg_buffer, 0); - match data_type { - metal::MTLDataType::Texture => { - let texture = heap.texture_slots.get(offset).and_then(|t| t.as_ref())?; - arg_encoder.set_texture(slot.binding_index as u64, texture); - }, - metal::MTLDataType::Pointer => { - let buffer = heap.buffer_slots.get(offset).and_then(|b| b.as_ref())?; - arg_encoder.set_buffer(slot.binding_index as u64, buffer, 0); - }, - _ => return None, - } - - // Bind the argument buffer - encoder.set_fragment_buffer(frag_idx as u64, Some(arg_buffer), 0); + let space_info = rp.fragment_space_buffers.get(&frag_idx)?; + self.encode_binding(super::ShaderType::Fragment, frag_idx, space_info, slot, heap, offset); } - // Handle vertex stage binding (similar logic) + // vertex stage binding if let Some(vert_idx) = slot.vertex_buffer_index { - let vert_key = (vert_idx, heap.id); - - if !self.current_vertex_arg_buffers.contains_key(&vert_key) { - let space_info = rp.vertex_space_buffers.get(&vert_idx)?; - - let arg_desc = metal::ArgumentDescriptor::new(); - arg_desc.set_index(0); - arg_desc.set_data_type(space_info.data_type); - arg_desc.set_array_length(space_info.array_length); - arg_desc.set_access(metal::MTLArgumentAccess::ReadOnly); - - let arg_encoder = self.metal_device.new_argument_encoder( - metal::Array::from_owned_slice(&[arg_desc.to_owned()]) - ); - let arg_buffer = self.metal_device.new_buffer( - arg_encoder.encoded_length(), - metal::MTLResourceOptions::StorageModeShared - ); - - self.transient_buffers.push(arg_buffer.clone()); - self.current_vertex_arg_buffers.insert(vert_key, (arg_buffer, arg_encoder)); - } - - let (arg_buffer, arg_encoder) = self.current_vertex_arg_buffers.get(&vert_key)?; - - arg_encoder.set_argument_buffer(arg_buffer, 0); - match data_type { - metal::MTLDataType::Texture => { - let texture = heap.texture_slots.get(offset).and_then(|t| t.as_ref())?; - arg_encoder.set_texture(slot.binding_index as u64, texture); - }, - metal::MTLDataType::Pointer => { - let buffer = heap.buffer_slots.get(offset).and_then(|b| b.as_ref())?; - arg_encoder.set_buffer(slot.binding_index as u64, buffer, 0); - }, - _ => return None, - } - - encoder.set_vertex_buffer(vert_idx as u64, Some(arg_buffer), 0); + let space_info = rp.fragment_space_buffers.get(&vert_idx)?; + let vert_key = (super::ShaderType::Vertex, vert_idx, heap.id); + self.encode_binding(super::ShaderType::Vertex, vert_idx, space_info, slot, heap, offset); } Some(()) @@ -927,12 +901,11 @@ pub struct RenderPipeline { slots: Vec, /// Unified slot lookup by (register, space, descriptor_type) slot_lookup: HashMap, - /// Sampler argument buffer (at buffer(4) per htwv convention) + /// Sampler argument buffer sampler_argument_buffer: Option, /// Primitive topology for draw calls topology: Topology, /// Info about argument buffer requirements per fragment buffer index - /// Used for on-the-fly allocation in set_binding fragment_space_buffers: HashMap, /// Info about argument buffer requirements per vertex buffer index vertex_space_buffers: HashMap, @@ -1547,36 +1520,6 @@ impl super::Device for Device { let cmd_queue = self.command_queue.clone(); let cmd = cmd_queue.new_command_buffer().to_owned(); - // Create transient encoders for on-the-fly argument buffer encoding - // Texture encoder (single texture at [[id(0)]]) - let tex_desc = metal::ArgumentDescriptor::new(); - tex_desc.set_index(0); - tex_desc.set_data_type(metal::MTLDataType::Texture); - tex_desc.set_array_length(1); - tex_desc.set_access(metal::MTLArgumentAccess::ReadOnly); - let transient_texture_encoder = self.metal_device.new_argument_encoder( - metal::Array::from_owned_slice(&[tex_desc.to_owned()]) - ); - - // Buffer encoder (single buffer at [[id(0)]]) - let buf_desc = metal::ArgumentDescriptor::new(); - buf_desc.set_index(0); - buf_desc.set_data_type(metal::MTLDataType::Pointer); - buf_desc.set_array_length(1); - buf_desc.set_access(metal::MTLArgumentAccess::ReadOnly); - let transient_buffer_encoder = self.metal_device.new_argument_encoder( - metal::Array::from_owned_slice(&[buf_desc.to_owned()]) - ); - - // Pointer encoder for push constants - let ptr_desc = metal::ArgumentDescriptor::new(); - ptr_desc.set_index(0); - ptr_desc.set_data_type(metal::MTLDataType::Pointer); - ptr_desc.set_access(metal::MTLArgumentAccess::ReadOnly); - let transient_pointer_encoder = self.metal_device.new_argument_encoder( - metal::Array::from_owned_slice(&[ptr_desc.to_owned()]) - ); - CmdBuf { cmd_queue, cmd: Some(cmd), @@ -1587,11 +1530,7 @@ impl super::Device for Device { bound_render_pipeline: None, metal_device: self.metal_device.clone(), transient_buffers: Vec::new(), - transient_texture_encoder, - transient_buffer_encoder, - transient_pointer_encoder, - current_fragment_arg_buffers: HashMap::new(), - current_vertex_arg_buffers: HashMap::new(), + binding_encoders: HashMap::new() } }) } From fc1afaf19b1a871b319f55b93fa929be8428b974 Mon Sep 17 00:00:00 2001 From: polymonster Date: Mon, 2 Mar 2026 17:50:44 +0000 Subject: [PATCH 26/62] - testing push constanbts sample --- plugins/ecs_examples/src/lib.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/plugins/ecs_examples/src/lib.rs b/plugins/ecs_examples/src/lib.rs index 4cb276d7..ad6a80fa 100644 --- a/plugins/ecs_examples/src/lib.rs +++ b/plugins/ecs_examples/src/lib.rs @@ -328,7 +328,10 @@ pub fn render_meshes( let camera = pmfx.get_camera_constants(&view.camera)?; cmd_buf.set_render_pipeline(&pipeline); - cmd_buf.push_render_constants(0, 16, 0, gfx::as_u8_slice(&camera.view_projection_matrix)); + + if let Some(c0) = pipeline.get_pipeline_slot(0, 0, gfx::DescriptorType::PushConstants) { + cmd_buf.push_render_constants(c0.index, 16, 0, gfx::as_u8_slice(&camera.view_projection_matrix)); + } let (mesh_draw_query, billboard_draw_query, cylindrical_draw_query) = queries; From b64f1b4df949e628204ca8cb6dd9f2b6d1d1f993 Mon Sep 17 00:00:00 2001 From: polymonster Date: Mon, 2 Mar 2026 18:14:50 +0000 Subject: [PATCH 27/62] - push constants bindings --- src/gfx/mtl.rs | 330 +++++++++++++++++++++++++++++++++++++------------ 1 file changed, 252 insertions(+), 78 deletions(-) diff --git a/src/gfx/mtl.rs b/src/gfx/mtl.rs index 58e55487..84cc0aae 100644 --- a/src/gfx/mtl.rs +++ b/src/gfx/mtl.rs @@ -306,6 +306,8 @@ pub struct CmdBuf { metal_device: metal::Device, transient_buffers: Vec, binding_encoders: HashMap, + vertex_binder: HashMap, + fragment_binder: HashMap, } impl Clone for CmdBuf { @@ -320,7 +322,9 @@ impl Clone for CmdBuf { bound_render_pipeline: self.bound_render_pipeline, metal_device: self.metal_device.clone(), transient_buffers: self.transient_buffers.clone(), - binding_encoders: self.binding_encoders.clone() + binding_encoders: self.binding_encoders.clone(), + vertex_binder: self.vertex_binder.clone(), + fragment_binder: self.fragment_binder.clone(), } } } @@ -382,6 +386,87 @@ impl CmdBuf { Some(()) } + + fn allocate_push_constants(&mut self) { + let encoder = match self.render_encoder.as_ref() { + Some(e) => e, + None => return, + }; + + // Allocate and bind vertex stage push constants + for binder in self.vertex_binder.values() { + if let PipelineStageBinder::PushConstants(pc) = binder { + // Create transient buffer with push constant data + let data_size = (pc.num_32_bit_constants * 4) as u64; + let data_buffer = self.metal_device.new_buffer( + data_size, + metal::MTLResourceOptions::StorageModeShared + ); + + // Copy data into transient buffer + let dest_ptr = data_buffer.contents() as *mut u32; + unsafe { + std::ptr::copy_nonoverlapping( + pc.data.as_ptr(), + dest_ptr, + pc.num_32_bit_constants as usize + ); + } + + // Create argument buffer and encode pointer + let arg_buffer = self.metal_device.new_buffer( + pc.argument_encoder.encoded_length(), + metal::MTLResourceOptions::StorageModeShared + ); + pc.argument_encoder.set_argument_buffer(&arg_buffer, 0); + pc.argument_encoder.set_buffer(0, &data_buffer, 0); + + // Bind to vertex stage + encoder.set_vertex_buffer(pc.buffer_index as u64, Some(&arg_buffer), 0); + + // Keep buffers alive + self.transient_buffers.push(data_buffer); + self.transient_buffers.push(arg_buffer); + } + } + + // Allocate and bind fragment stage push constants + for binder in self.fragment_binder.values() { + if let PipelineStageBinder::PushConstants(pc) = binder { + // Create transient buffer with push constant data + let data_size = (pc.num_32_bit_constants * 4) as u64; + let data_buffer = self.metal_device.new_buffer( + data_size, + metal::MTLResourceOptions::StorageModeShared + ); + + // Copy data into transient buffer + let dest_ptr = data_buffer.contents() as *mut u32; + unsafe { + std::ptr::copy_nonoverlapping( + pc.data.as_ptr(), + dest_ptr, + pc.num_32_bit_constants as usize + ); + } + + // Create argument buffer and encode pointer + let arg_buffer = self.metal_device.new_buffer( + pc.argument_encoder.encoded_length(), + metal::MTLResourceOptions::StorageModeShared + ); + pc.argument_encoder.set_argument_buffer(&arg_buffer, 0); + pc.argument_encoder.set_buffer(0, &data_buffer, 0); + + // Bind to fragment stage + encoder.set_fragment_buffer(pc.buffer_index as u64, Some(&arg_buffer), 0); + + // Keep buffers alive + self.transient_buffers.push(data_buffer); + self.transient_buffers.push(arg_buffer); + } + } + } } impl super::CmdBuf for CmdBuf { @@ -527,6 +612,10 @@ impl super::CmdBuf for CmdBuf { // store pipeline pointer for push_render_constants self.bound_render_pipeline = Some(pipeline as *const RenderPipeline); + + // Clone binder templates from pipeline to command buffer + self.vertex_binder = pipeline.vertex_binder.clone(); + self.fragment_binder = pipeline.fragment_binder.clone(); }); } @@ -556,12 +645,8 @@ impl super::CmdBuf for CmdBuf { // Bind heap's pre-encoded argument buffers to the slots specified by the pipeline for slot in rp.slot_lookup.values() { - // Skip push constants - if slot.data_buffer.is_some() { - continue; - } - // Get the appropriate heap argument buffer based on data type + // Push constants have data_type: None and will hit the _ => continue branch let arg_buffer = match slot.data_type { Some(metal::MTLDataType::Texture) => heap.get_texture_argument_buffer(), Some(metal::MTLDataType::Pointer) => heap.get_buffer_argument_buffer(), @@ -606,8 +691,7 @@ impl super::CmdBuf for CmdBuf { // vertex stage binding if let Some(vert_idx) = slot.vertex_buffer_index { - let space_info = rp.fragment_space_buffers.get(&vert_idx)?; - let vert_key = (super::ShaderType::Vertex, vert_idx, heap.id); + let space_info = rp.vertex_space_buffers.get(&vert_idx)?; self.encode_binding(super::ShaderType::Vertex, vert_idx, space_info, slot, heap, offset); } @@ -618,58 +702,38 @@ impl super::CmdBuf for CmdBuf { } fn push_render_constants(&mut self, slot: u32, num_values: u32, dest_offset: u32, data: &[T]) { - let encoder = self.render_encoder - .as_ref() - .expect("hotline_rs::gfx::metal expected a call to begin render pass before using render commands"); + let data_size_dwords = num_values as usize; + let data_u32 = unsafe { + std::slice::from_raw_parts( + data.as_ptr() as *const u32, + data_size_dwords + ) + }; + + // Write to vertex binder if matching slot found + for binder in self.vertex_binder.values_mut() { + if let PipelineStageBinder::PushConstants(ref mut pc) = binder { + if pc.buffer_index == slot { + let dest_start = dest_offset as usize; + let dest_end = dest_start + data_size_dwords; + if dest_end <= pc.data.len() { + pc.data[dest_start..dest_end].copy_from_slice(data_u32); + } + break; + } + } + } - // Find the pipeline slot by buffer index - if let Some(pipeline_ptr) = self.bound_render_pipeline { - let pipeline = unsafe { &*pipeline_ptr }; - - let data_size_bytes = (num_values * 4) as usize; - - // Find slot with matching buffer index - for pipeline_slot in pipeline.slot_lookup.values() { - if pipeline_slot.info.index == slot && pipeline_slot.data_buffer.is_some() { - // Copy data to the data buffer - if let Some(ref data_buffer) = pipeline_slot.data_buffer { - let data_bytes = unsafe { - std::slice::from_raw_parts( - data.as_ptr() as *const u8, - data_size_bytes - ) - }; - let dest_ptr = data_buffer.contents() as *mut u8; - let dest_offset_bytes = dest_offset as usize * 4; - unsafe { - std::ptr::copy_nonoverlapping( - data_bytes.as_ptr(), - dest_ptr.add(dest_offset_bytes), - data_size_bytes - ); - } - - // Re-encode the buffer pointer into the argument buffer - pipeline_slot.argument_encoder.set_argument_buffer(&pipeline_slot.argument_buffer, 0); - pipeline_slot.argument_encoder.set_buffer(0, data_buffer, 0); - - // Bind the argument buffer to the appropriate stage(s) - if let Some(vertex_idx) = pipeline_slot.vertex_buffer_index { - encoder.set_vertex_buffer( - vertex_idx as u64, - Some(&pipeline_slot.argument_buffer), - 0 - ); - } - if let Some(fragment_idx) = pipeline_slot.fragment_buffer_index { - encoder.set_fragment_buffer( - fragment_idx as u64, - Some(&pipeline_slot.argument_buffer), - 0 - ); - } + // Write to fragment binder if matching slot found + for binder in self.fragment_binder.values_mut() { + if let PipelineStageBinder::PushConstants(ref mut pc) = binder { + if pc.buffer_index == slot { + let dest_start = dest_offset as usize; + let dest_end = dest_start + data_size_dwords; + if dest_end <= pc.data.len() { + pc.data[dest_start..dest_end].copy_from_slice(data_u32); } - return; + break; } } } @@ -686,6 +750,8 @@ impl super::CmdBuf for CmdBuf { start_instance: u32, ) { objc::rc::autoreleasepool(|| { + self.allocate_push_constants(); + let primitive_type = self.bound_render_pipeline .map(|p| unsafe { (*p).topology }) .map(to_mtl_primitive_type) @@ -713,6 +779,8 @@ impl super::CmdBuf for CmdBuf { start_instance: u32, ) { objc::rc::autoreleasepool(|| { + self.allocate_push_constants(); + let primitive_type = self.bound_render_pipeline .map(|p| unsafe { (*p).topology }) .map(to_mtl_primitive_type) @@ -874,13 +942,28 @@ pub struct PipelineSlot { pub binding_index: u32, /// Metal Data type, for bindings this is Texture or Pointer (Buffer) pub data_type: Option, - /// Data buffer for push constants (None for regular descriptors) - pub data_buffer: Option, /// Slot info for API compatibility pub info: PipelineSlotInfo, /// Visibility for this slot pub visibility: ShaderVisibility, } +// when we make a draw call we need to create a transient buffer on the fly and fill it with data in the push constants +// this was subsequent draws can push their own push constants data +// we can the extrapolate how push constants work to refactor the bindings system they need to behave the same. +// we have a template of slots we bind onf cmdbuf from pipeline +// we mutate the biundings on the cmdbuf through push_render_constants and set_binding +#[derive(Clone)] +struct PushConstantsBinder { + pub data: Vec, + pub num_32_bit_constants: u32, + pub argument_encoder: metal::ArgumentEncoder, + pub buffer_index: u32, +} + +#[derive(Clone)] +enum PipelineStageBinder { + PushConstants(PushConstantsBinder) +} /// Key for slot lookup: (register, space, descriptor_type) type SlotKey = (u32, u32, DescriptorType); @@ -899,8 +982,15 @@ pub struct RenderPipeline { pipeline_state: metal::RenderPipelineState, static_samplers: Vec, slots: Vec, + /// Unified slot lookup by (register, space, descriptor_type) slot_lookup: HashMap, + + /// Vertex stage binders for push constants, keyed by (register, space, descriptor_type) + vertex_binder: HashMap, + /// Fragment stage binders for push constants, keyed by (register, space, descriptor_type) + fragment_binder: HashMap, + /// Sampler argument buffer sampler_argument_buffer: Option, /// Primitive topology for draw calls @@ -1249,16 +1339,6 @@ impl Device { metal::MTLResourceOptions::StorageModeShared ); - // Data buffer holds the actual push constant values - let data_buffer = self.metal_device.new_buffer( - push_constant.num_values as u64 * 4, - metal::MTLResourceOptions::StorageModeShared - ); - - // Encode the data buffer pointer into the argument buffer - argument_encoder.set_argument_buffer(&argument_buffer, 0); - argument_encoder.set_buffer(0, &data_buffer, 0); - // Determine stage indices based on visibility, using per-stage offsets let (vertex_idx, fragment_idx, canonical_index) = match push_constant.visibility { ShaderVisibility::Vertex => { @@ -1291,7 +1371,6 @@ impl Device { argument_buffer, binding_index: 0, // Not used for push constants data_type: None, // Not used for push constants - data_buffer: Some(data_buffer), info: PipelineSlotInfo { index: canonical_index, count: Some(push_constant.num_values), @@ -1383,7 +1462,6 @@ impl Device { binding_index: i as u32, // 0, 1, 2, 3 matching shader [[id()]] data_type: Some(to_mtl_data_type( binding.resource_type.expect("hotline_rs::gfx::mtl: requires resource type to be set for descriptor binding"))), - data_buffer: None, info: PipelineSlotInfo { index: canonical_index, count: binding.num_descriptors, @@ -1397,6 +1475,97 @@ impl Device { slot_lookup } + + fn build_stage_binders( + &self, + pipeline_push_constants: &Option>, + ) -> (HashMap, HashMap) { + let mut vertex_binder: HashMap = HashMap::new(); + let mut fragment_binder: HashMap = HashMap::new(); + + let vertex_samplers_offset: u32 = 2; + let fragment_samplers_offset: u32 = 0; + let mut vertex_binding_offset: u32 = vertex_samplers_offset + 1; + let mut fragment_binding_offset: u32 = fragment_samplers_offset + 1; + + if let Some(push_constants) = pipeline_push_constants.as_ref() { + for push_constant in push_constants { + let key: SlotKey = ( + push_constant.shader_register, + push_constant.register_space, + DescriptorType::PushConstants + ); + + let arg_desc = metal::ArgumentDescriptor::new(); + arg_desc.set_index(0); + arg_desc.set_data_type(metal::MTLDataType::Pointer); + arg_desc.set_access(metal::MTLArgumentAccess::ReadOnly); + + match push_constant.visibility { + ShaderVisibility::Vertex => { + let buffer_index = vertex_binding_offset; + vertex_binding_offset += 1; + + let argument_encoder = self.metal_device.new_argument_encoder( + metal::Array::from_owned_slice(&[arg_desc.to_owned()]) + ); + + vertex_binder.insert(key, PipelineStageBinder::PushConstants(PushConstantsBinder { + data: vec![0u32; push_constant.num_values as usize], + num_32_bit_constants: push_constant.num_values, + argument_encoder, + buffer_index, + })); + }, + ShaderVisibility::Fragment => { + let buffer_index = fragment_binding_offset; + fragment_binding_offset += 1; + + let argument_encoder = self.metal_device.new_argument_encoder( + metal::Array::from_owned_slice(&[arg_desc.to_owned()]) + ); + + fragment_binder.insert(key, PipelineStageBinder::PushConstants(PushConstantsBinder { + data: vec![0u32; push_constant.num_values as usize], + num_32_bit_constants: push_constant.num_values, + argument_encoder, + buffer_index, + })); + }, + ShaderVisibility::All => { + let v_buffer_index = vertex_binding_offset; + let f_buffer_index = fragment_binding_offset; + vertex_binding_offset += 1; + fragment_binding_offset += 1; + + let v_argument_encoder = self.metal_device.new_argument_encoder( + metal::Array::from_owned_slice(&[arg_desc.to_owned()]) + ); + let f_argument_encoder = self.metal_device.new_argument_encoder( + metal::Array::from_owned_slice(&[arg_desc.to_owned()]) + ); + + vertex_binder.insert(key, PipelineStageBinder::PushConstants(PushConstantsBinder { + data: vec![0u32; push_constant.num_values as usize], + num_32_bit_constants: push_constant.num_values, + argument_encoder: v_argument_encoder, + buffer_index: v_buffer_index, + })); + + fragment_binder.insert(key, PipelineStageBinder::PushConstants(PushConstantsBinder { + data: vec![0u32; push_constant.num_values as usize], + num_32_bit_constants: push_constant.num_values, + argument_encoder: f_argument_encoder, + buffer_index: f_buffer_index, + })); + }, + _ => {}, + } + } + } + + (vertex_binder, fragment_binder) + } } impl super::Device for Device { @@ -1530,7 +1699,9 @@ impl super::Device for Device { bound_render_pipeline: None, metal_device: self.metal_device.clone(), transient_buffers: Vec::new(), - binding_encoders: HashMap::new() + binding_encoders: HashMap::new(), + vertex_binder: HashMap::new(), + fragment_binder: HashMap::new(), } }) } @@ -1672,16 +1843,17 @@ impl super::Device for Device { &info.pipeline_layout.push_constants, ); + // Build stage binders for push constants + let (vertex_binder, fragment_binder) = self.build_stage_binders( + &info.pipeline_layout.push_constants, + ); + // Compute space buffer info from slot_lookup let mut fragment_space_buffers: HashMap = HashMap::new(); let mut vertex_space_buffers: HashMap = HashMap::new(); for slot in slot_lookup.values() { - // Skip push constants (they have data_buffer) - if slot.data_buffer.is_some() { - continue; - } - + // Skip push constants (they have data_type: None) if let Some(data_type) = slot.data_type { // Track max binding_index for each buffer index if let Some(frag_idx) = slot.fragment_buffer_index { @@ -1708,6 +1880,8 @@ impl super::Device for Device { slots: Vec::new(), static_samplers: pipeline_static_samplers, slot_lookup, + vertex_binder, + fragment_binder, sampler_argument_buffer, topology: info.topology, fragment_space_buffers, From 7592c2d1f9041c975a7c8566a9c4fe2f8519acf7 Mon Sep 17 00:00:00 2001 From: polymonster Date: Mon, 2 Mar 2026 18:49:46 +0000 Subject: [PATCH 28/62] - stage binding refactor 2 --- src/gfx/mtl.rs | 323 ++++++++++++++++++++++++++++--------------------- 1 file changed, 182 insertions(+), 141 deletions(-) diff --git a/src/gfx/mtl.rs b/src/gfx/mtl.rs index 84cc0aae..be11ec09 100644 --- a/src/gfx/mtl.rs +++ b/src/gfx/mtl.rs @@ -28,8 +28,6 @@ use core_graphics_types::geometry::CGSize; use std::path::Path; -type BindingEncoderKey = (super::ShaderType, u32, u16); - const MEGA_BYTE : usize = 1024 * 1024 * 1024; const fn to_mtl_vertex_format(format: super::Format) -> MTLVertexFormat { @@ -305,7 +303,6 @@ pub struct CmdBuf { bound_render_pipeline: Option<*const RenderPipeline>, metal_device: metal::Device, transient_buffers: Vec, - binding_encoders: HashMap, vertex_binder: HashMap, fragment_binder: HashMap, } @@ -322,7 +319,6 @@ impl Clone for CmdBuf { bound_render_pipeline: self.bound_render_pipeline, metal_device: self.metal_device.clone(), transient_buffers: self.transient_buffers.clone(), - binding_encoders: self.binding_encoders.clone(), vertex_binder: self.vertex_binder.clone(), fragment_binder: self.fragment_binder.clone(), } @@ -330,80 +326,25 @@ impl Clone for CmdBuf { } impl CmdBuf { - fn encode_binding(&mut self, stage: super::ShaderType, binding_index: u32, space_info: &SpaceBufferInfo, slot: &PipelineSlot, heap: &Heap, offset: usize) -> Option<()> { - let key = (stage, binding_index, heap.id); - if !self.binding_encoders.contains_key(&key) { - let arg_desc = metal::ArgumentDescriptor::new(); - arg_desc.set_index(0); - arg_desc.set_data_type(space_info.data_type); - arg_desc.set_array_length(space_info.array_length); - arg_desc.set_access(metal::MTLArgumentAccess::ReadOnly); - - let arg_encoder = self.metal_device.new_argument_encoder( - metal::Array::from_owned_slice(&[arg_desc.to_owned()]) - ); - let arg_buffer = self.metal_device.new_buffer( - arg_encoder.encoded_length(), - metal::MTLResourceOptions::StorageModeShared - ); - - // Keep buffer alive until command buffer completes - self.transient_buffers.push(arg_buffer.clone()); - self.binding_encoders.insert(key, (arg_buffer, arg_encoder)); - } - - let (arg_buffer, arg_encoder) = self.binding_encoders.get(&key)?; - - // Encode the resource at the correct id_offset (binding_index) - arg_encoder.set_argument_buffer(arg_buffer, 0); - match slot.data_type.unwrap() { - metal::MTLDataType::Texture => { - let texture = heap.texture_slots.get(offset).and_then(|t| t.as_ref())?; - arg_encoder.set_texture(slot.binding_index as u64, texture); - }, - metal::MTLDataType::Pointer => { - let buffer = heap.buffer_slots.get(offset).and_then(|b| b.as_ref())?; - arg_encoder.set_buffer(slot.binding_index as u64, buffer, 0); - }, - _ => {} - } - - match stage { - super::ShaderType::Vertex => { - let encoder = self.render_encoder.as_ref() - .expect("hotline_rs::gfx::metal expected a call to begin render pass before using render commands"); - encoder.set_vertex_buffer(binding_index as u64, Some(&arg_buffer), 0); - } - super::ShaderType::Fragment => { - let encoder = self.render_encoder.as_ref() - .expect("hotline_rs::gfx::metal expected a call to begin render pass before using render commands"); - encoder.set_fragment_buffer(binding_index as u64, Some(&arg_buffer), 0); - } - _ => { - unimplemented!() - } - } - - Some(()) - } - - fn allocate_push_constants(&mut self) { + fn allocate_stage_bindings( + &mut self, + binder: &HashMap, + stage: super::ShaderType, + ) { let encoder = match self.render_encoder.as_ref() { Some(e) => e, None => return, }; - // Allocate and bind vertex stage push constants - for binder in self.vertex_binder.values() { - if let PipelineStageBinder::PushConstants(pc) = binder { - // Create transient buffer with push constant data + // Allocate push constants for this stage + for b in binder.values() { + if let PipelineStageBinder::PushConstants(pc) = b { let data_size = (pc.num_32_bit_constants * 4) as u64; let data_buffer = self.metal_device.new_buffer( data_size, metal::MTLResourceOptions::StorageModeShared ); - // Copy data into transient buffer let dest_ptr = data_buffer.contents() as *mut u32; unsafe { std::ptr::copy_nonoverlapping( @@ -413,7 +354,6 @@ impl CmdBuf { ); } - // Create argument buffer and encode pointer let arg_buffer = self.metal_device.new_buffer( pc.argument_encoder.encoded_length(), metal::MTLResourceOptions::StorageModeShared @@ -421,52 +361,93 @@ impl CmdBuf { pc.argument_encoder.set_argument_buffer(&arg_buffer, 0); pc.argument_encoder.set_buffer(0, &data_buffer, 0); - // Bind to vertex stage - encoder.set_vertex_buffer(pc.buffer_index as u64, Some(&arg_buffer), 0); + match stage { + super::ShaderType::Vertex => encoder.set_vertex_buffer(pc.buffer_index as u64, Some(&arg_buffer), 0), + super::ShaderType::Fragment => encoder.set_fragment_buffer(pc.buffer_index as u64, Some(&arg_buffer), 0), + _ => unimplemented!(), + } - // Keep buffers alive self.transient_buffers.push(data_buffer); self.transient_buffers.push(arg_buffer); } } - // Allocate and bind fragment stage push constants - for binder in self.fragment_binder.values() { - if let PipelineStageBinder::PushConstants(pc) = binder { - // Create transient buffer with push constant data - let data_size = (pc.num_32_bit_constants * 4) as u64; - let data_buffer = self.metal_device.new_buffer( - data_size, - metal::MTLResourceOptions::StorageModeShared - ); - - // Copy data into transient buffer - let dest_ptr = data_buffer.contents() as *mut u32; - unsafe { - std::ptr::copy_nonoverlapping( - pc.data.as_ptr(), - dest_ptr, - pc.num_32_bit_constants as usize - ); + // Group resource bindings by buffer_index + let mut groups: HashMap> = HashMap::new(); + for b in binder.values() { + if let PipelineStageBinder::Resource(rb) = b { + if rb.bound_resource.is_some() { + groups.entry(rb.buffer_index).or_default().push(rb); } + } + } - // Create argument buffer and encode pointer - let arg_buffer = self.metal_device.new_buffer( - pc.argument_encoder.encoded_length(), - metal::MTLResourceOptions::StorageModeShared - ); - pc.argument_encoder.set_argument_buffer(&arg_buffer, 0); - pc.argument_encoder.set_buffer(0, &data_buffer, 0); + let render_stage = match stage { + super::ShaderType::Vertex => metal::MTLRenderStages::Vertex, + super::ShaderType::Fragment => metal::MTLRenderStages::Fragment, + _ => unimplemented!(), + }; - // Bind to fragment stage - encoder.set_fragment_buffer(pc.buffer_index as u64, Some(&arg_buffer), 0); + // Allocate resource bindings (grouped by buffer_index) + for (buffer_index, mut binders) in groups { + // Sort by binding_index to ensure deterministic order + binders.sort_by_key(|rb| rb.binding_index); - // Keep buffers alive - self.transient_buffers.push(data_buffer); - self.transient_buffers.push(arg_buffer); + let arg_descs: Vec = binders.iter().map(|rb| { + let arg_desc = metal::ArgumentDescriptor::new(); + arg_desc.set_index(rb.binding_index as u64); + arg_desc.set_data_type(rb.data_type); + arg_desc.set_array_length(rb.array_length); + arg_desc.set_access(metal::MTLArgumentAccess::ReadOnly); + arg_desc.to_owned() + }).collect(); + + let arg_encoder = self.metal_device.new_argument_encoder( + metal::Array::from_owned_slice(&arg_descs) + ); + let arg_buffer = self.metal_device.new_buffer( + arg_encoder.encoded_length(), + metal::MTLResourceOptions::StorageModeShared + ); + arg_encoder.set_argument_buffer(&arg_buffer, 0); + + for rb in &binders { + if let Some(ref binding) = rb.bound_resource { + let heap = unsafe { &*binding.heap_ptr }; + encoder.use_heap_at(&heap.mtl_heap, render_stage); + + match rb.data_type { + metal::MTLDataType::Texture => { + if let Some(texture) = heap.texture_slots.get(binding.offset).and_then(|t| t.as_ref()) { + arg_encoder.set_texture(rb.binding_index as u64, texture); + } + } + metal::MTLDataType::Pointer => { + if let Some(buffer) = heap.buffer_slots.get(binding.offset).and_then(|b| b.as_ref()) { + arg_encoder.set_buffer(rb.binding_index as u64, buffer, 0); + } + } + _ => {} + } + } } + + match stage { + super::ShaderType::Vertex => encoder.set_vertex_buffer(buffer_index as u64, Some(&arg_buffer), 0), + super::ShaderType::Fragment => encoder.set_fragment_buffer(buffer_index as u64, Some(&arg_buffer), 0), + _ => unimplemented!(), + } + self.transient_buffers.push(arg_buffer); } } + + fn allocate_stage_resources(&mut self) { + let vertex_binder = self.vertex_binder.clone(); + let fragment_binder = self.fragment_binder.clone(); + + self.allocate_stage_bindings(&vertex_binder, super::ShaderType::Vertex); + self.allocate_stage_bindings(&fragment_binder, super::ShaderType::Fragment); + } } impl super::CmdBuf for CmdBuf { @@ -475,8 +456,6 @@ impl super::CmdBuf for CmdBuf { self.cmd = Some(self.cmd_queue.new_command_buffer().to_owned()); // Clear transient buffers from previous frame self.transient_buffers.clear(); - // Clear argument buffer caches - self.binding_encoders.clear(); }); } @@ -603,13 +582,6 @@ impl super::CmdBuf for CmdBuf { ); } - // clear the arg buffers - if let Some(current) = self.bound_render_pipeline { - if pipeline as *const RenderPipeline != current { - self.binding_encoders.clear(); - } - } - // store pipeline pointer for push_render_constants self.bound_render_pipeline = Some(pipeline as *const RenderPipeline); @@ -669,30 +641,22 @@ impl super::CmdBuf for CmdBuf { } } - fn set_binding(&mut self, pipeline: &T, register: u32, space: u32, descriptor_type: super::DescriptorType, heap: &Heap, offset: usize) -> Option<()> { - let encoder = self.render_encoder.as_ref() - .expect("hotline_rs::gfx::metal expected a call to begin render pass before using render commands"); - - // Make the heap accessible to shaders - encoder.use_heap_at(&heap.mtl_heap, metal::MTLRenderStages::Fragment); - encoder.use_heap_at(&heap.mtl_heap, metal::MTLRenderStages::Vertex); - - let rp: &RenderPipeline = unsafe { std::mem::transmute(pipeline) }; - - // Look up the slot by (register, space, descriptor_type) - let slot = rp.slot_lookup.get(&(register, space, descriptor_type))?; - let data_type = slot.data_type?; + fn set_binding(&mut self, _pipeline: &T, register: u32, space: u32, descriptor_type: super::DescriptorType, heap: &Heap, offset: usize) -> Option<()> { + let key: SlotKey = (register, space, descriptor_type); + let heap_ptr = heap as *const Heap; - // fragment stage binding - if let Some(frag_idx) = slot.fragment_buffer_index { - let space_info = rp.fragment_space_buffers.get(&frag_idx)?; - self.encode_binding(super::ShaderType::Fragment, frag_idx, space_info, slot, heap, offset); + // Write to vertex binder if present + if let Some(binder) = self.vertex_binder.get_mut(&key) { + if let PipelineStageBinder::Resource(ref mut rb) = binder { + rb.bound_resource = Some(ResourceBinding { heap_ptr, offset }); + } } - // vertex stage binding - if let Some(vert_idx) = slot.vertex_buffer_index { - let space_info = rp.vertex_space_buffers.get(&vert_idx)?; - self.encode_binding(super::ShaderType::Vertex, vert_idx, space_info, slot, heap, offset); + // Write to fragment binder if present + if let Some(binder) = self.fragment_binder.get_mut(&key) { + if let PipelineStageBinder::Resource(ref mut rb) = binder { + rb.bound_resource = Some(ResourceBinding { heap_ptr, offset }); + } } Some(()) @@ -750,7 +714,7 @@ impl super::CmdBuf for CmdBuf { start_instance: u32, ) { objc::rc::autoreleasepool(|| { - self.allocate_push_constants(); + self.allocate_stage_resources(); let primitive_type = self.bound_render_pipeline .map(|p| unsafe { (*p).topology }) @@ -779,7 +743,7 @@ impl super::CmdBuf for CmdBuf { start_instance: u32, ) { objc::rc::autoreleasepool(|| { - self.allocate_push_constants(); + self.allocate_stage_resources(); let primitive_type = self.bound_render_pipeline .map(|p| unsafe { (*p).topology }) @@ -947,11 +911,6 @@ pub struct PipelineSlot { /// Visibility for this slot pub visibility: ShaderVisibility, } -// when we make a draw call we need to create a transient buffer on the fly and fill it with data in the push constants -// this was subsequent draws can push their own push constants data -// we can the extrapolate how push constants work to refactor the bindings system they need to behave the same. -// we have a template of slots we bind onf cmdbuf from pipeline -// we mutate the biundings on the cmdbuf through push_render_constants and set_binding #[derive(Clone)] struct PushConstantsBinder { pub data: Vec, @@ -960,9 +919,25 @@ struct PushConstantsBinder { pub buffer_index: u32, } +#[derive(Clone, Copy)] +struct ResourceBinding { + pub heap_ptr: *const Heap, + pub offset: usize, +} + +#[derive(Clone)] +struct ResourceBinder { + pub buffer_index: u32, + pub binding_index: u32, + pub data_type: metal::MTLDataType, + pub array_length: u64, + pub bound_resource: Option, +} + #[derive(Clone)] enum PipelineStageBinder { - PushConstants(PushConstantsBinder) + PushConstants(PushConstantsBinder), + Resource(ResourceBinder), } /// Key for slot lookup: (register, space, descriptor_type) @@ -1478,8 +1453,11 @@ impl Device { fn build_stage_binders( &self, + pipeline_bindings: &Option>, pipeline_push_constants: &Option>, ) -> (HashMap, HashMap) { + const MAX_BINDLESS_TEXTURES: u64 = 1024; + let mut vertex_binder: HashMap = HashMap::new(); let mut fragment_binder: HashMap = HashMap::new(); @@ -1488,6 +1466,7 @@ impl Device { let mut vertex_binding_offset: u32 = vertex_samplers_offset + 1; let mut fragment_binding_offset: u32 = fragment_samplers_offset + 1; + // Add push constant binders if let Some(push_constants) = pipeline_push_constants.as_ref() { for push_constant in push_constants { let key: SlotKey = ( @@ -1564,6 +1543,68 @@ impl Device { } } + // Add resource binders + if let Some(bindings) = pipeline_bindings.as_ref() { + if !bindings.is_empty() { + // Determine if any binding needs vertex or fragment visibility + let needs_vertex = bindings.iter().any(|b| + matches!(b.visibility, ShaderVisibility::Vertex | ShaderVisibility::All)); + let needs_fragment = bindings.iter().any(|b| + matches!(b.visibility, ShaderVisibility::Fragment | ShaderVisibility::All)); + + // Single buffer index per stage (only increment once, not per binding!) + let vertex_idx = if needs_vertex { + let idx = vertex_binding_offset; + vertex_binding_offset += 1; + Some(idx) + } else { + None + }; + let fragment_idx = if needs_fragment { + let idx = fragment_binding_offset; + fragment_binding_offset += 1; + Some(idx) + } else { + None + }; + + // Create ResourceBinder for each binding + for (i, binding) in bindings.iter().enumerate() { + let key: SlotKey = (binding.shader_register, binding.register_space, binding.binding_type); + let data_type = to_mtl_data_type( + binding.resource_type.expect("hotline_rs::gfx::mtl: requires resource type for binding") + ); + let array_length = binding.num_descriptors.map(|n| n as u64).unwrap_or(MAX_BINDLESS_TEXTURES); + + // Add to vertex binder if visible to vertex stage + if matches!(binding.visibility, ShaderVisibility::Vertex | ShaderVisibility::All) { + if let Some(v_idx) = vertex_idx { + vertex_binder.insert(key, PipelineStageBinder::Resource(ResourceBinder { + buffer_index: v_idx, + binding_index: i as u32, + data_type, + array_length, + bound_resource: None, + })); + } + } + + // Add to fragment binder if visible to fragment stage + if matches!(binding.visibility, ShaderVisibility::Fragment | ShaderVisibility::All) { + if let Some(f_idx) = fragment_idx { + fragment_binder.insert(key, PipelineStageBinder::Resource(ResourceBinder { + buffer_index: f_idx, + binding_index: i as u32, + data_type, + array_length, + bound_resource: None, + })); + } + } + } + } + } + (vertex_binder, fragment_binder) } } @@ -1699,7 +1740,6 @@ impl super::Device for Device { bound_render_pipeline: None, metal_device: self.metal_device.clone(), transient_buffers: Vec::new(), - binding_encoders: HashMap::new(), vertex_binder: HashMap::new(), fragment_binder: HashMap::new(), } @@ -1843,8 +1883,9 @@ impl super::Device for Device { &info.pipeline_layout.push_constants, ); - // Build stage binders for push constants + // Build stage binders for push constants and resource bindings let (vertex_binder, fragment_binder) = self.build_stage_binders( + &info.pipeline_layout.bindings, &info.pipeline_layout.push_constants, ); From 54715df6dda8d09fc633892913ce1330f5896863 Mon Sep 17 00:00:00 2001 From: polymonster Date: Mon, 2 Mar 2026 19:04:14 +0000 Subject: [PATCH 29/62] - cleanup unused stuff --- src/gfx/mtl.rs | 124 ++++--------------------------------------------- 1 file changed, 10 insertions(+), 114 deletions(-) diff --git a/src/gfx/mtl.rs b/src/gfx/mtl.rs index be11ec09..93906f31 100644 --- a/src/gfx/mtl.rs +++ b/src/gfx/mtl.rs @@ -898,18 +898,10 @@ pub struct PipelineSlot { pub vertex_buffer_index: Option, /// Metal buffer index for fragment stage (None if not visible to fragment) pub fragment_buffer_index: Option, - /// Argument encoder for encoding resources into argument buffer - pub argument_encoder: metal::ArgumentEncoder, - /// Argument buffer containing encoded resource pointers - pub argument_buffer: metal::Buffer, - /// Index within the shared argument buffer (for texture bindings) - pub binding_index: u32, /// Metal Data type, for bindings this is Texture or Pointer (Buffer) pub data_type: Option, /// Slot info for API compatibility pub info: PipelineSlotInfo, - /// Visibility for this slot - pub visibility: ShaderVisibility, } #[derive(Clone)] struct PushConstantsBinder { @@ -943,37 +935,24 @@ enum PipelineStageBinder { /// Key for slot lookup: (register, space, descriptor_type) type SlotKey = (u32, u32, DescriptorType); -/// Info about argument buffer requirements for a specific buffer index -/// Used for on-the-fly allocation in set_binding -#[derive(Clone)] -pub struct SpaceBufferInfo { - /// Number of elements in the argument buffer (max binding_index + 1) - pub array_length: u64, - /// Data type (Texture or Pointer) - pub data_type: metal::MTLDataType, -} - pub struct RenderPipeline { pipeline_state: metal::RenderPipelineState, - static_samplers: Vec, slots: Vec, + /// Primitive topology for draw calls + topology: Topology, + /// Unified slot lookup by (register, space, descriptor_type) slot_lookup: HashMap, + /// Static samplers + static_samplers: Vec, + /// Sampler argument buffer + sampler_argument_buffer: Option, /// Vertex stage binders for push constants, keyed by (register, space, descriptor_type) vertex_binder: HashMap, /// Fragment stage binders for push constants, keyed by (register, space, descriptor_type) fragment_binder: HashMap, - - /// Sampler argument buffer - sampler_argument_buffer: Option, - /// Primitive topology for draw calls - topology: Topology, - /// Info about argument buffer requirements per fragment buffer index - fragment_space_buffers: HashMap, - /// Info about argument buffer requirements per vertex buffer index - vertex_space_buffers: HashMap, } impl super::RenderPipeline for RenderPipeline {} @@ -1299,21 +1278,6 @@ impl Device { // Add push constant slots first (they come before regular bindings in htwv) if let Some(push_constants) = pipeline_push_constants.as_ref() { for push_constant in push_constants { - - // Create argument descriptor for pointer type (push constants use pointers in argument buffers) - let arg_desc = metal::ArgumentDescriptor::new(); - arg_desc.set_index(0); - arg_desc.set_data_type(metal::MTLDataType::Pointer); - arg_desc.set_access(metal::MTLArgumentAccess::ReadOnly); - - let argument_encoder = self.metal_device.new_argument_encoder( - metal::Array::from_owned_slice(&[arg_desc.to_owned()]) - ); - let argument_buffer = self.metal_device.new_buffer( - argument_encoder.encoded_length(), - metal::MTLResourceOptions::StorageModeShared - ); - // Determine stage indices based on visibility, using per-stage offsets let (vertex_idx, fragment_idx, canonical_index) = match push_constant.visibility { ShaderVisibility::Vertex => { @@ -1342,56 +1306,19 @@ impl Device { PipelineSlot { vertex_buffer_index: vertex_idx, fragment_buffer_index: fragment_idx, - argument_encoder, - argument_buffer, - binding_index: 0, // Not used for push constants data_type: None, // Not used for push constants info: PipelineSlotInfo { index: canonical_index, count: Some(push_constant.num_values), }, - visibility: push_constant.visibility, }, ); } } - // Add regular binding slots - ALL share ONE argument buffer - const MAX_BINDLESS_TEXTURES: u64 = 1024; + // Add regular binding slots if let Some(bindings) = pipeline_bindings.as_ref() { if !bindings.is_empty() { - // Build argument descriptors - one per binding with unique indices - let arg_descs: Vec = bindings.iter().enumerate() - .map(|(i, binding)| { - let arg_desc = metal::ArgumentDescriptor::new(); - arg_desc.set_index(i as u64); // Each binding gets unique index - let array_len = binding.num_descriptors.map(|n| n as u64).unwrap_or(MAX_BINDLESS_TEXTURES); - arg_desc.set_array_length(array_len); - - // Determine data type from resource_type (texture vs buffer/pointer) - let data_type = to_mtl_data_type(binding.resource_type.expect("hotline_rs::gfx::mtl: requires resource type to be set for descriptor binding")); - - // Determine access from binding_type (read vs read-write) - let access = match binding.binding_type { - DescriptorType::UnorderedAccess => metal::MTLArgumentAccess::ReadWrite, - _ => metal::MTLArgumentAccess::ReadOnly, - }; - - arg_desc.set_data_type(data_type); - arg_desc.set_access(access); - arg_desc.to_owned() - }) - .collect(); - - // Create SINGLE encoder/buffer for ALL bindings - let argument_encoder = self.metal_device.new_argument_encoder( - metal::Array::from_owned_slice(&arg_descs) - ); - let argument_buffer = self.metal_device.new_buffer( - argument_encoder.encoded_length(), - metal::MTLResourceOptions::StorageModeShared - ); - // Determine if any binding needs vertex or fragment visibility let needs_vertex = bindings.iter().any(|b| matches!(b.visibility, ShaderVisibility::Vertex | ShaderVisibility::All)); @@ -1415,8 +1342,8 @@ impl Device { }; let canonical_index = vertex_idx.or(fragment_idx).unwrap_or(0); - // Each binding shares buffer but has unique binding_index - for (i, binding) in bindings.iter().enumerate() { + // Each binding gets a slot entry + for binding in bindings.iter() { // Per-slot visibility based on the binding's visibility let slot_vertex_idx = match binding.visibility { ShaderVisibility::Vertex | ShaderVisibility::All => vertex_idx, @@ -1432,16 +1359,12 @@ impl Device { PipelineSlot { vertex_buffer_index: slot_vertex_idx, fragment_buffer_index: slot_fragment_idx, - argument_encoder: argument_encoder.clone(), - argument_buffer: argument_buffer.clone(), - binding_index: i as u32, // 0, 1, 2, 3 matching shader [[id()]] data_type: Some(to_mtl_data_type( binding.resource_type.expect("hotline_rs::gfx::mtl: requires resource type to be set for descriptor binding"))), info: PipelineSlotInfo { index: canonical_index, count: binding.num_descriptors, }, - visibility: binding.visibility, }, ); } @@ -1889,31 +1812,6 @@ impl super::Device for Device { &info.pipeline_layout.push_constants, ); - // Compute space buffer info from slot_lookup - let mut fragment_space_buffers: HashMap = HashMap::new(); - let mut vertex_space_buffers: HashMap = HashMap::new(); - - for slot in slot_lookup.values() { - // Skip push constants (they have data_type: None) - if let Some(data_type) = slot.data_type { - // Track max binding_index for each buffer index - if let Some(frag_idx) = slot.fragment_buffer_index { - let entry = fragment_space_buffers.entry(frag_idx).or_insert(SpaceBufferInfo { - array_length: 0, - data_type, - }); - entry.array_length = entry.array_length.max(slot.binding_index as u64 + 1); - } - if let Some(vert_idx) = slot.vertex_buffer_index { - let entry = vertex_space_buffers.entry(vert_idx).or_insert(SpaceBufferInfo { - array_length: 0, - data_type, - }); - entry.array_length = entry.array_length.max(slot.binding_index as u64 + 1); - } - } - } - let pipeline_state = self.metal_device.new_render_pipeline_state(&pipeline_state_descriptor)?; Ok(RenderPipeline { @@ -1925,8 +1823,6 @@ impl super::Device for Device { fragment_binder, sampler_argument_buffer, topology: info.topology, - fragment_space_buffers, - vertex_space_buffers, }) }) } From aa2df3fd7df62f8ffaa9340d152ff4e964d2bf32 Mon Sep 17 00:00:00 2001 From: polymonster Date: Tue, 3 Mar 2026 19:19:38 +0000 Subject: [PATCH 30/62] - push constants optimisation --- crates/htwv/src/macos_impl.rs | 41 +++++++++++++++++++++-- src/gfx/mtl.rs | 62 ++++++----------------------------- 2 files changed, 48 insertions(+), 55 deletions(-) diff --git a/crates/htwv/src/macos_impl.rs b/crates/htwv/src/macos_impl.rs index 3b6c55aa..1d937e9f 100644 --- a/crates/htwv/src/macos_impl.rs +++ b/crates/htwv/src/macos_impl.rs @@ -210,7 +210,11 @@ fn compile_shader_spirv( }) .collect(); - let samplers_offset = if filepath.ends_with(".vsc") { 2 } else { 0 }; + let samplers_offset = match stage + { + ShaderStage::Vertex => 2, + _ => 0 + }; // put samplers first all in single argument buffer for resource in &resources { @@ -227,18 +231,49 @@ fn compile_shader_spirv( } } - // put push constants next + // put push constants next - use discrete descriptor sets (no argument buffers) + // This enables using setVertexBytes/setFragmentBytes at runtime let mut binding_offset = samplers_offset + 1; + let exec_model = match stage { + ShaderStage::Vertex => SpvExecutionModel__SpvExecutionModelVertex, + ShaderStage::Fragment => SpvExecutionModel__SpvExecutionModelFragment, + ShaderStage::Compute => SpvExecutionModel__SpvExecutionModelGLCompute, + _ => SpvExecutionModel__SpvExecutionModelVertex, + }; + for resource in &resources { for push_constant in &pipeline.pipeline_layout.push_constants { + // Only process push constants visible to this shader stage + if push_constant.visibility != stage && push_constant.visibility != ShaderStage::All { + continue; + } let name = cstr_to_string(resource.name)?; if push_constant.name == name.strip_prefix("type.").unwrap_or(&name) { + let desc_set = binding_offset as u32; spvc_compiler_set_decoration( compiler, resource.id, SpvDecoration__SpvDecorationDescriptorSet, - binding_offset as u32, + desc_set, ); + // Mark as discrete so it uses direct buffer binding, not argument buffer + spvc_compiler_msl_add_discrete_descriptor_set(compiler, desc_set); + + // Explicitly map to Metal buffer index (without this, SPIRV-Cross uses buffer(0)) + // Get the original SPIR-V binding number from the resource + let spirv_binding = spvc_compiler_get_decoration( + compiler, + resource.id, + SpvDecoration__SpvDecorationBinding, + ); + let mut res_binding: spvc_msl_resource_binding = std::mem::zeroed(); + spvc_msl_resource_binding_init(&mut res_binding); + res_binding.stage = exec_model; + res_binding.desc_set = desc_set; + res_binding.binding = spirv_binding; + res_binding.msl_buffer = desc_set; + spvc_compiler_msl_add_resource_binding(compiler, &res_binding); + binding_offset += 1 } } diff --git a/src/gfx/mtl.rs b/src/gfx/mtl.rs index 93906f31..7a73fc8b 100644 --- a/src/gfx/mtl.rs +++ b/src/gfx/mtl.rs @@ -336,39 +336,21 @@ impl CmdBuf { None => return, }; - // Allocate push constants for this stage + // Bind push constants using setVertexBytes/setFragmentBytes (zero allocations) for b in binder.values() { if let PipelineStageBinder::PushConstants(pc) = b { let data_size = (pc.num_32_bit_constants * 4) as u64; - let data_buffer = self.metal_device.new_buffer( - data_size, - metal::MTLResourceOptions::StorageModeShared - ); - - let dest_ptr = data_buffer.contents() as *mut u32; - unsafe { - std::ptr::copy_nonoverlapping( - pc.data.as_ptr(), - dest_ptr, - pc.num_32_bit_constants as usize - ); - } - - let arg_buffer = self.metal_device.new_buffer( - pc.argument_encoder.encoded_length(), - metal::MTLResourceOptions::StorageModeShared - ); - pc.argument_encoder.set_argument_buffer(&arg_buffer, 0); - pc.argument_encoder.set_buffer(0, &data_buffer, 0); + let data_ptr = pc.data.as_ptr() as *const std::ffi::c_void; match stage { - super::ShaderType::Vertex => encoder.set_vertex_buffer(pc.buffer_index as u64, Some(&arg_buffer), 0), - super::ShaderType::Fragment => encoder.set_fragment_buffer(pc.buffer_index as u64, Some(&arg_buffer), 0), + super::ShaderType::Vertex => { + encoder.set_vertex_bytes(pc.buffer_index as u64, data_size, data_ptr); + } + super::ShaderType::Fragment => { + encoder.set_fragment_bytes(pc.buffer_index as u64, data_size, data_ptr); + } _ => unimplemented!(), } - - self.transient_buffers.push(data_buffer); - self.transient_buffers.push(arg_buffer); } } @@ -903,11 +885,11 @@ pub struct PipelineSlot { /// Slot info for API compatibility pub info: PipelineSlotInfo, } +/// Push constants binder - uses setVertexBytes/setFragmentBytes for zero-allocation binding #[derive(Clone)] struct PushConstantsBinder { pub data: Vec, pub num_32_bit_constants: u32, - pub argument_encoder: metal::ArgumentEncoder, pub buffer_index: u32, } @@ -1389,7 +1371,7 @@ impl Device { let mut vertex_binding_offset: u32 = vertex_samplers_offset + 1; let mut fragment_binding_offset: u32 = fragment_samplers_offset + 1; - // Add push constant binders + // Add push constant binders (no ArgumentEncoder needed - uses setVertexBytes/setFragmentBytes) if let Some(push_constants) = pipeline_push_constants.as_ref() { for push_constant in push_constants { let key: SlotKey = ( @@ -1398,24 +1380,14 @@ impl Device { DescriptorType::PushConstants ); - let arg_desc = metal::ArgumentDescriptor::new(); - arg_desc.set_index(0); - arg_desc.set_data_type(metal::MTLDataType::Pointer); - arg_desc.set_access(metal::MTLArgumentAccess::ReadOnly); - match push_constant.visibility { ShaderVisibility::Vertex => { let buffer_index = vertex_binding_offset; vertex_binding_offset += 1; - let argument_encoder = self.metal_device.new_argument_encoder( - metal::Array::from_owned_slice(&[arg_desc.to_owned()]) - ); - vertex_binder.insert(key, PipelineStageBinder::PushConstants(PushConstantsBinder { data: vec![0u32; push_constant.num_values as usize], num_32_bit_constants: push_constant.num_values, - argument_encoder, buffer_index, })); }, @@ -1423,14 +1395,9 @@ impl Device { let buffer_index = fragment_binding_offset; fragment_binding_offset += 1; - let argument_encoder = self.metal_device.new_argument_encoder( - metal::Array::from_owned_slice(&[arg_desc.to_owned()]) - ); - fragment_binder.insert(key, PipelineStageBinder::PushConstants(PushConstantsBinder { data: vec![0u32; push_constant.num_values as usize], num_32_bit_constants: push_constant.num_values, - argument_encoder, buffer_index, })); }, @@ -1440,24 +1407,15 @@ impl Device { vertex_binding_offset += 1; fragment_binding_offset += 1; - let v_argument_encoder = self.metal_device.new_argument_encoder( - metal::Array::from_owned_slice(&[arg_desc.to_owned()]) - ); - let f_argument_encoder = self.metal_device.new_argument_encoder( - metal::Array::from_owned_slice(&[arg_desc.to_owned()]) - ); - vertex_binder.insert(key, PipelineStageBinder::PushConstants(PushConstantsBinder { data: vec![0u32; push_constant.num_values as usize], num_32_bit_constants: push_constant.num_values, - argument_encoder: v_argument_encoder, buffer_index: v_buffer_index, })); fragment_binder.insert(key, PipelineStageBinder::PushConstants(PushConstantsBinder { data: vec![0u32; push_constant.num_values as usize], num_32_bit_constants: push_constant.num_values, - argument_encoder: f_argument_encoder, buffer_index: f_buffer_index, })); }, From 0c8e644b46143b0ed4ae848dec26ceec1fbf4584 Mon Sep 17 00:00:00 2001 From: polymonster Date: Tue, 3 Mar 2026 20:06:13 +0000 Subject: [PATCH 31/62] - clean up slot_lookup --- .gitmodules | 3 - crates/htwv/src/macos_impl.rs | 3 +- crates/htwv/third_party/pmfx-shader | 1 - hotline-data | 2 +- src/gfx.rs | 2 +- src/gfx/mtl.rs | 248 +++++++++++++++++++--------- 6 files changed, 169 insertions(+), 90 deletions(-) delete mode 160000 crates/htwv/third_party/pmfx-shader diff --git a/.gitmodules b/.gitmodules index cc8da8c6..78e4d8f5 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,6 +4,3 @@ [submodule "crates/htwv/third_party/SPIRV-Cross"] path = crates/htwv/third_party/SPIRV-Cross url = https://github.com/KhronosGroup/SPIRV-Cross.git -[submodule "crates/htwv/third_party/pmfx-shader"] - path = crates/htwv/third_party/pmfx-shader - url = https://github.com/polymonster/pmfx-shader.git diff --git a/crates/htwv/src/macos_impl.rs b/crates/htwv/src/macos_impl.rs index 1d937e9f..9cd27cfe 100644 --- a/crates/htwv/src/macos_impl.rs +++ b/crates/htwv/src/macos_impl.rs @@ -396,8 +396,7 @@ pub fn compile_dir(input_dir: &str, output_dir: &str) -> Result<(), Box MTLTextureUsage { mtl_usage } +fn to_mtl_compare_func(func: super::ComparisonFunc) -> metal::MTLCompareFunction { + match func { + super::ComparisonFunc::Never => metal::MTLCompareFunction::Never, + super::ComparisonFunc::Less => metal::MTLCompareFunction::Less, + super::ComparisonFunc::Equal => metal::MTLCompareFunction::Equal, + super::ComparisonFunc::LessEqual => metal::MTLCompareFunction::LessEqual, + super::ComparisonFunc::Greater => metal::MTLCompareFunction::Greater, + super::ComparisonFunc::NotEqual => metal::MTLCompareFunction::NotEqual, + super::ComparisonFunc::GreaterEqual => metal::MTLCompareFunction::GreaterEqual, + super::ComparisonFunc::Always => metal::MTLCompareFunction::Always, + } +} + +fn to_mtl_stencil_op(op: super::StencilOp) -> metal::MTLStencilOperation { + match op { + super::StencilOp::Keep => metal::MTLStencilOperation::Keep, + super::StencilOp::Zero => metal::MTLStencilOperation::Zero, + super::StencilOp::Replace => metal::MTLStencilOperation::Replace, + super::StencilOp::IncrSat => metal::MTLStencilOperation::IncrementClamp, + super::StencilOp::DecrSat => metal::MTLStencilOperation::DecrementClamp, + super::StencilOp::Invert => metal::MTLStencilOperation::Invert, + super::StencilOp::Incr => metal::MTLStencilOperation::IncrementWrap, + super::StencilOp::Decr => metal::MTLStencilOperation::DecrementWrap, + } +} + +fn has_stencil_component(format: metal::MTLPixelFormat) -> bool { + matches!(format, + metal::MTLPixelFormat::Depth32Float_Stencil8 + ) +} + fn to_mtl_pixel_format(format: super::Format) -> metal::MTLPixelFormat { match format { super::Format::Unknown => metal::MTLPixelFormat::Invalid, @@ -550,14 +582,18 @@ impl super::CmdBuf for CmdBuf { fn set_render_pipeline(&mut self, pipeline: &RenderPipeline) { objc::rc::autoreleasepool(|| { - self.render_encoder + let encoder = self.render_encoder .as_ref() - .expect("hotline_rs::gfx::metal expected a call to begin render pass before using render commands") - .set_render_pipeline_state(&pipeline.pipeline_state); + .expect("hotline_rs::gfx::metal expected a call to begin render pass before using render commands"); + + encoder.set_render_pipeline_state(&pipeline.pipeline_state); + + // Set depth stencil state + encoder.set_depth_stencil_state(&pipeline.depth_stencil_state); // Bind sampler argument buffer at buffer(0) in fragment shader if let Some(ref sampler_arg_buffer) = pipeline.sampler_argument_buffer { - self.render_encoder.as_ref().unwrap().set_fragment_buffer( + encoder.set_fragment_buffer( 0, Some(sampler_arg_buffer), 0 @@ -586,39 +622,38 @@ impl super::CmdBuf for CmdBuf { .as_ref() .expect("hotline_rs::gfx::metal expected a call to begin render pass before using render commands"); - // Make the heap accessible to shaders - encoder.use_heap_at(&heap.mtl_heap, metal::MTLRenderStages::Fragment); - encoder.use_heap_at(&heap.mtl_heap, metal::MTLRenderStages::Vertex); - // Cast pipeline to RenderPipeline to access slot_lookup let rp: &RenderPipeline = unsafe { std::mem::transmute(pipeline) }; - // Track which buffer indices we've already bound - let mut bound_vertex_buffers: std::collections::HashSet = std::collections::HashSet::new(); - let mut bound_fragment_buffers: std::collections::HashSet = std::collections::HashSet::new(); - - // Bind heap's pre-encoded argument buffers to the slots specified by the pipeline - for slot in rp.slot_lookup.values() { - // Get the appropriate heap argument buffer based on data type - // Push constants have data_type: None and will hit the _ => continue branch - let arg_buffer = match slot.data_type { - Some(metal::MTLDataType::Texture) => heap.get_texture_argument_buffer(), - Some(metal::MTLDataType::Pointer) => heap.get_buffer_argument_buffer(), - _ => continue, - }; - - // Bind to vertex stage if needed (once per buffer index) - if let Some(vertex_idx) = slot.vertex_buffer_index { - if bound_vertex_buffers.insert(vertex_idx as u64) { - encoder.set_vertex_buffer(vertex_idx as u64, Some(arg_buffer), 0); + // vertex bindings + encoder.use_heap_at(&heap.mtl_heap, metal::MTLRenderStages::Vertex); + for (key, slot) in &rp.vertex_binder { + match slot { + PipelineStageBinder::Resource(res) => { + let arg_buffer = match res.data_type { + metal::MTLDataType::Texture => heap.get_texture_argument_buffer(), + metal::MTLDataType::Pointer => heap.get_buffer_argument_buffer(), + _ => continue, + }; + encoder.set_vertex_buffer(res.buffer_index as u64, Some(arg_buffer), 0); } + _ => {} } + } - // Bind to fragment stage if needed (once per buffer index) - if let Some(fragment_idx) = slot.fragment_buffer_index { - if bound_fragment_buffers.insert(fragment_idx as u64) { - encoder.set_fragment_buffer(fragment_idx as u64, Some(arg_buffer), 0); + // fragment bindings + encoder.use_heap_at(&heap.mtl_heap, metal::MTLRenderStages::Fragment); + for (key, slot) in &rp.fragment_binder { + match slot { + PipelineStageBinder::Resource(res) => { + let arg_buffer = match res.data_type { + metal::MTLDataType::Texture => heap.get_texture_argument_buffer(), + metal::MTLDataType::Pointer => heap.get_buffer_argument_buffer(), + _ => continue, + }; + encoder.set_fragment_buffer(res.buffer_index as u64, Some(arg_buffer), 0); } + _ => {} } } } @@ -873,18 +908,6 @@ struct MetalSamplerBinding { sampler: metal::SamplerState } -/// Unified pipeline slot for both descriptors and push constants -/// Supports per-stage buffer indices for Metal argument buffers -pub struct PipelineSlot { - /// Metal buffer index for vertex stage (None if not visible to vertex) - pub vertex_buffer_index: Option, - /// Metal buffer index for fragment stage (None if not visible to fragment) - pub fragment_buffer_index: Option, - /// Metal Data type, for bindings this is Texture or Pointer (Buffer) - pub data_type: Option, - /// Slot info for API compatibility - pub info: PipelineSlotInfo, -} /// Push constants binder - uses setVertexBytes/setFragmentBytes for zero-allocation binding #[derive(Clone)] struct PushConstantsBinder { @@ -920,13 +943,10 @@ type SlotKey = (u32, u32, DescriptorType); pub struct RenderPipeline { pipeline_state: metal::RenderPipelineState, slots: Vec, - /// Primitive topology for draw calls topology: Topology, - /// Unified slot lookup by (register, space, descriptor_type) - slot_lookup: HashMap, - + slot_lookup: HashMap, /// Static samplers static_samplers: Vec, /// Sampler argument buffer @@ -935,13 +955,15 @@ pub struct RenderPipeline { vertex_binder: HashMap, /// Fragment stage binders for push constants, keyed by (register, space, descriptor_type) fragment_binder: HashMap, + /// Depth stencil state + depth_stencil_state: metal::DepthStencilState, } impl super::RenderPipeline for RenderPipeline {} impl super::Pipeline for RenderPipeline { fn get_pipeline_slot(&self, register: u32, space: u32, descriptor_type: DescriptorType) -> Option<&super::PipelineSlotInfo> { - self.slot_lookup.get(&(register, space, descriptor_type)).map(|slot| &slot.info) + self.slot_lookup.get(&(register, space, descriptor_type)) } fn get_pipeline_slots(&self) -> &Vec { @@ -1026,6 +1048,7 @@ impl super::ReadBackRequest for ReadBackRequest { pub struct RenderPass { desc: metal::RenderPassDescriptor, pixel_format: metal::MTLPixelFormat, + depth_format: Option, } impl super::RenderPass for RenderPass { @@ -1245,13 +1268,10 @@ impl Device { &self, pipeline_bindings: &Option>, pipeline_push_constants: &Option>, - ) -> HashMap { - let mut slot_lookup: HashMap = HashMap::new(); + ) -> HashMap { + let mut slot_lookup: HashMap = HashMap::new(); - // htwv convention: samplers at 2 on vs - // samplers at 0 on ps - // Track binding offsets separately per stage since different numbers of - // bindings and push constants might be active on each stage + // hardcoded sampler offsets let vertex_samplers_offset: u32 = 2; let fragment_samplers_offset: u32 = 0; let mut vertex_binding_offset: u32 = vertex_samplers_offset + 1; @@ -1285,14 +1305,9 @@ impl Device { slot_lookup.insert( (push_constant.shader_register, push_constant.register_space, DescriptorType::PushConstants), - PipelineSlot { - vertex_buffer_index: vertex_idx, - fragment_buffer_index: fragment_idx, - data_type: None, // Not used for push constants - info: PipelineSlotInfo { - index: canonical_index, - count: Some(push_constant.num_values), - }, + PipelineSlotInfo { + index: canonical_index, + count: Some(push_constant.num_values), }, ); } @@ -1326,28 +1341,12 @@ impl Device { // Each binding gets a slot entry for binding in bindings.iter() { - // Per-slot visibility based on the binding's visibility - let slot_vertex_idx = match binding.visibility { - ShaderVisibility::Vertex | ShaderVisibility::All => vertex_idx, - _ => None, - }; - let slot_fragment_idx = match binding.visibility { - ShaderVisibility::Fragment | ShaderVisibility::All => fragment_idx, - _ => None, - }; - slot_lookup.insert( (binding.shader_register, binding.register_space, binding.binding_type), - PipelineSlot { - vertex_buffer_index: slot_vertex_idx, - fragment_buffer_index: slot_fragment_idx, - data_type: Some(to_mtl_data_type( - binding.resource_type.expect("hotline_rs::gfx::mtl: requires resource type to be set for descriptor binding"))), - info: PipelineSlotInfo { - index: canonical_index, - count: binding.num_descriptors, - }, - }, + PipelineSlotInfo { + index: canonical_index, + count: binding.num_descriptors, + } ); } } @@ -1710,7 +1709,48 @@ impl super::Device for Device { attachment.set_blending_enabled(false); } - // TODO: depth stencil + // Set depth format on pipeline descriptor if pass has depth + if let Some(pass) = &info.pass { + if let Some(depth_format) = pass.depth_format { + pipeline_state_descriptor.set_depth_attachment_pixel_format(depth_format); + if has_stencil_component(depth_format) { + pipeline_state_descriptor.set_stencil_attachment_pixel_format(depth_format); + } + } + } + + // Create depth stencil state + let depth_stencil_state = { + let ds_info = &info.depth_stencil_info; + let ds_desc = metal::DepthStencilDescriptor::new(); + + ds_desc.set_depth_compare_function(to_mtl_compare_func(ds_info.depth_func)); + ds_desc.set_depth_write_enabled(ds_info.depth_write_mask == super::DepthWriteMask::All); + + if ds_info.stencil_enabled { + // Front face + let front = metal::StencilDescriptor::new(); + front.set_stencil_compare_function(to_mtl_compare_func(ds_info.front_face.func)); + front.set_stencil_failure_operation(to_mtl_stencil_op(ds_info.front_face.fail)); + front.set_depth_failure_operation(to_mtl_stencil_op(ds_info.front_face.depth_fail)); + front.set_depth_stencil_pass_operation(to_mtl_stencil_op(ds_info.front_face.pass)); + front.set_read_mask(ds_info.stencil_read_mask as u32); + front.set_write_mask(ds_info.stencil_write_mask as u32); + ds_desc.set_front_face_stencil(Some(&front)); + + // Back face + let back = metal::StencilDescriptor::new(); + back.set_stencil_compare_function(to_mtl_compare_func(ds_info.back_face.func)); + back.set_stencil_failure_operation(to_mtl_stencil_op(ds_info.back_face.fail)); + back.set_depth_failure_operation(to_mtl_stencil_op(ds_info.back_face.depth_fail)); + back.set_depth_stencil_pass_operation(to_mtl_stencil_op(ds_info.back_face.pass)); + back.set_read_mask(ds_info.stencil_read_mask as u32); + back.set_write_mask(ds_info.stencil_write_mask as u32); + ds_desc.set_back_face_stencil(Some(&back)); + } + + self.metal_device.new_depth_stencil_state(&ds_desc) + }; // TODO: raster @@ -1781,6 +1821,7 @@ impl super::Device for Device { fragment_binder, sampler_argument_buffer, topology: info.topology, + depth_stencil_state, }) }) } @@ -2042,9 +2083,52 @@ impl super::Device for Device { .map(|rt| rt.metal_texture.pixel_format()) .unwrap_or(metal::MTLPixelFormat::BGRA8Unorm); + // Handle depth stencil attachment + let depth_format = if let Some(ds_texture) = &info.depth_stencil { + let depth_attachment = descriptor.depth_attachment().unwrap(); + depth_attachment.set_texture(Some(&ds_texture.metal_texture)); + + if let Some(ds_clear) = &info.ds_clear { + if let Some(depth_val) = ds_clear.depth { + depth_attachment.set_load_action(metal::MTLLoadAction::Clear); + depth_attachment.set_clear_depth(depth_val as f64); + } else { + depth_attachment.set_load_action(metal::MTLLoadAction::Load); + } + } else { + depth_attachment.set_load_action(metal::MTLLoadAction::Load); + } + depth_attachment.set_store_action(metal::MTLStoreAction::Store); + + let format = ds_texture.metal_texture.pixel_format(); + + // Handle stencil if format has stencil component + if has_stencil_component(format) { + let stencil_attachment = descriptor.stencil_attachment().unwrap(); + stencil_attachment.set_texture(Some(&ds_texture.metal_texture)); + + if let Some(ds_clear) = &info.ds_clear { + if let Some(stencil_val) = ds_clear.stencil { + stencil_attachment.set_load_action(metal::MTLLoadAction::Clear); + stencil_attachment.set_clear_stencil(stencil_val as u32); + } else { + stencil_attachment.set_load_action(metal::MTLLoadAction::Load); + } + } else { + stencil_attachment.set_load_action(metal::MTLLoadAction::Load); + } + stencil_attachment.set_store_action(metal::MTLStoreAction::Store); + } + + Some(format) + } else { + None + }; + Ok(RenderPass{ desc: descriptor.to_owned(), pixel_format, + depth_format, }) }) } From d608c511eb62473297d75a5da710116fe168977d Mon Sep 17 00:00:00 2001 From: polymonster Date: Wed, 4 Mar 2026 19:08:38 +0000 Subject: [PATCH 32/62] - remove ensure pmfx --- crates/htwv/build.rs | 62 +------------------------------------------- 1 file changed, 1 insertion(+), 61 deletions(-) diff --git a/crates/htwv/build.rs b/crates/htwv/build.rs index 9f34935b..31860012 100644 --- a/crates/htwv/build.rs +++ b/crates/htwv/build.rs @@ -17,7 +17,6 @@ fn macos_build() { // Ensure third-party dependencies exist (download if missing for crates.io) ensure_spirv_cross(&spirv_cross_src); - ensure_pmfx_shader(&pmfx_shader_src); // Rerun if SPIRV-Cross source changes println!("cargo:rerun-if-changed={}/spirv_cross_c.h", spirv_cross_src); @@ -151,63 +150,4 @@ fn ensure_spirv_cross(spirv_cross_dir: &str) { .expect("Failed to rename extracted SPIRV-Cross directory"); println!("cargo:warning=SPIRV-Cross downloaded successfully"); -} - -#[cfg(target_os = "macos")] -fn ensure_pmfx_shader(pmfx_shader_dir: &str) { - use std::path::Path; - use std::process::{Command, Stdio}; - - let marker = Path::new(pmfx_shader_dir).join("pmfx.py"); - if marker.exists() { - return; // Already populated - } - - println!("cargo:warning=pmfx-shader not found, downloading..."); - - // Pin to a specific commit/tag for reproducibility - const PMFX_SHADER_REF: &str = "master"; // TODO: pin to specific tag/commit - let url = format!( - "https://github.com/polymonster/pmfx-shader/archive/refs/heads/{}.tar.gz", - PMFX_SHADER_REF - ); - - let parent = Path::new(pmfx_shader_dir) - .parent() - .expect("Invalid pmfx_shader_dir"); - std::fs::create_dir_all(parent).expect("Failed to create third_party dir"); - - // Download and extract - let status = Command::new("curl") - .args(["-L", "-o", "/tmp/pmfx-shader.tar.gz", &url]) - .stdout(Stdio::inherit()) - .stderr(Stdio::inherit()) - .status() - .expect("Failed to download pmfx-shader"); - - if !status.success() { - panic!("Failed to download pmfx-shader from {}", url); - } - - let status = Command::new("tar") - .args([ - "-xzf", - "/tmp/pmfx-shader.tar.gz", - "-C", - parent.to_str().unwrap(), - ]) - .status() - .expect("Failed to extract pmfx-shader"); - - if !status.success() { - panic!("Failed to extract pmfx-shader"); - } - - // Rename extracted directory - let extracted_name = format!("pmfx-shader-{}", PMFX_SHADER_REF); - let extracted_path = parent.join(&extracted_name); - std::fs::rename(&extracted_path, pmfx_shader_dir) - .expect("Failed to rename extracted pmfx-shader directory"); - - println!("cargo:warning=pmfx-shader downloaded successfully"); -} +} \ No newline at end of file From d7909f95e179ec7d6653aad04dc75cf17e4b1153 Mon Sep 17 00:00:00 2001 From: polymonster Date: Wed, 4 Mar 2026 19:14:48 +0000 Subject: [PATCH 33/62] - fix conflicts --- plugins/ecs_examples/src/draw_indexed.rs | 7 ----- plugins/ecs_examples/src/lib.rs | 35 ------------------------ 2 files changed, 42 deletions(-) diff --git a/plugins/ecs_examples/src/draw_indexed.rs b/plugins/ecs_examples/src/draw_indexed.rs index ce16ec59..8d91fa0a 100644 --- a/plugins/ecs_examples/src/draw_indexed.rs +++ b/plugins/ecs_examples/src/draw_indexed.rs @@ -50,14 +50,7 @@ pub fn draw_meshes_indexed( let camera = pmfx.get_camera_constants(&view.camera)?; cmd_buf.set_render_pipeline(pipeline); -<<<<<<< HEAD - - if let Some(c0) = pipeline.get_pipeline_slot(0, 0, gfx::DescriptorType::PushConstants) { - cmd_buf.push_render_constants(c0.index, 16, 0, gfx::as_u8_slice(&camera.view_projection_matrix)); - } -======= cmd_buf.push_render_constants(pipeline, 0, 0, 16, 0, gfx::as_u8_slice(&camera.view_projection_matrix)); ->>>>>>> master for (_, mesh) in &mesh_draw_query { cmd_buf.set_vertex_buffer(&mesh.0.vb, 0); diff --git a/plugins/ecs_examples/src/lib.rs b/plugins/ecs_examples/src/lib.rs index ba312380..f41c3e30 100644 --- a/plugins/ecs_examples/src/lib.rs +++ b/plugins/ecs_examples/src/lib.rs @@ -265,19 +265,6 @@ pub fn render_meshes_bindless( cmd_buf.push_render_constants(pipeline, 2, 0, gfx::num_32bit_constants(&world_buffer_info), 0, gfx::as_u8_slice(&world_buffer_info)); // bind resource uses -<<<<<<< HEAD - let using_slot = pipeline.get_pipeline_slot(0, 1, gfx::DescriptorType::PushConstants); - if let Some(_) = using_slot { - for i in 0..view.use_indices.len() { - let num_constants = gfx::num_32bit_constants(&view.use_indices[i]); - cmd_buf.push_compute_constants( - 0, - num_constants, - i as u32 * num_constants, - gfx::as_u8_slice(&view.use_indices[i]) - ); - } -======= for i in 0..view.use_indices.len() { let num_constants = gfx::num_32bit_constants(&view.use_indices[i]); cmd_buf.push_compute_constants( @@ -288,7 +275,6 @@ pub fn render_meshes_bindless( i as u32 * num_constants, gfx::as_u8_slice(&view.use_indices[i]) ); ->>>>>>> master } // bind the shader resource heap @@ -331,14 +317,7 @@ pub fn render_meshes( let camera = pmfx.get_camera_constants(&view.camera)?; cmd_buf.set_render_pipeline(&pipeline); -<<<<<<< HEAD - - if let Some(c0) = pipeline.get_pipeline_slot(0, 0, gfx::DescriptorType::PushConstants) { - cmd_buf.push_render_constants(c0.index, 16, 0, gfx::as_u8_slice(&camera.view_projection_matrix)); - } -======= cmd_buf.push_render_constants(pipeline, 0, 0, 16, 0, gfx::as_u8_slice(&camera.view_projection_matrix)); ->>>>>>> master let (mesh_draw_query, billboard_draw_query, cylindrical_draw_query) = queries; @@ -545,19 +524,6 @@ pub fn dispatch_compute( let pipeline = pmfx.get_compute_pipeline(&pass.pass_pipline)?; cmd_buf.set_compute_pipeline(&pipeline); -<<<<<<< HEAD - let using_slot = pipeline.get_pipeline_slot(0, 1, gfx::DescriptorType::PushConstants); - if let Some(slot) = using_slot { - for i in 0..pass.use_indices.len() { - let num_constants = gfx::num_32bit_constants(&pass.use_indices[i]); - cmd_buf.push_compute_constants( - slot.index, - num_constants, - i as u32 * num_constants, - gfx::as_u8_slice(&pass.use_indices[i]) - ); - } -======= for i in 0..pass.use_indices.len() { let num_constants = gfx::num_32bit_constants(&pass.use_indices[i]); cmd_buf.push_compute_constants( @@ -568,7 +534,6 @@ pub fn dispatch_compute( i as u32 * num_constants, gfx::as_u8_slice(&pass.use_indices[i]) ); ->>>>>>> master } cmd_buf.set_heap(pipeline, &pmfx.shader_heap); From 339423c4a25ce67e9e77539dabcf1b7cb8977105 Mon Sep 17 00:00:00 2001 From: polymonster Date: Wed, 4 Mar 2026 19:54:49 +0000 Subject: [PATCH 34/62] - add raster states and vertex buffer instancing (not fully working, but plumbed in) --- .../src/draw_vertex_buffer_instanced.rs | 8 +- shaders/draw_instanced.hlsl | 4 +- shaders/ecs.hlsl | 4 +- shaders/material.hlsl | 58 +++++------ shaders/texture.hlsl | 84 ++++++++-------- src/gfx/mtl.rs | 95 ++++++++++++++++--- 6 files changed, 160 insertions(+), 93 deletions(-) diff --git a/plugins/ecs_examples/src/draw_vertex_buffer_instanced.rs b/plugins/ecs_examples/src/draw_vertex_buffer_instanced.rs index e29aae58..47e137ee 100644 --- a/plugins/ecs_examples/src/draw_vertex_buffer_instanced.rs +++ b/plugins/ecs_examples/src/draw_vertex_buffer_instanced.rs @@ -1,6 +1,6 @@ /// /// Draw Vertex Buffer Instanced -/// +/// use crate::prelude::*; @@ -46,7 +46,7 @@ pub fn setup_draw_vertex_buffer_instanced( let parent = commands.spawn(InstanceBatch { mesh: MeshComponent(mesh.clone()), pipeline: PipelineComponent("mesh_vertex_buffer_instanced".to_string()), - instance_buffer: InstanceBuffer { + instance_buffer: InstanceBuffer { buffer: device.create_buffer(&gfx::BufferInfo{ usage: gfx::BufferUsage::VERTEX, cpu_access: gfx::CpuAccessFlags::WRITE, @@ -61,7 +61,7 @@ pub fn setup_draw_vertex_buffer_instanced( }).id(); for _ in 0..num { for _ in 0..num { - // spawn a bunch of entites with slightly randomised + // spawn a bunch of entites with slightly randomised let pos = vec3f(rng.gen(), rng.gen(), rng.gen()) * splat3f(range) * 2.0 - vec3f(range, 0.0, range); let rot = vec3f(rng.gen(), rng.gen(), rng.gen()) * f32::pi() * 2.0; commands.spawn(Instance { @@ -86,7 +86,7 @@ pub fn draw_meshes_vertex_buffer_instanced( cmd_buf: &mut ::CmdBuf, instance_draw_query: Query<(&InstanceBuffer, &MeshComponent, &PipelineComponent)> ) -> Result<(), hotline_rs::Error> { - + let pmfx = &pmfx; let fmt = view.pass.get_format_hash(); let camera = pmfx.get_camera_constants(&view.camera)?; diff --git a/shaders/draw_instanced.hlsl b/shaders/draw_instanced.hlsl index d1913f73..349f9f7c 100644 --- a/shaders/draw_instanced.hlsl +++ b/shaders/draw_instanced.hlsl @@ -25,7 +25,7 @@ vs_output vs_mesh_vertex_buffer_instanced(vs_input_mesh input, vs_input_instance output.texcoord = float4(input.texcoord, 0.0, 0.0); output.colour = float4(input.normal.xyz * 0.5 + 0.5, 1.0); output.normal = input.normal.xyz; - + return output; } @@ -34,7 +34,7 @@ vs_output vs_mesh_vertex_buffer_instanced(vs_input_mesh input, vs_input_instance // struct cbuffer_instance_data { - float3x4 cbuffer_world_matrix[1024]; + row_major float3x4 cbuffer_world_matrix[1024]; }; ConstantBuffer cbuffer_instance : register(b1); diff --git a/shaders/ecs.hlsl b/shaders/ecs.hlsl index 55da224a..7dbaa1d5 100644 --- a/shaders/ecs.hlsl +++ b/shaders/ecs.hlsl @@ -136,7 +136,7 @@ StructuredBuffer materials[1024] : register(t0, space2); StructuredBuffer point_lights[1024] : register(t0, space3); StructuredBuffer spot_lights[1024] : register(t0, space4); StructuredBuffer directional_lights[1024] : register(t0, space5); -StructuredBuffer shadow_matrices[1024] : register(t0, space6); +StructuredBuffer shadow_matrices[1024] : register(t0, space6); // textures Texture2D textures[1024] : register(t0, space7); @@ -185,6 +185,6 @@ camera_data get_camera_data() { } // utility to return a shadow matrix by index -float4x4 get_shadow_matrix(uint shadow_index) { +row_major float4x4 get_shadow_matrix(uint shadow_index) { return shadow_matrices[world_buffer_info.shadow_matrix.x][shadow_index]; } \ No newline at end of file diff --git a/shaders/material.hlsl b/shaders/material.hlsl index 36f0c548..39560a32 100644 --- a/shaders/material.hlsl +++ b/shaders/material.hlsl @@ -18,22 +18,22 @@ vs_output_material vs_mesh_material(vs_input_mesh input, vs_input_entity_ids ent // get draw call info and transform world matrix draw_data draw = get_draw_data(entity_input.ids[0]); - float4 pos = float4(input.position.xyz, 1.0); + float4 pos = float4(input.position.xyz, 1.0); pos.xyz = mul(draw.world_matrix, pos); output.position = mul(view_projection_matrix, pos); output.world_pos = pos; output.texcoord = float4(input.texcoord, 0.0, 0.0); - + float3x3 rot = (float3x3)draw.world_matrix; output.normal = normalize(mul(rot, input.normal)); output.tangent = normalize(mul(rot, input.tangent)); output.bitangent = normalize(mul(rot, input.bitangent)); - + // mat material_data mat = get_material_data(entity_input.ids[1]); output.ids = uint4(mat.albedo_id, mat.normal_id, mat.roughness_id, mat.padding); - + return output; } @@ -42,7 +42,7 @@ vs_output_material vs_mesh_material_indirect(vs_input_mesh input) { // get draw call info and transform world matrix draw_data draw = get_draw_data(indirect_ids.x); - float4 pos = float4(input.position.xyz, 1.0); + float4 pos = float4(input.position.xyz, 1.0); pos.xyz = mul(draw.world_matrix, pos); // get camera data and transform projection matrix @@ -60,14 +60,14 @@ vs_output_material vs_mesh_material_indirect(vs_input_mesh input) { material_data mat = get_material_data(indirect_ids.y); output.ids = uint4(mat.albedo_id, mat.normal_id, mat.roughness_id, mat.padding); - + return output; } vs_output_material vs_mesh_lit(vs_input_mesh input) { vs_output_material output; - float3x4 wm = world_matrix; + row_major float3x4 wm = world_matrix; float4 pos = float4(input.position.xyz, 1.0); pos.xyz = mul(wm, pos); @@ -109,7 +109,7 @@ ps_output ps_mesh_material(vs_output_material input) { output.colour = float4(0.0, 0.0, 0.0, 0.0); float2 tc = input.texcoord.xy; - + // sample maps // albedo @@ -150,7 +150,7 @@ ps_output ps_mesh_material(vs_output_material input) { light.radius, input.world_pos.xyz ); - + output.colour += atteniuation * light.colour * diffuse * albedo; output.colour += atteniuation * light.colour * specular; } @@ -240,7 +240,7 @@ ps_output ps_mesh_lit(vs_output input) { light.radius, input.world_pos.xyz ); - + output.colour += atteniuation * light.colour * diffuse; output.colour += atteniuation * light.colour * specular; } @@ -262,7 +262,7 @@ ps_output ps_mesh_lit(vs_output input) { light.cutoff, light.falloff ); - + output.colour += atteniuation * light.colour * diffuse; output.colour += atteniuation * light.colour * specular; } @@ -291,7 +291,7 @@ float4 ps_mesh_pbr_ibl(vs_output input) : SV_TARGET { float3 v = normalize(input.world_pos.xyz - view_position.xyz); float3 n = input.normal; - + float3 albedo = float3(1.0, 0.5, 0.0); float3 f0 = lerp(float3(0.04, 0.04, 0.04), albedo, metalness); @@ -299,7 +299,7 @@ float4 ps_mesh_pbr_ibl(vs_output input) : SV_TARGET { float3 rd = normalize(input.world_pos.xyz - view_position.xyz) * float3(1.0, 1.0, -1.0); float3 nd = normalize(input.normal.xyz * float3(1.0, 1.0, -1.0)); - float3 r = reflect(rd, nd); + float3 r = reflect(rd, nd); r.z *= -1.0; // irradiance / diffuse @@ -383,10 +383,10 @@ void scene_raygen_shader() // unproject ray float4 near = float4(ndc.x, ndc.y, 0.0, 1.0); float4 far = float4(ndc.x, ndc.y, 1.0, 1.0); - + float4 wnear = mul(inverse_wvp, near); wnear /= wnear.w; - + float4 wfar = mul(inverse_wvp, far); wfar /= wfar.w; @@ -399,13 +399,13 @@ void scene_raygen_shader() RayPayload payload = default_payload(); TraceRay( - scene_tlas[resource_indices.y], - RAY_FLAG_NONE, - 0xff, + scene_tlas[resource_indices.y], + RAY_FLAG_NONE, + 0xff, 0, 2, - 0, - ray, + 0, + ray, payload ); @@ -419,13 +419,13 @@ void scene_raygen_shader() payload = default_payload(); payload.bounce_count = bounce_count; TraceRay( - scene_tlas[resource_indices.y], - RAY_FLAG_NONE, - 0xff, + scene_tlas[resource_indices.y], + RAY_FLAG_NONE, + 0xff, 0, 2, - 0, - bounce_ray, + 0, + bounce_ray, payload ); @@ -543,7 +543,7 @@ void scene_closest_hit_shader(inout RayPayload payload, in BuiltInTriangleInters float3 ray_dir = refract(rd, geo_normal, refidx); float3 ray_start = ip + rd * 0.001; - + if(length(ray_dir) == 0.0) { ray_dir = reflect(rd, geo_normal); @@ -569,7 +569,7 @@ void scene_closest_hit_shader(inout RayPayload payload, in BuiltInTriangleInters return; } - + float2 tx = v0.texcoord * u + v1.texcoord * w + v2.texcoord * v; // checkerboard uv @@ -591,7 +591,7 @@ void scene_closest_hit_shader(inout RayPayload payload, in BuiltInTriangleInters float rxy = rx + ry > 1.0 ? 0.0 : rx + ry; float3 checkerboard = rxy < 0.001 ? 0.66 : 1.0; - + payload.col = float4(geo_normal, 1.0); payload.col.xyz = payload.col.xyz * 0.5 + 0.5 * checkerboard; @@ -667,7 +667,7 @@ ps_output ps_mesh_lit_rt_shadow(vs_output input) { light_colour += atteniuation * light.colour * specular; bool occluded = is_occluded(input.world_pos.xyz + input.normal * 0.1, -l, 0.1, rl + 0.1); - + if(!occluded) { output.colour += light_colour; } diff --git a/shaders/texture.hlsl b/shaders/texture.hlsl index d0a8bcfd..78a2c511 100644 --- a/shaders/texture.hlsl +++ b/shaders/texture.hlsl @@ -12,7 +12,7 @@ float4 ps_texture2d(vs_output input) : SV_Target { // // cubemap with bindless lookup -// +// float4 ps_cubemap(vs_output input) : SV_Target { float4 col = cubemaps[draw_indices.x] @@ -46,8 +46,8 @@ float4 ps_texture2d_array(vs_output input) : SV_Target { vs_output vs_texture3d(vs_input_mesh input) { vs_output output; - float3x4 wm = world_matrix; - + row_major float3x4 wm = world_matrix; + float4 pos = float4(input.position.xyz, 1.0); pos.xyz = mul(wm, pos); @@ -56,7 +56,7 @@ vs_output vs_texture3d(vs_input_mesh input) { output.texcoord = float4(input.position, 0.0); output.colour = float4(input.normal.xyz, 1.0); output.normal = input.normal.xyz; - + return output; } @@ -67,7 +67,7 @@ ps_output ps_volume_texture_ray_march_sdf(vs_output input) { float3 v = input.texcoord.xyz; float3 chebyshev_norm = chebyshev_normalize(v); float3 uvw = chebyshev_norm * 0.5 + 0.5; - + float max_samples = 64.0; float3x3 inv_rot; @@ -77,45 +77,45 @@ ps_output ps_volume_texture_ray_march_sdf(vs_output input) { inv_rot = transpose(inv_rot); float3 ray_dir = normalize(input.world_pos.xyz - view_position.xyz); - + ray_dir = mul(inv_rot, ray_dir); ray_dir = normalize(ray_dir); - + float3 vddx = ddx( uvw ); float3 vddy = ddy( uvw ); - + float3 scale = float3( - length(world_matrix[0].xyz), - length(world_matrix[1].xyz), + length(world_matrix[0].xyz), + length(world_matrix[1].xyz), length(world_matrix[2].xyz) ) * 2.0; - + float d = volume_textures[draw_indices.x].SampleGrad(sampler_wrap_linear, uvw, vddx, vddy).r; - + float3 col = float3( 0.0, 0.0, 0.0 ); float3 ray_pos = input.world_pos.xyz; float taken = 0.0; - float3 min_step = (scale / max_samples); - + float3 min_step = (scale / max_samples); + for( int s = 0; s < int(max_samples); ++s ) - { + { taken += 1.0 / max_samples; - + d = volume_textures[draw_indices.x].SampleGrad(sampler_wrap_linear, uvw, vddx, vddy).r; - + float3 step = ray_dir.xyz * float3(d / scale) * 0.5; - + uvw += step; - + if(uvw.x >= 1.0 || uvw.x <= 0.0) discard; - + if(uvw.y >= 1.0 || uvw.y <= 0.0) discard; - + if(uvw.z >= 1.0 || uvw.z <= 0.0) discard; - + if( d <= 0.3 ) break; } @@ -129,56 +129,56 @@ ps_output ps_volume_texture_ray_march_sdf(vs_output input) { ps_output ps_volume_texture_ray_march(vs_output input) { ps_output output; - + float depth = 1.0; float max_samples = 256.0; - + float3 v = input.texcoord.xyz; float3 chebyshev_norm = chebyshev_normalize(v); float3 uvw = chebyshev_norm * 0.5 + 0.5; - + float3x3 inv_rot; inv_rot[0] = world_matrix[0].xyz; inv_rot[1] = world_matrix[1].xyz; inv_rot[2] = world_matrix[2].xyz; inv_rot = transpose(inv_rot); - - float3 ray_dir = normalize(input.world_pos.xyz - view_position.xyz); + + float3 ray_dir = normalize(input.world_pos.xyz - view_position.xyz); ray_dir = mul( inv_rot, ray_dir ); - + float3 ray_step = chebyshev_normalize(ray_dir.xyz) / max_samples; - + float depth_step = 1.0 / max_samples; - + float3 vddx = ddx( uvw ); float3 vddy = ddy( uvw ); - + for(int s = 0; s < int(max_samples); ++s ) { - output.colour = + output.colour = volume_textures[draw_indices.x].SampleGrad(sampler_wrap_linear, uvw, vddx, vddy); - + if(output.colour.a != 0.0) break; - + depth -= depth_step; uvw += ray_step; - + if(uvw.x > 1.0 || uvw.x < 0.0) discard; - + if(uvw.y > 1.0 || uvw.y < 0.0) discard; - + if(uvw.z > 1.0 || uvw.z < 0.0) discard; - + if(s == int(max_samples)-1) discard; } - + output.colour.rgb *= lerp( 0.5, 1.0, depth ); - + return output; } @@ -200,8 +200,8 @@ void cs_write_texture3d(uint3 did : SV_DispatchThreadID) { float3 n = normalize(grid_pos); - float nn = - abs(dot(n, float3(0.0, 1.0, 0.0))) * nxz + float nn = + abs(dot(n, float3(0.0, 1.0, 0.0))) * nxz + abs(dot(n, float3(0.0, 0.0, 1.0))) * nxy + abs(dot(n, float3(1.0, 0.0, 0.0))) * nyz; diff --git a/src/gfx/mtl.rs b/src/gfx/mtl.rs index 3fb5fcc4..59d4f4bf 100644 --- a/src/gfx/mtl.rs +++ b/src/gfx/mtl.rs @@ -172,6 +172,37 @@ fn has_stencil_component(format: metal::MTLPixelFormat) -> bool { ) } +fn to_mtl_cull_mode(cull_mode: super::CullMode) -> metal::MTLCullMode { + match cull_mode { + super::CullMode::None => metal::MTLCullMode::None, + super::CullMode::Front => metal::MTLCullMode::Front, + super::CullMode::Back => metal::MTLCullMode::Back, + } +} + +fn to_mtl_winding(front_ccw: bool) -> metal::MTLWinding { + if front_ccw { + metal::MTLWinding::CounterClockwise + } else { + metal::MTLWinding::Clockwise + } +} + +fn to_mtl_triangle_fill_mode(fill_mode: super::FillMode) -> metal::MTLTriangleFillMode { + match fill_mode { + super::FillMode::Solid => metal::MTLTriangleFillMode::Fill, + super::FillMode::Wireframe => metal::MTLTriangleFillMode::Lines, + } +} + +fn to_mtl_index_type(stride: usize) -> metal::MTLIndexType { + match stride { + 2 => metal::MTLIndexType::UInt16, + 4 => metal::MTLIndexType::UInt32, + _ => panic!("Invalid index stride: {}, expected 2 or 4", stride), + } +} + fn to_mtl_pixel_format(format: super::Format) -> metal::MTLPixelFormat { match format { super::Format::Unknown => metal::MTLPixelFormat::Invalid, @@ -591,6 +622,13 @@ impl super::CmdBuf for CmdBuf { // Set depth stencil state encoder.set_depth_stencil_state(&pipeline.depth_stencil_state); + // Set rasterizer state + let raster = &pipeline.raster_info; + encoder.set_cull_mode(to_mtl_cull_mode(raster.cull_mode)); + encoder.set_front_facing_winding(to_mtl_winding(raster.front_ccw)); + encoder.set_triangle_fill_mode(to_mtl_triangle_fill_mode(raster.fill_mode)); + encoder.set_depth_bias(raster.depth_bias as f32, raster.slope_scaled_depth_bias, raster.depth_bias_clamp); + // Bind sampler argument buffer at buffer(0) in fragment shader if let Some(ref sampler_arg_buffer) = pipeline.sampler_argument_buffer { encoder.set_fragment_buffer( @@ -782,7 +820,7 @@ impl super::CmdBuf for CmdBuf { .draw_indexed_primitives_instanced_base_instance( primitive_type, index_count as u64, - metal::MTLIndexType::UInt16, + to_mtl_index_type(self.bound_index_stride), &self.bound_index_buffer.as_ref().unwrap(), start_index as u64 * self.bound_index_stride as u64, instance_count as u64, @@ -966,6 +1004,8 @@ pub struct RenderPipeline { fragment_binder: HashMap, /// Depth stencil state depth_stencil_state: metal::DepthStencilState, + /// Rasterizer state (applied dynamically on encoder in Metal) + raster_info: super::RasterInfo, } impl super::RenderPipeline for RenderPipeline {} @@ -1663,15 +1703,21 @@ impl super::Device for Device { let vertex_desc = metal::VertexDescriptor::new(); let mut attrib_index = 0; - // make spaces for slots to calculate the stride from offsets + size - let mut slot_strides = Vec::new(); + // track stride, step function, and step rate per slot + struct SlotLayout { + stride: u32, + input_slot_class: super::InputSlotClass, + step_rate: u32, + } + let mut slot_layouts: Vec> = Vec::new(); for element in &info.input_layout { - if slot_strides.len() < (element.input_slot + 1) as usize { - slot_strides.resize((element.input_slot + 1) as usize, 0); + let slot = element.input_slot as usize; + if slot_layouts.len() <= slot { + slot_layouts.resize_with(slot + 1, || None); } } - // make the idividual attributes and track the stride of each slot + // make the individual attributes and track the stride/stepping of each slot for element in &info.input_layout { let attribute = metal::VertexAttributeDescriptor::new(); attribute.set_format(to_mtl_vertex_format(element.format)); @@ -1681,14 +1727,36 @@ impl super::Device for Device { attrib_index += 1; let stride = element.aligned_byte_offset + block_size_for_format(element.format); - slot_strides[element.input_slot as usize] = max(slot_strides[element.input_slot as usize], stride); + let slot = element.input_slot as usize; + if let Some(ref mut layout) = slot_layouts[slot] { + layout.stride = max(layout.stride, stride); + } else { + slot_layouts[slot] = Some(SlotLayout { + stride, + input_slot_class: element.input_slot_class, + step_rate: element.step_rate, + }); + } } - // vertex layouts; TODO: work out MTLVertexStepFunction - let layout_desc = metal::VertexBufferLayoutDescriptor::new(); - layout_desc.set_step_function(metal::MTLVertexStepFunction::PerVertex); - layout_desc.set_stride(slot_strides[0] as NSUInteger); - vertex_desc.layouts().set_object_at(0, Some(&layout_desc)); + // create vertex buffer layouts for each slot + for (slot, layout_opt) in slot_layouts.iter().enumerate() { + if let Some(layout) = layout_opt { + let layout_desc = metal::VertexBufferLayoutDescriptor::new(); + layout_desc.set_stride(layout.stride as NSUInteger); + match layout.input_slot_class { + super::InputSlotClass::PerVertex => { + layout_desc.set_step_function(metal::MTLVertexStepFunction::PerVertex); + layout_desc.set_step_rate(1); + } + super::InputSlotClass::PerInstance => { + layout_desc.set_step_function(metal::MTLVertexStepFunction::PerInstance); + layout_desc.set_step_rate(layout.step_rate as NSUInteger); + } + } + vertex_desc.layouts().set_object_at(slot as NSUInteger, Some(&layout_desc)); + } + } pipeline_state_descriptor.set_vertex_descriptor(Some(&vertex_desc)); @@ -1761,8 +1829,6 @@ impl super::Device for Device { self.metal_device.new_depth_stencil_state(&ds_desc) }; - // TODO: raster - // Create static samplers and argument buffer (at buffer(4) per htwv convention) let mut pipeline_static_samplers = Vec::new(); let mut sampler_argument_buffer = None; @@ -1831,6 +1897,7 @@ impl super::Device for Device { sampler_argument_buffer, topology: info.topology, depth_stencil_state, + raster_info: info.raster_info, }) }) } From 34011318789c87f19dc7cccf5d9b164c35cbc1c6 Mon Sep 17 00:00:00 2001 From: polymonster Date: Sun, 8 Mar 2026 18:00:36 +0000 Subject: [PATCH 35/62] vb instancing, point lights working --- crates/htwv/src/macos_impl.rs | 5 +- plugins/ecs_examples/src/point_lights.rs | 13 ++--- shaders/draw_instanced.hlsl | 15 +++--- shaders/ecs.hlsl | 6 +-- shaders/util.hlsl | 12 ++--- src/gfx/mtl.rs | 64 +++++++++++++++++++++--- 6 files changed, 81 insertions(+), 34 deletions(-) diff --git a/crates/htwv/src/macos_impl.rs b/crates/htwv/src/macos_impl.rs index 9cd27cfe..9f9a8841 100644 --- a/crates/htwv/src/macos_impl.rs +++ b/crates/htwv/src/macos_impl.rs @@ -248,7 +248,10 @@ fn compile_shader_spirv( continue; } let name = cstr_to_string(resource.name)?; - if push_constant.name == name.strip_prefix("type.").unwrap_or(&name) { + // Match if the resource name contains the push constant name + // Handles various naming conventions: "type.view_push_constants", + // "type.ConstantBuffer.world_buffer_info_data", etc. + if name.contains(&push_constant.name) { let desc_set = binding_offset as u32; spvc_compiler_set_decoration( compiler, diff --git a/plugins/ecs_examples/src/point_lights.rs b/plugins/ecs_examples/src/point_lights.rs index 3e159d0c..9a17ae7e 100644 --- a/plugins/ecs_examples/src/point_lights.rs +++ b/plugins/ecs_examples/src/point_lights.rs @@ -1,11 +1,8 @@ -// currently windows only because here we need a concrete gfx and os implementation -#![cfg(target_os = "windows")] - use crate::prelude::*; /// /// Point Lights -/// +/// /// Init function for primitives demo #[no_mangle] @@ -65,7 +62,7 @@ pub fn setup_point_lights( let irc = rc as i32; let size = 10.0; - let half_size = size * 0.5; + let half_size = size * 0.5; let step = size * half_size; let half_extent = (rc-1.0) * step * 0.5; let start_pos = vec3f(-half_extent, size, -half_extent); @@ -97,9 +94,9 @@ pub fn setup_point_lights( #[export_update_fn] pub fn animate_point_lights( - time: Res, + time: Res, mut light_query: Query<&mut Position, With>) -> Result<(), hotline_rs::Error> { - + let t = time.accumulated; let r = sin(t); @@ -107,7 +104,7 @@ pub fn animate_point_lights( let rot1 = sin(-t); let rot2 = sin(t * 0.5); let rot3 = sin(-t * 0.5); - + let step = 1.0 / 16.0; let mut f = 0.0; let mut i = 0; diff --git a/shaders/draw_instanced.hlsl b/shaders/draw_instanced.hlsl index 349f9f7c..c3d7d25f 100644 --- a/shaders/draw_instanced.hlsl +++ b/shaders/draw_instanced.hlsl @@ -6,21 +6,20 @@ struct vs_input_instance { float4 row0: TEXCOORD4; float4 row1: TEXCOORD5; float4 row2: TEXCOORD6; - float4 row3: TEXCOORD7; }; vs_output vs_mesh_vertex_buffer_instanced(vs_input_mesh input, vs_input_instance instance_input) { vs_output output; - float3x4 instance_matrix; - instance_matrix[0] = instance_input.row0; - instance_matrix[1] = instance_input.row1; - instance_matrix[2] = instance_input.row2; - float4 pos = float4(input.position.xyz, 1.0); - pos.xyz = mul(instance_matrix, pos); - output.position = mul(view_projection_matrix, pos); + float3 transformed; + transformed.x = dot(instance_input.row0, pos); + transformed.y = dot(instance_input.row1, pos); + transformed.z = dot(instance_input.row2, pos); + pos.xyz = transformed; + + output.position = mul(view_projection_matrix, float4(pos.xyz, 1.0)); output.world_pos = pos; output.texcoord = float4(input.texcoord, 0.0, 0.0); output.colour = float4(input.normal.xyz * 0.5 + 0.5, 1.0); diff --git a/shaders/ecs.hlsl b/shaders/ecs.hlsl index 7dbaa1d5..9742ec2f 100644 --- a/shaders/ecs.hlsl +++ b/shaders/ecs.hlsl @@ -133,9 +133,9 @@ struct extent_data { StructuredBuffer draws[1024] : register(t0, space0); StructuredBuffer extents[1024] : register(t0, space1); StructuredBuffer materials[1024] : register(t0, space2); -StructuredBuffer point_lights[1024] : register(t0, space3); -StructuredBuffer spot_lights[1024] : register(t0, space4); -StructuredBuffer directional_lights[1024] : register(t0, space5); +StructuredBuffer point_lights[64] : register(t0, space3); +StructuredBuffer spot_lights[64] : register(t0, space4); +StructuredBuffer directional_lights[64] : register(t0, space5); StructuredBuffer shadow_matrices[1024] : register(t0, space6); // textures diff --git a/shaders/util.hlsl b/shaders/util.hlsl index bf5a7ecf..cc0649f3 100644 --- a/shaders/util.hlsl +++ b/shaders/util.hlsl @@ -26,11 +26,11 @@ void cs_mip_chain_texture2d(uint2 did: SV_DispatchThreadID) { pmfx_touch(group_accumulated[0]); float4 level_up = float4(0.0, 0.0, 0.0, 0.0); - + for(int i = 0; i < 9; ++i) { level_up += rw_texture[read][did.xy * 2]; } - + rw_texture[write][did.xy] = level_up / 9.0; } @@ -56,21 +56,21 @@ vs_output_ndc vs_ndc(vs_input_2d_texcoord input) { } cbuffer cubemap_clear_constants : register(b0) { - float4x4 inverse_wvp; + row_major float4x4 inverse_wvp; }; TextureCube cubemap : register(t0); -SamplerState sampler_wrap_linear : register(s0); +SamplerState sampler_wrap_linear : register(s0); float4 ps_cubemap_clear(vs_output_ndc input) : SV_Target { // unproject ray float2 ndc = input.ndc; float4 near = float4(ndc.x, ndc.y, 0.0, 1.0); float4 far = float4(ndc.x, ndc.y, 1.0, 1.0); - + float4 wnear = mul(inverse_wvp, near); wnear /= wnear.w; - + float4 wfar = mul(inverse_wvp, far); wfar /= wfar.w; diff --git a/src/gfx/mtl.rs b/src/gfx/mtl.rs index 59d4f4bf..28b643d0 100644 --- a/src/gfx/mtl.rs +++ b/src/gfx/mtl.rs @@ -892,7 +892,10 @@ impl super::CmdBuf for CmdBuf { #[derive(Clone)] pub struct Buffer { metal_buffer: metal::Buffer, - element_stride: usize + element_stride: usize, + srv_index: Option, + uav_index: Option, + cbv_index: Option, } impl super::Buffer for Buffer { @@ -907,19 +910,19 @@ impl super::Buffer for Buffer { } fn write(&mut self, offset: usize, data: &[T]) -> result::Result<(), super::Error> { - Ok(()) + self.update(offset, data) } fn get_cbv_index(&self) -> Option { - None + self.cbv_index } fn get_srv_index(&self) -> Option { - None + self.srv_index } fn get_uav_index(&self) -> Option { - None + self.uav_index } fn get_vbv(&self) -> Option { @@ -1416,6 +1419,7 @@ impl Device { let vertex_samplers_offset: u32 = 2; let fragment_samplers_offset: u32 = 0; + let mut vertex_binding_offset: u32 = vertex_samplers_offset + 1; let mut fragment_binding_offset: u32 = fragment_samplers_offset + 1; @@ -1978,9 +1982,39 @@ impl super::Device for Device { self.metal_device.new_buffer(byte_len, opt) }; + // allocate on the heap + let alloc_index = heap.allocate(); + heap.buffer_slots[alloc_index] = Some(buf.to_owned()); + heap.encode_buffer(alloc_index, &buf); + + // assign srv or uav + let srv_index = if info.usage.contains(BufferUsage::SHADER_RESOURCE) { + Some(alloc_index) + } + else { + None + }; + + let uav_index = if info.usage.contains(BufferUsage::UNORDERED_ACCESS) { + Some(alloc_index) + } + else { + None + }; + + let cbv_index = if info.usage.contains(BufferUsage::CONSTANT_BUFFER) { + Some(alloc_index) + } + else { + None + }; + Ok(Buffer{ metal_buffer: buf, - element_stride: info.stride + element_stride: info.stride, + srv_index, + uav_index, + cbv_index }) }) } @@ -1990,6 +2024,7 @@ impl super::Device for Device { info: &super::BufferInfo, data: Option<&[T]>, ) -> result::Result { + /* objc::rc::autoreleasepool(|| { let opt = metal::MTLResourceOptions::CPUCacheModeDefaultCache | metal::MTLResourceOptions::StorageModeManaged; @@ -2006,9 +2041,19 @@ impl super::Device for Device { Ok(Buffer{ metal_buffer: buf, - element_stride: info.stride + element_stride: info.stride, + srv_index: None, + uav_index: None, + cbv_index: None }) }) + */ + + self.create_buffer_with_heap( + info, + data, + &mut self.shader_heap.clone() + ) } fn create_read_back_buffer( @@ -2025,7 +2070,10 @@ impl super::Device for Device { Ok(Buffer{ metal_buffer: buf, - element_stride: size + element_stride: size, + srv_index: None, + uav_index: None, + cbv_index: None }) }) } From 54dac20bd3eef869e32c64ed0284d6ea9727bff1 Mon Sep 17 00:00:00 2001 From: polymonster Date: Sun, 8 Mar 2026 19:01:19 +0000 Subject: [PATCH 36/62] - bindless texture working --- config.jsn | 1 + hotline-data | 2 +- src/gfx/mtl.rs | 100 +++++++++++++++++++++++++++++-------------------- 3 files changed, 62 insertions(+), 41 deletions(-) diff --git a/config.jsn b/config.jsn index 0d405753..4698d7fc 100644 --- a/config.jsn +++ b/config.jsn @@ -8,6 +8,7 @@ tools: { pmfx_dev: "python3 ../pmfx-shader/pmfx.py" + texturec: "hotline-data/bin/macos/texturec" } tools_help: { diff --git a/hotline-data b/hotline-data index d8f117c4..26dfb2c6 160000 --- a/hotline-data +++ b/hotline-data @@ -1 +1 @@ -Subproject commit d8f117c42d9e9960800eb288cae30231ebcaaf65 +Subproject commit 26dfb2c6a49275eac101f92f4f354ba473a62bb6 diff --git a/src/gfx/mtl.rs b/src/gfx/mtl.rs index 28b643d0..3717b232 100644 --- a/src/gfx/mtl.rs +++ b/src/gfx/mtl.rs @@ -720,8 +720,8 @@ impl super::CmdBuf for CmdBuf { fn set_marker(&mut self, colour: u32, name: &str) { } - fn push_render_constants(&mut self, pipeline: &P, register: u32, space: u32, num_values: u32, dest_offset: u32, data: &[T]) -> Option<()> { - let slot = pipeline.get_pipeline_slot(register, space, super::DescriptorType::PushConstants)?.index; + fn push_render_constants(&mut self, _pipeline: &P, register: u32, space: u32, num_values: u32, dest_offset: u32, data: &[T]) -> Option<()> { + let key = (register, space, super::DescriptorType::PushConstants); let data_size_dwords = num_values as usize; let data_u32 = unsafe { @@ -733,34 +733,24 @@ impl super::CmdBuf for CmdBuf { let mut result = None; - // Write to vertex binder if matching slot found - for binder in self.vertex_binder.values_mut() { - if let PipelineStageBinder::PushConstants(ref mut pc) = binder { - if pc.buffer_index == slot { - let dest_start = dest_offset as usize; - let dest_end = dest_start + data_size_dwords; - if dest_end <= pc.data.len() { - pc.data[dest_start..dest_end].copy_from_slice(data_u32); - } - result = Some(()); - break; - } + // Write to vertex binder if matching key found + if let Some(PipelineStageBinder::PushConstants(ref mut pc)) = self.vertex_binder.get_mut(&key) { + let dest_start = dest_offset as usize; + let dest_end = dest_start + data_size_dwords; + if dest_end <= pc.data.len() { + pc.data[dest_start..dest_end].copy_from_slice(data_u32); } + result = Some(()); } - // Write to fragment binder if matching slot found - for binder in self.fragment_binder.values_mut() { - if let PipelineStageBinder::PushConstants(ref mut pc) = binder { - if pc.buffer_index == slot { - let dest_start = dest_offset as usize; - let dest_end = dest_start + data_size_dwords; - if dest_end <= pc.data.len() { - pc.data[dest_start..dest_end].copy_from_slice(data_u32); - } - result = Some(()); - break; - } + // Write to fragment binder if matching key found + if let Some(PipelineStageBinder::PushConstants(ref mut pc)) = self.fragment_binder.get_mut(&key) { + let dest_start = dest_offset as usize; + let dest_end = dest_start + data_size_dwords; + if dest_end <= pc.data.len() { + pc.data[dest_start..dest_end].copy_from_slice(data_u32); } + result = Some(()); } result @@ -1974,6 +1964,8 @@ impl super::Device for Device { let byte_len = (info.stride * info.num_elements) as NSUInteger; + // TODO: allocating with metal_device works since StorageModeManaged + // we should migrate to actually sing the heap. let buf = if let Some(data) = data { let bytes = data.as_ptr() as *const std::ffi::c_void; self.metal_device.new_buffer_with_data(bytes, byte_len, opt) @@ -2130,21 +2122,49 @@ impl super::Device for Device { let tex = shader_heap.mtl_heap.new_texture(&desc) .expect("hotline_rs::gfx::mtl failed to allocate texture in heap!"); - // data + // upload texture data with support for mips, cubemaps, and array slices if let Some(data) = data { - tex.replace_region( - metal::MTLRegion { - origin: metal::MTLOrigin { x: 0, y: 0, z: 0 }, - size: metal::MTLSize { - width: info.width, - height: info.height, - depth: info.depth as u64, - }, - }, - 0, - data.as_ptr() as _, - info.width * 4, // TODO size from format - ); + let block_size = super::block_size_for_format(info.format) as u64; + let tpb = super::texels_per_block_for_format(info.format); + let mut data_offset: usize = 0; + + for a in 0..info.array_layers { + let mut mip_w = info.width; + let mut mip_h = info.height; + let mut mip_d = info.depth as u64; + + for mip in 0..info.mip_levels { + let pitch = block_size * (mip_w / tpb).max(1); + let depth_pitch = pitch * (mip_h / tpb).max(1); + + let region = metal::MTLRegion { + origin: metal::MTLOrigin { x: 0, y: 0, z: 0 }, + size: metal::MTLSize { + width: mip_w, + height: mip_h, + depth: mip_d, + }, + }; + + let mip_data_ptr = unsafe { (data.as_ptr() as *const u8).add(data_offset) }; + + tex.replace_region_in_slice( + region, + mip as NSUInteger, + a as NSUInteger, + mip_data_ptr as _, + pitch as NSUInteger, + depth_pitch as NSUInteger, + ); + + data_offset += (depth_pitch * mip_d.max(1)) as usize; + + // halve dimensions for next mip (non-pot safe) + mip_w = (mip_w / 2).max(1); + mip_h = (mip_h / 2).max(1); + mip_d = (mip_d / 2).max(1); + } + } } // allocate on the heap From ae2a051981185c44fbf3032eb7565642eca12479 Mon Sep 17 00:00:00 2001 From: polymonster Date: Sun, 8 Mar 2026 19:18:20 +0000 Subject: [PATCH 37/62] - textures working (cubemaps, arrays) --- src/gfx/mtl.rs | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/src/gfx/mtl.rs b/src/gfx/mtl.rs index 3717b232..83d69a06 100644 --- a/src/gfx/mtl.rs +++ b/src/gfx/mtl.rs @@ -122,6 +122,18 @@ fn to_mtl_write_mask(mask: &super::WriteMask) -> metal::MTLColorWriteMask { mtl_mask } +fn to_mtl_texture_type(tex_type: super::TextureType) -> metal::MTLTextureType { + match tex_type { + super::TextureType::Texture1D => metal::MTLTextureType::D1, + super::TextureType::Texture1DArray => metal::MTLTextureType::D1Array, + super::TextureType::Texture2D => metal::MTLTextureType::D2, + super::TextureType::Texture2DArray => metal::MTLTextureType::D2Array, + super::TextureType::Texture3D => metal::MTLTextureType::D3, + super::TextureType::TextureCube => metal::MTLTextureType::Cube, + super::TextureType::TextureCubeArray => metal::MTLTextureType::CubeArray, + } +} + fn to_mtl_texture_usage(usage: TextureUsage) -> MTLTextureUsage { let mut mtl_usage : MTLTextureUsage = MTLTextureUsage::Unknown; if usage.contains(super::TextureUsage::SHADER_RESOURCE) { @@ -2092,7 +2104,6 @@ impl super::Device for Device { let desc = TextureDescriptor::new(); // TODO: - // tex_type // initial_state // desc @@ -2100,11 +2111,19 @@ impl super::Device for Device { desc.set_width(info.width as NSUInteger); desc.set_height(info.height as NSUInteger); desc.set_depth(info.depth as NSUInteger); - desc.set_array_length(info.array_layers as NSUInteger); desc.set_mipmap_level_count(info.mip_levels as NSUInteger); desc.set_usage(to_mtl_texture_usage(info.usage)); desc.set_storage_mode(metal::MTLStorageMode::Shared); - desc.set_texture_type(metal::MTLTextureType::D2); + desc.set_texture_type(to_mtl_texture_type(info.tex_type)); + + // For cubemaps, arrayLength must be 1 (6 faces are implicit) + // For cube arrays, arrayLength is the number of cubemaps (not faces) + let array_length = match info.tex_type { + super::TextureType::TextureCube => 1, + super::TextureType::TextureCubeArray => info.array_layers / 6, + _ => info.array_layers, + }; + desc.set_array_length(array_length as NSUInteger); // TODO: multi sample // desc.set_sample_count(info.samples as NSUInteger); From fc3d8d5099b7ad6fa3aea23dae626ca0fa488da9 Mon Sep 17 00:00:00 2001 From: polymonster Date: Mon, 9 Mar 2026 19:47:38 +0000 Subject: [PATCH 38/62] - improve handling of constant buffer type name matching spirv cross to assign buffer indices --- crates/htwv/src/macos_impl.rs | 31 ++++++++++++++----- .../src/tangent_space_normal_maps.rs | 19 +++++------- 2 files changed, 32 insertions(+), 18 deletions(-) diff --git a/crates/htwv/src/macos_impl.rs b/crates/htwv/src/macos_impl.rs index 9f9a8841..83003444 100644 --- a/crates/htwv/src/macos_impl.rs +++ b/crates/htwv/src/macos_impl.rs @@ -218,9 +218,9 @@ fn compile_shader_spirv( // put samplers first all in single argument buffer for resource in &resources { - for push_constant in &pipeline.pipeline_layout.static_samplers { + for sampler in &pipeline.pipeline_layout.static_samplers { let name = cstr_to_string(resource.name)?; - if push_constant.name == name.strip_prefix("type.").unwrap_or(&name) { + if sampler.name == name.strip_prefix("type.").unwrap_or(&name) { spvc_compiler_set_decoration( compiler, resource.id, @@ -248,10 +248,17 @@ fn compile_shader_spirv( continue; } let name = cstr_to_string(resource.name)?; - // Match if the resource name contains the push constant name - // Handles various naming conventions: "type.view_push_constants", - // "type.ConstantBuffer.world_buffer_info_data", etc. - if name.contains(&push_constant.name) { + + // stip .type.ConstantBuffer.NAME_data prefix and suffix + // or .type prefix + let name = if let Some(name) = name.strip_prefix("type.ConstantBuffer.") { + name.strip_suffix("_data").unwrap_or(name) + } + else { + name.strip_prefix("type.").unwrap_or(&name) + }; + + if push_constant.name == name { let desc_set = binding_offset as u32; spvc_compiler_set_decoration( compiler, @@ -288,7 +295,17 @@ fn compile_shader_spirv( for (_, binding) in pipeline.pipeline_layout.bindings.iter().enumerate() { if binding.visibility == stage || binding.visibility == ShaderStage::All { let name = cstr_to_string(resource.name)?; - if &binding.name == name.strip_prefix("type.").unwrap_or(&name) { + + // stip .type.ConstantBuffer.NAME_data prefix and suffix + // or .type prefix + let name = if let Some(name) = name.strip_prefix("type.ConstantBuffer.") { + name.strip_suffix("_data").unwrap_or(name) + } + else { + name.strip_prefix("type.").unwrap_or(&name) + }; + + if &binding.name == name { spvc_compiler_set_decoration( compiler, resource.id, diff --git a/plugins/ecs_examples/src/tangent_space_normal_maps.rs b/plugins/ecs_examples/src/tangent_space_normal_maps.rs index a55b7954..40b7e2dd 100644 --- a/plugins/ecs_examples/src/tangent_space_normal_maps.rs +++ b/plugins/ecs_examples/src/tangent_space_normal_maps.rs @@ -1,13 +1,10 @@ -// currently windows only because here we need a concrete gfx and os implementation -#![cfg(target_os = "windows")] - -/// +/// /// Tangent Space Normal Maps -/// +/// -use crate::prelude::*; +use crate::prelude::*; -/// Init function for tangent space normal maps to debug tangents +/// Init function for tangent space normal maps to debug tangents #[no_mangle] pub fn tangent_space_normal_maps(client: &mut Client) -> ScheduleInfo { client.pmfx.load(hotline_rs::get_data_path("shaders/ecs_examples").as_str()).unwrap(); @@ -28,10 +25,10 @@ pub fn setup_tangent_space_normal_maps( mut device: ResMut, mut pmfx: ResMut, mut commands: Commands) -> Result<(), hotline_rs::Error> { - + let textures = [ - TextureComponent(image::load_texture_from_file(&mut device, - &hotline_rs::get_data_path("textures/pbr/antique-grate1/antique-grate1_normal.dds"), + TextureComponent(image::load_texture_from_file(&mut device, + &hotline_rs::get_data_path("textures/pbr/antique-grate1/antique-grate1_normal.dds"), Some(&mut pmfx.shader_heap) ).unwrap()) ]; @@ -55,7 +52,7 @@ pub fn render_meshes_debug_tangent_space( Query<&TextureComponent>, Query<(&WorldMatrix, &MeshComponent)> )) -> Result<(), hotline_rs::Error> { - + let pmfx = &pmfx; let fmt = view.pass.get_format_hash(); let pipeline = pmfx.get_render_pipeline_for_format(&view.view_pipeline, fmt)?; From 2cbce6acd87e840401cfa3c13ed638f45a14f3bf Mon Sep 17 00:00:00 2001 From: polymonster Date: Mon, 9 Mar 2026 21:19:55 +0000 Subject: [PATCH 39/62] - bindless working for multiple sub bindings, spots and points working w/ all the textures in tact --- build.rs | 2 +- crates/htwv/src/macos_impl.rs | 47 ++++++++++++++++++++++++++++++++--- shaders/ecs.hlsl | 16 ++++++------ 3 files changed, 53 insertions(+), 12 deletions(-) diff --git a/build.rs b/build.rs index ac2ef215..0841cd61 100644 --- a/build.rs +++ b/build.rs @@ -45,7 +45,7 @@ fn main() { println!("cargo:warning=Compiling shaders..."); match htwv::compile_dir("shaders", "target/data/shaders") { Ok(_) => println!("cargo:warning=Shader compilation succeeded"), - Err(e) => {} //panic!("Shader compilation failed: {e}"), + Err(e) => {} // panic!("Shader compilation failed: {e}"), } } } \ No newline at end of file diff --git a/crates/htwv/src/macos_impl.rs b/crates/htwv/src/macos_impl.rs index 83003444..d7c3db34 100644 --- a/crates/htwv/src/macos_impl.rs +++ b/crates/htwv/src/macos_impl.rs @@ -69,6 +69,10 @@ enum ShaderStage { struct Resource { name: String, visibility: ShaderStage, + #[serde(default)] + resource_type: Option, + #[serde(default)] + num_descriptors: Option, } #[derive(Serialize, Deserialize, Clone)] @@ -161,11 +165,11 @@ fn compile_shader_spirv( 1, ); - // Set argument buffer tier (0 or 1) + // Set argument buffer tier 2 (required for runtime-sized arrays in device space) spvc_compiler_options_set_uint( compiler_options, spvc_compiler_option_SPVC_COMPILER_OPTION_MSL_ARGUMENT_BUFFERS_TIER, - 1, + 2, ); let result = spvc_compiler_install_compiler_options(compiler, compiler_options); @@ -296,7 +300,7 @@ fn compile_shader_spirv( if binding.visibility == stage || binding.visibility == ShaderStage::All { let name = cstr_to_string(resource.name)?; - // stip .type.ConstantBuffer.NAME_data prefix and suffix + // strip .type.ConstantBuffer.NAME_data prefix and suffix // or .type prefix let name = if let Some(name) = name.strip_prefix("type.ConstantBuffer.") { name.strip_suffix("_data").unwrap_or(name) @@ -306,24 +310,61 @@ fn compile_shader_spirv( }; if &binding.name == name { + // Set descriptor set spvc_compiler_set_decoration( compiler, resource.id, SpvDecoration__SpvDecorationDescriptorSet, binding_offset as u32, ); + + // Set binding index within the descriptor set spvc_compiler_set_decoration( compiler, resource.id, SpvDecoration__SpvDecorationBinding, binding_sub_offset as u32, ); + + // Use resource_binding_2 to explicitly set argument buffer member binding + let mut res_binding: spvc_msl_resource_binding_2 = std::mem::zeroed(); + spvc_msl_resource_binding_init_2(&mut res_binding); + res_binding.stage = exec_model; + res_binding.desc_set = binding_offset as u32; + res_binding.binding = binding_sub_offset as u32; + // For unbounded/runtime arrays (null or large num_descriptors), don't set count + // to let SPIRV-Cross use the unsized array hack + if let Some(num_desc) = binding.num_descriptors { + if num_desc <= 16 { + res_binding.count = num_desc; + } + } + + // Set appropriate MSL binding based on resource type + let is_texture = binding.resource_type.as_ref().map_or(false, |t| { + t.starts_with("Texture") || t.starts_with("RWTexture") + }); + if is_texture { + res_binding.msl_texture = binding_sub_offset as u32; + } else { + res_binding.msl_buffer = binding_sub_offset as u32; + } + spvc_compiler_msl_add_resource_binding_2(compiler, &res_binding); + binding_sub_offset += 1; } } } } + // Enable device address space for the bindings argument buffer + // This allows runtime-sized arrays in the argument buffer + spvc_compiler_msl_set_argument_buffer_device_address_space( + compiler, + binding_offset as u32, + 1, // true - use device address space + ); + let mut msl_src = std::ptr::null(); let result = spvc_compiler_compile(compiler, &mut msl_src); if result == spvc_result_SPVC_ERROR_UNSUPPORTED_SPIRV { diff --git a/shaders/ecs.hlsl b/shaders/ecs.hlsl index 9742ec2f..a5165007 100644 --- a/shaders/ecs.hlsl +++ b/shaders/ecs.hlsl @@ -133,17 +133,17 @@ struct extent_data { StructuredBuffer draws[1024] : register(t0, space0); StructuredBuffer extents[1024] : register(t0, space1); StructuredBuffer materials[1024] : register(t0, space2); -StructuredBuffer point_lights[64] : register(t0, space3); -StructuredBuffer spot_lights[64] : register(t0, space4); -StructuredBuffer directional_lights[64] : register(t0, space5); +StructuredBuffer point_lights[] : register(t0, space3); +StructuredBuffer spot_lights[] : register(t0, space4); +StructuredBuffer directional_lights[] : register(t0, space5); StructuredBuffer shadow_matrices[1024] : register(t0, space6); // textures -Texture2D textures[1024] : register(t0, space7); -Texture2DMS msaa8x_textures[1024] : register(t0, space8); -TextureCube cubemaps[1024] : register(t0, space9); -Texture2DArray texture_arrays[1024] : register(t0, space10); -Texture3D volume_textures[1024] : register(t0, space11); +Texture2D textures[] : register(t0, space7); +Texture2DMS msaa8x_textures[] : register(t0, space8); +TextureCube cubemaps[] : register(t0, space9); +Texture2DArray texture_arrays[] : register(t0, space10); +Texture3D volume_textures[] : register(t0, space11); // tlas RaytracingAccelerationStructure scene_tlas[1024] : register(t0, space12); From 142c78708e0860d013c9197c0c495c4ab279664f Mon Sep 17 00:00:00 2001 From: polymonster Date: Sun, 17 May 2026 16:13:47 +0200 Subject: [PATCH 40/62] - sync fixes... still issues@ --- .claude/settings.local.json | 8 +- Cargo.toml | 2 +- build.rs | 2 +- crates/htwv/src/macos_impl.rs | 17 ++- readme.md | 38 ++--- shaders/ecs.hlsl | 2 +- src/gfx/mtl.rs | 47 +++++- src/os/macos.rs | 275 +++++++++++++++++----------------- src/pmfx.rs | 14 +- 9 files changed, 229 insertions(+), 176 deletions(-) diff --git a/.claude/settings.local.json b/.claude/settings.local.json index bbe8b7b2..fc079cc0 100644 --- a/.claude/settings.local.json +++ b/.claude/settings.local.json @@ -9,7 +9,13 @@ "Bash(cargo check:*)", "Bash(cargo tree:*)", "Bash(xargs:*)", - "Bash(cargo doc:*)" + "Bash(cargo doc:*)", + "Bash(curl -s \"https://crates.io/api/v1/crates/winit\")", + "Bash(cargo add *)", + "Bash(sed -i '' 's/winit = \"0.29.1\"/winit = \"0.30\"/' Cargo.toml)", + "Bash(cargo fetch *)", + "Bash(ls ~/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/ | grep winit)", + "Read(//Users/alex.dixon/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/**)" ] } } diff --git a/Cargo.toml b/Cargo.toml index 69f9b06f..b7967b74 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -54,7 +54,7 @@ features = ["docking"] [target.'cfg(target_os = "macos")'.dependencies] metal = "0.28.0" -winit = "0.29.1" +winit = "0.30" objc = "0.2.4" cocoa = "0.25.0" core-graphics-types = "0.1.3" diff --git a/build.rs b/build.rs index 0841cd61..ba3d27bc 100644 --- a/build.rs +++ b/build.rs @@ -45,7 +45,7 @@ fn main() { println!("cargo:warning=Compiling shaders..."); match htwv::compile_dir("shaders", "target/data/shaders") { Ok(_) => println!("cargo:warning=Shader compilation succeeded"), - Err(e) => {} // panic!("Shader compilation failed: {e}"), + Err(e) => println!("cargo:warning=Shader compilation errors:\n{e}"), } } } \ No newline at end of file diff --git a/crates/htwv/src/macos_impl.rs b/crates/htwv/src/macos_impl.rs index d7c3db34..edf880c4 100644 --- a/crates/htwv/src/macos_impl.rs +++ b/crates/htwv/src/macos_impl.rs @@ -423,7 +423,7 @@ fn compile_shader_spirv( // let _ = fs::remove_file(&temp_metal_file); let _ = fs::remove_file(&air_file); - println!("Compiled Metal shader: {}", output_file); + println!("cargo:warning= compiled: {}", output_file); Ok(()) } } @@ -493,13 +493,22 @@ pub fn compile_dir(input_dir: &str, output_dir: &str) -> Result<(), Box + Checkout a live [demo](https://www.youtube.com/watch?v=8a_qcqmpZlg)!. @@ -34,17 +34,17 @@ Windows with Direct3D12 is the first fully supported platform, macOS with metal For the time being it is recommended to use the repository from GitHub if you want to use the example `plugins` or standalone `examples`. If you just want to use the library then `crates.io` is suitable. There are some difficulties with publishing data and plugins which I hope to iron out in time. -### Building / Fetching Data +### Building / Fetching Data The [hotline-data](https://github.com/polymonster/hotline-data) repository is required to build and serve data for the examples and the example plugins, it is included as a submodule of this repository, you can clone with submodules as so: -``` +```text git clone https://github.com/polymonster/hotline.git --recursive ``` You can add the submodule after cloning or update the submodule to keep it in-sync with the main repository as follows: -``` +```text git submodule update --init --recursive ``` @@ -70,7 +70,7 @@ Any code changes made to the plugin libs will cause a rebuild and reload to happ ### Building from Visual Studio Code -There are included `tasks` and `launch` files for vscode including configurations for the client and the examples. Launching the `client` from vscode in debug or release will build the core hotline `lib`, `client`, `data` and `plugins`. +There are included `tasks` and `launch` files for vscode including configurations for the client and the examples. Launching the `client` from vscode in debug or release will build the core hotline `lib`, `client`, `data` and `plugins`. ## Adding Plugins @@ -100,7 +100,7 @@ impl Plugin for EmptyPlugin { } } - fn setup(&mut self, client: Client) + fn setup(&mut self, client: Client) -> Client { println!("plugin setup"); client @@ -159,7 +159,7 @@ You can then provide an initialisation function named after the demo this return pub fn primitives(client: &mut Client) -> ScheduleInfo { // load resources we may need client.pmfx.load(&hotline_rs::get_data_path("shaders/debug").as_str()).unwrap(); - + // fill out info ScheduleInfo { setup: systems![ @@ -209,10 +209,10 @@ You can also supply your own `update` systems to animate and move your entities. ```rust #[export_update_fn] fn update_cameras( - app: Res, - main_window: Res, + app: Res, + main_window: Res, mut query: Query<(&mut Position, &mut Rotation, &mut ViewProjectionMatrix), With> -) -> Result<(), { +) -> Result<(), { let app = &app.0; for (mut position, mut rotation, mut view_proj) in &mut query { // .. @@ -231,7 +231,7 @@ pub fn render_meshes( view: &pmfx::View, cmd_buf: &mut ::CmdBuf, mesh_draw_query: Query<(&WorldMatrix, &MeshComponent)>) -> Result<(), hotline_rs::Error> { - + let fmt = view.pass.get_format_hash(); let mesh_debug = pmfx.get_render_pipeline_for_format(&view.view_pipeline, fmt)?; let camera = pmfx.get_camera_constants(&view.camera)?; @@ -282,7 +282,7 @@ pub fn dispatch_compute( } cmd_buf.set_heap(pipeline, &pmfx.shader_heap); - + cmd_buf.dispatch( pass.group_count, pass.numthreads @@ -360,7 +360,7 @@ A quick example of a basic application setup: // include prelude for convenience use hotline_rs::prelude::*; -pub fn main() -> Result<(), hotline_rs::Error> { +pub fn main() -> Result<(), hotline_rs::Error> { // Create an Application let mut app = os_platform::App::create(os::AppInfo { name: String::from("triangle"), @@ -391,7 +391,7 @@ pub fn main() -> Result<(), hotline_rs::Error> { ..Default::default() }; let mut swap_chain = device.create_swap_chain::(&swap_chain_info, &window)?; - + /// Create a command buffer let mut cmd = device.create_cmd_buf(num_buffers); @@ -670,11 +670,11 @@ while app.run() { if player.is_ended() { // .. handle case where video is ended } - + // get texture if let Some(video_tex) = &player.get_texture() { let size = player.get_size(); - + // .. render } } @@ -844,7 +844,7 @@ This example provides instanced draws by updating entity world matrices on the C -Bindless texturing example - uses push constants to push a per draw call texture id for each entity. The texture id (shader resource view index) is used to lookup the texture inside an unbounded descriptor array in the fragment shader. +Bindless texturing example - uses push constants to push a per draw call texture id for each entity. The texture id (shader resource view index) is used to lookup the texture inside an unbounded descriptor array in the fragment shader. ### Tangent Space Normal Maps @@ -968,7 +968,7 @@ Inline raytracing shadows with mixed raster and raytracing workload. Raster pipe ## Tests -There are standalone tests and client/plugin tests to test graphics API features. This requires a test runner which has a GPU and is not headless, so I am using my home machine as a self-hosted actions runner. You can run the tests yourself but because of the requirement of a GPU device and plugin loading the tests need to be ran single threaded. +There are standalone tests and client/plugin tests to test graphics API features. This requires a test runner which has a GPU and is not headless, so I am using my home machine as a self-hosted actions runner. You can run the tests yourself but because of the requirement of a GPU device and plugin loading the tests need to be ran single threaded. ```text cargo test -- --test-threads=1 @@ -982,4 +982,4 @@ pmbuild test ## Contributing -Contributions of all kinds are welcome, you can make a fork and send a PR if you want to submit small fixes or improvements. Anyone interested in being more involved in development I am happy to take on people to help with the project of all experience levels, especially people with more experience in Rust. You can contact me if interested via [Twitter](twitter.com/polymonster) or [Discord](https://discord.com/invite/3yjXwJ8wJC). +Contributions of all kinds are welcome, you can make a fork and send a PR if you want to submit small fixes or improvements. Anyone interested in being more involved in development I am happy to take on people to help with the project of all experience levels, especially people with more experience in Rust. You can contact me if interested via [Twitter](twitter.com/polymonster) or [Discord](https://discord.com/invite/3yjXwJ8wJC). diff --git a/shaders/ecs.hlsl b/shaders/ecs.hlsl index a5165007..2472dc98 100644 --- a/shaders/ecs.hlsl +++ b/shaders/ecs.hlsl @@ -136,7 +136,7 @@ StructuredBuffer materials[1024] : register(t0, space2); StructuredBuffer point_lights[] : register(t0, space3); StructuredBuffer spot_lights[] : register(t0, space4); StructuredBuffer directional_lights[] : register(t0, space5); -StructuredBuffer shadow_matrices[1024] : register(t0, space6); +StructuredBuffer shadow_matrices[] : register(t0, space6); // textures Texture2D textures[] : register(t0, space7); diff --git a/src/gfx/mtl.rs b/src/gfx/mtl.rs index 83d69a06..85620965 100644 --- a/src/gfx/mtl.rs +++ b/src/gfx/mtl.rs @@ -24,6 +24,8 @@ use std::collections::HashMap; use std::result; use cocoa::{appkit::NSView, base::id as cocoa_id}; +#[allow(unused_imports)] +use objc::{msg_send, sel, sel_impl}; use core_graphics_types::geometry::CGSize; use std::path::Path; @@ -293,6 +295,13 @@ pub struct SwapChain { backbuffer_texture: Texture, backbuffer_pass: RenderPass, backbuffer_pass_no_clear: RenderPass, + num_buffers: u32, + // GPU-side fence: present CB signals, each new CB waits — serialises GPU frames without blocking CPU + frame_event: metal::Event, + frame_value: u64, + // CPU-side ring: blocks the CPU only when num_buffers frames are already in flight, + // preventing shared-memory DynamicBuffer slots from being overwritten before the GPU is done + in_flight: std::sync::Arc>>, } impl super::SwapChain for SwapChain { @@ -300,10 +309,17 @@ impl super::SwapChain for SwapChain { } fn wait_for_last_frame(&self) { + let mut in_flight = self.in_flight.lock().unwrap(); + if in_flight.len() >= self.num_buffers as usize { + if let Some(oldest) = in_flight.pop_front() { + drop(in_flight); + oldest.wait_until_completed(); + } + } } fn get_num_buffers(&self) -> u32 { - 3 + self.num_buffers } fn get_frame_fence_value(&self) -> u64 { @@ -361,9 +377,13 @@ impl super::SwapChain for SwapChain { fn swap(&mut self, device: &mut Device) { objc::rc::autoreleasepool(|| { - let cmd = device.command_queue.new_command_buffer(); + self.frame_value += 1; + let in_flight_count = self.in_flight.lock().unwrap().len(); + let cmd = device.command_queue.new_command_buffer().to_owned(); cmd.present_drawable(&self.drawable); + cmd.encode_signal_event(&self.frame_event, self.frame_value); cmd.commit(); + self.in_flight.lock().unwrap().push_back(cmd); }); } } @@ -510,8 +530,12 @@ impl CmdBuf { impl super::CmdBuf for CmdBuf { fn reset(&mut self, swap_chain: &SwapChain) { objc::rc::autoreleasepool(|| { - self.cmd = Some(self.cmd_queue.new_command_buffer().to_owned()); - // Clear transient buffers from previous frame + let cmd = self.cmd_queue.new_command_buffer().to_owned(); + // GPU waits for the previous frame's present signal before executing any work + if swap_chain.frame_value > 0 { + cmd.encode_wait_for_event(&swap_chain.frame_event, swap_chain.frame_value); + } + self.cmd = Some(cmd); self.transient_buffers.clear(); }); } @@ -1269,6 +1293,9 @@ impl Device { let heap_descriptor = metal::HeapDescriptor::new(); heap_descriptor.set_storage_mode(metal::MTLStorageMode::Shared); heap_descriptor.set_size(heap_size); + // Enable hazard tracking so Metal automatically synchronizes heap-allocated + // textures across command buffers (by default heaps are MTLHazardTrackingModeUntracked) + unsafe { let _: () = msg_send![&*heap_descriptor, setHazardTrackingMode: metal::MTLHazardTrackingMode::Tracked]; }; let heap = mtl_device.new_heap(&heap_descriptor); @@ -1655,6 +1682,10 @@ impl super::Device for Device { backbuffer_texture: backbuffer_texture, backbuffer_pass: render_pass, backbuffer_pass_no_clear: render_pass_no_clear, + num_buffers: info.num_buffers, + frame_event: self.metal_device.new_event(), + frame_value: 0, + in_flight: std::sync::Arc::new(std::sync::Mutex::new(std::collections::VecDeque::new())), }) }) } @@ -1971,13 +2002,15 @@ impl super::Device for Device { heap: &mut Heap ) -> result::Result { objc::rc::autoreleasepool(|| { + // StorageModeShared: CPU and GPU share the same physical memory — no didModifyRange + // needed and no stale-copy hazard. StorageModeManaged has a separate GPU copy that + // requires an explicit sync notification after every CPU write; without it the GPU + // reads stale data, which is the source of the world-buffer tearing. let opt = metal::MTLResourceOptions::CPUCacheModeDefaultCache | - metal::MTLResourceOptions::StorageModeManaged; + metal::MTLResourceOptions::StorageModeShared; let byte_len = (info.stride * info.num_elements) as NSUInteger; - // TODO: allocating with metal_device works since StorageModeManaged - // we should migrate to actually sing the heap. let buf = if let Some(data) = data { let bytes = data.as_ptr() as *const std::ffi::c_void; self.metal_device.new_buffer_with_data(bytes, byte_len, opt) diff --git a/src/os/macos.rs b/src/os/macos.rs index 2fa48640..50657176 100644 --- a/src/os/macos.rs +++ b/src/os/macos.rs @@ -10,11 +10,10 @@ use std::sync::RwLock; use winit::{ dpi::{LogicalPosition, LogicalSize}, - event::{Event, WindowEvent, ElementState}, - event_loop::{self, ControlFlow}, + event::{WindowEvent, ElementState}, + event_loop::ActiveEventLoop, keyboard::{Key, PhysicalKey, KeyCode}, - platform::pump_events::{EventLoopExtPumpEvents, PumpStatus}, - raw_window_handle::{HasWindowHandle, RawWindowHandle} + raw_window_handle::{HasWindowHandle, RawWindowHandle}, }; use cocoa::base::id as cocoa_id; @@ -80,6 +79,8 @@ pub struct App { event_loop: Arc>>, input_state: Arc>, windows: Arc>>>, + monitors: Arc>>, + window_sizes: Arc>>>>>, } unsafe impl Send for App {} @@ -91,6 +92,7 @@ pub struct Window { window_id: winit::window::WindowId, input_state: Arc>, events: Arc>, + cached_size: Arc>>, } unsafe impl Send for Window {} @@ -186,6 +188,110 @@ impl App { } } +struct FrameHandler<'a> { + resume: &'a mut bool, + input_state: Arc>, + monitors: Arc>>, + window_sizes: Arc>>>>>, +} + +impl winit::application::ApplicationHandler for FrameHandler<'_> { + fn resumed(&mut self, elwt: &ActiveEventLoop) { + let primary = elwt.primary_monitor(); + *self.monitors.write().unwrap() = elwt.available_monitors().map(|m| { + let winit::dpi::PhysicalSize { width, height } = m.size(); + let winit::dpi::PhysicalPosition { x, y } = m.position(); + super::MonitorInfo { + rect: Rect { x, y, width: width as i32, height: height as i32 }, + client_rect: Rect { x, y, width: width as i32, height: height as i32 }, + dpi_scale: m.scale_factor() as f32, + primary: primary.as_ref() == Some(&m), + } + }).collect(); + } + + fn window_event(&mut self, _elwt: &ActiveEventLoop, window_id: winit::window::WindowId, event: WindowEvent) { + if let WindowEvent::Resized(new_size) = event { + if let Some(size) = self.window_sizes.read().unwrap().get(&window_id) { + *size.write().unwrap() = new_size; + } + return; + } + + let mut state = self.input_state.write().unwrap(); + match event { + WindowEvent::CloseRequested => { + *self.resume = false; + } + WindowEvent::RedrawRequested => {} + WindowEvent::CursorMoved { position, .. } => { + state.mouse_client_pos = super::Point { + x: position.x as i32, + y: position.y as i32, + }; + state.hovered_window_id = Some(window_id); + } + WindowEvent::CursorEntered { .. } => { + state.hovered_window_id = Some(window_id); + } + WindowEvent::CursorLeft { .. } => { + if state.hovered_window_id == Some(window_id) { + state.hovered_window_id = None; + } + } + WindowEvent::MouseInput { state: element_state, button, .. } => { + let pressed = element_state == ElementState::Pressed; + let index = match button { + winit::event::MouseButton::Left => Some(super::MouseButton::Left as usize), + winit::event::MouseButton::Middle => Some(super::MouseButton::Middle as usize), + winit::event::MouseButton::Right => Some(super::MouseButton::Right as usize), + winit::event::MouseButton::Back => Some(super::MouseButton::X1 as usize), + winit::event::MouseButton::Forward => Some(super::MouseButton::X2 as usize), + winit::event::MouseButton::Other(_) => None, + }; + if let Some(idx) = index { + state.mouse_down[idx] = pressed; + } + } + WindowEvent::MouseWheel { delta, .. } => { + match delta { + winit::event::MouseScrollDelta::LineDelta(h, v) => { + state.mouse_wheel += v; + state.mouse_hwheel += h; + } + winit::event::MouseScrollDelta::PixelDelta(pos) => { + state.mouse_wheel += (pos.y / 20.0) as f32; + state.mouse_hwheel += (pos.x / 20.0) as f32; + } + } + } + WindowEvent::KeyboardInput { event, .. } => { + let pressed = event.state == ElementState::Pressed; + if let PhysicalKey::Code(key_code) = event.physical_key { + let code = key_code as usize; + if code < 256 { + state.key_down[code] = pressed; + } + } + if pressed { + if let Key::Character(ref c) = event.logical_key { + for ch in c.encode_utf16() { + state.utf16_inputs.push(ch); + } + } + } + } + WindowEvent::ModifiersChanged(modifiers) => { + let mods = modifiers.state(); + state.sys_key_down[super::SysKey::Ctrl as usize] = mods.control_key(); + state.sys_key_down[super::SysKey::Shift as usize] = mods.shift_key(); + state.sys_key_down[super::SysKey::Alt as usize] = mods.alt_key(); + } + _ => {} + } + } +} + impl super::App for App { type Window = Window; type NativeHandle = NativeHandle; @@ -196,16 +302,21 @@ impl super::App for App { event_loop: Arc::new(RwLock::new(winit::event_loop::EventLoop::new().unwrap())), input_state: Arc::new(RwLock::new(InputState::new())), windows: Arc::new(RwLock::new(HashMap::new())), + monitors: Arc::new(RwLock::new(Vec::new())), + window_sizes: Arc::new(RwLock::new(HashMap::new())), } } /// Create a new operating system window fn create_window(&mut self, info: super::WindowInfo) -> Self::Window { - let window = winit::window::WindowBuilder::new() - .with_inner_size(winit::dpi::LogicalSize::new(info.rect.width, info.rect.height)) - .with_position(winit::dpi::LogicalPosition::new(info.rect.x, info.rect.y)) - .with_title(info.title) - .build(&*self.event_loop.read().unwrap()) + #[allow(deprecated)] + let window = self.event_loop.read().unwrap() + .create_window( + winit::window::Window::default_attributes() + .with_inner_size(winit::dpi::LogicalSize::new(info.rect.width, info.rect.height)) + .with_position(winit::dpi::LogicalPosition::new(info.rect.x, info.rect.y)) + .with_title(info.title) + ) .unwrap(); let window_id = window.id(); let winit_window = Arc::new(window); @@ -213,11 +324,16 @@ impl super::App for App { // Register window for position lookups self.windows.write().unwrap().insert(window_id, winit_window.clone()); + let initial_size = winit_window.inner_size(); + let cached_size = Arc::new(RwLock::new(initial_size)); + self.window_sizes.write().unwrap().insert(window_id, cached_size.clone()); + Window { winit_window, window_id, input_state: self.input_state.clone(), events: Arc::new(RwLock::new(super::WindowEventFlags::NONE)), + cached_size, } } @@ -229,113 +345,19 @@ impl super::App for App { /// Call to update windows and os state each frame, when false is returned the app has been requested to close fn run(&mut self) -> bool { objc::rc::autoreleasepool(|| { - // Update input state at frame start self.update_input_state(); let mut resume = true; - let input_state = self.input_state.clone(); + let mut handler = FrameHandler { + resume: &mut resume, + input_state: self.input_state.clone(), + monitors: self.monitors.clone(), + window_sizes: self.window_sizes.clone(), + }; let _ = self.event_loop.write().and_then(|mut event_loop| { - let _status = event_loop.pump_events(Some(Duration::ZERO), |event, _elwt| { - match event { - Event::WindowEvent { event, window_id } => { - let mut state = input_state.write().unwrap(); - - match event { - WindowEvent::CloseRequested => { - resume = false; - } - WindowEvent::RedrawRequested => {} - - // Mouse cursor position (window-relative from winit) - WindowEvent::CursorMoved { position, .. } => { - // winit gives us logical coordinates relative to window content area - state.mouse_client_pos = super::Point { - x: position.x as i32, - y: position.y as i32, - }; - state.hovered_window_id = Some(window_id); - } - - // Mouse enter/leave for hover tracking - WindowEvent::CursorEntered { .. } => { - state.hovered_window_id = Some(window_id); - } - WindowEvent::CursorLeft { .. } => { - if state.hovered_window_id == Some(window_id) { - state.hovered_window_id = None; - } - } - - // Mouse buttons - WindowEvent::MouseInput { state: element_state, button, .. } => { - let pressed = element_state == ElementState::Pressed; - // Map to MouseButton enum order: Left=0, Middle=1, Right=2, X1=3, X2=4 - let index = match button { - winit::event::MouseButton::Left => Some(super::MouseButton::Left as usize), - winit::event::MouseButton::Middle => Some(super::MouseButton::Middle as usize), - winit::event::MouseButton::Right => Some(super::MouseButton::Right as usize), - winit::event::MouseButton::Back => Some(super::MouseButton::X1 as usize), - winit::event::MouseButton::Forward => Some(super::MouseButton::X2 as usize), - winit::event::MouseButton::Other(_) => None, - }; - if let Some(idx) = index { - state.mouse_down[idx] = pressed; - } - } - - // Mouse wheel - WindowEvent::MouseWheel { delta, .. } => { - match delta { - winit::event::MouseScrollDelta::LineDelta(h, v) => { - state.mouse_wheel += v; - state.mouse_hwheel += h; - } - winit::event::MouseScrollDelta::PixelDelta(pos) => { - // Convert pixel delta to line delta (approximate) - state.mouse_wheel += (pos.y / 20.0) as f32; - state.mouse_hwheel += (pos.x / 20.0) as f32; - } - } - } - - // Keyboard input - WindowEvent::KeyboardInput { event, .. } => { - let pressed = event.state == ElementState::Pressed; - - // Get physical key code for key_down array - if let PhysicalKey::Code(key_code) = event.physical_key { - let code = key_code as usize; - if code < 256 { - state.key_down[code] = pressed; - } - } - - // Handle text input from logical key - if pressed { - if let Key::Character(ref c) = event.logical_key { - for ch in c.encode_utf16() { - state.utf16_inputs.push(ch); - } - } - } - } - - // Modifier keys - WindowEvent::ModifiersChanged(modifiers) => { - let mods = modifiers.state(); - state.sys_key_down[super::SysKey::Ctrl as usize] = mods.control_key(); - state.sys_key_down[super::SysKey::Shift as usize] = mods.shift_key(); - state.sys_key_down[super::SysKey::Alt as usize] = mods.alt_key(); - } - - _ => {} - } - } - _ => {} - } - }); - + use winit::platform::pump_events::EventLoopExtPumpEvents; + event_loop.pump_app_events(Some(Duration::ZERO), &mut handler); Ok(()) }); resume @@ -438,26 +460,7 @@ impl super::App for App { } fn enumerate_display_monitors(&self) -> Vec { - let event_loop = &*self.event_loop.read().unwrap(); - let primary_monitor = event_loop.primary_monitor(); - event_loop.available_monitors().map(|monitor| { - let winit::dpi::PhysicalSize { width, height } = monitor.size(); - let winit::dpi::PhysicalPosition { x, y } = monitor.position(); - super::MonitorInfo { - rect: Rect { - x, y, - width: width as i32, - height: height as i32 - }, - client_rect: Rect { - x, y, - width: width as i32, - height: height as i32 - }, - dpi_scale: monitor.scale_factor() as f32, - primary: primary_monitor.as_ref() == Some(&monitor) - } - }).collect() + self.monitors.read().unwrap().clone() } /// Sets the mouse cursor @@ -564,7 +567,7 @@ impl super::Window for Window { /// Returns the screen position for the top-left corner of the window fn get_pos(&self) -> super::Point { - let pos = self.winit_window.outer_position().unwrap(); + let pos = self.winit_window.outer_position().unwrap_or_default(); super::Point { x: pos.x, y: pos.y @@ -573,7 +576,7 @@ impl super::Window for Window { /// Returns a gfx friendly full window rect to use as `gfx::Viewport` or `gfx::Scissor` fn get_viewport_rect(&self) -> super::Rect { - let size = self.winit_window.inner_size(); + let size = *self.cached_size.read().unwrap(); super::Rect { x: 0, y: 0, @@ -584,7 +587,7 @@ impl super::Window for Window { /// Returns the screen position for the top-left corner of the window fn get_size(&self) -> super::Size { - let size = self.winit_window.inner_size(); + let size = *self.cached_size.read().unwrap(); super::Size { x: size.width as i32, y: size.height as i32 @@ -593,8 +596,8 @@ impl super::Window for Window { /// Returns the screen rect of the window screen pos x, y , size x, y. fn get_window_rect(&self) -> super::Rect { - let pos = self.winit_window.outer_position().unwrap(); - let size = self.winit_window.inner_size(); + let pos = self.winit_window.outer_position().unwrap_or_default(); + let size = *self.cached_size.read().unwrap(); super::Rect { x: pos.x, y: pos.y, diff --git a/src/pmfx.rs b/src/pmfx.rs index ef4302c4..e40c84e0 100644 --- a/src/pmfx.rs +++ b/src/pmfx.rs @@ -2668,9 +2668,10 @@ impl Pmfx where D: gfx::Device { cmd_buf.reset(swap_chain); // inserts markers for timing and tracking pipeline stats - let mut stats = self.pass_stats.remove(name).unwrap(); - Self::stats_start(cmd_buf, &mut stats); - self.pass_stats.insert(name.to_string(), stats); + if let Some(mut stats) = self.pass_stats.remove(name) { + Self::stats_start(cmd_buf, &mut stats); + self.pass_stats.insert(name.to_string(), stats); + } } } } @@ -2728,9 +2729,10 @@ impl Pmfx where D: gfx::Device { } else if let Some(cmd_buf) = cmd_bufs.get_mut(node) { // inserts markers for timing and tracking pipeline stats - let mut stats = self.pass_stats.remove(node).unwrap(); - Self::stats_end(cmd_buf, &mut stats); - self.pass_stats.insert(node.to_string(), stats); + if let Some(mut stats) = self.pass_stats.remove(node) { + Self::stats_end(cmd_buf, &mut stats); + self.pass_stats.insert(node.to_string(), stats); + } cmd_buf.close().unwrap(); device.execute(cmd_buf); From 3bfe2dc08cb84fbdc114574e9437fe36e212e2bf Mon Sep 17 00:00:00 2001 From: polymonster Date: Mon, 18 May 2026 11:42:24 +0200 Subject: [PATCH 41/62] - fix flickering / sync issues, mtl id offset, required| | --- LIGHTS_BUG.md | 91 +++++++++++++++++++ crates/htwv/src/macos_impl.rs | 19 +++- .../ecs_examples/src/bindless_material_ibl.rs | 2 +- .../ecs_examples/src/gpu_frustum_culling.rs | 4 +- plugins/ecs_examples/src/lib.rs | 2 +- .../ecs_examples/src/raytracing_pipeline.rs | 2 +- src/gfx.rs | 10 +- src/gfx/d3d12.rs | 6 +- src/gfx/mtl.rs | 14 ++- src/pmfx.rs | 64 ++++++++----- 10 files changed, 178 insertions(+), 36 deletions(-) create mode 100644 LIGHTS_BUG.md diff --git a/LIGHTS_BUG.md b/LIGHTS_BUG.md new file mode 100644 index 00000000..fc379215 --- /dev/null +++ b/LIGHTS_BUG.md @@ -0,0 +1,91 @@ +# Metal Light Buffer Strobing — Root Cause + +## What we confirmed + +- CPU always sends correct count (eprintln verified, sentinel shader confirmed solid cyan) +- GPU receives the push constants correctly — `world_buffer_info` arrives intact +- Orange/black flicker = GPU reads zero data from some ring-buffer slots + +## Root cause + +The MSL generated by spirv-cross for `ps_mesh_lit` has: + +```metal +struct spvDescriptorSetBuffer3 // bound at [[buffer(3)]] +{ + spvDescriptor<...> point_lights [[id(0)]][1]; // starts at slot 0 + spvDescriptor<...> spot_lights [[id(1)]][1]; // starts at slot 1 +}; +``` + +`spvDescriptorArray::operator[]` is: +```metal +const device T& operator [] (size_t i) const { return ptr[i]; } +// ptr points to the start of spot_lights array, which is [[id(1)]] +``` + +So `spot_lights[spot_lights_id]` reads argument-buffer slot **`1 + spot_lights_id`**. + +But in Rust, `encode_buffer(heap_index, buf)` puts the buffer at slot `heap_index`. + +**Mismatch:** For heap index 7, the buffer is at slot 7. The shader reads slot `1+7 = 8` — which is the *next* ring-buffer slot's buffer, or an empty slot. + +With 3 ring-buffer slots at heap indices 7, 8, 9: + +| Frame | bb | heap_idx | shader reads slot | what's there | +|-------|----|----------|-------------------|--------------| +| 0 | 0 | 7 | 1+7 = 8 | previous frame's bb=1 data (orange, stale) | +| 1 | 1 | 8 | 1+8 = 9 | previous frame's bb=2 data (orange, stale) | +| 2 | 2 | 9 | 1+9 = 10 | EMPTY (never written) → black | + +This explains the 2-orange/1-black cycle that looks like "flickering orange and black". + +## Why it only affects spot/directional lights, not point lights + +`point_lights [[id(0)]]` — starts at slot 0. +`point_lights[point_lights_id]` → reads slot `0 + point_lights_id = point_lights_id`. +`encode_buffer(heap_index, buf)` → buf at slot `heap_index`. +These match → point lights work. + +## Where the id offsets come from + +`htwv/src/macos_impl.rs` assigns `binding_sub_offset` sequentially for each named binding in the pipeline layout. In `ecs_examples.json`, `mesh_lit` pipeline has: +``` +[0] point_lights → binding_sub_offset=0 → id(0) +[1] spot_lights → binding_sub_offset=1 → id(1) +``` + +`directional_lights` is **not** in the pipeline layout bindings, so it retains its original SPIRV descriptor set from DXC and lands in a separate argument buffer. Its id offset is likely 0 within its own buffer — but this needs to be verified by compiling a shader that includes the directional lights loop before the return. + +## The fix + +For each bindless structured-buffer type, the shader-side index sent in `world_buffer_info` must be `heap_index - id_offset`, where `id_offset` is the `[[id(N)]]` value that spirv-cross assigns to that type's array in its descriptor set buffer. + +**Option A — Adjust index in `get_world_buffer_info()`** (minimal change): +```rust +WorldBufferInfo { + point_light: self.point_light.get_lookup(), // offset 0, no change + spot_light: self.spot_light.get_lookup_with_id_offset(1), // subtract 1 + directional_light: self.directional_light.get_lookup(), // verify offset first + .. +} +``` + +Add `get_lookup_with_id_offset(offset: u32)` to `DynamicBuffer`: +```rust +pub fn get_lookup_with_id_offset(&self, id_offset: u32) -> GpuBufferLookup { + GpuBufferLookup { + index: self.get_index() as u32 - id_offset, + count: self.len as u32, + } +} +``` + +**Option B — Longer-term fix**: track `id_offset` as a field on `DynamicBuffer`, set at allocation time from the pipeline layout, so `get_lookup()` always returns the correct index automatically. + +## Next steps + +1. Verify directional_lights id offset: restore the directional lights loop in `ps_mesh_lit` and recompile, then look at the generated `.psc.metal` for `directional_lights [[id(?)]]`. +2. Apply the fix (Option A is quick, Option B is cleaner). +3. Remove all debug code from `batch_lights`, `render_meshes_bindless`, the shader, and `spot_lights.rs`. +4. Re-enable animation for both spot and directional lights. diff --git a/crates/htwv/src/macos_impl.rs b/crates/htwv/src/macos_impl.rs index edf880c4..1ae4b6bc 100644 --- a/crates/htwv/src/macos_impl.rs +++ b/crates/htwv/src/macos_impl.rs @@ -435,21 +435,32 @@ pub fn compile_piepline( ) -> Result<(), Box> { let file_data = std::fs::read(filepath).unwrap(); let file: Pmfx = serde_json::from_slice(&file_data)?; + let mut errors = Vec::new(); for (_, permutation) in file.pipelines { for (_, pipeline) in &permutation { if let Some(vs) = &pipeline.vs { - compile_shader_spirv(&vs, input_dir, output_dir, &pipeline, ShaderStage::Vertex)?; + if let Err(e) = compile_shader_spirv(vs, input_dir, output_dir, &pipeline, ShaderStage::Vertex) { + errors.push(format!("{vs}: {e}")); + } } if let Some(ps) = &pipeline.ps { - compile_shader_spirv(&ps, input_dir, output_dir, &pipeline, ShaderStage::Fragment)?; + if let Err(e) = compile_shader_spirv(ps, input_dir, output_dir, &pipeline, ShaderStage::Fragment) { + errors.push(format!("{ps}: {e}")); + } } if let Some(cs) = &pipeline.cs { - compile_shader_spirv(&cs, input_dir, output_dir, &pipeline, ShaderStage::Compute)?; + if let Err(e) = compile_shader_spirv(cs, input_dir, output_dir, &pipeline, ShaderStage::Compute) { + errors.push(format!("{cs}: {e}")); + } } } } - Ok(()) + if errors.is_empty() { + Ok(()) + } else { + Err(errors.join("\n").into()) + } } pub fn compile_dir(input_dir: &str, output_dir: &str) -> Result<(), Box> { diff --git a/plugins/ecs_examples/src/bindless_material_ibl.rs b/plugins/ecs_examples/src/bindless_material_ibl.rs index 6f4d45d7..7f9ef7f7 100644 --- a/plugins/ecs_examples/src/bindless_material_ibl.rs +++ b/plugins/ecs_examples/src/bindless_material_ibl.rs @@ -183,7 +183,7 @@ pub fn render_meshes_bindless_ibl( cmd_buf.push_render_constants(pipeline, 0, 0, 4, 16, gfx::as_u8_slice(&camera.view_position)); // bind world buffer info with IBL indices in user_data - let mut world_buffer_info = pmfx.get_world_buffer_info(); + let mut world_buffer_info = pmfx.get_world_buffer_info(pipeline); world_buffer_info.user_data[0] = ibl_data.cubemap_srv; world_buffer_info.user_data[1] = ibl_data.lut_srv; cmd_buf.push_render_constants( diff --git a/plugins/ecs_examples/src/gpu_frustum_culling.rs b/plugins/ecs_examples/src/gpu_frustum_culling.rs index f4138144..1fa68776 100644 --- a/plugins/ecs_examples/src/gpu_frustum_culling.rs +++ b/plugins/ecs_examples/src/gpu_frustum_culling.rs @@ -364,7 +364,7 @@ pub fn dispatch_compute_frustum_cull( gfx::as_u8_slice(&indirect_draw.arg_buffer.get_srv_index().unwrap())); // world buffer info to lookup matrices and aabb info - let world_buffer_info = pmfx.get_world_buffer_info(); + let world_buffer_info = pmfx.get_world_buffer_info(pipeline); cmd_buf.push_compute_constants( pipeline, 2, 0, gfx::num_32bit_constants(&world_buffer_info), 0, gfx::as_u8_slice(&world_buffer_info)); @@ -405,7 +405,7 @@ pub fn draw_meshes_indirect_culling( cmd_buf.set_render_pipeline(&pipeline); // bind the world buffer info - let world_buffer_info = pmfx.get_world_buffer_info(); + let world_buffer_info = pmfx.get_world_buffer_info(pipeline); cmd_buf.push_render_constants( pipeline, 2, 0, gfx::num_32bit_constants(&world_buffer_info), 0, gfx::as_u8_slice(&world_buffer_info)); diff --git a/plugins/ecs_examples/src/lib.rs b/plugins/ecs_examples/src/lib.rs index f41c3e30..403bd874 100644 --- a/plugins/ecs_examples/src/lib.rs +++ b/plugins/ecs_examples/src/lib.rs @@ -261,7 +261,7 @@ pub fn render_meshes_bindless( cmd_buf.push_render_constants(pipeline, 0, 0, 4, 16, gfx::as_u8_slice(&camera.view_position)); // bind the world buffer info - let world_buffer_info = pmfx.get_world_buffer_info(); + let world_buffer_info = pmfx.get_world_buffer_info(pipeline); cmd_buf.push_render_constants(pipeline, 2, 0, gfx::num_32bit_constants(&world_buffer_info), 0, gfx::as_u8_slice(&world_buffer_info)); // bind resource uses diff --git a/plugins/ecs_examples/src/raytracing_pipeline.rs b/plugins/ecs_examples/src/raytracing_pipeline.rs index 5b00c67e..41b97fa5 100644 --- a/plugins/ecs_examples/src/raytracing_pipeline.rs +++ b/plugins/ecs_examples/src/raytracing_pipeline.rs @@ -244,7 +244,7 @@ pub fn render_meshes_raytraced( cmd_buf.push_compute_constants(&raytracing_pipeline.pipeline, 0, 0, 1, 17, gfx::as_u8_slice(&srv0)); // point light info - let world_buffer_info = pmfx.get_world_buffer_info(); + let world_buffer_info = pmfx.get_world_buffer_info(&raytracing_pipeline.pipeline); cmd_buf.push_compute_constants(&raytracing_pipeline.pipeline, 0, 0, 2, 18, gfx::as_u8_slice(&world_buffer_info.point_light)); cmd_buf.set_heap(&raytracing_pipeline.pipeline, &pmfx.shader_heap); diff --git a/src/gfx.rs b/src/gfx.rs index e2daf6c9..c78e98a5 100644 --- a/src/gfx.rs +++ b/src/gfx.rs @@ -687,7 +687,9 @@ pub struct PipelineSlotInfo { /// The slot in the pipeline layout to bind to pub index: u32, /// The number of descriptors or the number of 32-bit push constant values, if `None` the table is unbounded - pub count: Option + pub count: Option, + /// Sub-binding offset within the descriptor set (Metal [[id(N)]]); always 0 on D3D12 + pub sub_offset: u32, } /// Input layout describes the layout of vertex buffers bound to the input assembler. @@ -1271,6 +1273,12 @@ pub trait Pipeline { fn get_pipeline_slots(&self) -> &Vec; /// Returns the pipeline type fn get_pipeline_type() -> PipelineType; + /// Returns the sub-binding offset within the descriptor set for the given binding key. + /// On Metal this corresponds to the [[id(N)]] value assigned by spirv-cross. + /// On D3D12 the default impl returns 0 (heap index is used directly). + fn get_sub_binding_offset(&self, _register: u32, _space: u32, _descriptor_type: DescriptorType) -> u32 { + 0 + } } /// A command signature is used to `execute_indirect` commands diff --git a/src/gfx/d3d12.rs b/src/gfx/d3d12.rs index 275d57a6..b587e2d7 100644 --- a/src/gfx/d3d12.rs +++ b/src/gfx/d3d12.rs @@ -1290,7 +1290,8 @@ impl Device { let h = get_binding_descriptor_hash(constants.shader_register, constants.register_space, super::DescriptorType::PushConstants); lookup.insert(h, PipelineSlotInfo { index: slot_iter, - count: Some(constants.num_values) + count: Some(constants.num_values), + sub_offset: 0, }); slot_iter += 1; } @@ -1357,7 +1358,8 @@ impl Device { let h = get_binding_descriptor_hash(binding.shader_register, binding.register_space, binding.binding_type); lookup.entry(h).or_insert(PipelineSlotInfo { index: slot_iter, - count: binding.num_descriptors + count: binding.num_descriptors, + sub_offset: 0, }); } slot_iter += 1; diff --git a/src/gfx/mtl.rs b/src/gfx/mtl.rs index 85620965..60baacd5 100644 --- a/src/gfx/mtl.rs +++ b/src/gfx/mtl.rs @@ -1051,6 +1051,13 @@ impl super::Pipeline for RenderPipeline { fn get_pipeline_type() -> PipelineType { super::PipelineType::Render } + + fn get_sub_binding_offset(&self, register: u32, space: u32, descriptor_type: DescriptorType) -> u32 { + self.slot_lookup + .get(&(register, space, descriptor_type)) + .map(|s| s.sub_offset) + .unwrap_or(0) + } } #[derive(Clone)] @@ -1389,6 +1396,7 @@ impl Device { PipelineSlotInfo { index: canonical_index, count: Some(push_constant.num_values), + sub_offset: 0, }, ); } @@ -1420,13 +1428,15 @@ impl Device { }; let canonical_index = vertex_idx.or(fragment_idx).unwrap_or(0); - // Each binding gets a slot entry - for binding in bindings.iter() { + // Each binding gets a slot entry; sub_offset is the position within the group + // matching the [[id(N)]] value spirv-cross assigns in the descriptor set struct + for (sub_offset, binding) in bindings.iter().enumerate() { slot_lookup.insert( (binding.shader_register, binding.register_space, binding.binding_type), PipelineSlotInfo { index: canonical_index, count: binding.num_descriptors, + sub_offset: sub_offset as u32, } ); } diff --git a/src/pmfx.rs b/src/pmfx.rs index e40c84e0..d1085a35 100644 --- a/src/pmfx.rs +++ b/src/pmfx.rs @@ -445,6 +445,9 @@ pub struct DynamicBuffer { usage: gfx::BufferUsage, bb: usize, num_buffers: usize, + shader_register: u32, + register_space: u32, + binding_type: gfx::DescriptorType, resource_type: std::marker::PhantomData } @@ -458,10 +461,23 @@ impl DynamicBuffer where D: gfx::Device, T: Sized { usage, bb: 0, num_buffers, + shader_register: 0, + register_space: 0, + binding_type: gfx::DescriptorType::ShaderResource, resource_type: std::marker::PhantomData } } + /// Set the shader binding location so `get_lookup` can resolve the Metal sub-binding offset + pub fn with_binding(mut self, register: u32, space: u32, binding_type: gfx::DescriptorType) -> Self { + self.shader_register = register; + self.register_space = space; + self.binding_type = binding_type; + self + } + + pub fn get_bb(&self) -> usize { self.bb } + /// Swap buffers once a frame for safe CPU writes an GPU in flight reads pub fn swap(&mut self) { self.bb = (self.bb + 1) % self.num_buffers @@ -558,10 +574,12 @@ impl DynamicBuffer where D: gfx::Device, T: Sized { } } - pub fn get_lookup(&self) -> GpuBufferLookup { + pub fn get_lookup(&self, pipeline: &P) -> GpuBufferLookup { + let sub_offset = pipeline.get_sub_binding_offset( + self.shader_register, self.register_space, self.binding_type); GpuBufferLookup { - index: self.get_index() as u32, - count: self.len as u32 + index: (self.get_index() as u32).saturating_sub(sub_offset), + count: self.len as u32, } } } @@ -588,14 +606,17 @@ pub struct DynamicWorldBuffers { impl Default for DynamicWorldBuffers where D: gfx::Device { fn default() -> Self { Self { - draw: DynamicBuffer::::new(gfx::BufferUsage::SHADER_RESOURCE, 3), - extent: DynamicBuffer::::new(gfx::BufferUsage::SHADER_RESOURCE, 3), - material: DynamicBuffer::::new(gfx::BufferUsage::SHADER_RESOURCE, 3), - point_light: DynamicBuffer::::new(gfx::BufferUsage::SHADER_RESOURCE, 3), - spot_light: DynamicBuffer::::new(gfx::BufferUsage::SHADER_RESOURCE, 3), - directional_light: DynamicBuffer::::new(gfx::BufferUsage::SHADER_RESOURCE, 3), - camera: DynamicBuffer::::new(gfx::BufferUsage::CONSTANT_BUFFER, 3), - shadow_matrix: DynamicBuffer::::new(gfx::BufferUsage::SHADER_RESOURCE, 3), + draw: DynamicBuffer::::new(gfx::BufferUsage::SHADER_RESOURCE, 3), + extent: DynamicBuffer::::new(gfx::BufferUsage::SHADER_RESOURCE, 3), + material: DynamicBuffer::::new(gfx::BufferUsage::SHADER_RESOURCE, 3), + point_light: DynamicBuffer::::new(gfx::BufferUsage::SHADER_RESOURCE, 3) + .with_binding(0, 3, gfx::DescriptorType::ShaderResource), + spot_light: DynamicBuffer::::new(gfx::BufferUsage::SHADER_RESOURCE, 3) + .with_binding(0, 4, gfx::DescriptorType::ShaderResource), + directional_light: DynamicBuffer::::new(gfx::BufferUsage::SHADER_RESOURCE, 3) + .with_binding(0, 5, gfx::DescriptorType::ShaderResource), + camera: DynamicBuffer::::new(gfx::BufferUsage::CONSTANT_BUFFER, 3), + shadow_matrix: DynamicBuffer::::new(gfx::BufferUsage::SHADER_RESOURCE, 3), } } } @@ -1046,18 +1067,17 @@ impl Pmfx where D: gfx::Device { /// Retunrs a `WorldBufferInfo` that contains the serv index and count of the various world buffers used /// during rendering - pub fn get_world_buffer_info(&self) -> WorldBufferInfo { - // construct on the fly + pub fn get_world_buffer_info(&self, pipeline: &P) -> WorldBufferInfo { WorldBufferInfo { - draw: self.world_buffers.draw.get_lookup(), - extent: self.world_buffers.extent.get_lookup(), - material: self.world_buffers.material.get_lookup(), - point_light: self.world_buffers.point_light.get_lookup(), - spot_light: self.world_buffers.spot_light.get_lookup(), - directional_light: self.world_buffers.directional_light.get_lookup(), - camera: self.world_buffers.camera.get_lookup(), - shadow_matrix: self.world_buffers.shadow_matrix.get_lookup(), - user_data: self.push_constant_user_data + draw: self.world_buffers.draw.get_lookup(pipeline), + extent: self.world_buffers.extent.get_lookup(pipeline), + material: self.world_buffers.material.get_lookup(pipeline), + point_light: self.world_buffers.point_light.get_lookup(pipeline), + spot_light: self.world_buffers.spot_light.get_lookup(pipeline), + directional_light: self.world_buffers.directional_light.get_lookup(pipeline), + camera: self.world_buffers.camera.get_lookup(pipeline), + shadow_matrix: self.world_buffers.shadow_matrix.get_lookup(pipeline), + user_data: self.push_constant_user_data, } } From 292ebeccf18f48e0a0272362ea858f2df14bb9dc Mon Sep 17 00:00:00 2001 From: polymonster Date: Mon, 18 May 2026 11:56:57 +0200 Subject: [PATCH 42/62] move htwv crate to hotline-data Relocates the HLSL to Vulkan to Metal shader compilation toolchain from crates/htwv/ into the hotline-data submodule. The SPIRV-Cross submodule moves with it, so hotline-data is now the single external repo to sync. Co-Authored-By: Claude Sonnet 4.6 --- .gitmodules | 3 - Cargo.toml | 3 +- crates/htwv/Cargo.toml | 21 - crates/htwv/build.rs | 153 - crates/htwv/src/lib.rs | 33 - crates/htwv/src/macos_impl.rs | 531 --- crates/htwv/src/spirv_cross_bindings.rs | 5530 ----------------------- crates/htwv/third_party/SPIRV-Cross | 1 - hotline-data | 2 +- 9 files changed, 2 insertions(+), 6275 deletions(-) delete mode 100644 crates/htwv/Cargo.toml delete mode 100644 crates/htwv/build.rs delete mode 100644 crates/htwv/src/lib.rs delete mode 100644 crates/htwv/src/macos_impl.rs delete mode 100644 crates/htwv/src/spirv_cross_bindings.rs delete mode 160000 crates/htwv/third_party/SPIRV-Cross diff --git a/.gitmodules b/.gitmodules index 78e4d8f5..0994c715 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,6 +1,3 @@ [submodule "hotline-data"] path = hotline-data url = https://github.com/polymonster/hotline-data.git -[submodule "crates/htwv/third_party/SPIRV-Cross"] - path = crates/htwv/third_party/SPIRV-Cross - url = https://github.com/KhronosGroup/SPIRV-Cross.git diff --git a/Cargo.toml b/Cargo.toml index b7967b74..54f730fa 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,7 +2,6 @@ resolver = "2" members = [ ".", - "crates/htwv", "plugins/empty", "plugins/ecs", "plugins/ecs_examples", @@ -46,7 +45,7 @@ bevy_ecs.workspace = true ddsfile = "0.5.1" [build-dependencies] -htwv = { path = "crates/htwv" } +htwv = { path = "hotline-data/htwv" } [dependencies.imgui-sys] version = "0.9.0" diff --git a/crates/htwv/Cargo.toml b/crates/htwv/Cargo.toml deleted file mode 100644 index 24e06e40..00000000 --- a/crates/htwv/Cargo.toml +++ /dev/null @@ -1,21 +0,0 @@ -[package] -name = "htwv" -version = "0.1.0" -edition = "2021" -description = "HLSL to Vulkan to Metal shader compilation toolchain" - -[dependencies] -glob = "0.3" -serde = { version = "1.0", features = ["derive"] } -serde_json = "1.0.81" - -# Build dependencies only needed on macOS -[target.'cfg(target_os = "macos")'.build-dependencies] -bindgen = "0.65.1" -cmake = "0.1" - -[features] -# Use Release build for C++ (faster shader compilation) -cpp-release = [] -# For regenerating bindings (developer use only) -generate-bindings = [] diff --git a/crates/htwv/build.rs b/crates/htwv/build.rs deleted file mode 100644 index 31860012..00000000 --- a/crates/htwv/build.rs +++ /dev/null @@ -1,153 +0,0 @@ -fn main() { - #[cfg(target_os = "macos")] - macos_build(); -} - -#[cfg(target_os = "macos")] -fn macos_build() { - use std::path::Path; - use std::process::{Command, Stdio}; - - let manifest_dir = - std::env::var("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR not set"); - let out_dir = std::env::var("OUT_DIR").expect("OUT_DIR not set"); - - let spirv_cross_src = format!("{}/third_party/SPIRV-Cross", manifest_dir); - let pmfx_shader_src = format!("{}/third_party/pmfx-shader", manifest_dir); - - // Ensure third-party dependencies exist (download if missing for crates.io) - ensure_spirv_cross(&spirv_cross_src); - - // Rerun if SPIRV-Cross source changes - println!("cargo:rerun-if-changed={}/spirv_cross_c.h", spirv_cross_src); - - // Select build profile - let profile = if std::env::var("CARGO_FEATURE_CPP_RELEASE").is_ok() { - "Release" - } else { - match std::env::var("PROFILE") - .unwrap_or_default() - .as_str() - { - "debug" => "Debug", - _ => "Release", - } - }; - - // Build SPIRV-Cross in OUT_DIR - let build_dir = format!("{}/SPIRV-Cross", out_dir); - std::fs::create_dir_all(&build_dir).unwrap(); - - // Configure CMake - let status = Command::new("cmake") - .args([ - "-S", - &spirv_cross_src, - "-B", - &build_dir, - &format!("-DCMAKE_BUILD_TYPE={}", profile), - "-DCMAKE_OSX_DEPLOYMENT_TARGET=15.0", - "-DCMAKE_CXX_COMPILER=clang++", - ]) - .stdout(Stdio::inherit()) - .stderr(Stdio::inherit()) - .status() - .expect("Failed to run cmake configure"); - - if !status.success() { - panic!("CMake configure failed"); - } - - // Build - let status = Command::new("cmake") - .args(["--build", &build_dir, "--config", profile]) - .status() - .expect("Failed to run cmake build"); - - if !status.success() { - panic!("CMake build failed"); - } - - // Optionally regenerate bindings - if std::env::var("CARGO_FEATURE_GENERATE_BINDINGS").is_ok() { - let bindings = bindgen::Builder::default() - .header(format!("{}/spirv_cross_c.h", spirv_cross_src)) - .generate() - .expect("Failed to generate bindings for spirv_cross_c.h"); - - bindings - .write_to_file(format!("{}/src/spirv_cross_bindings.rs", manifest_dir)) - .expect("Couldn't write bindings!"); - } - - // Setup link paths - println!("cargo:rustc-link-search=native={}", build_dir); - println!("cargo:rustc-link-lib=static=spirv-cross-c"); - println!("cargo:rustc-link-lib=static=spirv-cross-core"); - println!("cargo:rustc-link-lib=static=spirv-cross-cpp"); - println!("cargo:rustc-link-lib=static=spirv-cross-glsl"); - println!("cargo:rustc-link-lib=static=spirv-cross-hlsl"); - println!("cargo:rustc-link-lib=static=spirv-cross-msl"); - println!("cargo:rustc-link-lib=static=spirv-cross-reflect"); - println!("cargo:rustc-link-lib=static=spirv-cross-util"); - println!("cargo:rustc-link-lib=c++"); -} - -#[cfg(target_os = "macos")] -fn ensure_spirv_cross(spirv_cross_dir: &str) { - use std::path::Path; - use std::process::{Command, Stdio}; - - let marker = Path::new(spirv_cross_dir).join("CMakeLists.txt"); - if marker.exists() { - return; // Already populated (submodule or previous download) - } - - println!("cargo:warning=SPIRV-Cross not found, downloading..."); - - // Pin to a specific release for reproducibility - const SPIRV_CROSS_VERSION: &str = "vulkan-sdk-1.3.275.0"; - let url = format!( - "https://github.com/KhronosGroup/SPIRV-Cross/archive/refs/tags/{}.tar.gz", - SPIRV_CROSS_VERSION - ); - - let parent = Path::new(spirv_cross_dir) - .parent() - .expect("Invalid spirv_cross_dir"); - std::fs::create_dir_all(parent).expect("Failed to create third_party dir"); - - // Download and extract - let status = Command::new("curl") - .args(["-L", "-o", "/tmp/spirv-cross.tar.gz", &url]) - .stdout(Stdio::inherit()) - .stderr(Stdio::inherit()) - .status() - .expect("Failed to download SPIRV-Cross"); - - if !status.success() { - panic!("Failed to download SPIRV-Cross from {}", url); - } - - let status = Command::new("tar") - .args([ - "-xzf", - "/tmp/spirv-cross.tar.gz", - "-C", - parent.to_str().unwrap(), - ]) - .status() - .expect("Failed to extract SPIRV-Cross"); - - if !status.success() { - panic!("Failed to extract SPIRV-Cross"); - } - - // Rename extracted directory - let extracted_name = format!("SPIRV-Cross-{}", SPIRV_CROSS_VERSION); - let extracted_path = parent.join(&extracted_name); - std::fs::rename(&extracted_path, spirv_cross_dir) - .expect("Failed to rename extracted SPIRV-Cross directory"); - - println!("cargo:warning=SPIRV-Cross downloaded successfully"); -} \ No newline at end of file diff --git a/crates/htwv/src/lib.rs b/crates/htwv/src/lib.rs deleted file mode 100644 index 79e067bf..00000000 --- a/crates/htwv/src/lib.rs +++ /dev/null @@ -1,33 +0,0 @@ -//! HTWV - HLSL To Vulkan to Metal shader compilation toolchain -//! -//! This crate compiles HLSL shaders through SPIR-V to Metal Shading Language (MSL). -//! It is only functional on macOS - on other platforms it provides stub functions -//! that return errors. - -#[cfg(target_os = "macos")] -#[allow(warnings)] -mod spirv_cross_bindings; - -#[cfg(target_os = "macos")] -mod macos_impl; - -#[cfg(target_os = "macos")] -pub use macos_impl::*; - -// Stub implementations for non-macOS platforms -#[cfg(not(target_os = "macos"))] -pub fn compile_dir( - _input_dir: &str, - _output_dir: &str, -) -> Result<(), Box> { - Err("htwv shader compilation is only available on macOS".into()) -} - -#[cfg(not(target_os = "macos"))] -pub fn compile_piepline( - _filepath: &str, - _input_dir: &str, - _output_dir: &str, -) -> Result<(), Box> { - Err("htwv shader compilation is only available on macOS".into()) -} diff --git a/crates/htwv/src/macos_impl.rs b/crates/htwv/src/macos_impl.rs deleted file mode 100644 index 1ae4b6bc..00000000 --- a/crates/htwv/src/macos_impl.rs +++ /dev/null @@ -1,531 +0,0 @@ -use std::collections::HashMap; -use std::error::Error; -use std::fs::{self, File}; -use std::io::Read; -use std::path::Path; -use std::process::{Command, Stdio}; -use std::string::FromUtf8Error; - -use glob::glob; -use serde::{Deserialize, Serialize}; - -use crate::spirv_cross_bindings::*; - -fn print_cstr(msg: *const ::std::os::raw::c_char) { - println!("{}", cstr_to_string(msg).unwrap()); -} - -unsafe extern "C" fn error_callback( - _: *mut ::std::os::raw::c_void, - error: *const ::std::os::raw::c_char, -) { - print_cstr(error); -} - -fn cstr_to_string(msg: *const ::std::os::raw::c_char) -> Result { - let mut buf: Vec = Vec::new(); - unsafe { - let mut msg_iter = msg; - loop { - if *msg_iter != 0 { - buf.push(*msg_iter as u8); - } else { - break; - } - msg_iter = msg_iter.offset(1); - } - } - String::from_utf8(buf) -} - -fn load_spirv_file(path: &str) -> Vec { - println!("{}", path); - - let mut file = File::open(path).expect("failed to open .spv file"); - let mut buffer = Vec::new(); - file.read_to_end(&mut buffer) - .expect("failed to read .spv file"); - - // Convert byte buffer to u32 vector - assert!( - buffer.len() % 4 == 0, - ".spv file must align to 32-bit words" - ); - buffer - .chunks_exact(4) - .map(|chunk| u32::from_le_bytes([chunk[0], chunk[1], chunk[2], chunk[3]])) - .collect() -} - -#[derive(Serialize, Deserialize, Clone, PartialEq)] -enum ShaderStage { - Vertex, - Fragment, - Compute, - All, -} - -#[derive(Serialize, Deserialize, Clone)] -struct Resource { - name: String, - visibility: ShaderStage, - #[serde(default)] - resource_type: Option, - #[serde(default)] - num_descriptors: Option, -} - -#[derive(Serialize, Deserialize, Clone)] -struct PipelineLayout { - bindings: Vec, - push_constants: Vec, - static_samplers: Vec, -} - -#[derive(Serialize, Deserialize, Clone)] -struct Pipeline { - vs: Option, - ps: Option, - cs: Option, - lib: Option>, - pipeline_layout: PipelineLayout, -} -type PipelinePermutations = HashMap; - -#[derive(Serialize, Deserialize, Clone)] -struct Pmfx { - pipelines: HashMap, -} - -fn compile_shader_spirv( - filepath: &str, - input_dir: &str, - output_dir: &str, - pipeline: &Pipeline, - stage: ShaderStage, -) -> Result<(), Box> { - unsafe { - let temp_spirv = filepath - .replace(".vsc", ".spirv") - .replace(".psc", ".spirv") - .replace(".csc", ".spirv"); - - let spirv_file = format!("{}/{}", input_dir, temp_spirv); - let output_file = format!("{}/{}", output_dir, filepath); - - let spirv_binary = load_spirv_file(&spirv_file); - - let mut ctx = std::ptr::null_mut(); - let res = spvc_context_create(&mut ctx); - assert_eq!(res, spvc_result_SPVC_SUCCESS); - - // set error callback - spvc_context_set_error_callback(ctx, Some(error_callback), std::ptr::null_mut()); - - // parse IR - let mut ir = std::ptr::null_mut(); - let result = - spvc_context_parse_spirv(ctx, spirv_binary.as_ptr(), spirv_binary.len(), &mut ir); - assert_eq!(result, spvc_result_SPVC_SUCCESS); - - // create a pssl compiler - let mut compiler = std::ptr::null_mut(); - spvc_context_create_compiler( - ctx, - spvc_backend_SPVC_BACKEND_MSL, - ir, - spvc_capture_mode_SPVC_CAPTURE_MODE_TAKE_OWNERSHIP, - &mut compiler, - ); - - // create compiler options - let mut compiler_options = std::ptr::null_mut(); - let result = spvc_compiler_create_compiler_options(compiler, &mut compiler_options); - assert_eq!(result, spvc_result_SPVC_SUCCESS); - - // set compiler options - - // set MSL version - spvc_compiler_options_set_uint( - compiler_options, - spvc_compiler_option_SPVC_COMPILER_OPTION_MSL_VERSION, - 202300, // example: MSL version 2.3.0 - ); - - // Enable MSL argument buffers - spvc_compiler_options_set_bool( - compiler_options, - spvc_compiler_option_SPVC_COMPILER_OPTION_MSL_ARGUMENT_BUFFERS, - 1, - ); - - spvc_compiler_options_set_bool( - compiler_options, - spvc_compiler_option_SPVC_COMPILER_OPTION_MSL_FORCE_ACTIVE_ARGUMENT_BUFFER_RESOURCES, - 1, - ); - - // Set argument buffer tier 2 (required for runtime-sized arrays in device space) - spvc_compiler_options_set_uint( - compiler_options, - spvc_compiler_option_SPVC_COMPILER_OPTION_MSL_ARGUMENT_BUFFERS_TIER, - 2, - ); - - let result = spvc_compiler_install_compiler_options(compiler, compiler_options); - assert_eq!(result, spvc_result_SPVC_SUCCESS); - - // set bindings - - // Assume you already have a valid compiler and resources - let mut resources: spvc_resources = std::ptr::null_mut(); - let result = spvc_compiler_create_shader_resources(compiler, &mut resources); - assert_eq!(result, spvc_result_SPVC_SUCCESS); - - let resource_types = vec![ - spvc_resource_type_SPVC_RESOURCE_TYPE_UNIFORM_BUFFER, - spvc_resource_type_SPVC_RESOURCE_TYPE_STORAGE_BUFFER, - spvc_resource_type_SPVC_RESOURCE_TYPE_SEPARATE_IMAGE, - spvc_resource_type_SPVC_RESOURCE_TYPE_STORAGE_IMAGE, - spvc_resource_type_SPVC_RESOURCE_TYPE_SAMPLED_IMAGE, - spvc_resource_type_SPVC_RESOURCE_TYPE_SEPARATE_SAMPLERS, - ]; - - let resources: Vec<_> = resource_types - .into_iter() - .flat_map(|x| { - // Choose the resource type you want to query - let resource_type = x; - - // Prepare output pointers - let mut resource_list: *const spvc_reflected_resource = std::ptr::null(); - let mut resource_count: usize = 0; - - // Get the list of resources of the given type - let list_result = spvc_resources_get_resource_list_for_type( - resources, - resource_type, - &mut resource_list, - &mut resource_count, - ); - assert_eq!(list_result, spvc_result_SPVC_SUCCESS); - - (0..resource_count).map(move |i| *resource_list.add(i)) - }) - .collect(); - - let samplers_offset = match stage - { - ShaderStage::Vertex => 2, - _ => 0 - }; - - // put samplers first all in single argument buffer - for resource in &resources { - for sampler in &pipeline.pipeline_layout.static_samplers { - let name = cstr_to_string(resource.name)?; - if sampler.name == name.strip_prefix("type.").unwrap_or(&name) { - spvc_compiler_set_decoration( - compiler, - resource.id, - SpvDecoration__SpvDecorationDescriptorSet, - samplers_offset as u32, - ); - } - } - } - - // put push constants next - use discrete descriptor sets (no argument buffers) - // This enables using setVertexBytes/setFragmentBytes at runtime - let mut binding_offset = samplers_offset + 1; - let exec_model = match stage { - ShaderStage::Vertex => SpvExecutionModel__SpvExecutionModelVertex, - ShaderStage::Fragment => SpvExecutionModel__SpvExecutionModelFragment, - ShaderStage::Compute => SpvExecutionModel__SpvExecutionModelGLCompute, - _ => SpvExecutionModel__SpvExecutionModelVertex, - }; - - for resource in &resources { - for push_constant in &pipeline.pipeline_layout.push_constants { - // Only process push constants visible to this shader stage - if push_constant.visibility != stage && push_constant.visibility != ShaderStage::All { - continue; - } - let name = cstr_to_string(resource.name)?; - - // stip .type.ConstantBuffer.NAME_data prefix and suffix - // or .type prefix - let name = if let Some(name) = name.strip_prefix("type.ConstantBuffer.") { - name.strip_suffix("_data").unwrap_or(name) - } - else { - name.strip_prefix("type.").unwrap_or(&name) - }; - - if push_constant.name == name { - let desc_set = binding_offset as u32; - spvc_compiler_set_decoration( - compiler, - resource.id, - SpvDecoration__SpvDecorationDescriptorSet, - desc_set, - ); - // Mark as discrete so it uses direct buffer binding, not argument buffer - spvc_compiler_msl_add_discrete_descriptor_set(compiler, desc_set); - - // Explicitly map to Metal buffer index (without this, SPIRV-Cross uses buffer(0)) - // Get the original SPIR-V binding number from the resource - let spirv_binding = spvc_compiler_get_decoration( - compiler, - resource.id, - SpvDecoration__SpvDecorationBinding, - ); - let mut res_binding: spvc_msl_resource_binding = std::mem::zeroed(); - spvc_msl_resource_binding_init(&mut res_binding); - res_binding.stage = exec_model; - res_binding.desc_set = desc_set; - res_binding.binding = spirv_binding; - res_binding.msl_buffer = desc_set; - spvc_compiler_msl_add_resource_binding(compiler, &res_binding); - - binding_offset += 1 - } - } - } - - // set bindings based on pipeline layout - let mut binding_sub_offset = 0; - for resource in &resources { - for (_, binding) in pipeline.pipeline_layout.bindings.iter().enumerate() { - if binding.visibility == stage || binding.visibility == ShaderStage::All { - let name = cstr_to_string(resource.name)?; - - // strip .type.ConstantBuffer.NAME_data prefix and suffix - // or .type prefix - let name = if let Some(name) = name.strip_prefix("type.ConstantBuffer.") { - name.strip_suffix("_data").unwrap_or(name) - } - else { - name.strip_prefix("type.").unwrap_or(&name) - }; - - if &binding.name == name { - // Set descriptor set - spvc_compiler_set_decoration( - compiler, - resource.id, - SpvDecoration__SpvDecorationDescriptorSet, - binding_offset as u32, - ); - - // Set binding index within the descriptor set - spvc_compiler_set_decoration( - compiler, - resource.id, - SpvDecoration__SpvDecorationBinding, - binding_sub_offset as u32, - ); - - // Use resource_binding_2 to explicitly set argument buffer member binding - let mut res_binding: spvc_msl_resource_binding_2 = std::mem::zeroed(); - spvc_msl_resource_binding_init_2(&mut res_binding); - res_binding.stage = exec_model; - res_binding.desc_set = binding_offset as u32; - res_binding.binding = binding_sub_offset as u32; - // For unbounded/runtime arrays (null or large num_descriptors), don't set count - // to let SPIRV-Cross use the unsized array hack - if let Some(num_desc) = binding.num_descriptors { - if num_desc <= 16 { - res_binding.count = num_desc; - } - } - - // Set appropriate MSL binding based on resource type - let is_texture = binding.resource_type.as_ref().map_or(false, |t| { - t.starts_with("Texture") || t.starts_with("RWTexture") - }); - if is_texture { - res_binding.msl_texture = binding_sub_offset as u32; - } else { - res_binding.msl_buffer = binding_sub_offset as u32; - } - spvc_compiler_msl_add_resource_binding_2(compiler, &res_binding); - - binding_sub_offset += 1; - } - } - } - } - - // Enable device address space for the bindings argument buffer - // This allows runtime-sized arrays in the argument buffer - spvc_compiler_msl_set_argument_buffer_device_address_space( - compiler, - binding_offset as u32, - 1, // true - use device address space - ); - - let mut msl_src = std::ptr::null(); - let result = spvc_compiler_compile(compiler, &mut msl_src); - if result == spvc_result_SPVC_ERROR_UNSUPPORTED_SPIRV { - println!("spirv_to_pssl: spirv binary is unsupported"); - spvc_context_destroy(ctx); - } - - if result != spvc_result_SPVC_SUCCESS { - return Err(format!("SPIRV-Cross compilation failed for {}", filepath).into()); - } - - let msl_source = cstr_to_string(msl_src)?; - - // Ensure output directory exists - if let Some(parent) = Path::new(&output_file).parent() { - fs::create_dir_all(parent)?; - } - - // Write MSL source to temp .metal file - let temp_metal_file = format!("{}.metal", output_file); - fs::write(&temp_metal_file, &msl_source)?; - - // Compile .metal to .air - let air_file = format!("{}.air", output_file); - let compile_status = Command::new("xcrun") - .args([ - "-sdk", - "macosx", - "metal", - "-c", - "-frecord-sources", - &temp_metal_file, - "-o", - &air_file, - ]) - .stdout(Stdio::inherit()) - .stderr(Stdio::inherit()) - .status()?; - - if !compile_status.success() { - return Err(format!("Metal compilation failed for {}", temp_metal_file).into()); - } - - // Link .air to final output (metallib) - let link_status = Command::new("xcrun") - .args(["-sdk", "macosx", "metal", &air_file, "-o", &output_file]) - .stdout(Stdio::inherit()) - .stderr(Stdio::inherit()) - .status()?; - - if !link_status.success() { - return Err(format!("Metal linking failed for {}", air_file).into()); - } - - // Clean up intermediate files - // let _ = fs::remove_file(&temp_metal_file); - let _ = fs::remove_file(&air_file); - - println!("cargo:warning= compiled: {}", output_file); - Ok(()) - } -} - -pub fn compile_piepline( - filepath: &str, - input_dir: &str, - output_dir: &str, -) -> Result<(), Box> { - let file_data = std::fs::read(filepath).unwrap(); - let file: Pmfx = serde_json::from_slice(&file_data)?; - let mut errors = Vec::new(); - for (_, permutation) in file.pipelines { - for (_, pipeline) in &permutation { - if let Some(vs) = &pipeline.vs { - if let Err(e) = compile_shader_spirv(vs, input_dir, output_dir, &pipeline, ShaderStage::Vertex) { - errors.push(format!("{vs}: {e}")); - } - } - if let Some(ps) = &pipeline.ps { - if let Err(e) = compile_shader_spirv(ps, input_dir, output_dir, &pipeline, ShaderStage::Fragment) { - errors.push(format!("{ps}: {e}")); - } - } - if let Some(cs) = &pipeline.cs { - if let Err(e) = compile_shader_spirv(cs, input_dir, output_dir, &pipeline, ShaderStage::Compute) { - errors.push(format!("{cs}: {e}")); - } - } - } - } - - if errors.is_empty() { - Ok(()) - } else { - Err(errors.join("\n").into()) - } -} - -pub fn compile_dir(input_dir: &str, output_dir: &str) -> Result<(), Box> { - let temp_dir = "target/temp/shaders"; - - // Use CARGO_MANIFEST_DIR to locate pmfx.py relative to this crate - let pmfx_path = format!( - "hotline-data/pmfx-shader/pmfx.py" - ); - - let status = Command::new("python3") - .args(&[ - &pmfx_path, - "-shader_platform", - "spirv", - "-shader_version", - "6_5", - "-i", - input_dir, - "-o", - output_dir, - "-t", - temp_dir, - "-num_threads", - "1", - "-f", - "-args", - "-Zpr", - "-ignores", - "raytracing", - "compute_frustum_cull", - "mesh_lit_rt_shadow", - "mesh_lit_rt_shadow2", - "mip_chain_texture2d", - "heightmap_mrt_resolve", - ]) - .stdout(Stdio::inherit()) - .stderr(Stdio::inherit()) - .status() - .expect("failed compiling pmfx"); - - assert!(status.code().unwrap() == 0); - - let mut errors = Vec::new(); - for entry in glob(&format!("{output_dir}/**/*.json")).expect("") { - if let Ok(path) = entry { - let path_str = path.to_str().unwrap(); - println!("cargo:warning= compiling pipeline: {path_str}"); - if let Err(e) = compile_piepline(path_str, temp_dir, output_dir) { - println!("cargo:warning= pipeline error ({path_str}): {e}"); - errors.push(format!("{}: {}", path_str, e)); - } - } - } - if errors.is_empty() { - Ok(()) - } else { - Err(errors.join("\n").into()) - } -} - -#[cfg(test)] -mod tests { - #[test] - fn run() { - super::compile_dir("../hotline/shaders", "target/shaders").unwrap(); - } -} diff --git a/crates/htwv/src/spirv_cross_bindings.rs b/crates/htwv/src/spirv_cross_bindings.rs deleted file mode 100644 index e59a889d..00000000 --- a/crates/htwv/src/spirv_cross_bindings.rs +++ /dev/null @@ -1,5530 +0,0 @@ -/* automatically generated by rust-bindgen 0.65.1 */ - -pub const _VCRT_COMPILER_PREPROCESSOR: u32 = 1; -pub const _SAL_VERSION: u32 = 20; -pub const __SAL_H_VERSION: u32 = 180000000; -pub const _USE_DECLSPECS_FOR_SAL: u32 = 0; -pub const _USE_ATTRIBUTES_FOR_SAL: u32 = 0; -pub const _CRT_PACKING: u32 = 8; -pub const _HAS_EXCEPTIONS: u32 = 1; -pub const _STL_LANG: u32 = 0; -pub const _HAS_CXX17: u32 = 0; -pub const _HAS_CXX20: u32 = 0; -pub const _HAS_CXX23: u32 = 0; -pub const _HAS_NODISCARD: u32 = 0; -pub const _ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE: u32 = 1; -pub const _CRT_BUILD_DESKTOP_APP: u32 = 1; -pub const _ARGMAX: u32 = 100; -pub const _CRT_INT_MAX: u32 = 2147483647; -pub const _CRT_FUNCTIONS_REQUIRED: u32 = 1; -pub const _CRT_HAS_CXX17: u32 = 0; -pub const _CRT_HAS_C11: u32 = 1; -pub const _CRT_INTERNAL_NONSTDC_NAMES: u32 = 1; -pub const __STDC_SECURE_LIB__: u32 = 200411; -pub const __GOT_SECURE_LIB__: u32 = 200411; -pub const __STDC_WANT_SECURE_LIB__: u32 = 1; -pub const _SECURECRT_FILL_BUFFER_PATTERN: u32 = 254; -pub const _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES: u32 = 0; -pub const _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES_COUNT: u32 = 0; -pub const _CRT_SECURE_CPP_OVERLOAD_SECURE_NAMES: u32 = 1; -pub const _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES_MEMORY: u32 = 0; -pub const _CRT_SECURE_CPP_OVERLOAD_SECURE_NAMES_MEMORY: u32 = 0; -pub const SPV_VERSION: u32 = 67072; -pub const SPV_REVISION: u32 = 1; -pub const SPVC_C_API_VERSION_MAJOR: u32 = 0; -pub const SPVC_C_API_VERSION_MINOR: u32 = 67; -pub const SPVC_C_API_VERSION_PATCH: u32 = 0; -pub const SPVC_COMPILER_OPTION_COMMON_BIT: u32 = 16777216; -pub const SPVC_COMPILER_OPTION_GLSL_BIT: u32 = 33554432; -pub const SPVC_COMPILER_OPTION_HLSL_BIT: u32 = 67108864; -pub const SPVC_COMPILER_OPTION_MSL_BIT: u32 = 134217728; -pub const SPVC_COMPILER_OPTION_LANG_BITS: u32 = 251658240; -pub const SPVC_COMPILER_OPTION_ENUM_BITS: u32 = 16777215; -pub const SPVC_MSL_PUSH_CONSTANT_DESC_SET: i32 = -1; -pub const SPVC_MSL_PUSH_CONSTANT_BINDING: u32 = 0; -pub const SPVC_MSL_SWIZZLE_BUFFER_BINDING: i32 = -2; -pub const SPVC_MSL_BUFFER_SIZE_BUFFER_BINDING: i32 = -3; -pub const SPVC_MSL_ARGUMENT_BUFFER_BINDING: i32 = -4; -pub const SPVC_MSL_AUX_BUFFER_STRUCT_VERSION: u32 = 1; -pub const SPVC_HLSL_PUSH_CONSTANT_DESC_SET: i32 = -1; -pub const SPVC_HLSL_PUSH_CONSTANT_BINDING: u32 = 0; -pub type va_list = *mut ::std::os::raw::c_char; -extern "C" { - pub fn __va_start(arg1: *mut *mut ::std::os::raw::c_char, ...); -} -pub type __vcrt_bool = bool; -pub type wchar_t = ::std::os::raw::c_ushort; -extern "C" { - pub fn __security_init_cookie(); -} -extern "C" { - pub fn __security_check_cookie(_StackCookie: usize); -} -extern "C" { - pub fn __report_gsfailure(_StackCookie: usize) -> !; -} -extern "C" { - pub static mut __security_cookie: usize; -} -pub type __crt_bool = bool; -extern "C" { - pub fn _invalid_parameter_noinfo(); -} -extern "C" { - pub fn _invalid_parameter_noinfo_noreturn() -> !; -} -extern "C" { - pub fn _invoke_watson( - _Expression: *const wchar_t, - _FunctionName: *const wchar_t, - _FileName: *const wchar_t, - _LineNo: ::std::os::raw::c_uint, - _Reserved: usize, - ) -> !; -} -pub type errno_t = ::std::os::raw::c_int; -pub type wint_t = ::std::os::raw::c_ushort; -pub type wctype_t = ::std::os::raw::c_ushort; -pub type __time32_t = ::std::os::raw::c_long; -pub type __time64_t = ::std::os::raw::c_longlong; -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct __crt_locale_data_public { - pub _locale_pctype: *const ::std::os::raw::c_ushort, - pub _locale_mb_cur_max: ::std::os::raw::c_int, - pub _locale_lc_codepage: ::std::os::raw::c_uint, -} -#[test] -fn bindgen_test_layout___crt_locale_data_public() { - const UNINIT: ::std::mem::MaybeUninit<__crt_locale_data_public> = - ::std::mem::MaybeUninit::uninit(); - let ptr = UNINIT.as_ptr(); - assert_eq!( - ::std::mem::size_of::<__crt_locale_data_public>(), - 16usize, - concat!("Size of: ", stringify!(__crt_locale_data_public)) - ); - assert_eq!( - ::std::mem::align_of::<__crt_locale_data_public>(), - 8usize, - concat!("Alignment of ", stringify!(__crt_locale_data_public)) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr)._locale_pctype) as usize - ptr as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(__crt_locale_data_public), - "::", - stringify!(_locale_pctype) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr)._locale_mb_cur_max) as usize - ptr as usize }, - 8usize, - concat!( - "Offset of field: ", - stringify!(__crt_locale_data_public), - "::", - stringify!(_locale_mb_cur_max) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr)._locale_lc_codepage) as usize - ptr as usize }, - 12usize, - concat!( - "Offset of field: ", - stringify!(__crt_locale_data_public), - "::", - stringify!(_locale_lc_codepage) - ) - ); -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct __crt_locale_pointers { - pub locinfo: *mut __crt_locale_data, - pub mbcinfo: *mut __crt_multibyte_data, -} -#[test] -fn bindgen_test_layout___crt_locale_pointers() { - const UNINIT: ::std::mem::MaybeUninit<__crt_locale_pointers> = - ::std::mem::MaybeUninit::uninit(); - let ptr = UNINIT.as_ptr(); - assert_eq!( - ::std::mem::size_of::<__crt_locale_pointers>(), - 16usize, - concat!("Size of: ", stringify!(__crt_locale_pointers)) - ); - assert_eq!( - ::std::mem::align_of::<__crt_locale_pointers>(), - 8usize, - concat!("Alignment of ", stringify!(__crt_locale_pointers)) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).locinfo) as usize - ptr as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(__crt_locale_pointers), - "::", - stringify!(locinfo) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).mbcinfo) as usize - ptr as usize }, - 8usize, - concat!( - "Offset of field: ", - stringify!(__crt_locale_pointers), - "::", - stringify!(mbcinfo) - ) - ); -} -pub type _locale_t = *mut __crt_locale_pointers; -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct _Mbstatet { - pub _Wchar: ::std::os::raw::c_ulong, - pub _Byte: ::std::os::raw::c_ushort, - pub _State: ::std::os::raw::c_ushort, -} -#[test] -fn bindgen_test_layout__Mbstatet() { - const UNINIT: ::std::mem::MaybeUninit<_Mbstatet> = ::std::mem::MaybeUninit::uninit(); - let ptr = UNINIT.as_ptr(); - assert_eq!( - ::std::mem::size_of::<_Mbstatet>(), - 8usize, - concat!("Size of: ", stringify!(_Mbstatet)) - ); - assert_eq!( - ::std::mem::align_of::<_Mbstatet>(), - 4usize, - concat!("Alignment of ", stringify!(_Mbstatet)) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr)._Wchar) as usize - ptr as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(_Mbstatet), - "::", - stringify!(_Wchar) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr)._Byte) as usize - ptr as usize }, - 4usize, - concat!( - "Offset of field: ", - stringify!(_Mbstatet), - "::", - stringify!(_Byte) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr)._State) as usize - ptr as usize }, - 6usize, - concat!( - "Offset of field: ", - stringify!(_Mbstatet), - "::", - stringify!(_State) - ) - ); -} -pub type mbstate_t = _Mbstatet; -pub type time_t = __time64_t; -pub type rsize_t = usize; -extern "C" { - pub fn _errno() -> *mut ::std::os::raw::c_int; -} -extern "C" { - pub fn _set_errno(_Value: ::std::os::raw::c_int) -> errno_t; -} -extern "C" { - pub fn _get_errno(_Value: *mut ::std::os::raw::c_int) -> errno_t; -} -extern "C" { - pub fn __threadid() -> ::std::os::raw::c_ulong; -} -extern "C" { - pub fn __threadhandle() -> usize; -} -pub type SpvId = ::std::os::raw::c_uint; -pub const SpvMagicNumber: ::std::os::raw::c_uint = 119734787; -pub const SpvVersion: ::std::os::raw::c_uint = 67072; -pub const SpvRevision: ::std::os::raw::c_uint = 1; -pub const SpvOpCodeMask: ::std::os::raw::c_uint = 65535; -pub const SpvWordCountShift: ::std::os::raw::c_uint = 16; -pub const SpvSourceLanguage__SpvSourceLanguageUnknown: SpvSourceLanguage_ = 0; -pub const SpvSourceLanguage__SpvSourceLanguageESSL: SpvSourceLanguage_ = 1; -pub const SpvSourceLanguage__SpvSourceLanguageGLSL: SpvSourceLanguage_ = 2; -pub const SpvSourceLanguage__SpvSourceLanguageOpenCL_C: SpvSourceLanguage_ = 3; -pub const SpvSourceLanguage__SpvSourceLanguageOpenCL_CPP: SpvSourceLanguage_ = 4; -pub const SpvSourceLanguage__SpvSourceLanguageHLSL: SpvSourceLanguage_ = 5; -pub const SpvSourceLanguage__SpvSourceLanguageCPP_for_OpenCL: SpvSourceLanguage_ = 6; -pub const SpvSourceLanguage__SpvSourceLanguageSYCL: SpvSourceLanguage_ = 7; -pub const SpvSourceLanguage__SpvSourceLanguageHERO_C: SpvSourceLanguage_ = 8; -pub const SpvSourceLanguage__SpvSourceLanguageNZSL: SpvSourceLanguage_ = 9; -pub const SpvSourceLanguage__SpvSourceLanguageWGSL: SpvSourceLanguage_ = 10; -pub const SpvSourceLanguage__SpvSourceLanguageSlang: SpvSourceLanguage_ = 11; -pub const SpvSourceLanguage__SpvSourceLanguageZig: SpvSourceLanguage_ = 12; -pub const SpvSourceLanguage__SpvSourceLanguageRust: SpvSourceLanguage_ = 13; -pub const SpvSourceLanguage__SpvSourceLanguageMax: SpvSourceLanguage_ = 2147483647; -pub type SpvSourceLanguage_ = ::std::os::raw::c_int; -pub use self::SpvSourceLanguage_ as SpvSourceLanguage; -pub const SpvExecutionModel__SpvExecutionModelVertex: SpvExecutionModel_ = 0; -pub const SpvExecutionModel__SpvExecutionModelTessellationControl: SpvExecutionModel_ = 1; -pub const SpvExecutionModel__SpvExecutionModelTessellationEvaluation: SpvExecutionModel_ = 2; -pub const SpvExecutionModel__SpvExecutionModelGeometry: SpvExecutionModel_ = 3; -pub const SpvExecutionModel__SpvExecutionModelFragment: SpvExecutionModel_ = 4; -pub const SpvExecutionModel__SpvExecutionModelGLCompute: SpvExecutionModel_ = 5; -pub const SpvExecutionModel__SpvExecutionModelKernel: SpvExecutionModel_ = 6; -pub const SpvExecutionModel__SpvExecutionModelTaskNV: SpvExecutionModel_ = 5267; -pub const SpvExecutionModel__SpvExecutionModelMeshNV: SpvExecutionModel_ = 5268; -pub const SpvExecutionModel__SpvExecutionModelRayGenerationKHR: SpvExecutionModel_ = 5313; -pub const SpvExecutionModel__SpvExecutionModelRayGenerationNV: SpvExecutionModel_ = 5313; -pub const SpvExecutionModel__SpvExecutionModelIntersectionKHR: SpvExecutionModel_ = 5314; -pub const SpvExecutionModel__SpvExecutionModelIntersectionNV: SpvExecutionModel_ = 5314; -pub const SpvExecutionModel__SpvExecutionModelAnyHitKHR: SpvExecutionModel_ = 5315; -pub const SpvExecutionModel__SpvExecutionModelAnyHitNV: SpvExecutionModel_ = 5315; -pub const SpvExecutionModel__SpvExecutionModelClosestHitKHR: SpvExecutionModel_ = 5316; -pub const SpvExecutionModel__SpvExecutionModelClosestHitNV: SpvExecutionModel_ = 5316; -pub const SpvExecutionModel__SpvExecutionModelMissKHR: SpvExecutionModel_ = 5317; -pub const SpvExecutionModel__SpvExecutionModelMissNV: SpvExecutionModel_ = 5317; -pub const SpvExecutionModel__SpvExecutionModelCallableKHR: SpvExecutionModel_ = 5318; -pub const SpvExecutionModel__SpvExecutionModelCallableNV: SpvExecutionModel_ = 5318; -pub const SpvExecutionModel__SpvExecutionModelTaskEXT: SpvExecutionModel_ = 5364; -pub const SpvExecutionModel__SpvExecutionModelMeshEXT: SpvExecutionModel_ = 5365; -pub const SpvExecutionModel__SpvExecutionModelMax: SpvExecutionModel_ = 2147483647; -pub type SpvExecutionModel_ = ::std::os::raw::c_int; -pub use self::SpvExecutionModel_ as SpvExecutionModel; -pub const SpvAddressingModel__SpvAddressingModelLogical: SpvAddressingModel_ = 0; -pub const SpvAddressingModel__SpvAddressingModelPhysical32: SpvAddressingModel_ = 1; -pub const SpvAddressingModel__SpvAddressingModelPhysical64: SpvAddressingModel_ = 2; -pub const SpvAddressingModel__SpvAddressingModelPhysicalStorageBuffer64: SpvAddressingModel_ = 5348; -pub const SpvAddressingModel__SpvAddressingModelPhysicalStorageBuffer64EXT: SpvAddressingModel_ = - 5348; -pub const SpvAddressingModel__SpvAddressingModelMax: SpvAddressingModel_ = 2147483647; -pub type SpvAddressingModel_ = ::std::os::raw::c_int; -pub use self::SpvAddressingModel_ as SpvAddressingModel; -pub const SpvMemoryModel__SpvMemoryModelSimple: SpvMemoryModel_ = 0; -pub const SpvMemoryModel__SpvMemoryModelGLSL450: SpvMemoryModel_ = 1; -pub const SpvMemoryModel__SpvMemoryModelOpenCL: SpvMemoryModel_ = 2; -pub const SpvMemoryModel__SpvMemoryModelVulkan: SpvMemoryModel_ = 3; -pub const SpvMemoryModel__SpvMemoryModelVulkanKHR: SpvMemoryModel_ = 3; -pub const SpvMemoryModel__SpvMemoryModelMax: SpvMemoryModel_ = 2147483647; -pub type SpvMemoryModel_ = ::std::os::raw::c_int; -pub use self::SpvMemoryModel_ as SpvMemoryModel; -pub const SpvExecutionMode__SpvExecutionModeInvocations: SpvExecutionMode_ = 0; -pub const SpvExecutionMode__SpvExecutionModeSpacingEqual: SpvExecutionMode_ = 1; -pub const SpvExecutionMode__SpvExecutionModeSpacingFractionalEven: SpvExecutionMode_ = 2; -pub const SpvExecutionMode__SpvExecutionModeSpacingFractionalOdd: SpvExecutionMode_ = 3; -pub const SpvExecutionMode__SpvExecutionModeVertexOrderCw: SpvExecutionMode_ = 4; -pub const SpvExecutionMode__SpvExecutionModeVertexOrderCcw: SpvExecutionMode_ = 5; -pub const SpvExecutionMode__SpvExecutionModePixelCenterInteger: SpvExecutionMode_ = 6; -pub const SpvExecutionMode__SpvExecutionModeOriginUpperLeft: SpvExecutionMode_ = 7; -pub const SpvExecutionMode__SpvExecutionModeOriginLowerLeft: SpvExecutionMode_ = 8; -pub const SpvExecutionMode__SpvExecutionModeEarlyFragmentTests: SpvExecutionMode_ = 9; -pub const SpvExecutionMode__SpvExecutionModePointMode: SpvExecutionMode_ = 10; -pub const SpvExecutionMode__SpvExecutionModeXfb: SpvExecutionMode_ = 11; -pub const SpvExecutionMode__SpvExecutionModeDepthReplacing: SpvExecutionMode_ = 12; -pub const SpvExecutionMode__SpvExecutionModeDepthGreater: SpvExecutionMode_ = 14; -pub const SpvExecutionMode__SpvExecutionModeDepthLess: SpvExecutionMode_ = 15; -pub const SpvExecutionMode__SpvExecutionModeDepthUnchanged: SpvExecutionMode_ = 16; -pub const SpvExecutionMode__SpvExecutionModeLocalSize: SpvExecutionMode_ = 17; -pub const SpvExecutionMode__SpvExecutionModeLocalSizeHint: SpvExecutionMode_ = 18; -pub const SpvExecutionMode__SpvExecutionModeInputPoints: SpvExecutionMode_ = 19; -pub const SpvExecutionMode__SpvExecutionModeInputLines: SpvExecutionMode_ = 20; -pub const SpvExecutionMode__SpvExecutionModeInputLinesAdjacency: SpvExecutionMode_ = 21; -pub const SpvExecutionMode__SpvExecutionModeTriangles: SpvExecutionMode_ = 22; -pub const SpvExecutionMode__SpvExecutionModeInputTrianglesAdjacency: SpvExecutionMode_ = 23; -pub const SpvExecutionMode__SpvExecutionModeQuads: SpvExecutionMode_ = 24; -pub const SpvExecutionMode__SpvExecutionModeIsolines: SpvExecutionMode_ = 25; -pub const SpvExecutionMode__SpvExecutionModeOutputVertices: SpvExecutionMode_ = 26; -pub const SpvExecutionMode__SpvExecutionModeOutputPoints: SpvExecutionMode_ = 27; -pub const SpvExecutionMode__SpvExecutionModeOutputLineStrip: SpvExecutionMode_ = 28; -pub const SpvExecutionMode__SpvExecutionModeOutputTriangleStrip: SpvExecutionMode_ = 29; -pub const SpvExecutionMode__SpvExecutionModeVecTypeHint: SpvExecutionMode_ = 30; -pub const SpvExecutionMode__SpvExecutionModeContractionOff: SpvExecutionMode_ = 31; -pub const SpvExecutionMode__SpvExecutionModeInitializer: SpvExecutionMode_ = 33; -pub const SpvExecutionMode__SpvExecutionModeFinalizer: SpvExecutionMode_ = 34; -pub const SpvExecutionMode__SpvExecutionModeSubgroupSize: SpvExecutionMode_ = 35; -pub const SpvExecutionMode__SpvExecutionModeSubgroupsPerWorkgroup: SpvExecutionMode_ = 36; -pub const SpvExecutionMode__SpvExecutionModeSubgroupsPerWorkgroupId: SpvExecutionMode_ = 37; -pub const SpvExecutionMode__SpvExecutionModeLocalSizeId: SpvExecutionMode_ = 38; -pub const SpvExecutionMode__SpvExecutionModeLocalSizeHintId: SpvExecutionMode_ = 39; -pub const SpvExecutionMode__SpvExecutionModeNonCoherentColorAttachmentReadEXT: SpvExecutionMode_ = - 4169; -pub const SpvExecutionMode__SpvExecutionModeNonCoherentDepthAttachmentReadEXT: SpvExecutionMode_ = - 4170; -pub const SpvExecutionMode__SpvExecutionModeNonCoherentStencilAttachmentReadEXT: SpvExecutionMode_ = - 4171; -pub const SpvExecutionMode__SpvExecutionModeSubgroupUniformControlFlowKHR: SpvExecutionMode_ = 4421; -pub const SpvExecutionMode__SpvExecutionModePostDepthCoverage: SpvExecutionMode_ = 4446; -pub const SpvExecutionMode__SpvExecutionModeDenormPreserve: SpvExecutionMode_ = 4459; -pub const SpvExecutionMode__SpvExecutionModeDenormFlushToZero: SpvExecutionMode_ = 4460; -pub const SpvExecutionMode__SpvExecutionModeSignedZeroInfNanPreserve: SpvExecutionMode_ = 4461; -pub const SpvExecutionMode__SpvExecutionModeRoundingModeRTE: SpvExecutionMode_ = 4462; -pub const SpvExecutionMode__SpvExecutionModeRoundingModeRTZ: SpvExecutionMode_ = 4463; -pub const SpvExecutionMode__SpvExecutionModeNonCoherentTileAttachmentReadQCOM: SpvExecutionMode_ = - 4489; -pub const SpvExecutionMode__SpvExecutionModeTileShadingRateQCOM: SpvExecutionMode_ = 4490; -pub const SpvExecutionMode__SpvExecutionModeEarlyAndLateFragmentTestsAMD: SpvExecutionMode_ = 5017; -pub const SpvExecutionMode__SpvExecutionModeStencilRefReplacingEXT: SpvExecutionMode_ = 5027; -pub const SpvExecutionMode__SpvExecutionModeCoalescingAMDX: SpvExecutionMode_ = 5069; -pub const SpvExecutionMode__SpvExecutionModeIsApiEntryAMDX: SpvExecutionMode_ = 5070; -pub const SpvExecutionMode__SpvExecutionModeMaxNodeRecursionAMDX: SpvExecutionMode_ = 5071; -pub const SpvExecutionMode__SpvExecutionModeStaticNumWorkgroupsAMDX: SpvExecutionMode_ = 5072; -pub const SpvExecutionMode__SpvExecutionModeShaderIndexAMDX: SpvExecutionMode_ = 5073; -pub const SpvExecutionMode__SpvExecutionModeMaxNumWorkgroupsAMDX: SpvExecutionMode_ = 5077; -pub const SpvExecutionMode__SpvExecutionModeStencilRefUnchangedFrontAMD: SpvExecutionMode_ = 5079; -pub const SpvExecutionMode__SpvExecutionModeStencilRefGreaterFrontAMD: SpvExecutionMode_ = 5080; -pub const SpvExecutionMode__SpvExecutionModeStencilRefLessFrontAMD: SpvExecutionMode_ = 5081; -pub const SpvExecutionMode__SpvExecutionModeStencilRefUnchangedBackAMD: SpvExecutionMode_ = 5082; -pub const SpvExecutionMode__SpvExecutionModeStencilRefGreaterBackAMD: SpvExecutionMode_ = 5083; -pub const SpvExecutionMode__SpvExecutionModeStencilRefLessBackAMD: SpvExecutionMode_ = 5084; -pub const SpvExecutionMode__SpvExecutionModeQuadDerivativesKHR: SpvExecutionMode_ = 5088; -pub const SpvExecutionMode__SpvExecutionModeRequireFullQuadsKHR: SpvExecutionMode_ = 5089; -pub const SpvExecutionMode__SpvExecutionModeSharesInputWithAMDX: SpvExecutionMode_ = 5102; -pub const SpvExecutionMode__SpvExecutionModeOutputLinesEXT: SpvExecutionMode_ = 5269; -pub const SpvExecutionMode__SpvExecutionModeOutputLinesNV: SpvExecutionMode_ = 5269; -pub const SpvExecutionMode__SpvExecutionModeOutputPrimitivesEXT: SpvExecutionMode_ = 5270; -pub const SpvExecutionMode__SpvExecutionModeOutputPrimitivesNV: SpvExecutionMode_ = 5270; -pub const SpvExecutionMode__SpvExecutionModeDerivativeGroupQuadsKHR: SpvExecutionMode_ = 5289; -pub const SpvExecutionMode__SpvExecutionModeDerivativeGroupQuadsNV: SpvExecutionMode_ = 5289; -pub const SpvExecutionMode__SpvExecutionModeDerivativeGroupLinearKHR: SpvExecutionMode_ = 5290; -pub const SpvExecutionMode__SpvExecutionModeDerivativeGroupLinearNV: SpvExecutionMode_ = 5290; -pub const SpvExecutionMode__SpvExecutionModeOutputTrianglesEXT: SpvExecutionMode_ = 5298; -pub const SpvExecutionMode__SpvExecutionModeOutputTrianglesNV: SpvExecutionMode_ = 5298; -pub const SpvExecutionMode__SpvExecutionModePixelInterlockOrderedEXT: SpvExecutionMode_ = 5366; -pub const SpvExecutionMode__SpvExecutionModePixelInterlockUnorderedEXT: SpvExecutionMode_ = 5367; -pub const SpvExecutionMode__SpvExecutionModeSampleInterlockOrderedEXT: SpvExecutionMode_ = 5368; -pub const SpvExecutionMode__SpvExecutionModeSampleInterlockUnorderedEXT: SpvExecutionMode_ = 5369; -pub const SpvExecutionMode__SpvExecutionModeShadingRateInterlockOrderedEXT: SpvExecutionMode_ = - 5370; -pub const SpvExecutionMode__SpvExecutionModeShadingRateInterlockUnorderedEXT: SpvExecutionMode_ = - 5371; -pub const SpvExecutionMode__SpvExecutionModeSharedLocalMemorySizeINTEL: SpvExecutionMode_ = 5618; -pub const SpvExecutionMode__SpvExecutionModeRoundingModeRTPINTEL: SpvExecutionMode_ = 5620; -pub const SpvExecutionMode__SpvExecutionModeRoundingModeRTNINTEL: SpvExecutionMode_ = 5621; -pub const SpvExecutionMode__SpvExecutionModeFloatingPointModeALTINTEL: SpvExecutionMode_ = 5622; -pub const SpvExecutionMode__SpvExecutionModeFloatingPointModeIEEEINTEL: SpvExecutionMode_ = 5623; -pub const SpvExecutionMode__SpvExecutionModeMaxWorkgroupSizeINTEL: SpvExecutionMode_ = 5893; -pub const SpvExecutionMode__SpvExecutionModeMaxWorkDimINTEL: SpvExecutionMode_ = 5894; -pub const SpvExecutionMode__SpvExecutionModeNoGlobalOffsetINTEL: SpvExecutionMode_ = 5895; -pub const SpvExecutionMode__SpvExecutionModeNumSIMDWorkitemsINTEL: SpvExecutionMode_ = 5896; -pub const SpvExecutionMode__SpvExecutionModeSchedulerTargetFmaxMhzINTEL: SpvExecutionMode_ = 5903; -pub const SpvExecutionMode__SpvExecutionModeMaximallyReconvergesKHR: SpvExecutionMode_ = 6023; -pub const SpvExecutionMode__SpvExecutionModeFPFastMathDefault: SpvExecutionMode_ = 6028; -pub const SpvExecutionMode__SpvExecutionModeStreamingInterfaceINTEL: SpvExecutionMode_ = 6154; -pub const SpvExecutionMode__SpvExecutionModeRegisterMapInterfaceINTEL: SpvExecutionMode_ = 6160; -pub const SpvExecutionMode__SpvExecutionModeNamedBarrierCountINTEL: SpvExecutionMode_ = 6417; -pub const SpvExecutionMode__SpvExecutionModeMaximumRegistersINTEL: SpvExecutionMode_ = 6461; -pub const SpvExecutionMode__SpvExecutionModeMaximumRegistersIdINTEL: SpvExecutionMode_ = 6462; -pub const SpvExecutionMode__SpvExecutionModeNamedMaximumRegistersINTEL: SpvExecutionMode_ = 6463; -pub const SpvExecutionMode__SpvExecutionModeMax: SpvExecutionMode_ = 2147483647; -pub type SpvExecutionMode_ = ::std::os::raw::c_int; -pub use self::SpvExecutionMode_ as SpvExecutionMode; -pub const SpvStorageClass__SpvStorageClassUniformConstant: SpvStorageClass_ = 0; -pub const SpvStorageClass__SpvStorageClassInput: SpvStorageClass_ = 1; -pub const SpvStorageClass__SpvStorageClassUniform: SpvStorageClass_ = 2; -pub const SpvStorageClass__SpvStorageClassOutput: SpvStorageClass_ = 3; -pub const SpvStorageClass__SpvStorageClassWorkgroup: SpvStorageClass_ = 4; -pub const SpvStorageClass__SpvStorageClassCrossWorkgroup: SpvStorageClass_ = 5; -pub const SpvStorageClass__SpvStorageClassPrivate: SpvStorageClass_ = 6; -pub const SpvStorageClass__SpvStorageClassFunction: SpvStorageClass_ = 7; -pub const SpvStorageClass__SpvStorageClassGeneric: SpvStorageClass_ = 8; -pub const SpvStorageClass__SpvStorageClassPushConstant: SpvStorageClass_ = 9; -pub const SpvStorageClass__SpvStorageClassAtomicCounter: SpvStorageClass_ = 10; -pub const SpvStorageClass__SpvStorageClassImage: SpvStorageClass_ = 11; -pub const SpvStorageClass__SpvStorageClassStorageBuffer: SpvStorageClass_ = 12; -pub const SpvStorageClass__SpvStorageClassTileImageEXT: SpvStorageClass_ = 4172; -pub const SpvStorageClass__SpvStorageClassTileAttachmentQCOM: SpvStorageClass_ = 4491; -pub const SpvStorageClass__SpvStorageClassNodePayloadAMDX: SpvStorageClass_ = 5068; -pub const SpvStorageClass__SpvStorageClassCallableDataKHR: SpvStorageClass_ = 5328; -pub const SpvStorageClass__SpvStorageClassCallableDataNV: SpvStorageClass_ = 5328; -pub const SpvStorageClass__SpvStorageClassIncomingCallableDataKHR: SpvStorageClass_ = 5329; -pub const SpvStorageClass__SpvStorageClassIncomingCallableDataNV: SpvStorageClass_ = 5329; -pub const SpvStorageClass__SpvStorageClassRayPayloadKHR: SpvStorageClass_ = 5338; -pub const SpvStorageClass__SpvStorageClassRayPayloadNV: SpvStorageClass_ = 5338; -pub const SpvStorageClass__SpvStorageClassHitAttributeKHR: SpvStorageClass_ = 5339; -pub const SpvStorageClass__SpvStorageClassHitAttributeNV: SpvStorageClass_ = 5339; -pub const SpvStorageClass__SpvStorageClassIncomingRayPayloadKHR: SpvStorageClass_ = 5342; -pub const SpvStorageClass__SpvStorageClassIncomingRayPayloadNV: SpvStorageClass_ = 5342; -pub const SpvStorageClass__SpvStorageClassShaderRecordBufferKHR: SpvStorageClass_ = 5343; -pub const SpvStorageClass__SpvStorageClassShaderRecordBufferNV: SpvStorageClass_ = 5343; -pub const SpvStorageClass__SpvStorageClassPhysicalStorageBuffer: SpvStorageClass_ = 5349; -pub const SpvStorageClass__SpvStorageClassPhysicalStorageBufferEXT: SpvStorageClass_ = 5349; -pub const SpvStorageClass__SpvStorageClassHitObjectAttributeNV: SpvStorageClass_ = 5385; -pub const SpvStorageClass__SpvStorageClassTaskPayloadWorkgroupEXT: SpvStorageClass_ = 5402; -pub const SpvStorageClass__SpvStorageClassCodeSectionINTEL: SpvStorageClass_ = 5605; -pub const SpvStorageClass__SpvStorageClassDeviceOnlyINTEL: SpvStorageClass_ = 5936; -pub const SpvStorageClass__SpvStorageClassHostOnlyINTEL: SpvStorageClass_ = 5937; -pub const SpvStorageClass__SpvStorageClassMax: SpvStorageClass_ = 2147483647; -pub type SpvStorageClass_ = ::std::os::raw::c_int; -pub use self::SpvStorageClass_ as SpvStorageClass; -pub const SpvDim__SpvDim1D: SpvDim_ = 0; -pub const SpvDim__SpvDim2D: SpvDim_ = 1; -pub const SpvDim__SpvDim3D: SpvDim_ = 2; -pub const SpvDim__SpvDimCube: SpvDim_ = 3; -pub const SpvDim__SpvDimRect: SpvDim_ = 4; -pub const SpvDim__SpvDimBuffer: SpvDim_ = 5; -pub const SpvDim__SpvDimSubpassData: SpvDim_ = 6; -pub const SpvDim__SpvDimTileImageDataEXT: SpvDim_ = 4173; -pub const SpvDim__SpvDimMax: SpvDim_ = 2147483647; -pub type SpvDim_ = ::std::os::raw::c_int; -pub use self::SpvDim_ as SpvDim; -pub const SpvSamplerAddressingMode__SpvSamplerAddressingModeNone: SpvSamplerAddressingMode_ = 0; -pub const SpvSamplerAddressingMode__SpvSamplerAddressingModeClampToEdge: SpvSamplerAddressingMode_ = - 1; -pub const SpvSamplerAddressingMode__SpvSamplerAddressingModeClamp: SpvSamplerAddressingMode_ = 2; -pub const SpvSamplerAddressingMode__SpvSamplerAddressingModeRepeat: SpvSamplerAddressingMode_ = 3; -pub const SpvSamplerAddressingMode__SpvSamplerAddressingModeRepeatMirrored: - SpvSamplerAddressingMode_ = 4; -pub const SpvSamplerAddressingMode__SpvSamplerAddressingModeMax: SpvSamplerAddressingMode_ = - 2147483647; -pub type SpvSamplerAddressingMode_ = ::std::os::raw::c_int; -pub use self::SpvSamplerAddressingMode_ as SpvSamplerAddressingMode; -pub const SpvSamplerFilterMode__SpvSamplerFilterModeNearest: SpvSamplerFilterMode_ = 0; -pub const SpvSamplerFilterMode__SpvSamplerFilterModeLinear: SpvSamplerFilterMode_ = 1; -pub const SpvSamplerFilterMode__SpvSamplerFilterModeMax: SpvSamplerFilterMode_ = 2147483647; -pub type SpvSamplerFilterMode_ = ::std::os::raw::c_int; -pub use self::SpvSamplerFilterMode_ as SpvSamplerFilterMode; -pub const SpvImageFormat__SpvImageFormatUnknown: SpvImageFormat_ = 0; -pub const SpvImageFormat__SpvImageFormatRgba32f: SpvImageFormat_ = 1; -pub const SpvImageFormat__SpvImageFormatRgba16f: SpvImageFormat_ = 2; -pub const SpvImageFormat__SpvImageFormatR32f: SpvImageFormat_ = 3; -pub const SpvImageFormat__SpvImageFormatRgba8: SpvImageFormat_ = 4; -pub const SpvImageFormat__SpvImageFormatRgba8Snorm: SpvImageFormat_ = 5; -pub const SpvImageFormat__SpvImageFormatRg32f: SpvImageFormat_ = 6; -pub const SpvImageFormat__SpvImageFormatRg16f: SpvImageFormat_ = 7; -pub const SpvImageFormat__SpvImageFormatR11fG11fB10f: SpvImageFormat_ = 8; -pub const SpvImageFormat__SpvImageFormatR16f: SpvImageFormat_ = 9; -pub const SpvImageFormat__SpvImageFormatRgba16: SpvImageFormat_ = 10; -pub const SpvImageFormat__SpvImageFormatRgb10A2: SpvImageFormat_ = 11; -pub const SpvImageFormat__SpvImageFormatRg16: SpvImageFormat_ = 12; -pub const SpvImageFormat__SpvImageFormatRg8: SpvImageFormat_ = 13; -pub const SpvImageFormat__SpvImageFormatR16: SpvImageFormat_ = 14; -pub const SpvImageFormat__SpvImageFormatR8: SpvImageFormat_ = 15; -pub const SpvImageFormat__SpvImageFormatRgba16Snorm: SpvImageFormat_ = 16; -pub const SpvImageFormat__SpvImageFormatRg16Snorm: SpvImageFormat_ = 17; -pub const SpvImageFormat__SpvImageFormatRg8Snorm: SpvImageFormat_ = 18; -pub const SpvImageFormat__SpvImageFormatR16Snorm: SpvImageFormat_ = 19; -pub const SpvImageFormat__SpvImageFormatR8Snorm: SpvImageFormat_ = 20; -pub const SpvImageFormat__SpvImageFormatRgba32i: SpvImageFormat_ = 21; -pub const SpvImageFormat__SpvImageFormatRgba16i: SpvImageFormat_ = 22; -pub const SpvImageFormat__SpvImageFormatRgba8i: SpvImageFormat_ = 23; -pub const SpvImageFormat__SpvImageFormatR32i: SpvImageFormat_ = 24; -pub const SpvImageFormat__SpvImageFormatRg32i: SpvImageFormat_ = 25; -pub const SpvImageFormat__SpvImageFormatRg16i: SpvImageFormat_ = 26; -pub const SpvImageFormat__SpvImageFormatRg8i: SpvImageFormat_ = 27; -pub const SpvImageFormat__SpvImageFormatR16i: SpvImageFormat_ = 28; -pub const SpvImageFormat__SpvImageFormatR8i: SpvImageFormat_ = 29; -pub const SpvImageFormat__SpvImageFormatRgba32ui: SpvImageFormat_ = 30; -pub const SpvImageFormat__SpvImageFormatRgba16ui: SpvImageFormat_ = 31; -pub const SpvImageFormat__SpvImageFormatRgba8ui: SpvImageFormat_ = 32; -pub const SpvImageFormat__SpvImageFormatR32ui: SpvImageFormat_ = 33; -pub const SpvImageFormat__SpvImageFormatRgb10a2ui: SpvImageFormat_ = 34; -pub const SpvImageFormat__SpvImageFormatRg32ui: SpvImageFormat_ = 35; -pub const SpvImageFormat__SpvImageFormatRg16ui: SpvImageFormat_ = 36; -pub const SpvImageFormat__SpvImageFormatRg8ui: SpvImageFormat_ = 37; -pub const SpvImageFormat__SpvImageFormatR16ui: SpvImageFormat_ = 38; -pub const SpvImageFormat__SpvImageFormatR8ui: SpvImageFormat_ = 39; -pub const SpvImageFormat__SpvImageFormatR64ui: SpvImageFormat_ = 40; -pub const SpvImageFormat__SpvImageFormatR64i: SpvImageFormat_ = 41; -pub const SpvImageFormat__SpvImageFormatMax: SpvImageFormat_ = 2147483647; -pub type SpvImageFormat_ = ::std::os::raw::c_int; -pub use self::SpvImageFormat_ as SpvImageFormat; -pub const SpvImageChannelOrder__SpvImageChannelOrderR: SpvImageChannelOrder_ = 0; -pub const SpvImageChannelOrder__SpvImageChannelOrderA: SpvImageChannelOrder_ = 1; -pub const SpvImageChannelOrder__SpvImageChannelOrderRG: SpvImageChannelOrder_ = 2; -pub const SpvImageChannelOrder__SpvImageChannelOrderRA: SpvImageChannelOrder_ = 3; -pub const SpvImageChannelOrder__SpvImageChannelOrderRGB: SpvImageChannelOrder_ = 4; -pub const SpvImageChannelOrder__SpvImageChannelOrderRGBA: SpvImageChannelOrder_ = 5; -pub const SpvImageChannelOrder__SpvImageChannelOrderBGRA: SpvImageChannelOrder_ = 6; -pub const SpvImageChannelOrder__SpvImageChannelOrderARGB: SpvImageChannelOrder_ = 7; -pub const SpvImageChannelOrder__SpvImageChannelOrderIntensity: SpvImageChannelOrder_ = 8; -pub const SpvImageChannelOrder__SpvImageChannelOrderLuminance: SpvImageChannelOrder_ = 9; -pub const SpvImageChannelOrder__SpvImageChannelOrderRx: SpvImageChannelOrder_ = 10; -pub const SpvImageChannelOrder__SpvImageChannelOrderRGx: SpvImageChannelOrder_ = 11; -pub const SpvImageChannelOrder__SpvImageChannelOrderRGBx: SpvImageChannelOrder_ = 12; -pub const SpvImageChannelOrder__SpvImageChannelOrderDepth: SpvImageChannelOrder_ = 13; -pub const SpvImageChannelOrder__SpvImageChannelOrderDepthStencil: SpvImageChannelOrder_ = 14; -pub const SpvImageChannelOrder__SpvImageChannelOrdersRGB: SpvImageChannelOrder_ = 15; -pub const SpvImageChannelOrder__SpvImageChannelOrdersRGBx: SpvImageChannelOrder_ = 16; -pub const SpvImageChannelOrder__SpvImageChannelOrdersRGBA: SpvImageChannelOrder_ = 17; -pub const SpvImageChannelOrder__SpvImageChannelOrdersBGRA: SpvImageChannelOrder_ = 18; -pub const SpvImageChannelOrder__SpvImageChannelOrderABGR: SpvImageChannelOrder_ = 19; -pub const SpvImageChannelOrder__SpvImageChannelOrderMax: SpvImageChannelOrder_ = 2147483647; -pub type SpvImageChannelOrder_ = ::std::os::raw::c_int; -pub use self::SpvImageChannelOrder_ as SpvImageChannelOrder; -pub const SpvImageChannelDataType__SpvImageChannelDataTypeSnormInt8: SpvImageChannelDataType_ = 0; -pub const SpvImageChannelDataType__SpvImageChannelDataTypeSnormInt16: SpvImageChannelDataType_ = 1; -pub const SpvImageChannelDataType__SpvImageChannelDataTypeUnormInt8: SpvImageChannelDataType_ = 2; -pub const SpvImageChannelDataType__SpvImageChannelDataTypeUnormInt16: SpvImageChannelDataType_ = 3; -pub const SpvImageChannelDataType__SpvImageChannelDataTypeUnormShort565: SpvImageChannelDataType_ = - 4; -pub const SpvImageChannelDataType__SpvImageChannelDataTypeUnormShort555: SpvImageChannelDataType_ = - 5; -pub const SpvImageChannelDataType__SpvImageChannelDataTypeUnormInt101010: SpvImageChannelDataType_ = - 6; -pub const SpvImageChannelDataType__SpvImageChannelDataTypeSignedInt8: SpvImageChannelDataType_ = 7; -pub const SpvImageChannelDataType__SpvImageChannelDataTypeSignedInt16: SpvImageChannelDataType_ = 8; -pub const SpvImageChannelDataType__SpvImageChannelDataTypeSignedInt32: SpvImageChannelDataType_ = 9; -pub const SpvImageChannelDataType__SpvImageChannelDataTypeUnsignedInt8: SpvImageChannelDataType_ = - 10; -pub const SpvImageChannelDataType__SpvImageChannelDataTypeUnsignedInt16: SpvImageChannelDataType_ = - 11; -pub const SpvImageChannelDataType__SpvImageChannelDataTypeUnsignedInt32: SpvImageChannelDataType_ = - 12; -pub const SpvImageChannelDataType__SpvImageChannelDataTypeHalfFloat: SpvImageChannelDataType_ = 13; -pub const SpvImageChannelDataType__SpvImageChannelDataTypeFloat: SpvImageChannelDataType_ = 14; -pub const SpvImageChannelDataType__SpvImageChannelDataTypeUnormInt24: SpvImageChannelDataType_ = 15; -pub const SpvImageChannelDataType__SpvImageChannelDataTypeUnormInt101010_2: - SpvImageChannelDataType_ = 16; -pub const SpvImageChannelDataType__SpvImageChannelDataTypeUnormInt10X6EXT: - SpvImageChannelDataType_ = 17; -pub const SpvImageChannelDataType__SpvImageChannelDataTypeUnsignedIntRaw10EXT: - SpvImageChannelDataType_ = 19; -pub const SpvImageChannelDataType__SpvImageChannelDataTypeUnsignedIntRaw12EXT: - SpvImageChannelDataType_ = 20; -pub const SpvImageChannelDataType__SpvImageChannelDataTypeUnormInt2_101010EXT: - SpvImageChannelDataType_ = 21; -pub const SpvImageChannelDataType__SpvImageChannelDataTypeUnsignedInt10X6EXT: - SpvImageChannelDataType_ = 22; -pub const SpvImageChannelDataType__SpvImageChannelDataTypeUnsignedInt12X4EXT: - SpvImageChannelDataType_ = 23; -pub const SpvImageChannelDataType__SpvImageChannelDataTypeUnsignedInt14X2EXT: - SpvImageChannelDataType_ = 24; -pub const SpvImageChannelDataType__SpvImageChannelDataTypeUnormInt12X4EXT: - SpvImageChannelDataType_ = 25; -pub const SpvImageChannelDataType__SpvImageChannelDataTypeUnormInt14X2EXT: - SpvImageChannelDataType_ = 26; -pub const SpvImageChannelDataType__SpvImageChannelDataTypeMax: SpvImageChannelDataType_ = - 2147483647; -pub type SpvImageChannelDataType_ = ::std::os::raw::c_int; -pub use self::SpvImageChannelDataType_ as SpvImageChannelDataType; -pub const SpvImageOperandsShift__SpvImageOperandsBiasShift: SpvImageOperandsShift_ = 0; -pub const SpvImageOperandsShift__SpvImageOperandsLodShift: SpvImageOperandsShift_ = 1; -pub const SpvImageOperandsShift__SpvImageOperandsGradShift: SpvImageOperandsShift_ = 2; -pub const SpvImageOperandsShift__SpvImageOperandsConstOffsetShift: SpvImageOperandsShift_ = 3; -pub const SpvImageOperandsShift__SpvImageOperandsOffsetShift: SpvImageOperandsShift_ = 4; -pub const SpvImageOperandsShift__SpvImageOperandsConstOffsetsShift: SpvImageOperandsShift_ = 5; -pub const SpvImageOperandsShift__SpvImageOperandsSampleShift: SpvImageOperandsShift_ = 6; -pub const SpvImageOperandsShift__SpvImageOperandsMinLodShift: SpvImageOperandsShift_ = 7; -pub const SpvImageOperandsShift__SpvImageOperandsMakeTexelAvailableShift: SpvImageOperandsShift_ = - 8; -pub const SpvImageOperandsShift__SpvImageOperandsMakeTexelAvailableKHRShift: - SpvImageOperandsShift_ = 8; -pub const SpvImageOperandsShift__SpvImageOperandsMakeTexelVisibleShift: SpvImageOperandsShift_ = 9; -pub const SpvImageOperandsShift__SpvImageOperandsMakeTexelVisibleKHRShift: SpvImageOperandsShift_ = - 9; -pub const SpvImageOperandsShift__SpvImageOperandsNonPrivateTexelShift: SpvImageOperandsShift_ = 10; -pub const SpvImageOperandsShift__SpvImageOperandsNonPrivateTexelKHRShift: SpvImageOperandsShift_ = - 10; -pub const SpvImageOperandsShift__SpvImageOperandsVolatileTexelShift: SpvImageOperandsShift_ = 11; -pub const SpvImageOperandsShift__SpvImageOperandsVolatileTexelKHRShift: SpvImageOperandsShift_ = 11; -pub const SpvImageOperandsShift__SpvImageOperandsSignExtendShift: SpvImageOperandsShift_ = 12; -pub const SpvImageOperandsShift__SpvImageOperandsZeroExtendShift: SpvImageOperandsShift_ = 13; -pub const SpvImageOperandsShift__SpvImageOperandsNontemporalShift: SpvImageOperandsShift_ = 14; -pub const SpvImageOperandsShift__SpvImageOperandsOffsetsShift: SpvImageOperandsShift_ = 16; -pub const SpvImageOperandsShift__SpvImageOperandsMax: SpvImageOperandsShift_ = 2147483647; -pub type SpvImageOperandsShift_ = ::std::os::raw::c_int; -pub use self::SpvImageOperandsShift_ as SpvImageOperandsShift; -pub const SpvImageOperandsMask__SpvImageOperandsMaskNone: SpvImageOperandsMask_ = 0; -pub const SpvImageOperandsMask__SpvImageOperandsBiasMask: SpvImageOperandsMask_ = 1; -pub const SpvImageOperandsMask__SpvImageOperandsLodMask: SpvImageOperandsMask_ = 2; -pub const SpvImageOperandsMask__SpvImageOperandsGradMask: SpvImageOperandsMask_ = 4; -pub const SpvImageOperandsMask__SpvImageOperandsConstOffsetMask: SpvImageOperandsMask_ = 8; -pub const SpvImageOperandsMask__SpvImageOperandsOffsetMask: SpvImageOperandsMask_ = 16; -pub const SpvImageOperandsMask__SpvImageOperandsConstOffsetsMask: SpvImageOperandsMask_ = 32; -pub const SpvImageOperandsMask__SpvImageOperandsSampleMask: SpvImageOperandsMask_ = 64; -pub const SpvImageOperandsMask__SpvImageOperandsMinLodMask: SpvImageOperandsMask_ = 128; -pub const SpvImageOperandsMask__SpvImageOperandsMakeTexelAvailableMask: SpvImageOperandsMask_ = 256; -pub const SpvImageOperandsMask__SpvImageOperandsMakeTexelAvailableKHRMask: SpvImageOperandsMask_ = - 256; -pub const SpvImageOperandsMask__SpvImageOperandsMakeTexelVisibleMask: SpvImageOperandsMask_ = 512; -pub const SpvImageOperandsMask__SpvImageOperandsMakeTexelVisibleKHRMask: SpvImageOperandsMask_ = - 512; -pub const SpvImageOperandsMask__SpvImageOperandsNonPrivateTexelMask: SpvImageOperandsMask_ = 1024; -pub const SpvImageOperandsMask__SpvImageOperandsNonPrivateTexelKHRMask: SpvImageOperandsMask_ = - 1024; -pub const SpvImageOperandsMask__SpvImageOperandsVolatileTexelMask: SpvImageOperandsMask_ = 2048; -pub const SpvImageOperandsMask__SpvImageOperandsVolatileTexelKHRMask: SpvImageOperandsMask_ = 2048; -pub const SpvImageOperandsMask__SpvImageOperandsSignExtendMask: SpvImageOperandsMask_ = 4096; -pub const SpvImageOperandsMask__SpvImageOperandsZeroExtendMask: SpvImageOperandsMask_ = 8192; -pub const SpvImageOperandsMask__SpvImageOperandsNontemporalMask: SpvImageOperandsMask_ = 16384; -pub const SpvImageOperandsMask__SpvImageOperandsOffsetsMask: SpvImageOperandsMask_ = 65536; -pub type SpvImageOperandsMask_ = ::std::os::raw::c_int; -pub use self::SpvImageOperandsMask_ as SpvImageOperandsMask; -pub const SpvFPFastMathModeShift__SpvFPFastMathModeNotNaNShift: SpvFPFastMathModeShift_ = 0; -pub const SpvFPFastMathModeShift__SpvFPFastMathModeNotInfShift: SpvFPFastMathModeShift_ = 1; -pub const SpvFPFastMathModeShift__SpvFPFastMathModeNSZShift: SpvFPFastMathModeShift_ = 2; -pub const SpvFPFastMathModeShift__SpvFPFastMathModeAllowRecipShift: SpvFPFastMathModeShift_ = 3; -pub const SpvFPFastMathModeShift__SpvFPFastMathModeFastShift: SpvFPFastMathModeShift_ = 4; -pub const SpvFPFastMathModeShift__SpvFPFastMathModeAllowContractShift: SpvFPFastMathModeShift_ = 16; -pub const SpvFPFastMathModeShift__SpvFPFastMathModeAllowContractFastINTELShift: - SpvFPFastMathModeShift_ = 16; -pub const SpvFPFastMathModeShift__SpvFPFastMathModeAllowReassocShift: SpvFPFastMathModeShift_ = 17; -pub const SpvFPFastMathModeShift__SpvFPFastMathModeAllowReassocINTELShift: SpvFPFastMathModeShift_ = - 17; -pub const SpvFPFastMathModeShift__SpvFPFastMathModeAllowTransformShift: SpvFPFastMathModeShift_ = - 18; -pub const SpvFPFastMathModeShift__SpvFPFastMathModeMax: SpvFPFastMathModeShift_ = 2147483647; -pub type SpvFPFastMathModeShift_ = ::std::os::raw::c_int; -pub use self::SpvFPFastMathModeShift_ as SpvFPFastMathModeShift; -pub const SpvFPFastMathModeMask__SpvFPFastMathModeMaskNone: SpvFPFastMathModeMask_ = 0; -pub const SpvFPFastMathModeMask__SpvFPFastMathModeNotNaNMask: SpvFPFastMathModeMask_ = 1; -pub const SpvFPFastMathModeMask__SpvFPFastMathModeNotInfMask: SpvFPFastMathModeMask_ = 2; -pub const SpvFPFastMathModeMask__SpvFPFastMathModeNSZMask: SpvFPFastMathModeMask_ = 4; -pub const SpvFPFastMathModeMask__SpvFPFastMathModeAllowRecipMask: SpvFPFastMathModeMask_ = 8; -pub const SpvFPFastMathModeMask__SpvFPFastMathModeFastMask: SpvFPFastMathModeMask_ = 16; -pub const SpvFPFastMathModeMask__SpvFPFastMathModeAllowContractMask: SpvFPFastMathModeMask_ = 65536; -pub const SpvFPFastMathModeMask__SpvFPFastMathModeAllowContractFastINTELMask: - SpvFPFastMathModeMask_ = 65536; -pub const SpvFPFastMathModeMask__SpvFPFastMathModeAllowReassocMask: SpvFPFastMathModeMask_ = 131072; -pub const SpvFPFastMathModeMask__SpvFPFastMathModeAllowReassocINTELMask: SpvFPFastMathModeMask_ = - 131072; -pub const SpvFPFastMathModeMask__SpvFPFastMathModeAllowTransformMask: SpvFPFastMathModeMask_ = - 262144; -pub type SpvFPFastMathModeMask_ = ::std::os::raw::c_int; -pub use self::SpvFPFastMathModeMask_ as SpvFPFastMathModeMask; -pub const SpvFPRoundingMode__SpvFPRoundingModeRTE: SpvFPRoundingMode_ = 0; -pub const SpvFPRoundingMode__SpvFPRoundingModeRTZ: SpvFPRoundingMode_ = 1; -pub const SpvFPRoundingMode__SpvFPRoundingModeRTP: SpvFPRoundingMode_ = 2; -pub const SpvFPRoundingMode__SpvFPRoundingModeRTN: SpvFPRoundingMode_ = 3; -pub const SpvFPRoundingMode__SpvFPRoundingModeMax: SpvFPRoundingMode_ = 2147483647; -pub type SpvFPRoundingMode_ = ::std::os::raw::c_int; -pub use self::SpvFPRoundingMode_ as SpvFPRoundingMode; -pub const SpvLinkageType__SpvLinkageTypeExport: SpvLinkageType_ = 0; -pub const SpvLinkageType__SpvLinkageTypeImport: SpvLinkageType_ = 1; -pub const SpvLinkageType__SpvLinkageTypeLinkOnceODR: SpvLinkageType_ = 2; -pub const SpvLinkageType__SpvLinkageTypeMax: SpvLinkageType_ = 2147483647; -pub type SpvLinkageType_ = ::std::os::raw::c_int; -pub use self::SpvLinkageType_ as SpvLinkageType; -pub const SpvAccessQualifier__SpvAccessQualifierReadOnly: SpvAccessQualifier_ = 0; -pub const SpvAccessQualifier__SpvAccessQualifierWriteOnly: SpvAccessQualifier_ = 1; -pub const SpvAccessQualifier__SpvAccessQualifierReadWrite: SpvAccessQualifier_ = 2; -pub const SpvAccessQualifier__SpvAccessQualifierMax: SpvAccessQualifier_ = 2147483647; -pub type SpvAccessQualifier_ = ::std::os::raw::c_int; -pub use self::SpvAccessQualifier_ as SpvAccessQualifier; -pub const SpvFunctionParameterAttribute__SpvFunctionParameterAttributeZext: - SpvFunctionParameterAttribute_ = 0; -pub const SpvFunctionParameterAttribute__SpvFunctionParameterAttributeSext: - SpvFunctionParameterAttribute_ = 1; -pub const SpvFunctionParameterAttribute__SpvFunctionParameterAttributeByVal: - SpvFunctionParameterAttribute_ = 2; -pub const SpvFunctionParameterAttribute__SpvFunctionParameterAttributeSret: - SpvFunctionParameterAttribute_ = 3; -pub const SpvFunctionParameterAttribute__SpvFunctionParameterAttributeNoAlias: - SpvFunctionParameterAttribute_ = 4; -pub const SpvFunctionParameterAttribute__SpvFunctionParameterAttributeNoCapture: - SpvFunctionParameterAttribute_ = 5; -pub const SpvFunctionParameterAttribute__SpvFunctionParameterAttributeNoWrite: - SpvFunctionParameterAttribute_ = 6; -pub const SpvFunctionParameterAttribute__SpvFunctionParameterAttributeNoReadWrite: - SpvFunctionParameterAttribute_ = 7; -pub const SpvFunctionParameterAttribute__SpvFunctionParameterAttributeRuntimeAlignedINTEL: - SpvFunctionParameterAttribute_ = 5940; -pub const SpvFunctionParameterAttribute__SpvFunctionParameterAttributeMax: - SpvFunctionParameterAttribute_ = 2147483647; -pub type SpvFunctionParameterAttribute_ = ::std::os::raw::c_int; -pub use self::SpvFunctionParameterAttribute_ as SpvFunctionParameterAttribute; -pub const SpvDecoration__SpvDecorationRelaxedPrecision: SpvDecoration_ = 0; -pub const SpvDecoration__SpvDecorationSpecId: SpvDecoration_ = 1; -pub const SpvDecoration__SpvDecorationBlock: SpvDecoration_ = 2; -pub const SpvDecoration__SpvDecorationBufferBlock: SpvDecoration_ = 3; -pub const SpvDecoration__SpvDecorationRowMajor: SpvDecoration_ = 4; -pub const SpvDecoration__SpvDecorationColMajor: SpvDecoration_ = 5; -pub const SpvDecoration__SpvDecorationArrayStride: SpvDecoration_ = 6; -pub const SpvDecoration__SpvDecorationMatrixStride: SpvDecoration_ = 7; -pub const SpvDecoration__SpvDecorationGLSLShared: SpvDecoration_ = 8; -pub const SpvDecoration__SpvDecorationGLSLPacked: SpvDecoration_ = 9; -pub const SpvDecoration__SpvDecorationCPacked: SpvDecoration_ = 10; -pub const SpvDecoration__SpvDecorationBuiltIn: SpvDecoration_ = 11; -pub const SpvDecoration__SpvDecorationNoPerspective: SpvDecoration_ = 13; -pub const SpvDecoration__SpvDecorationFlat: SpvDecoration_ = 14; -pub const SpvDecoration__SpvDecorationPatch: SpvDecoration_ = 15; -pub const SpvDecoration__SpvDecorationCentroid: SpvDecoration_ = 16; -pub const SpvDecoration__SpvDecorationSample: SpvDecoration_ = 17; -pub const SpvDecoration__SpvDecorationInvariant: SpvDecoration_ = 18; -pub const SpvDecoration__SpvDecorationRestrict: SpvDecoration_ = 19; -pub const SpvDecoration__SpvDecorationAliased: SpvDecoration_ = 20; -pub const SpvDecoration__SpvDecorationVolatile: SpvDecoration_ = 21; -pub const SpvDecoration__SpvDecorationConstant: SpvDecoration_ = 22; -pub const SpvDecoration__SpvDecorationCoherent: SpvDecoration_ = 23; -pub const SpvDecoration__SpvDecorationNonWritable: SpvDecoration_ = 24; -pub const SpvDecoration__SpvDecorationNonReadable: SpvDecoration_ = 25; -pub const SpvDecoration__SpvDecorationUniform: SpvDecoration_ = 26; -pub const SpvDecoration__SpvDecorationUniformId: SpvDecoration_ = 27; -pub const SpvDecoration__SpvDecorationSaturatedConversion: SpvDecoration_ = 28; -pub const SpvDecoration__SpvDecorationStream: SpvDecoration_ = 29; -pub const SpvDecoration__SpvDecorationLocation: SpvDecoration_ = 30; -pub const SpvDecoration__SpvDecorationComponent: SpvDecoration_ = 31; -pub const SpvDecoration__SpvDecorationIndex: SpvDecoration_ = 32; -pub const SpvDecoration__SpvDecorationBinding: SpvDecoration_ = 33; -pub const SpvDecoration__SpvDecorationDescriptorSet: SpvDecoration_ = 34; -pub const SpvDecoration__SpvDecorationOffset: SpvDecoration_ = 35; -pub const SpvDecoration__SpvDecorationXfbBuffer: SpvDecoration_ = 36; -pub const SpvDecoration__SpvDecorationXfbStride: SpvDecoration_ = 37; -pub const SpvDecoration__SpvDecorationFuncParamAttr: SpvDecoration_ = 38; -pub const SpvDecoration__SpvDecorationFPRoundingMode: SpvDecoration_ = 39; -pub const SpvDecoration__SpvDecorationFPFastMathMode: SpvDecoration_ = 40; -pub const SpvDecoration__SpvDecorationLinkageAttributes: SpvDecoration_ = 41; -pub const SpvDecoration__SpvDecorationNoContraction: SpvDecoration_ = 42; -pub const SpvDecoration__SpvDecorationInputAttachmentIndex: SpvDecoration_ = 43; -pub const SpvDecoration__SpvDecorationAlignment: SpvDecoration_ = 44; -pub const SpvDecoration__SpvDecorationMaxByteOffset: SpvDecoration_ = 45; -pub const SpvDecoration__SpvDecorationAlignmentId: SpvDecoration_ = 46; -pub const SpvDecoration__SpvDecorationMaxByteOffsetId: SpvDecoration_ = 47; -pub const SpvDecoration__SpvDecorationSaturatedToLargestFloat8NormalConversionEXT: SpvDecoration_ = - 4216; -pub const SpvDecoration__SpvDecorationNoSignedWrap: SpvDecoration_ = 4469; -pub const SpvDecoration__SpvDecorationNoUnsignedWrap: SpvDecoration_ = 4470; -pub const SpvDecoration__SpvDecorationWeightTextureQCOM: SpvDecoration_ = 4487; -pub const SpvDecoration__SpvDecorationBlockMatchTextureQCOM: SpvDecoration_ = 4488; -pub const SpvDecoration__SpvDecorationBlockMatchSamplerQCOM: SpvDecoration_ = 4499; -pub const SpvDecoration__SpvDecorationExplicitInterpAMD: SpvDecoration_ = 4999; -pub const SpvDecoration__SpvDecorationNodeSharesPayloadLimitsWithAMDX: SpvDecoration_ = 5019; -pub const SpvDecoration__SpvDecorationNodeMaxPayloadsAMDX: SpvDecoration_ = 5020; -pub const SpvDecoration__SpvDecorationTrackFinishWritingAMDX: SpvDecoration_ = 5078; -pub const SpvDecoration__SpvDecorationPayloadNodeNameAMDX: SpvDecoration_ = 5091; -pub const SpvDecoration__SpvDecorationPayloadNodeBaseIndexAMDX: SpvDecoration_ = 5098; -pub const SpvDecoration__SpvDecorationPayloadNodeSparseArrayAMDX: SpvDecoration_ = 5099; -pub const SpvDecoration__SpvDecorationPayloadNodeArraySizeAMDX: SpvDecoration_ = 5100; -pub const SpvDecoration__SpvDecorationPayloadDispatchIndirectAMDX: SpvDecoration_ = 5105; -pub const SpvDecoration__SpvDecorationOverrideCoverageNV: SpvDecoration_ = 5248; -pub const SpvDecoration__SpvDecorationPassthroughNV: SpvDecoration_ = 5250; -pub const SpvDecoration__SpvDecorationViewportRelativeNV: SpvDecoration_ = 5252; -pub const SpvDecoration__SpvDecorationSecondaryViewportRelativeNV: SpvDecoration_ = 5256; -pub const SpvDecoration__SpvDecorationPerPrimitiveEXT: SpvDecoration_ = 5271; -pub const SpvDecoration__SpvDecorationPerPrimitiveNV: SpvDecoration_ = 5271; -pub const SpvDecoration__SpvDecorationPerViewNV: SpvDecoration_ = 5272; -pub const SpvDecoration__SpvDecorationPerTaskNV: SpvDecoration_ = 5273; -pub const SpvDecoration__SpvDecorationPerVertexKHR: SpvDecoration_ = 5285; -pub const SpvDecoration__SpvDecorationPerVertexNV: SpvDecoration_ = 5285; -pub const SpvDecoration__SpvDecorationNonUniform: SpvDecoration_ = 5300; -pub const SpvDecoration__SpvDecorationNonUniformEXT: SpvDecoration_ = 5300; -pub const SpvDecoration__SpvDecorationRestrictPointer: SpvDecoration_ = 5355; -pub const SpvDecoration__SpvDecorationRestrictPointerEXT: SpvDecoration_ = 5355; -pub const SpvDecoration__SpvDecorationAliasedPointer: SpvDecoration_ = 5356; -pub const SpvDecoration__SpvDecorationAliasedPointerEXT: SpvDecoration_ = 5356; -pub const SpvDecoration__SpvDecorationHitObjectShaderRecordBufferNV: SpvDecoration_ = 5386; -pub const SpvDecoration__SpvDecorationBindlessSamplerNV: SpvDecoration_ = 5398; -pub const SpvDecoration__SpvDecorationBindlessImageNV: SpvDecoration_ = 5399; -pub const SpvDecoration__SpvDecorationBoundSamplerNV: SpvDecoration_ = 5400; -pub const SpvDecoration__SpvDecorationBoundImageNV: SpvDecoration_ = 5401; -pub const SpvDecoration__SpvDecorationSIMTCallINTEL: SpvDecoration_ = 5599; -pub const SpvDecoration__SpvDecorationReferencedIndirectlyINTEL: SpvDecoration_ = 5602; -pub const SpvDecoration__SpvDecorationClobberINTEL: SpvDecoration_ = 5607; -pub const SpvDecoration__SpvDecorationSideEffectsINTEL: SpvDecoration_ = 5608; -pub const SpvDecoration__SpvDecorationVectorComputeVariableINTEL: SpvDecoration_ = 5624; -pub const SpvDecoration__SpvDecorationFuncParamIOKindINTEL: SpvDecoration_ = 5625; -pub const SpvDecoration__SpvDecorationVectorComputeFunctionINTEL: SpvDecoration_ = 5626; -pub const SpvDecoration__SpvDecorationStackCallINTEL: SpvDecoration_ = 5627; -pub const SpvDecoration__SpvDecorationGlobalVariableOffsetINTEL: SpvDecoration_ = 5628; -pub const SpvDecoration__SpvDecorationCounterBuffer: SpvDecoration_ = 5634; -pub const SpvDecoration__SpvDecorationHlslCounterBufferGOOGLE: SpvDecoration_ = 5634; -pub const SpvDecoration__SpvDecorationHlslSemanticGOOGLE: SpvDecoration_ = 5635; -pub const SpvDecoration__SpvDecorationUserSemantic: SpvDecoration_ = 5635; -pub const SpvDecoration__SpvDecorationUserTypeGOOGLE: SpvDecoration_ = 5636; -pub const SpvDecoration__SpvDecorationFunctionRoundingModeINTEL: SpvDecoration_ = 5822; -pub const SpvDecoration__SpvDecorationFunctionDenormModeINTEL: SpvDecoration_ = 5823; -pub const SpvDecoration__SpvDecorationRegisterINTEL: SpvDecoration_ = 5825; -pub const SpvDecoration__SpvDecorationMemoryINTEL: SpvDecoration_ = 5826; -pub const SpvDecoration__SpvDecorationNumbanksINTEL: SpvDecoration_ = 5827; -pub const SpvDecoration__SpvDecorationBankwidthINTEL: SpvDecoration_ = 5828; -pub const SpvDecoration__SpvDecorationMaxPrivateCopiesINTEL: SpvDecoration_ = 5829; -pub const SpvDecoration__SpvDecorationSinglepumpINTEL: SpvDecoration_ = 5830; -pub const SpvDecoration__SpvDecorationDoublepumpINTEL: SpvDecoration_ = 5831; -pub const SpvDecoration__SpvDecorationMaxReplicatesINTEL: SpvDecoration_ = 5832; -pub const SpvDecoration__SpvDecorationSimpleDualPortINTEL: SpvDecoration_ = 5833; -pub const SpvDecoration__SpvDecorationMergeINTEL: SpvDecoration_ = 5834; -pub const SpvDecoration__SpvDecorationBankBitsINTEL: SpvDecoration_ = 5835; -pub const SpvDecoration__SpvDecorationForcePow2DepthINTEL: SpvDecoration_ = 5836; -pub const SpvDecoration__SpvDecorationStridesizeINTEL: SpvDecoration_ = 5883; -pub const SpvDecoration__SpvDecorationWordsizeINTEL: SpvDecoration_ = 5884; -pub const SpvDecoration__SpvDecorationTrueDualPortINTEL: SpvDecoration_ = 5885; -pub const SpvDecoration__SpvDecorationBurstCoalesceINTEL: SpvDecoration_ = 5899; -pub const SpvDecoration__SpvDecorationCacheSizeINTEL: SpvDecoration_ = 5900; -pub const SpvDecoration__SpvDecorationDontStaticallyCoalesceINTEL: SpvDecoration_ = 5901; -pub const SpvDecoration__SpvDecorationPrefetchINTEL: SpvDecoration_ = 5902; -pub const SpvDecoration__SpvDecorationStallEnableINTEL: SpvDecoration_ = 5905; -pub const SpvDecoration__SpvDecorationFuseLoopsInFunctionINTEL: SpvDecoration_ = 5907; -pub const SpvDecoration__SpvDecorationMathOpDSPModeINTEL: SpvDecoration_ = 5909; -pub const SpvDecoration__SpvDecorationAliasScopeINTEL: SpvDecoration_ = 5914; -pub const SpvDecoration__SpvDecorationNoAliasINTEL: SpvDecoration_ = 5915; -pub const SpvDecoration__SpvDecorationInitiationIntervalINTEL: SpvDecoration_ = 5917; -pub const SpvDecoration__SpvDecorationMaxConcurrencyINTEL: SpvDecoration_ = 5918; -pub const SpvDecoration__SpvDecorationPipelineEnableINTEL: SpvDecoration_ = 5919; -pub const SpvDecoration__SpvDecorationBufferLocationINTEL: SpvDecoration_ = 5921; -pub const SpvDecoration__SpvDecorationIOPipeStorageINTEL: SpvDecoration_ = 5944; -pub const SpvDecoration__SpvDecorationFunctionFloatingPointModeINTEL: SpvDecoration_ = 6080; -pub const SpvDecoration__SpvDecorationSingleElementVectorINTEL: SpvDecoration_ = 6085; -pub const SpvDecoration__SpvDecorationVectorComputeCallableFunctionINTEL: SpvDecoration_ = 6087; -pub const SpvDecoration__SpvDecorationMediaBlockIOINTEL: SpvDecoration_ = 6140; -pub const SpvDecoration__SpvDecorationStallFreeINTEL: SpvDecoration_ = 6151; -pub const SpvDecoration__SpvDecorationFPMaxErrorDecorationINTEL: SpvDecoration_ = 6170; -pub const SpvDecoration__SpvDecorationLatencyControlLabelINTEL: SpvDecoration_ = 6172; -pub const SpvDecoration__SpvDecorationLatencyControlConstraintINTEL: SpvDecoration_ = 6173; -pub const SpvDecoration__SpvDecorationConduitKernelArgumentINTEL: SpvDecoration_ = 6175; -pub const SpvDecoration__SpvDecorationRegisterMapKernelArgumentINTEL: SpvDecoration_ = 6176; -pub const SpvDecoration__SpvDecorationMMHostInterfaceAddressWidthINTEL: SpvDecoration_ = 6177; -pub const SpvDecoration__SpvDecorationMMHostInterfaceDataWidthINTEL: SpvDecoration_ = 6178; -pub const SpvDecoration__SpvDecorationMMHostInterfaceLatencyINTEL: SpvDecoration_ = 6179; -pub const SpvDecoration__SpvDecorationMMHostInterfaceReadWriteModeINTEL: SpvDecoration_ = 6180; -pub const SpvDecoration__SpvDecorationMMHostInterfaceMaxBurstINTEL: SpvDecoration_ = 6181; -pub const SpvDecoration__SpvDecorationMMHostInterfaceWaitRequestINTEL: SpvDecoration_ = 6182; -pub const SpvDecoration__SpvDecorationStableKernelArgumentINTEL: SpvDecoration_ = 6183; -pub const SpvDecoration__SpvDecorationHostAccessINTEL: SpvDecoration_ = 6188; -pub const SpvDecoration__SpvDecorationInitModeINTEL: SpvDecoration_ = 6190; -pub const SpvDecoration__SpvDecorationImplementInRegisterMapINTEL: SpvDecoration_ = 6191; -pub const SpvDecoration__SpvDecorationConditionalINTEL: SpvDecoration_ = 6247; -pub const SpvDecoration__SpvDecorationCacheControlLoadINTEL: SpvDecoration_ = 6442; -pub const SpvDecoration__SpvDecorationCacheControlStoreINTEL: SpvDecoration_ = 6443; -pub const SpvDecoration__SpvDecorationMax: SpvDecoration_ = 2147483647; -pub type SpvDecoration_ = ::std::os::raw::c_int; -pub use self::SpvDecoration_ as SpvDecoration; -pub const SpvBuiltIn__SpvBuiltInPosition: SpvBuiltIn_ = 0; -pub const SpvBuiltIn__SpvBuiltInPointSize: SpvBuiltIn_ = 1; -pub const SpvBuiltIn__SpvBuiltInClipDistance: SpvBuiltIn_ = 3; -pub const SpvBuiltIn__SpvBuiltInCullDistance: SpvBuiltIn_ = 4; -pub const SpvBuiltIn__SpvBuiltInVertexId: SpvBuiltIn_ = 5; -pub const SpvBuiltIn__SpvBuiltInInstanceId: SpvBuiltIn_ = 6; -pub const SpvBuiltIn__SpvBuiltInPrimitiveId: SpvBuiltIn_ = 7; -pub const SpvBuiltIn__SpvBuiltInInvocationId: SpvBuiltIn_ = 8; -pub const SpvBuiltIn__SpvBuiltInLayer: SpvBuiltIn_ = 9; -pub const SpvBuiltIn__SpvBuiltInViewportIndex: SpvBuiltIn_ = 10; -pub const SpvBuiltIn__SpvBuiltInTessLevelOuter: SpvBuiltIn_ = 11; -pub const SpvBuiltIn__SpvBuiltInTessLevelInner: SpvBuiltIn_ = 12; -pub const SpvBuiltIn__SpvBuiltInTessCoord: SpvBuiltIn_ = 13; -pub const SpvBuiltIn__SpvBuiltInPatchVertices: SpvBuiltIn_ = 14; -pub const SpvBuiltIn__SpvBuiltInFragCoord: SpvBuiltIn_ = 15; -pub const SpvBuiltIn__SpvBuiltInPointCoord: SpvBuiltIn_ = 16; -pub const SpvBuiltIn__SpvBuiltInFrontFacing: SpvBuiltIn_ = 17; -pub const SpvBuiltIn__SpvBuiltInSampleId: SpvBuiltIn_ = 18; -pub const SpvBuiltIn__SpvBuiltInSamplePosition: SpvBuiltIn_ = 19; -pub const SpvBuiltIn__SpvBuiltInSampleMask: SpvBuiltIn_ = 20; -pub const SpvBuiltIn__SpvBuiltInFragDepth: SpvBuiltIn_ = 22; -pub const SpvBuiltIn__SpvBuiltInHelperInvocation: SpvBuiltIn_ = 23; -pub const SpvBuiltIn__SpvBuiltInNumWorkgroups: SpvBuiltIn_ = 24; -pub const SpvBuiltIn__SpvBuiltInWorkgroupSize: SpvBuiltIn_ = 25; -pub const SpvBuiltIn__SpvBuiltInWorkgroupId: SpvBuiltIn_ = 26; -pub const SpvBuiltIn__SpvBuiltInLocalInvocationId: SpvBuiltIn_ = 27; -pub const SpvBuiltIn__SpvBuiltInGlobalInvocationId: SpvBuiltIn_ = 28; -pub const SpvBuiltIn__SpvBuiltInLocalInvocationIndex: SpvBuiltIn_ = 29; -pub const SpvBuiltIn__SpvBuiltInWorkDim: SpvBuiltIn_ = 30; -pub const SpvBuiltIn__SpvBuiltInGlobalSize: SpvBuiltIn_ = 31; -pub const SpvBuiltIn__SpvBuiltInEnqueuedWorkgroupSize: SpvBuiltIn_ = 32; -pub const SpvBuiltIn__SpvBuiltInGlobalOffset: SpvBuiltIn_ = 33; -pub const SpvBuiltIn__SpvBuiltInGlobalLinearId: SpvBuiltIn_ = 34; -pub const SpvBuiltIn__SpvBuiltInSubgroupSize: SpvBuiltIn_ = 36; -pub const SpvBuiltIn__SpvBuiltInSubgroupMaxSize: SpvBuiltIn_ = 37; -pub const SpvBuiltIn__SpvBuiltInNumSubgroups: SpvBuiltIn_ = 38; -pub const SpvBuiltIn__SpvBuiltInNumEnqueuedSubgroups: SpvBuiltIn_ = 39; -pub const SpvBuiltIn__SpvBuiltInSubgroupId: SpvBuiltIn_ = 40; -pub const SpvBuiltIn__SpvBuiltInSubgroupLocalInvocationId: SpvBuiltIn_ = 41; -pub const SpvBuiltIn__SpvBuiltInVertexIndex: SpvBuiltIn_ = 42; -pub const SpvBuiltIn__SpvBuiltInInstanceIndex: SpvBuiltIn_ = 43; -pub const SpvBuiltIn__SpvBuiltInCoreIDARM: SpvBuiltIn_ = 4160; -pub const SpvBuiltIn__SpvBuiltInCoreCountARM: SpvBuiltIn_ = 4161; -pub const SpvBuiltIn__SpvBuiltInCoreMaxIDARM: SpvBuiltIn_ = 4162; -pub const SpvBuiltIn__SpvBuiltInWarpIDARM: SpvBuiltIn_ = 4163; -pub const SpvBuiltIn__SpvBuiltInWarpMaxIDARM: SpvBuiltIn_ = 4164; -pub const SpvBuiltIn__SpvBuiltInSubgroupEqMask: SpvBuiltIn_ = 4416; -pub const SpvBuiltIn__SpvBuiltInSubgroupEqMaskKHR: SpvBuiltIn_ = 4416; -pub const SpvBuiltIn__SpvBuiltInSubgroupGeMask: SpvBuiltIn_ = 4417; -pub const SpvBuiltIn__SpvBuiltInSubgroupGeMaskKHR: SpvBuiltIn_ = 4417; -pub const SpvBuiltIn__SpvBuiltInSubgroupGtMask: SpvBuiltIn_ = 4418; -pub const SpvBuiltIn__SpvBuiltInSubgroupGtMaskKHR: SpvBuiltIn_ = 4418; -pub const SpvBuiltIn__SpvBuiltInSubgroupLeMask: SpvBuiltIn_ = 4419; -pub const SpvBuiltIn__SpvBuiltInSubgroupLeMaskKHR: SpvBuiltIn_ = 4419; -pub const SpvBuiltIn__SpvBuiltInSubgroupLtMask: SpvBuiltIn_ = 4420; -pub const SpvBuiltIn__SpvBuiltInSubgroupLtMaskKHR: SpvBuiltIn_ = 4420; -pub const SpvBuiltIn__SpvBuiltInBaseVertex: SpvBuiltIn_ = 4424; -pub const SpvBuiltIn__SpvBuiltInBaseInstance: SpvBuiltIn_ = 4425; -pub const SpvBuiltIn__SpvBuiltInDrawIndex: SpvBuiltIn_ = 4426; -pub const SpvBuiltIn__SpvBuiltInPrimitiveShadingRateKHR: SpvBuiltIn_ = 4432; -pub const SpvBuiltIn__SpvBuiltInDeviceIndex: SpvBuiltIn_ = 4438; -pub const SpvBuiltIn__SpvBuiltInViewIndex: SpvBuiltIn_ = 4440; -pub const SpvBuiltIn__SpvBuiltInShadingRateKHR: SpvBuiltIn_ = 4444; -pub const SpvBuiltIn__SpvBuiltInTileOffsetQCOM: SpvBuiltIn_ = 4492; -pub const SpvBuiltIn__SpvBuiltInTileDimensionQCOM: SpvBuiltIn_ = 4493; -pub const SpvBuiltIn__SpvBuiltInTileApronSizeQCOM: SpvBuiltIn_ = 4494; -pub const SpvBuiltIn__SpvBuiltInBaryCoordNoPerspAMD: SpvBuiltIn_ = 4992; -pub const SpvBuiltIn__SpvBuiltInBaryCoordNoPerspCentroidAMD: SpvBuiltIn_ = 4993; -pub const SpvBuiltIn__SpvBuiltInBaryCoordNoPerspSampleAMD: SpvBuiltIn_ = 4994; -pub const SpvBuiltIn__SpvBuiltInBaryCoordSmoothAMD: SpvBuiltIn_ = 4995; -pub const SpvBuiltIn__SpvBuiltInBaryCoordSmoothCentroidAMD: SpvBuiltIn_ = 4996; -pub const SpvBuiltIn__SpvBuiltInBaryCoordSmoothSampleAMD: SpvBuiltIn_ = 4997; -pub const SpvBuiltIn__SpvBuiltInBaryCoordPullModelAMD: SpvBuiltIn_ = 4998; -pub const SpvBuiltIn__SpvBuiltInFragStencilRefEXT: SpvBuiltIn_ = 5014; -pub const SpvBuiltIn__SpvBuiltInRemainingRecursionLevelsAMDX: SpvBuiltIn_ = 5021; -pub const SpvBuiltIn__SpvBuiltInShaderIndexAMDX: SpvBuiltIn_ = 5073; -pub const SpvBuiltIn__SpvBuiltInViewportMaskNV: SpvBuiltIn_ = 5253; -pub const SpvBuiltIn__SpvBuiltInSecondaryPositionNV: SpvBuiltIn_ = 5257; -pub const SpvBuiltIn__SpvBuiltInSecondaryViewportMaskNV: SpvBuiltIn_ = 5258; -pub const SpvBuiltIn__SpvBuiltInPositionPerViewNV: SpvBuiltIn_ = 5261; -pub const SpvBuiltIn__SpvBuiltInViewportMaskPerViewNV: SpvBuiltIn_ = 5262; -pub const SpvBuiltIn__SpvBuiltInFullyCoveredEXT: SpvBuiltIn_ = 5264; -pub const SpvBuiltIn__SpvBuiltInTaskCountNV: SpvBuiltIn_ = 5274; -pub const SpvBuiltIn__SpvBuiltInPrimitiveCountNV: SpvBuiltIn_ = 5275; -pub const SpvBuiltIn__SpvBuiltInPrimitiveIndicesNV: SpvBuiltIn_ = 5276; -pub const SpvBuiltIn__SpvBuiltInClipDistancePerViewNV: SpvBuiltIn_ = 5277; -pub const SpvBuiltIn__SpvBuiltInCullDistancePerViewNV: SpvBuiltIn_ = 5278; -pub const SpvBuiltIn__SpvBuiltInLayerPerViewNV: SpvBuiltIn_ = 5279; -pub const SpvBuiltIn__SpvBuiltInMeshViewCountNV: SpvBuiltIn_ = 5280; -pub const SpvBuiltIn__SpvBuiltInMeshViewIndicesNV: SpvBuiltIn_ = 5281; -pub const SpvBuiltIn__SpvBuiltInBaryCoordKHR: SpvBuiltIn_ = 5286; -pub const SpvBuiltIn__SpvBuiltInBaryCoordNV: SpvBuiltIn_ = 5286; -pub const SpvBuiltIn__SpvBuiltInBaryCoordNoPerspKHR: SpvBuiltIn_ = 5287; -pub const SpvBuiltIn__SpvBuiltInBaryCoordNoPerspNV: SpvBuiltIn_ = 5287; -pub const SpvBuiltIn__SpvBuiltInFragSizeEXT: SpvBuiltIn_ = 5292; -pub const SpvBuiltIn__SpvBuiltInFragmentSizeNV: SpvBuiltIn_ = 5292; -pub const SpvBuiltIn__SpvBuiltInFragInvocationCountEXT: SpvBuiltIn_ = 5293; -pub const SpvBuiltIn__SpvBuiltInInvocationsPerPixelNV: SpvBuiltIn_ = 5293; -pub const SpvBuiltIn__SpvBuiltInPrimitivePointIndicesEXT: SpvBuiltIn_ = 5294; -pub const SpvBuiltIn__SpvBuiltInPrimitiveLineIndicesEXT: SpvBuiltIn_ = 5295; -pub const SpvBuiltIn__SpvBuiltInPrimitiveTriangleIndicesEXT: SpvBuiltIn_ = 5296; -pub const SpvBuiltIn__SpvBuiltInCullPrimitiveEXT: SpvBuiltIn_ = 5299; -pub const SpvBuiltIn__SpvBuiltInLaunchIdKHR: SpvBuiltIn_ = 5319; -pub const SpvBuiltIn__SpvBuiltInLaunchIdNV: SpvBuiltIn_ = 5319; -pub const SpvBuiltIn__SpvBuiltInLaunchSizeKHR: SpvBuiltIn_ = 5320; -pub const SpvBuiltIn__SpvBuiltInLaunchSizeNV: SpvBuiltIn_ = 5320; -pub const SpvBuiltIn__SpvBuiltInWorldRayOriginKHR: SpvBuiltIn_ = 5321; -pub const SpvBuiltIn__SpvBuiltInWorldRayOriginNV: SpvBuiltIn_ = 5321; -pub const SpvBuiltIn__SpvBuiltInWorldRayDirectionKHR: SpvBuiltIn_ = 5322; -pub const SpvBuiltIn__SpvBuiltInWorldRayDirectionNV: SpvBuiltIn_ = 5322; -pub const SpvBuiltIn__SpvBuiltInObjectRayOriginKHR: SpvBuiltIn_ = 5323; -pub const SpvBuiltIn__SpvBuiltInObjectRayOriginNV: SpvBuiltIn_ = 5323; -pub const SpvBuiltIn__SpvBuiltInObjectRayDirectionKHR: SpvBuiltIn_ = 5324; -pub const SpvBuiltIn__SpvBuiltInObjectRayDirectionNV: SpvBuiltIn_ = 5324; -pub const SpvBuiltIn__SpvBuiltInRayTminKHR: SpvBuiltIn_ = 5325; -pub const SpvBuiltIn__SpvBuiltInRayTminNV: SpvBuiltIn_ = 5325; -pub const SpvBuiltIn__SpvBuiltInRayTmaxKHR: SpvBuiltIn_ = 5326; -pub const SpvBuiltIn__SpvBuiltInRayTmaxNV: SpvBuiltIn_ = 5326; -pub const SpvBuiltIn__SpvBuiltInInstanceCustomIndexKHR: SpvBuiltIn_ = 5327; -pub const SpvBuiltIn__SpvBuiltInInstanceCustomIndexNV: SpvBuiltIn_ = 5327; -pub const SpvBuiltIn__SpvBuiltInObjectToWorldKHR: SpvBuiltIn_ = 5330; -pub const SpvBuiltIn__SpvBuiltInObjectToWorldNV: SpvBuiltIn_ = 5330; -pub const SpvBuiltIn__SpvBuiltInWorldToObjectKHR: SpvBuiltIn_ = 5331; -pub const SpvBuiltIn__SpvBuiltInWorldToObjectNV: SpvBuiltIn_ = 5331; -pub const SpvBuiltIn__SpvBuiltInHitTNV: SpvBuiltIn_ = 5332; -pub const SpvBuiltIn__SpvBuiltInHitKindKHR: SpvBuiltIn_ = 5333; -pub const SpvBuiltIn__SpvBuiltInHitKindNV: SpvBuiltIn_ = 5333; -pub const SpvBuiltIn__SpvBuiltInCurrentRayTimeNV: SpvBuiltIn_ = 5334; -pub const SpvBuiltIn__SpvBuiltInHitTriangleVertexPositionsKHR: SpvBuiltIn_ = 5335; -pub const SpvBuiltIn__SpvBuiltInHitMicroTriangleVertexPositionsNV: SpvBuiltIn_ = 5337; -pub const SpvBuiltIn__SpvBuiltInHitMicroTriangleVertexBarycentricsNV: SpvBuiltIn_ = 5344; -pub const SpvBuiltIn__SpvBuiltInIncomingRayFlagsKHR: SpvBuiltIn_ = 5351; -pub const SpvBuiltIn__SpvBuiltInIncomingRayFlagsNV: SpvBuiltIn_ = 5351; -pub const SpvBuiltIn__SpvBuiltInRayGeometryIndexKHR: SpvBuiltIn_ = 5352; -pub const SpvBuiltIn__SpvBuiltInHitIsSphereNV: SpvBuiltIn_ = 5359; -pub const SpvBuiltIn__SpvBuiltInHitIsLSSNV: SpvBuiltIn_ = 5360; -pub const SpvBuiltIn__SpvBuiltInHitSpherePositionNV: SpvBuiltIn_ = 5361; -pub const SpvBuiltIn__SpvBuiltInWarpsPerSMNV: SpvBuiltIn_ = 5374; -pub const SpvBuiltIn__SpvBuiltInSMCountNV: SpvBuiltIn_ = 5375; -pub const SpvBuiltIn__SpvBuiltInWarpIDNV: SpvBuiltIn_ = 5376; -pub const SpvBuiltIn__SpvBuiltInSMIDNV: SpvBuiltIn_ = 5377; -pub const SpvBuiltIn__SpvBuiltInHitLSSPositionsNV: SpvBuiltIn_ = 5396; -pub const SpvBuiltIn__SpvBuiltInHitKindFrontFacingMicroTriangleNV: SpvBuiltIn_ = 5405; -pub const SpvBuiltIn__SpvBuiltInHitKindBackFacingMicroTriangleNV: SpvBuiltIn_ = 5406; -pub const SpvBuiltIn__SpvBuiltInHitSphereRadiusNV: SpvBuiltIn_ = 5420; -pub const SpvBuiltIn__SpvBuiltInHitLSSRadiiNV: SpvBuiltIn_ = 5421; -pub const SpvBuiltIn__SpvBuiltInClusterIDNV: SpvBuiltIn_ = 5436; -pub const SpvBuiltIn__SpvBuiltInCullMaskKHR: SpvBuiltIn_ = 6021; -pub const SpvBuiltIn__SpvBuiltInMax: SpvBuiltIn_ = 2147483647; -pub type SpvBuiltIn_ = ::std::os::raw::c_int; -pub use self::SpvBuiltIn_ as SpvBuiltIn; -pub const SpvSelectionControlShift__SpvSelectionControlFlattenShift: SpvSelectionControlShift_ = 0; -pub const SpvSelectionControlShift__SpvSelectionControlDontFlattenShift: SpvSelectionControlShift_ = - 1; -pub const SpvSelectionControlShift__SpvSelectionControlMax: SpvSelectionControlShift_ = 2147483647; -pub type SpvSelectionControlShift_ = ::std::os::raw::c_int; -pub use self::SpvSelectionControlShift_ as SpvSelectionControlShift; -pub const SpvSelectionControlMask__SpvSelectionControlMaskNone: SpvSelectionControlMask_ = 0; -pub const SpvSelectionControlMask__SpvSelectionControlFlattenMask: SpvSelectionControlMask_ = 1; -pub const SpvSelectionControlMask__SpvSelectionControlDontFlattenMask: SpvSelectionControlMask_ = 2; -pub type SpvSelectionControlMask_ = ::std::os::raw::c_int; -pub use self::SpvSelectionControlMask_ as SpvSelectionControlMask; -pub const SpvLoopControlShift__SpvLoopControlUnrollShift: SpvLoopControlShift_ = 0; -pub const SpvLoopControlShift__SpvLoopControlDontUnrollShift: SpvLoopControlShift_ = 1; -pub const SpvLoopControlShift__SpvLoopControlDependencyInfiniteShift: SpvLoopControlShift_ = 2; -pub const SpvLoopControlShift__SpvLoopControlDependencyLengthShift: SpvLoopControlShift_ = 3; -pub const SpvLoopControlShift__SpvLoopControlMinIterationsShift: SpvLoopControlShift_ = 4; -pub const SpvLoopControlShift__SpvLoopControlMaxIterationsShift: SpvLoopControlShift_ = 5; -pub const SpvLoopControlShift__SpvLoopControlIterationMultipleShift: SpvLoopControlShift_ = 6; -pub const SpvLoopControlShift__SpvLoopControlPeelCountShift: SpvLoopControlShift_ = 7; -pub const SpvLoopControlShift__SpvLoopControlPartialCountShift: SpvLoopControlShift_ = 8; -pub const SpvLoopControlShift__SpvLoopControlInitiationIntervalINTELShift: SpvLoopControlShift_ = - 16; -pub const SpvLoopControlShift__SpvLoopControlMaxConcurrencyINTELShift: SpvLoopControlShift_ = 17; -pub const SpvLoopControlShift__SpvLoopControlDependencyArrayINTELShift: SpvLoopControlShift_ = 18; -pub const SpvLoopControlShift__SpvLoopControlPipelineEnableINTELShift: SpvLoopControlShift_ = 19; -pub const SpvLoopControlShift__SpvLoopControlLoopCoalesceINTELShift: SpvLoopControlShift_ = 20; -pub const SpvLoopControlShift__SpvLoopControlMaxInterleavingINTELShift: SpvLoopControlShift_ = 21; -pub const SpvLoopControlShift__SpvLoopControlSpeculatedIterationsINTELShift: SpvLoopControlShift_ = - 22; -pub const SpvLoopControlShift__SpvLoopControlNoFusionINTELShift: SpvLoopControlShift_ = 23; -pub const SpvLoopControlShift__SpvLoopControlLoopCountINTELShift: SpvLoopControlShift_ = 24; -pub const SpvLoopControlShift__SpvLoopControlMaxReinvocationDelayINTELShift: SpvLoopControlShift_ = - 25; -pub const SpvLoopControlShift__SpvLoopControlMax: SpvLoopControlShift_ = 2147483647; -pub type SpvLoopControlShift_ = ::std::os::raw::c_int; -pub use self::SpvLoopControlShift_ as SpvLoopControlShift; -pub const SpvLoopControlMask__SpvLoopControlMaskNone: SpvLoopControlMask_ = 0; -pub const SpvLoopControlMask__SpvLoopControlUnrollMask: SpvLoopControlMask_ = 1; -pub const SpvLoopControlMask__SpvLoopControlDontUnrollMask: SpvLoopControlMask_ = 2; -pub const SpvLoopControlMask__SpvLoopControlDependencyInfiniteMask: SpvLoopControlMask_ = 4; -pub const SpvLoopControlMask__SpvLoopControlDependencyLengthMask: SpvLoopControlMask_ = 8; -pub const SpvLoopControlMask__SpvLoopControlMinIterationsMask: SpvLoopControlMask_ = 16; -pub const SpvLoopControlMask__SpvLoopControlMaxIterationsMask: SpvLoopControlMask_ = 32; -pub const SpvLoopControlMask__SpvLoopControlIterationMultipleMask: SpvLoopControlMask_ = 64; -pub const SpvLoopControlMask__SpvLoopControlPeelCountMask: SpvLoopControlMask_ = 128; -pub const SpvLoopControlMask__SpvLoopControlPartialCountMask: SpvLoopControlMask_ = 256; -pub const SpvLoopControlMask__SpvLoopControlInitiationIntervalINTELMask: SpvLoopControlMask_ = - 65536; -pub const SpvLoopControlMask__SpvLoopControlMaxConcurrencyINTELMask: SpvLoopControlMask_ = 131072; -pub const SpvLoopControlMask__SpvLoopControlDependencyArrayINTELMask: SpvLoopControlMask_ = 262144; -pub const SpvLoopControlMask__SpvLoopControlPipelineEnableINTELMask: SpvLoopControlMask_ = 524288; -pub const SpvLoopControlMask__SpvLoopControlLoopCoalesceINTELMask: SpvLoopControlMask_ = 1048576; -pub const SpvLoopControlMask__SpvLoopControlMaxInterleavingINTELMask: SpvLoopControlMask_ = 2097152; -pub const SpvLoopControlMask__SpvLoopControlSpeculatedIterationsINTELMask: SpvLoopControlMask_ = - 4194304; -pub const SpvLoopControlMask__SpvLoopControlNoFusionINTELMask: SpvLoopControlMask_ = 8388608; -pub const SpvLoopControlMask__SpvLoopControlLoopCountINTELMask: SpvLoopControlMask_ = 16777216; -pub const SpvLoopControlMask__SpvLoopControlMaxReinvocationDelayINTELMask: SpvLoopControlMask_ = - 33554432; -pub type SpvLoopControlMask_ = ::std::os::raw::c_int; -pub use self::SpvLoopControlMask_ as SpvLoopControlMask; -pub const SpvFunctionControlShift__SpvFunctionControlInlineShift: SpvFunctionControlShift_ = 0; -pub const SpvFunctionControlShift__SpvFunctionControlDontInlineShift: SpvFunctionControlShift_ = 1; -pub const SpvFunctionControlShift__SpvFunctionControlPureShift: SpvFunctionControlShift_ = 2; -pub const SpvFunctionControlShift__SpvFunctionControlConstShift: SpvFunctionControlShift_ = 3; -pub const SpvFunctionControlShift__SpvFunctionControlOptNoneEXTShift: SpvFunctionControlShift_ = 16; -pub const SpvFunctionControlShift__SpvFunctionControlOptNoneINTELShift: SpvFunctionControlShift_ = - 16; -pub const SpvFunctionControlShift__SpvFunctionControlMax: SpvFunctionControlShift_ = 2147483647; -pub type SpvFunctionControlShift_ = ::std::os::raw::c_int; -pub use self::SpvFunctionControlShift_ as SpvFunctionControlShift; -pub const SpvFunctionControlMask__SpvFunctionControlMaskNone: SpvFunctionControlMask_ = 0; -pub const SpvFunctionControlMask__SpvFunctionControlInlineMask: SpvFunctionControlMask_ = 1; -pub const SpvFunctionControlMask__SpvFunctionControlDontInlineMask: SpvFunctionControlMask_ = 2; -pub const SpvFunctionControlMask__SpvFunctionControlPureMask: SpvFunctionControlMask_ = 4; -pub const SpvFunctionControlMask__SpvFunctionControlConstMask: SpvFunctionControlMask_ = 8; -pub const SpvFunctionControlMask__SpvFunctionControlOptNoneEXTMask: SpvFunctionControlMask_ = 65536; -pub const SpvFunctionControlMask__SpvFunctionControlOptNoneINTELMask: SpvFunctionControlMask_ = - 65536; -pub type SpvFunctionControlMask_ = ::std::os::raw::c_int; -pub use self::SpvFunctionControlMask_ as SpvFunctionControlMask; -pub const SpvMemorySemanticsShift__SpvMemorySemanticsAcquireShift: SpvMemorySemanticsShift_ = 1; -pub const SpvMemorySemanticsShift__SpvMemorySemanticsReleaseShift: SpvMemorySemanticsShift_ = 2; -pub const SpvMemorySemanticsShift__SpvMemorySemanticsAcquireReleaseShift: SpvMemorySemanticsShift_ = - 3; -pub const SpvMemorySemanticsShift__SpvMemorySemanticsSequentiallyConsistentShift: - SpvMemorySemanticsShift_ = 4; -pub const SpvMemorySemanticsShift__SpvMemorySemanticsUniformMemoryShift: SpvMemorySemanticsShift_ = - 6; -pub const SpvMemorySemanticsShift__SpvMemorySemanticsSubgroupMemoryShift: SpvMemorySemanticsShift_ = - 7; -pub const SpvMemorySemanticsShift__SpvMemorySemanticsWorkgroupMemoryShift: - SpvMemorySemanticsShift_ = 8; -pub const SpvMemorySemanticsShift__SpvMemorySemanticsCrossWorkgroupMemoryShift: - SpvMemorySemanticsShift_ = 9; -pub const SpvMemorySemanticsShift__SpvMemorySemanticsAtomicCounterMemoryShift: - SpvMemorySemanticsShift_ = 10; -pub const SpvMemorySemanticsShift__SpvMemorySemanticsImageMemoryShift: SpvMemorySemanticsShift_ = - 11; -pub const SpvMemorySemanticsShift__SpvMemorySemanticsOutputMemoryShift: SpvMemorySemanticsShift_ = - 12; -pub const SpvMemorySemanticsShift__SpvMemorySemanticsOutputMemoryKHRShift: - SpvMemorySemanticsShift_ = 12; -pub const SpvMemorySemanticsShift__SpvMemorySemanticsMakeAvailableShift: SpvMemorySemanticsShift_ = - 13; -pub const SpvMemorySemanticsShift__SpvMemorySemanticsMakeAvailableKHRShift: - SpvMemorySemanticsShift_ = 13; -pub const SpvMemorySemanticsShift__SpvMemorySemanticsMakeVisibleShift: SpvMemorySemanticsShift_ = - 14; -pub const SpvMemorySemanticsShift__SpvMemorySemanticsMakeVisibleKHRShift: SpvMemorySemanticsShift_ = - 14; -pub const SpvMemorySemanticsShift__SpvMemorySemanticsVolatileShift: SpvMemorySemanticsShift_ = 15; -pub const SpvMemorySemanticsShift__SpvMemorySemanticsMax: SpvMemorySemanticsShift_ = 2147483647; -pub type SpvMemorySemanticsShift_ = ::std::os::raw::c_int; -pub use self::SpvMemorySemanticsShift_ as SpvMemorySemanticsShift; -pub const SpvMemorySemanticsMask__SpvMemorySemanticsMaskNone: SpvMemorySemanticsMask_ = 0; -pub const SpvMemorySemanticsMask__SpvMemorySemanticsAcquireMask: SpvMemorySemanticsMask_ = 2; -pub const SpvMemorySemanticsMask__SpvMemorySemanticsReleaseMask: SpvMemorySemanticsMask_ = 4; -pub const SpvMemorySemanticsMask__SpvMemorySemanticsAcquireReleaseMask: SpvMemorySemanticsMask_ = 8; -pub const SpvMemorySemanticsMask__SpvMemorySemanticsSequentiallyConsistentMask: - SpvMemorySemanticsMask_ = 16; -pub const SpvMemorySemanticsMask__SpvMemorySemanticsUniformMemoryMask: SpvMemorySemanticsMask_ = 64; -pub const SpvMemorySemanticsMask__SpvMemorySemanticsSubgroupMemoryMask: SpvMemorySemanticsMask_ = - 128; -pub const SpvMemorySemanticsMask__SpvMemorySemanticsWorkgroupMemoryMask: SpvMemorySemanticsMask_ = - 256; -pub const SpvMemorySemanticsMask__SpvMemorySemanticsCrossWorkgroupMemoryMask: - SpvMemorySemanticsMask_ = 512; -pub const SpvMemorySemanticsMask__SpvMemorySemanticsAtomicCounterMemoryMask: - SpvMemorySemanticsMask_ = 1024; -pub const SpvMemorySemanticsMask__SpvMemorySemanticsImageMemoryMask: SpvMemorySemanticsMask_ = 2048; -pub const SpvMemorySemanticsMask__SpvMemorySemanticsOutputMemoryMask: SpvMemorySemanticsMask_ = - 4096; -pub const SpvMemorySemanticsMask__SpvMemorySemanticsOutputMemoryKHRMask: SpvMemorySemanticsMask_ = - 4096; -pub const SpvMemorySemanticsMask__SpvMemorySemanticsMakeAvailableMask: SpvMemorySemanticsMask_ = - 8192; -pub const SpvMemorySemanticsMask__SpvMemorySemanticsMakeAvailableKHRMask: SpvMemorySemanticsMask_ = - 8192; -pub const SpvMemorySemanticsMask__SpvMemorySemanticsMakeVisibleMask: SpvMemorySemanticsMask_ = - 16384; -pub const SpvMemorySemanticsMask__SpvMemorySemanticsMakeVisibleKHRMask: SpvMemorySemanticsMask_ = - 16384; -pub const SpvMemorySemanticsMask__SpvMemorySemanticsVolatileMask: SpvMemorySemanticsMask_ = 32768; -pub type SpvMemorySemanticsMask_ = ::std::os::raw::c_int; -pub use self::SpvMemorySemanticsMask_ as SpvMemorySemanticsMask; -pub const SpvMemoryAccessShift__SpvMemoryAccessVolatileShift: SpvMemoryAccessShift_ = 0; -pub const SpvMemoryAccessShift__SpvMemoryAccessAlignedShift: SpvMemoryAccessShift_ = 1; -pub const SpvMemoryAccessShift__SpvMemoryAccessNontemporalShift: SpvMemoryAccessShift_ = 2; -pub const SpvMemoryAccessShift__SpvMemoryAccessMakePointerAvailableShift: SpvMemoryAccessShift_ = 3; -pub const SpvMemoryAccessShift__SpvMemoryAccessMakePointerAvailableKHRShift: SpvMemoryAccessShift_ = - 3; -pub const SpvMemoryAccessShift__SpvMemoryAccessMakePointerVisibleShift: SpvMemoryAccessShift_ = 4; -pub const SpvMemoryAccessShift__SpvMemoryAccessMakePointerVisibleKHRShift: SpvMemoryAccessShift_ = - 4; -pub const SpvMemoryAccessShift__SpvMemoryAccessNonPrivatePointerShift: SpvMemoryAccessShift_ = 5; -pub const SpvMemoryAccessShift__SpvMemoryAccessNonPrivatePointerKHRShift: SpvMemoryAccessShift_ = 5; -pub const SpvMemoryAccessShift__SpvMemoryAccessAliasScopeINTELMaskShift: SpvMemoryAccessShift_ = 16; -pub const SpvMemoryAccessShift__SpvMemoryAccessNoAliasINTELMaskShift: SpvMemoryAccessShift_ = 17; -pub const SpvMemoryAccessShift__SpvMemoryAccessMax: SpvMemoryAccessShift_ = 2147483647; -pub type SpvMemoryAccessShift_ = ::std::os::raw::c_int; -pub use self::SpvMemoryAccessShift_ as SpvMemoryAccessShift; -pub const SpvMemoryAccessMask__SpvMemoryAccessMaskNone: SpvMemoryAccessMask_ = 0; -pub const SpvMemoryAccessMask__SpvMemoryAccessVolatileMask: SpvMemoryAccessMask_ = 1; -pub const SpvMemoryAccessMask__SpvMemoryAccessAlignedMask: SpvMemoryAccessMask_ = 2; -pub const SpvMemoryAccessMask__SpvMemoryAccessNontemporalMask: SpvMemoryAccessMask_ = 4; -pub const SpvMemoryAccessMask__SpvMemoryAccessMakePointerAvailableMask: SpvMemoryAccessMask_ = 8; -pub const SpvMemoryAccessMask__SpvMemoryAccessMakePointerAvailableKHRMask: SpvMemoryAccessMask_ = 8; -pub const SpvMemoryAccessMask__SpvMemoryAccessMakePointerVisibleMask: SpvMemoryAccessMask_ = 16; -pub const SpvMemoryAccessMask__SpvMemoryAccessMakePointerVisibleKHRMask: SpvMemoryAccessMask_ = 16; -pub const SpvMemoryAccessMask__SpvMemoryAccessNonPrivatePointerMask: SpvMemoryAccessMask_ = 32; -pub const SpvMemoryAccessMask__SpvMemoryAccessNonPrivatePointerKHRMask: SpvMemoryAccessMask_ = 32; -pub const SpvMemoryAccessMask__SpvMemoryAccessAliasScopeINTELMaskMask: SpvMemoryAccessMask_ = 65536; -pub const SpvMemoryAccessMask__SpvMemoryAccessNoAliasINTELMaskMask: SpvMemoryAccessMask_ = 131072; -pub type SpvMemoryAccessMask_ = ::std::os::raw::c_int; -pub use self::SpvMemoryAccessMask_ as SpvMemoryAccessMask; -pub const SpvScope__SpvScopeCrossDevice: SpvScope_ = 0; -pub const SpvScope__SpvScopeDevice: SpvScope_ = 1; -pub const SpvScope__SpvScopeWorkgroup: SpvScope_ = 2; -pub const SpvScope__SpvScopeSubgroup: SpvScope_ = 3; -pub const SpvScope__SpvScopeInvocation: SpvScope_ = 4; -pub const SpvScope__SpvScopeQueueFamily: SpvScope_ = 5; -pub const SpvScope__SpvScopeQueueFamilyKHR: SpvScope_ = 5; -pub const SpvScope__SpvScopeShaderCallKHR: SpvScope_ = 6; -pub const SpvScope__SpvScopeMax: SpvScope_ = 2147483647; -pub type SpvScope_ = ::std::os::raw::c_int; -pub use self::SpvScope_ as SpvScope; -pub const SpvGroupOperation__SpvGroupOperationReduce: SpvGroupOperation_ = 0; -pub const SpvGroupOperation__SpvGroupOperationInclusiveScan: SpvGroupOperation_ = 1; -pub const SpvGroupOperation__SpvGroupOperationExclusiveScan: SpvGroupOperation_ = 2; -pub const SpvGroupOperation__SpvGroupOperationClusteredReduce: SpvGroupOperation_ = 3; -pub const SpvGroupOperation__SpvGroupOperationPartitionedReduceNV: SpvGroupOperation_ = 6; -pub const SpvGroupOperation__SpvGroupOperationPartitionedInclusiveScanNV: SpvGroupOperation_ = 7; -pub const SpvGroupOperation__SpvGroupOperationPartitionedExclusiveScanNV: SpvGroupOperation_ = 8; -pub const SpvGroupOperation__SpvGroupOperationMax: SpvGroupOperation_ = 2147483647; -pub type SpvGroupOperation_ = ::std::os::raw::c_int; -pub use self::SpvGroupOperation_ as SpvGroupOperation; -pub const SpvKernelEnqueueFlags__SpvKernelEnqueueFlagsNoWait: SpvKernelEnqueueFlags_ = 0; -pub const SpvKernelEnqueueFlags__SpvKernelEnqueueFlagsWaitKernel: SpvKernelEnqueueFlags_ = 1; -pub const SpvKernelEnqueueFlags__SpvKernelEnqueueFlagsWaitWorkGroup: SpvKernelEnqueueFlags_ = 2; -pub const SpvKernelEnqueueFlags__SpvKernelEnqueueFlagsMax: SpvKernelEnqueueFlags_ = 2147483647; -pub type SpvKernelEnqueueFlags_ = ::std::os::raw::c_int; -pub use self::SpvKernelEnqueueFlags_ as SpvKernelEnqueueFlags; -pub const SpvKernelProfilingInfoShift__SpvKernelProfilingInfoCmdExecTimeShift: - SpvKernelProfilingInfoShift_ = 0; -pub const SpvKernelProfilingInfoShift__SpvKernelProfilingInfoMax: SpvKernelProfilingInfoShift_ = - 2147483647; -pub type SpvKernelProfilingInfoShift_ = ::std::os::raw::c_int; -pub use self::SpvKernelProfilingInfoShift_ as SpvKernelProfilingInfoShift; -pub const SpvKernelProfilingInfoMask__SpvKernelProfilingInfoMaskNone: SpvKernelProfilingInfoMask_ = - 0; -pub const SpvKernelProfilingInfoMask__SpvKernelProfilingInfoCmdExecTimeMask: - SpvKernelProfilingInfoMask_ = 1; -pub type SpvKernelProfilingInfoMask_ = ::std::os::raw::c_int; -pub use self::SpvKernelProfilingInfoMask_ as SpvKernelProfilingInfoMask; -pub const SpvCapability__SpvCapabilityMatrix: SpvCapability_ = 0; -pub const SpvCapability__SpvCapabilityShader: SpvCapability_ = 1; -pub const SpvCapability__SpvCapabilityGeometry: SpvCapability_ = 2; -pub const SpvCapability__SpvCapabilityTessellation: SpvCapability_ = 3; -pub const SpvCapability__SpvCapabilityAddresses: SpvCapability_ = 4; -pub const SpvCapability__SpvCapabilityLinkage: SpvCapability_ = 5; -pub const SpvCapability__SpvCapabilityKernel: SpvCapability_ = 6; -pub const SpvCapability__SpvCapabilityVector16: SpvCapability_ = 7; -pub const SpvCapability__SpvCapabilityFloat16Buffer: SpvCapability_ = 8; -pub const SpvCapability__SpvCapabilityFloat16: SpvCapability_ = 9; -pub const SpvCapability__SpvCapabilityFloat64: SpvCapability_ = 10; -pub const SpvCapability__SpvCapabilityInt64: SpvCapability_ = 11; -pub const SpvCapability__SpvCapabilityInt64Atomics: SpvCapability_ = 12; -pub const SpvCapability__SpvCapabilityImageBasic: SpvCapability_ = 13; -pub const SpvCapability__SpvCapabilityImageReadWrite: SpvCapability_ = 14; -pub const SpvCapability__SpvCapabilityImageMipmap: SpvCapability_ = 15; -pub const SpvCapability__SpvCapabilityPipes: SpvCapability_ = 17; -pub const SpvCapability__SpvCapabilityGroups: SpvCapability_ = 18; -pub const SpvCapability__SpvCapabilityDeviceEnqueue: SpvCapability_ = 19; -pub const SpvCapability__SpvCapabilityLiteralSampler: SpvCapability_ = 20; -pub const SpvCapability__SpvCapabilityAtomicStorage: SpvCapability_ = 21; -pub const SpvCapability__SpvCapabilityInt16: SpvCapability_ = 22; -pub const SpvCapability__SpvCapabilityTessellationPointSize: SpvCapability_ = 23; -pub const SpvCapability__SpvCapabilityGeometryPointSize: SpvCapability_ = 24; -pub const SpvCapability__SpvCapabilityImageGatherExtended: SpvCapability_ = 25; -pub const SpvCapability__SpvCapabilityStorageImageMultisample: SpvCapability_ = 27; -pub const SpvCapability__SpvCapabilityUniformBufferArrayDynamicIndexing: SpvCapability_ = 28; -pub const SpvCapability__SpvCapabilitySampledImageArrayDynamicIndexing: SpvCapability_ = 29; -pub const SpvCapability__SpvCapabilityStorageBufferArrayDynamicIndexing: SpvCapability_ = 30; -pub const SpvCapability__SpvCapabilityStorageImageArrayDynamicIndexing: SpvCapability_ = 31; -pub const SpvCapability__SpvCapabilityClipDistance: SpvCapability_ = 32; -pub const SpvCapability__SpvCapabilityCullDistance: SpvCapability_ = 33; -pub const SpvCapability__SpvCapabilityImageCubeArray: SpvCapability_ = 34; -pub const SpvCapability__SpvCapabilitySampleRateShading: SpvCapability_ = 35; -pub const SpvCapability__SpvCapabilityImageRect: SpvCapability_ = 36; -pub const SpvCapability__SpvCapabilitySampledRect: SpvCapability_ = 37; -pub const SpvCapability__SpvCapabilityGenericPointer: SpvCapability_ = 38; -pub const SpvCapability__SpvCapabilityInt8: SpvCapability_ = 39; -pub const SpvCapability__SpvCapabilityInputAttachment: SpvCapability_ = 40; -pub const SpvCapability__SpvCapabilitySparseResidency: SpvCapability_ = 41; -pub const SpvCapability__SpvCapabilityMinLod: SpvCapability_ = 42; -pub const SpvCapability__SpvCapabilitySampled1D: SpvCapability_ = 43; -pub const SpvCapability__SpvCapabilityImage1D: SpvCapability_ = 44; -pub const SpvCapability__SpvCapabilitySampledCubeArray: SpvCapability_ = 45; -pub const SpvCapability__SpvCapabilitySampledBuffer: SpvCapability_ = 46; -pub const SpvCapability__SpvCapabilityImageBuffer: SpvCapability_ = 47; -pub const SpvCapability__SpvCapabilityImageMSArray: SpvCapability_ = 48; -pub const SpvCapability__SpvCapabilityStorageImageExtendedFormats: SpvCapability_ = 49; -pub const SpvCapability__SpvCapabilityImageQuery: SpvCapability_ = 50; -pub const SpvCapability__SpvCapabilityDerivativeControl: SpvCapability_ = 51; -pub const SpvCapability__SpvCapabilityInterpolationFunction: SpvCapability_ = 52; -pub const SpvCapability__SpvCapabilityTransformFeedback: SpvCapability_ = 53; -pub const SpvCapability__SpvCapabilityGeometryStreams: SpvCapability_ = 54; -pub const SpvCapability__SpvCapabilityStorageImageReadWithoutFormat: SpvCapability_ = 55; -pub const SpvCapability__SpvCapabilityStorageImageWriteWithoutFormat: SpvCapability_ = 56; -pub const SpvCapability__SpvCapabilityMultiViewport: SpvCapability_ = 57; -pub const SpvCapability__SpvCapabilitySubgroupDispatch: SpvCapability_ = 58; -pub const SpvCapability__SpvCapabilityNamedBarrier: SpvCapability_ = 59; -pub const SpvCapability__SpvCapabilityPipeStorage: SpvCapability_ = 60; -pub const SpvCapability__SpvCapabilityGroupNonUniform: SpvCapability_ = 61; -pub const SpvCapability__SpvCapabilityGroupNonUniformVote: SpvCapability_ = 62; -pub const SpvCapability__SpvCapabilityGroupNonUniformArithmetic: SpvCapability_ = 63; -pub const SpvCapability__SpvCapabilityGroupNonUniformBallot: SpvCapability_ = 64; -pub const SpvCapability__SpvCapabilityGroupNonUniformShuffle: SpvCapability_ = 65; -pub const SpvCapability__SpvCapabilityGroupNonUniformShuffleRelative: SpvCapability_ = 66; -pub const SpvCapability__SpvCapabilityGroupNonUniformClustered: SpvCapability_ = 67; -pub const SpvCapability__SpvCapabilityGroupNonUniformQuad: SpvCapability_ = 68; -pub const SpvCapability__SpvCapabilityShaderLayer: SpvCapability_ = 69; -pub const SpvCapability__SpvCapabilityShaderViewportIndex: SpvCapability_ = 70; -pub const SpvCapability__SpvCapabilityUniformDecoration: SpvCapability_ = 71; -pub const SpvCapability__SpvCapabilityCoreBuiltinsARM: SpvCapability_ = 4165; -pub const SpvCapability__SpvCapabilityTileImageColorReadAccessEXT: SpvCapability_ = 4166; -pub const SpvCapability__SpvCapabilityTileImageDepthReadAccessEXT: SpvCapability_ = 4167; -pub const SpvCapability__SpvCapabilityTileImageStencilReadAccessEXT: SpvCapability_ = 4168; -pub const SpvCapability__SpvCapabilityTensorsARM: SpvCapability_ = 4174; -pub const SpvCapability__SpvCapabilityStorageTensorArrayDynamicIndexingARM: SpvCapability_ = 4175; -pub const SpvCapability__SpvCapabilityStorageTensorArrayNonUniformIndexingARM: SpvCapability_ = - 4176; -pub const SpvCapability__SpvCapabilityGraphARM: SpvCapability_ = 4191; -pub const SpvCapability__SpvCapabilityCooperativeMatrixLayoutsARM: SpvCapability_ = 4201; -pub const SpvCapability__SpvCapabilityFloat8EXT: SpvCapability_ = 4212; -pub const SpvCapability__SpvCapabilityFloat8CooperativeMatrixEXT: SpvCapability_ = 4213; -pub const SpvCapability__SpvCapabilityFragmentShadingRateKHR: SpvCapability_ = 4422; -pub const SpvCapability__SpvCapabilitySubgroupBallotKHR: SpvCapability_ = 4423; -pub const SpvCapability__SpvCapabilityDrawParameters: SpvCapability_ = 4427; -pub const SpvCapability__SpvCapabilityWorkgroupMemoryExplicitLayoutKHR: SpvCapability_ = 4428; -pub const SpvCapability__SpvCapabilityWorkgroupMemoryExplicitLayout8BitAccessKHR: SpvCapability_ = - 4429; -pub const SpvCapability__SpvCapabilityWorkgroupMemoryExplicitLayout16BitAccessKHR: SpvCapability_ = - 4430; -pub const SpvCapability__SpvCapabilitySubgroupVoteKHR: SpvCapability_ = 4431; -pub const SpvCapability__SpvCapabilityStorageBuffer16BitAccess: SpvCapability_ = 4433; -pub const SpvCapability__SpvCapabilityStorageUniformBufferBlock16: SpvCapability_ = 4433; -pub const SpvCapability__SpvCapabilityStorageUniform16: SpvCapability_ = 4434; -pub const SpvCapability__SpvCapabilityUniformAndStorageBuffer16BitAccess: SpvCapability_ = 4434; -pub const SpvCapability__SpvCapabilityStoragePushConstant16: SpvCapability_ = 4435; -pub const SpvCapability__SpvCapabilityStorageInputOutput16: SpvCapability_ = 4436; -pub const SpvCapability__SpvCapabilityDeviceGroup: SpvCapability_ = 4437; -pub const SpvCapability__SpvCapabilityMultiView: SpvCapability_ = 4439; -pub const SpvCapability__SpvCapabilityVariablePointersStorageBuffer: SpvCapability_ = 4441; -pub const SpvCapability__SpvCapabilityVariablePointers: SpvCapability_ = 4442; -pub const SpvCapability__SpvCapabilityAtomicStorageOps: SpvCapability_ = 4445; -pub const SpvCapability__SpvCapabilitySampleMaskPostDepthCoverage: SpvCapability_ = 4447; -pub const SpvCapability__SpvCapabilityStorageBuffer8BitAccess: SpvCapability_ = 4448; -pub const SpvCapability__SpvCapabilityUniformAndStorageBuffer8BitAccess: SpvCapability_ = 4449; -pub const SpvCapability__SpvCapabilityStoragePushConstant8: SpvCapability_ = 4450; -pub const SpvCapability__SpvCapabilityDenormPreserve: SpvCapability_ = 4464; -pub const SpvCapability__SpvCapabilityDenormFlushToZero: SpvCapability_ = 4465; -pub const SpvCapability__SpvCapabilitySignedZeroInfNanPreserve: SpvCapability_ = 4466; -pub const SpvCapability__SpvCapabilityRoundingModeRTE: SpvCapability_ = 4467; -pub const SpvCapability__SpvCapabilityRoundingModeRTZ: SpvCapability_ = 4468; -pub const SpvCapability__SpvCapabilityRayQueryProvisionalKHR: SpvCapability_ = 4471; -pub const SpvCapability__SpvCapabilityRayQueryKHR: SpvCapability_ = 4472; -pub const SpvCapability__SpvCapabilityUntypedPointersKHR: SpvCapability_ = 4473; -pub const SpvCapability__SpvCapabilityRayTraversalPrimitiveCullingKHR: SpvCapability_ = 4478; -pub const SpvCapability__SpvCapabilityRayTracingKHR: SpvCapability_ = 4479; -pub const SpvCapability__SpvCapabilityTextureSampleWeightedQCOM: SpvCapability_ = 4484; -pub const SpvCapability__SpvCapabilityTextureBoxFilterQCOM: SpvCapability_ = 4485; -pub const SpvCapability__SpvCapabilityTextureBlockMatchQCOM: SpvCapability_ = 4486; -pub const SpvCapability__SpvCapabilityTileShadingQCOM: SpvCapability_ = 4495; -pub const SpvCapability__SpvCapabilityCooperativeMatrixConversionQCOM: SpvCapability_ = 4496; -pub const SpvCapability__SpvCapabilityTextureBlockMatch2QCOM: SpvCapability_ = 4498; -pub const SpvCapability__SpvCapabilityFloat16ImageAMD: SpvCapability_ = 5008; -pub const SpvCapability__SpvCapabilityImageGatherBiasLodAMD: SpvCapability_ = 5009; -pub const SpvCapability__SpvCapabilityFragmentMaskAMD: SpvCapability_ = 5010; -pub const SpvCapability__SpvCapabilityStencilExportEXT: SpvCapability_ = 5013; -pub const SpvCapability__SpvCapabilityImageReadWriteLodAMD: SpvCapability_ = 5015; -pub const SpvCapability__SpvCapabilityInt64ImageEXT: SpvCapability_ = 5016; -pub const SpvCapability__SpvCapabilityShaderClockKHR: SpvCapability_ = 5055; -pub const SpvCapability__SpvCapabilityShaderEnqueueAMDX: SpvCapability_ = 5067; -pub const SpvCapability__SpvCapabilityQuadControlKHR: SpvCapability_ = 5087; -pub const SpvCapability__SpvCapabilityInt4TypeINTEL: SpvCapability_ = 5112; -pub const SpvCapability__SpvCapabilityInt4CooperativeMatrixINTEL: SpvCapability_ = 5114; -pub const SpvCapability__SpvCapabilityBFloat16TypeKHR: SpvCapability_ = 5116; -pub const SpvCapability__SpvCapabilityBFloat16DotProductKHR: SpvCapability_ = 5117; -pub const SpvCapability__SpvCapabilityBFloat16CooperativeMatrixKHR: SpvCapability_ = 5118; -pub const SpvCapability__SpvCapabilitySampleMaskOverrideCoverageNV: SpvCapability_ = 5249; -pub const SpvCapability__SpvCapabilityGeometryShaderPassthroughNV: SpvCapability_ = 5251; -pub const SpvCapability__SpvCapabilityShaderViewportIndexLayerEXT: SpvCapability_ = 5254; -pub const SpvCapability__SpvCapabilityShaderViewportIndexLayerNV: SpvCapability_ = 5254; -pub const SpvCapability__SpvCapabilityShaderViewportMaskNV: SpvCapability_ = 5255; -pub const SpvCapability__SpvCapabilityShaderStereoViewNV: SpvCapability_ = 5259; -pub const SpvCapability__SpvCapabilityPerViewAttributesNV: SpvCapability_ = 5260; -pub const SpvCapability__SpvCapabilityFragmentFullyCoveredEXT: SpvCapability_ = 5265; -pub const SpvCapability__SpvCapabilityMeshShadingNV: SpvCapability_ = 5266; -pub const SpvCapability__SpvCapabilityImageFootprintNV: SpvCapability_ = 5282; -pub const SpvCapability__SpvCapabilityMeshShadingEXT: SpvCapability_ = 5283; -pub const SpvCapability__SpvCapabilityFragmentBarycentricKHR: SpvCapability_ = 5284; -pub const SpvCapability__SpvCapabilityFragmentBarycentricNV: SpvCapability_ = 5284; -pub const SpvCapability__SpvCapabilityComputeDerivativeGroupQuadsKHR: SpvCapability_ = 5288; -pub const SpvCapability__SpvCapabilityComputeDerivativeGroupQuadsNV: SpvCapability_ = 5288; -pub const SpvCapability__SpvCapabilityFragmentDensityEXT: SpvCapability_ = 5291; -pub const SpvCapability__SpvCapabilityShadingRateNV: SpvCapability_ = 5291; -pub const SpvCapability__SpvCapabilityGroupNonUniformPartitionedNV: SpvCapability_ = 5297; -pub const SpvCapability__SpvCapabilityShaderNonUniform: SpvCapability_ = 5301; -pub const SpvCapability__SpvCapabilityShaderNonUniformEXT: SpvCapability_ = 5301; -pub const SpvCapability__SpvCapabilityRuntimeDescriptorArray: SpvCapability_ = 5302; -pub const SpvCapability__SpvCapabilityRuntimeDescriptorArrayEXT: SpvCapability_ = 5302; -pub const SpvCapability__SpvCapabilityInputAttachmentArrayDynamicIndexing: SpvCapability_ = 5303; -pub const SpvCapability__SpvCapabilityInputAttachmentArrayDynamicIndexingEXT: SpvCapability_ = 5303; -pub const SpvCapability__SpvCapabilityUniformTexelBufferArrayDynamicIndexing: SpvCapability_ = 5304; -pub const SpvCapability__SpvCapabilityUniformTexelBufferArrayDynamicIndexingEXT: SpvCapability_ = - 5304; -pub const SpvCapability__SpvCapabilityStorageTexelBufferArrayDynamicIndexing: SpvCapability_ = 5305; -pub const SpvCapability__SpvCapabilityStorageTexelBufferArrayDynamicIndexingEXT: SpvCapability_ = - 5305; -pub const SpvCapability__SpvCapabilityUniformBufferArrayNonUniformIndexing: SpvCapability_ = 5306; -pub const SpvCapability__SpvCapabilityUniformBufferArrayNonUniformIndexingEXT: SpvCapability_ = - 5306; -pub const SpvCapability__SpvCapabilitySampledImageArrayNonUniformIndexing: SpvCapability_ = 5307; -pub const SpvCapability__SpvCapabilitySampledImageArrayNonUniformIndexingEXT: SpvCapability_ = 5307; -pub const SpvCapability__SpvCapabilityStorageBufferArrayNonUniformIndexing: SpvCapability_ = 5308; -pub const SpvCapability__SpvCapabilityStorageBufferArrayNonUniformIndexingEXT: SpvCapability_ = - 5308; -pub const SpvCapability__SpvCapabilityStorageImageArrayNonUniformIndexing: SpvCapability_ = 5309; -pub const SpvCapability__SpvCapabilityStorageImageArrayNonUniformIndexingEXT: SpvCapability_ = 5309; -pub const SpvCapability__SpvCapabilityInputAttachmentArrayNonUniformIndexing: SpvCapability_ = 5310; -pub const SpvCapability__SpvCapabilityInputAttachmentArrayNonUniformIndexingEXT: SpvCapability_ = - 5310; -pub const SpvCapability__SpvCapabilityUniformTexelBufferArrayNonUniformIndexing: SpvCapability_ = - 5311; -pub const SpvCapability__SpvCapabilityUniformTexelBufferArrayNonUniformIndexingEXT: SpvCapability_ = - 5311; -pub const SpvCapability__SpvCapabilityStorageTexelBufferArrayNonUniformIndexing: SpvCapability_ = - 5312; -pub const SpvCapability__SpvCapabilityStorageTexelBufferArrayNonUniformIndexingEXT: SpvCapability_ = - 5312; -pub const SpvCapability__SpvCapabilityRayTracingPositionFetchKHR: SpvCapability_ = 5336; -pub const SpvCapability__SpvCapabilityRayTracingNV: SpvCapability_ = 5340; -pub const SpvCapability__SpvCapabilityRayTracingMotionBlurNV: SpvCapability_ = 5341; -pub const SpvCapability__SpvCapabilityVulkanMemoryModel: SpvCapability_ = 5345; -pub const SpvCapability__SpvCapabilityVulkanMemoryModelKHR: SpvCapability_ = 5345; -pub const SpvCapability__SpvCapabilityVulkanMemoryModelDeviceScope: SpvCapability_ = 5346; -pub const SpvCapability__SpvCapabilityVulkanMemoryModelDeviceScopeKHR: SpvCapability_ = 5346; -pub const SpvCapability__SpvCapabilityPhysicalStorageBufferAddresses: SpvCapability_ = 5347; -pub const SpvCapability__SpvCapabilityPhysicalStorageBufferAddressesEXT: SpvCapability_ = 5347; -pub const SpvCapability__SpvCapabilityComputeDerivativeGroupLinearKHR: SpvCapability_ = 5350; -pub const SpvCapability__SpvCapabilityComputeDerivativeGroupLinearNV: SpvCapability_ = 5350; -pub const SpvCapability__SpvCapabilityRayTracingProvisionalKHR: SpvCapability_ = 5353; -pub const SpvCapability__SpvCapabilityCooperativeMatrixNV: SpvCapability_ = 5357; -pub const SpvCapability__SpvCapabilityFragmentShaderSampleInterlockEXT: SpvCapability_ = 5363; -pub const SpvCapability__SpvCapabilityFragmentShaderShadingRateInterlockEXT: SpvCapability_ = 5372; -pub const SpvCapability__SpvCapabilityShaderSMBuiltinsNV: SpvCapability_ = 5373; -pub const SpvCapability__SpvCapabilityFragmentShaderPixelInterlockEXT: SpvCapability_ = 5378; -pub const SpvCapability__SpvCapabilityDemoteToHelperInvocation: SpvCapability_ = 5379; -pub const SpvCapability__SpvCapabilityDemoteToHelperInvocationEXT: SpvCapability_ = 5379; -pub const SpvCapability__SpvCapabilityDisplacementMicromapNV: SpvCapability_ = 5380; -pub const SpvCapability__SpvCapabilityRayTracingOpacityMicromapEXT: SpvCapability_ = 5381; -pub const SpvCapability__SpvCapabilityShaderInvocationReorderNV: SpvCapability_ = 5383; -pub const SpvCapability__SpvCapabilityBindlessTextureNV: SpvCapability_ = 5390; -pub const SpvCapability__SpvCapabilityRayQueryPositionFetchKHR: SpvCapability_ = 5391; -pub const SpvCapability__SpvCapabilityCooperativeVectorNV: SpvCapability_ = 5394; -pub const SpvCapability__SpvCapabilityAtomicFloat16VectorNV: SpvCapability_ = 5404; -pub const SpvCapability__SpvCapabilityRayTracingDisplacementMicromapNV: SpvCapability_ = 5409; -pub const SpvCapability__SpvCapabilityRawAccessChainsNV: SpvCapability_ = 5414; -pub const SpvCapability__SpvCapabilityRayTracingSpheresGeometryNV: SpvCapability_ = 5418; -pub const SpvCapability__SpvCapabilityRayTracingLinearSweptSpheresGeometryNV: SpvCapability_ = 5419; -pub const SpvCapability__SpvCapabilityCooperativeMatrixReductionsNV: SpvCapability_ = 5430; -pub const SpvCapability__SpvCapabilityCooperativeMatrixConversionsNV: SpvCapability_ = 5431; -pub const SpvCapability__SpvCapabilityCooperativeMatrixPerElementOperationsNV: SpvCapability_ = - 5432; -pub const SpvCapability__SpvCapabilityCooperativeMatrixTensorAddressingNV: SpvCapability_ = 5433; -pub const SpvCapability__SpvCapabilityCooperativeMatrixBlockLoadsNV: SpvCapability_ = 5434; -pub const SpvCapability__SpvCapabilityCooperativeVectorTrainingNV: SpvCapability_ = 5435; -pub const SpvCapability__SpvCapabilityRayTracingClusterAccelerationStructureNV: SpvCapability_ = - 5437; -pub const SpvCapability__SpvCapabilityTensorAddressingNV: SpvCapability_ = 5439; -pub const SpvCapability__SpvCapabilitySubgroupShuffleINTEL: SpvCapability_ = 5568; -pub const SpvCapability__SpvCapabilitySubgroupBufferBlockIOINTEL: SpvCapability_ = 5569; -pub const SpvCapability__SpvCapabilitySubgroupImageBlockIOINTEL: SpvCapability_ = 5570; -pub const SpvCapability__SpvCapabilitySubgroupImageMediaBlockIOINTEL: SpvCapability_ = 5579; -pub const SpvCapability__SpvCapabilityRoundToInfinityINTEL: SpvCapability_ = 5582; -pub const SpvCapability__SpvCapabilityFloatingPointModeINTEL: SpvCapability_ = 5583; -pub const SpvCapability__SpvCapabilityIntegerFunctions2INTEL: SpvCapability_ = 5584; -pub const SpvCapability__SpvCapabilityFunctionPointersINTEL: SpvCapability_ = 5603; -pub const SpvCapability__SpvCapabilityIndirectReferencesINTEL: SpvCapability_ = 5604; -pub const SpvCapability__SpvCapabilityAsmINTEL: SpvCapability_ = 5606; -pub const SpvCapability__SpvCapabilityAtomicFloat32MinMaxEXT: SpvCapability_ = 5612; -pub const SpvCapability__SpvCapabilityAtomicFloat64MinMaxEXT: SpvCapability_ = 5613; -pub const SpvCapability__SpvCapabilityAtomicFloat16MinMaxEXT: SpvCapability_ = 5616; -pub const SpvCapability__SpvCapabilityVectorComputeINTEL: SpvCapability_ = 5617; -pub const SpvCapability__SpvCapabilityVectorAnyINTEL: SpvCapability_ = 5619; -pub const SpvCapability__SpvCapabilityExpectAssumeKHR: SpvCapability_ = 5629; -pub const SpvCapability__SpvCapabilitySubgroupAvcMotionEstimationINTEL: SpvCapability_ = 5696; -pub const SpvCapability__SpvCapabilitySubgroupAvcMotionEstimationIntraINTEL: SpvCapability_ = 5697; -pub const SpvCapability__SpvCapabilitySubgroupAvcMotionEstimationChromaINTEL: SpvCapability_ = 5698; -pub const SpvCapability__SpvCapabilityVariableLengthArrayINTEL: SpvCapability_ = 5817; -pub const SpvCapability__SpvCapabilityFunctionFloatControlINTEL: SpvCapability_ = 5821; -pub const SpvCapability__SpvCapabilityFPGAMemoryAttributesINTEL: SpvCapability_ = 5824; -pub const SpvCapability__SpvCapabilityFPFastMathModeINTEL: SpvCapability_ = 5837; -pub const SpvCapability__SpvCapabilityArbitraryPrecisionIntegersINTEL: SpvCapability_ = 5844; -pub const SpvCapability__SpvCapabilityArbitraryPrecisionFloatingPointINTEL: SpvCapability_ = 5845; -pub const SpvCapability__SpvCapabilityUnstructuredLoopControlsINTEL: SpvCapability_ = 5886; -pub const SpvCapability__SpvCapabilityFPGALoopControlsINTEL: SpvCapability_ = 5888; -pub const SpvCapability__SpvCapabilityKernelAttributesINTEL: SpvCapability_ = 5892; -pub const SpvCapability__SpvCapabilityFPGAKernelAttributesINTEL: SpvCapability_ = 5897; -pub const SpvCapability__SpvCapabilityFPGAMemoryAccessesINTEL: SpvCapability_ = 5898; -pub const SpvCapability__SpvCapabilityFPGAClusterAttributesINTEL: SpvCapability_ = 5904; -pub const SpvCapability__SpvCapabilityLoopFuseINTEL: SpvCapability_ = 5906; -pub const SpvCapability__SpvCapabilityFPGADSPControlINTEL: SpvCapability_ = 5908; -pub const SpvCapability__SpvCapabilityMemoryAccessAliasingINTEL: SpvCapability_ = 5910; -pub const SpvCapability__SpvCapabilityFPGAInvocationPipeliningAttributesINTEL: SpvCapability_ = - 5916; -pub const SpvCapability__SpvCapabilityFPGABufferLocationINTEL: SpvCapability_ = 5920; -pub const SpvCapability__SpvCapabilityArbitraryPrecisionFixedPointINTEL: SpvCapability_ = 5922; -pub const SpvCapability__SpvCapabilityUSMStorageClassesINTEL: SpvCapability_ = 5935; -pub const SpvCapability__SpvCapabilityRuntimeAlignedAttributeINTEL: SpvCapability_ = 5939; -pub const SpvCapability__SpvCapabilityIOPipesINTEL: SpvCapability_ = 5943; -pub const SpvCapability__SpvCapabilityBlockingPipesINTEL: SpvCapability_ = 5945; -pub const SpvCapability__SpvCapabilityFPGARegINTEL: SpvCapability_ = 5948; -pub const SpvCapability__SpvCapabilityDotProductInputAll: SpvCapability_ = 6016; -pub const SpvCapability__SpvCapabilityDotProductInputAllKHR: SpvCapability_ = 6016; -pub const SpvCapability__SpvCapabilityDotProductInput4x8Bit: SpvCapability_ = 6017; -pub const SpvCapability__SpvCapabilityDotProductInput4x8BitKHR: SpvCapability_ = 6017; -pub const SpvCapability__SpvCapabilityDotProductInput4x8BitPacked: SpvCapability_ = 6018; -pub const SpvCapability__SpvCapabilityDotProductInput4x8BitPackedKHR: SpvCapability_ = 6018; -pub const SpvCapability__SpvCapabilityDotProduct: SpvCapability_ = 6019; -pub const SpvCapability__SpvCapabilityDotProductKHR: SpvCapability_ = 6019; -pub const SpvCapability__SpvCapabilityRayCullMaskKHR: SpvCapability_ = 6020; -pub const SpvCapability__SpvCapabilityCooperativeMatrixKHR: SpvCapability_ = 6022; -pub const SpvCapability__SpvCapabilityReplicatedCompositesEXT: SpvCapability_ = 6024; -pub const SpvCapability__SpvCapabilityBitInstructions: SpvCapability_ = 6025; -pub const SpvCapability__SpvCapabilityGroupNonUniformRotateKHR: SpvCapability_ = 6026; -pub const SpvCapability__SpvCapabilityFloatControls2: SpvCapability_ = 6029; -pub const SpvCapability__SpvCapabilityFMAKHR: SpvCapability_ = 6030; -pub const SpvCapability__SpvCapabilityAtomicFloat32AddEXT: SpvCapability_ = 6033; -pub const SpvCapability__SpvCapabilityAtomicFloat64AddEXT: SpvCapability_ = 6034; -pub const SpvCapability__SpvCapabilityLongCompositesINTEL: SpvCapability_ = 6089; -pub const SpvCapability__SpvCapabilityOptNoneEXT: SpvCapability_ = 6094; -pub const SpvCapability__SpvCapabilityOptNoneINTEL: SpvCapability_ = 6094; -pub const SpvCapability__SpvCapabilityAtomicFloat16AddEXT: SpvCapability_ = 6095; -pub const SpvCapability__SpvCapabilityDebugInfoModuleINTEL: SpvCapability_ = 6114; -pub const SpvCapability__SpvCapabilityBFloat16ConversionINTEL: SpvCapability_ = 6115; -pub const SpvCapability__SpvCapabilitySplitBarrierINTEL: SpvCapability_ = 6141; -pub const SpvCapability__SpvCapabilityArithmeticFenceEXT: SpvCapability_ = 6144; -pub const SpvCapability__SpvCapabilityFPGAClusterAttributesV2INTEL: SpvCapability_ = 6150; -pub const SpvCapability__SpvCapabilityFPGAKernelAttributesv2INTEL: SpvCapability_ = 6161; -pub const SpvCapability__SpvCapabilityTaskSequenceINTEL: SpvCapability_ = 6162; -pub const SpvCapability__SpvCapabilityFPMaxErrorINTEL: SpvCapability_ = 6169; -pub const SpvCapability__SpvCapabilityFPGALatencyControlINTEL: SpvCapability_ = 6171; -pub const SpvCapability__SpvCapabilityFPGAArgumentInterfacesINTEL: SpvCapability_ = 6174; -pub const SpvCapability__SpvCapabilityGlobalVariableHostAccessINTEL: SpvCapability_ = 6187; -pub const SpvCapability__SpvCapabilityGlobalVariableFPGADecorationsINTEL: SpvCapability_ = 6189; -pub const SpvCapability__SpvCapabilitySubgroupBufferPrefetchINTEL: SpvCapability_ = 6220; -pub const SpvCapability__SpvCapabilitySubgroup2DBlockIOINTEL: SpvCapability_ = 6228; -pub const SpvCapability__SpvCapabilitySubgroup2DBlockTransformINTEL: SpvCapability_ = 6229; -pub const SpvCapability__SpvCapabilitySubgroup2DBlockTransposeINTEL: SpvCapability_ = 6230; -pub const SpvCapability__SpvCapabilitySubgroupMatrixMultiplyAccumulateINTEL: SpvCapability_ = 6236; -pub const SpvCapability__SpvCapabilityTernaryBitwiseFunctionINTEL: SpvCapability_ = 6241; -pub const SpvCapability__SpvCapabilityUntypedVariableLengthArrayINTEL: SpvCapability_ = 6243; -pub const SpvCapability__SpvCapabilitySpecConditionalINTEL: SpvCapability_ = 6245; -pub const SpvCapability__SpvCapabilityFunctionVariantsINTEL: SpvCapability_ = 6246; -pub const SpvCapability__SpvCapabilityGroupUniformArithmeticKHR: SpvCapability_ = 6400; -pub const SpvCapability__SpvCapabilityTensorFloat32RoundingINTEL: SpvCapability_ = 6425; -pub const SpvCapability__SpvCapabilityMaskedGatherScatterINTEL: SpvCapability_ = 6427; -pub const SpvCapability__SpvCapabilityCacheControlsINTEL: SpvCapability_ = 6441; -pub const SpvCapability__SpvCapabilityRegisterLimitsINTEL: SpvCapability_ = 6460; -pub const SpvCapability__SpvCapabilityBindlessImagesINTEL: SpvCapability_ = 6528; -pub const SpvCapability__SpvCapabilityMax: SpvCapability_ = 2147483647; -pub type SpvCapability_ = ::std::os::raw::c_int; -pub use self::SpvCapability_ as SpvCapability; -pub const SpvRayFlagsShift__SpvRayFlagsOpaqueKHRShift: SpvRayFlagsShift_ = 0; -pub const SpvRayFlagsShift__SpvRayFlagsNoOpaqueKHRShift: SpvRayFlagsShift_ = 1; -pub const SpvRayFlagsShift__SpvRayFlagsTerminateOnFirstHitKHRShift: SpvRayFlagsShift_ = 2; -pub const SpvRayFlagsShift__SpvRayFlagsSkipClosestHitShaderKHRShift: SpvRayFlagsShift_ = 3; -pub const SpvRayFlagsShift__SpvRayFlagsCullBackFacingTrianglesKHRShift: SpvRayFlagsShift_ = 4; -pub const SpvRayFlagsShift__SpvRayFlagsCullFrontFacingTrianglesKHRShift: SpvRayFlagsShift_ = 5; -pub const SpvRayFlagsShift__SpvRayFlagsCullOpaqueKHRShift: SpvRayFlagsShift_ = 6; -pub const SpvRayFlagsShift__SpvRayFlagsCullNoOpaqueKHRShift: SpvRayFlagsShift_ = 7; -pub const SpvRayFlagsShift__SpvRayFlagsSkipBuiltinPrimitivesNVShift: SpvRayFlagsShift_ = 8; -pub const SpvRayFlagsShift__SpvRayFlagsSkipTrianglesKHRShift: SpvRayFlagsShift_ = 8; -pub const SpvRayFlagsShift__SpvRayFlagsSkipAABBsKHRShift: SpvRayFlagsShift_ = 9; -pub const SpvRayFlagsShift__SpvRayFlagsForceOpacityMicromap2StateEXTShift: SpvRayFlagsShift_ = 10; -pub const SpvRayFlagsShift__SpvRayFlagsMax: SpvRayFlagsShift_ = 2147483647; -pub type SpvRayFlagsShift_ = ::std::os::raw::c_int; -pub use self::SpvRayFlagsShift_ as SpvRayFlagsShift; -pub const SpvRayFlagsMask__SpvRayFlagsMaskNone: SpvRayFlagsMask_ = 0; -pub const SpvRayFlagsMask__SpvRayFlagsOpaqueKHRMask: SpvRayFlagsMask_ = 1; -pub const SpvRayFlagsMask__SpvRayFlagsNoOpaqueKHRMask: SpvRayFlagsMask_ = 2; -pub const SpvRayFlagsMask__SpvRayFlagsTerminateOnFirstHitKHRMask: SpvRayFlagsMask_ = 4; -pub const SpvRayFlagsMask__SpvRayFlagsSkipClosestHitShaderKHRMask: SpvRayFlagsMask_ = 8; -pub const SpvRayFlagsMask__SpvRayFlagsCullBackFacingTrianglesKHRMask: SpvRayFlagsMask_ = 16; -pub const SpvRayFlagsMask__SpvRayFlagsCullFrontFacingTrianglesKHRMask: SpvRayFlagsMask_ = 32; -pub const SpvRayFlagsMask__SpvRayFlagsCullOpaqueKHRMask: SpvRayFlagsMask_ = 64; -pub const SpvRayFlagsMask__SpvRayFlagsCullNoOpaqueKHRMask: SpvRayFlagsMask_ = 128; -pub const SpvRayFlagsMask__SpvRayFlagsSkipBuiltinPrimitivesNVMask: SpvRayFlagsMask_ = 256; -pub const SpvRayFlagsMask__SpvRayFlagsSkipTrianglesKHRMask: SpvRayFlagsMask_ = 256; -pub const SpvRayFlagsMask__SpvRayFlagsSkipAABBsKHRMask: SpvRayFlagsMask_ = 512; -pub const SpvRayFlagsMask__SpvRayFlagsForceOpacityMicromap2StateEXTMask: SpvRayFlagsMask_ = 1024; -pub type SpvRayFlagsMask_ = ::std::os::raw::c_int; -pub use self::SpvRayFlagsMask_ as SpvRayFlagsMask; -pub const SpvRayQueryIntersection__SpvRayQueryIntersectionRayQueryCandidateIntersectionKHR: - SpvRayQueryIntersection_ = 0; -pub const SpvRayQueryIntersection__SpvRayQueryIntersectionRayQueryCommittedIntersectionKHR: - SpvRayQueryIntersection_ = 1; -pub const SpvRayQueryIntersection__SpvRayQueryIntersectionMax: SpvRayQueryIntersection_ = - 2147483647; -pub type SpvRayQueryIntersection_ = ::std::os::raw::c_int; -pub use self::SpvRayQueryIntersection_ as SpvRayQueryIntersection; -pub const SpvRayQueryCommittedIntersectionType__SpvRayQueryCommittedIntersectionTypeRayQueryCommittedIntersectionNoneKHR : SpvRayQueryCommittedIntersectionType_ = 0 ; -pub const SpvRayQueryCommittedIntersectionType__SpvRayQueryCommittedIntersectionTypeRayQueryCommittedIntersectionTriangleKHR : SpvRayQueryCommittedIntersectionType_ = 1 ; -pub const SpvRayQueryCommittedIntersectionType__SpvRayQueryCommittedIntersectionTypeRayQueryCommittedIntersectionGeneratedKHR : SpvRayQueryCommittedIntersectionType_ = 2 ; -pub const SpvRayQueryCommittedIntersectionType__SpvRayQueryCommittedIntersectionTypeMax: - SpvRayQueryCommittedIntersectionType_ = 2147483647; -pub type SpvRayQueryCommittedIntersectionType_ = ::std::os::raw::c_int; -pub use self::SpvRayQueryCommittedIntersectionType_ as SpvRayQueryCommittedIntersectionType; -pub const SpvRayQueryCandidateIntersectionType__SpvRayQueryCandidateIntersectionTypeRayQueryCandidateIntersectionTriangleKHR : SpvRayQueryCandidateIntersectionType_ = 0 ; -pub const SpvRayQueryCandidateIntersectionType__SpvRayQueryCandidateIntersectionTypeRayQueryCandidateIntersectionAABBKHR : SpvRayQueryCandidateIntersectionType_ = 1 ; -pub const SpvRayQueryCandidateIntersectionType__SpvRayQueryCandidateIntersectionTypeMax: - SpvRayQueryCandidateIntersectionType_ = 2147483647; -pub type SpvRayQueryCandidateIntersectionType_ = ::std::os::raw::c_int; -pub use self::SpvRayQueryCandidateIntersectionType_ as SpvRayQueryCandidateIntersectionType; -pub const SpvFragmentShadingRateShift__SpvFragmentShadingRateVertical2PixelsShift: - SpvFragmentShadingRateShift_ = 0; -pub const SpvFragmentShadingRateShift__SpvFragmentShadingRateVertical4PixelsShift: - SpvFragmentShadingRateShift_ = 1; -pub const SpvFragmentShadingRateShift__SpvFragmentShadingRateHorizontal2PixelsShift: - SpvFragmentShadingRateShift_ = 2; -pub const SpvFragmentShadingRateShift__SpvFragmentShadingRateHorizontal4PixelsShift: - SpvFragmentShadingRateShift_ = 3; -pub const SpvFragmentShadingRateShift__SpvFragmentShadingRateMax: SpvFragmentShadingRateShift_ = - 2147483647; -pub type SpvFragmentShadingRateShift_ = ::std::os::raw::c_int; -pub use self::SpvFragmentShadingRateShift_ as SpvFragmentShadingRateShift; -pub const SpvFragmentShadingRateMask__SpvFragmentShadingRateMaskNone: SpvFragmentShadingRateMask_ = - 0; -pub const SpvFragmentShadingRateMask__SpvFragmentShadingRateVertical2PixelsMask: - SpvFragmentShadingRateMask_ = 1; -pub const SpvFragmentShadingRateMask__SpvFragmentShadingRateVertical4PixelsMask: - SpvFragmentShadingRateMask_ = 2; -pub const SpvFragmentShadingRateMask__SpvFragmentShadingRateHorizontal2PixelsMask: - SpvFragmentShadingRateMask_ = 4; -pub const SpvFragmentShadingRateMask__SpvFragmentShadingRateHorizontal4PixelsMask: - SpvFragmentShadingRateMask_ = 8; -pub type SpvFragmentShadingRateMask_ = ::std::os::raw::c_int; -pub use self::SpvFragmentShadingRateMask_ as SpvFragmentShadingRateMask; -pub const SpvFPDenormMode__SpvFPDenormModePreserve: SpvFPDenormMode_ = 0; -pub const SpvFPDenormMode__SpvFPDenormModeFlushToZero: SpvFPDenormMode_ = 1; -pub const SpvFPDenormMode__SpvFPDenormModeMax: SpvFPDenormMode_ = 2147483647; -pub type SpvFPDenormMode_ = ::std::os::raw::c_int; -pub use self::SpvFPDenormMode_ as SpvFPDenormMode; -pub const SpvFPOperationMode__SpvFPOperationModeIEEE: SpvFPOperationMode_ = 0; -pub const SpvFPOperationMode__SpvFPOperationModeALT: SpvFPOperationMode_ = 1; -pub const SpvFPOperationMode__SpvFPOperationModeMax: SpvFPOperationMode_ = 2147483647; -pub type SpvFPOperationMode_ = ::std::os::raw::c_int; -pub use self::SpvFPOperationMode_ as SpvFPOperationMode; -pub const SpvQuantizationModes__SpvQuantizationModesTRN: SpvQuantizationModes_ = 0; -pub const SpvQuantizationModes__SpvQuantizationModesTRN_ZERO: SpvQuantizationModes_ = 1; -pub const SpvQuantizationModes__SpvQuantizationModesRND: SpvQuantizationModes_ = 2; -pub const SpvQuantizationModes__SpvQuantizationModesRND_ZERO: SpvQuantizationModes_ = 3; -pub const SpvQuantizationModes__SpvQuantizationModesRND_INF: SpvQuantizationModes_ = 4; -pub const SpvQuantizationModes__SpvQuantizationModesRND_MIN_INF: SpvQuantizationModes_ = 5; -pub const SpvQuantizationModes__SpvQuantizationModesRND_CONV: SpvQuantizationModes_ = 6; -pub const SpvQuantizationModes__SpvQuantizationModesRND_CONV_ODD: SpvQuantizationModes_ = 7; -pub const SpvQuantizationModes__SpvQuantizationModesMax: SpvQuantizationModes_ = 2147483647; -pub type SpvQuantizationModes_ = ::std::os::raw::c_int; -pub use self::SpvQuantizationModes_ as SpvQuantizationModes; -pub const SpvOverflowModes__SpvOverflowModesWRAP: SpvOverflowModes_ = 0; -pub const SpvOverflowModes__SpvOverflowModesSAT: SpvOverflowModes_ = 1; -pub const SpvOverflowModes__SpvOverflowModesSAT_ZERO: SpvOverflowModes_ = 2; -pub const SpvOverflowModes__SpvOverflowModesSAT_SYM: SpvOverflowModes_ = 3; -pub const SpvOverflowModes__SpvOverflowModesMax: SpvOverflowModes_ = 2147483647; -pub type SpvOverflowModes_ = ::std::os::raw::c_int; -pub use self::SpvOverflowModes_ as SpvOverflowModes; -pub const SpvPackedVectorFormat__SpvPackedVectorFormatPackedVectorFormat4x8Bit: - SpvPackedVectorFormat_ = 0; -pub const SpvPackedVectorFormat__SpvPackedVectorFormatPackedVectorFormat4x8BitKHR: - SpvPackedVectorFormat_ = 0; -pub const SpvPackedVectorFormat__SpvPackedVectorFormatMax: SpvPackedVectorFormat_ = 2147483647; -pub type SpvPackedVectorFormat_ = ::std::os::raw::c_int; -pub use self::SpvPackedVectorFormat_ as SpvPackedVectorFormat; -pub const SpvCooperativeMatrixOperandsShift__SpvCooperativeMatrixOperandsMatrixASignedComponentsKHRShift : SpvCooperativeMatrixOperandsShift_ = 0 ; -pub const SpvCooperativeMatrixOperandsShift__SpvCooperativeMatrixOperandsMatrixBSignedComponentsKHRShift : SpvCooperativeMatrixOperandsShift_ = 1 ; -pub const SpvCooperativeMatrixOperandsShift__SpvCooperativeMatrixOperandsMatrixCSignedComponentsKHRShift : SpvCooperativeMatrixOperandsShift_ = 2 ; -pub const SpvCooperativeMatrixOperandsShift__SpvCooperativeMatrixOperandsMatrixResultSignedComponentsKHRShift : SpvCooperativeMatrixOperandsShift_ = 3 ; -pub const SpvCooperativeMatrixOperandsShift__SpvCooperativeMatrixOperandsSaturatingAccumulationKHRShift : SpvCooperativeMatrixOperandsShift_ = 4 ; -pub const SpvCooperativeMatrixOperandsShift__SpvCooperativeMatrixOperandsMax: - SpvCooperativeMatrixOperandsShift_ = 2147483647; -pub type SpvCooperativeMatrixOperandsShift_ = ::std::os::raw::c_int; -pub use self::SpvCooperativeMatrixOperandsShift_ as SpvCooperativeMatrixOperandsShift; -pub const SpvCooperativeMatrixOperandsMask__SpvCooperativeMatrixOperandsMaskNone: - SpvCooperativeMatrixOperandsMask_ = 0; -pub const SpvCooperativeMatrixOperandsMask__SpvCooperativeMatrixOperandsMatrixASignedComponentsKHRMask : SpvCooperativeMatrixOperandsMask_ = 1 ; -pub const SpvCooperativeMatrixOperandsMask__SpvCooperativeMatrixOperandsMatrixBSignedComponentsKHRMask : SpvCooperativeMatrixOperandsMask_ = 2 ; -pub const SpvCooperativeMatrixOperandsMask__SpvCooperativeMatrixOperandsMatrixCSignedComponentsKHRMask : SpvCooperativeMatrixOperandsMask_ = 4 ; -pub const SpvCooperativeMatrixOperandsMask__SpvCooperativeMatrixOperandsMatrixResultSignedComponentsKHRMask : SpvCooperativeMatrixOperandsMask_ = 8 ; -pub const SpvCooperativeMatrixOperandsMask__SpvCooperativeMatrixOperandsSaturatingAccumulationKHRMask : SpvCooperativeMatrixOperandsMask_ = 16 ; -pub type SpvCooperativeMatrixOperandsMask_ = ::std::os::raw::c_int; -pub use self::SpvCooperativeMatrixOperandsMask_ as SpvCooperativeMatrixOperandsMask; -pub const SpvCooperativeMatrixLayout__SpvCooperativeMatrixLayoutRowMajorKHR: - SpvCooperativeMatrixLayout_ = 0; -pub const SpvCooperativeMatrixLayout__SpvCooperativeMatrixLayoutColumnMajorKHR: - SpvCooperativeMatrixLayout_ = 1; -pub const SpvCooperativeMatrixLayout__SpvCooperativeMatrixLayoutRowBlockedInterleavedARM: - SpvCooperativeMatrixLayout_ = 4202; -pub const SpvCooperativeMatrixLayout__SpvCooperativeMatrixLayoutColumnBlockedInterleavedARM: - SpvCooperativeMatrixLayout_ = 4203; -pub const SpvCooperativeMatrixLayout__SpvCooperativeMatrixLayoutMax: SpvCooperativeMatrixLayout_ = - 2147483647; -pub type SpvCooperativeMatrixLayout_ = ::std::os::raw::c_int; -pub use self::SpvCooperativeMatrixLayout_ as SpvCooperativeMatrixLayout; -pub const SpvCooperativeMatrixUse__SpvCooperativeMatrixUseMatrixAKHR: SpvCooperativeMatrixUse_ = 0; -pub const SpvCooperativeMatrixUse__SpvCooperativeMatrixUseMatrixBKHR: SpvCooperativeMatrixUse_ = 1; -pub const SpvCooperativeMatrixUse__SpvCooperativeMatrixUseMatrixAccumulatorKHR: - SpvCooperativeMatrixUse_ = 2; -pub const SpvCooperativeMatrixUse__SpvCooperativeMatrixUseMax: SpvCooperativeMatrixUse_ = - 2147483647; -pub type SpvCooperativeMatrixUse_ = ::std::os::raw::c_int; -pub use self::SpvCooperativeMatrixUse_ as SpvCooperativeMatrixUse; -pub const SpvCooperativeMatrixReduceShift__SpvCooperativeMatrixReduceRowShift: - SpvCooperativeMatrixReduceShift_ = 0; -pub const SpvCooperativeMatrixReduceShift__SpvCooperativeMatrixReduceColumnShift: - SpvCooperativeMatrixReduceShift_ = 1; -pub const SpvCooperativeMatrixReduceShift__SpvCooperativeMatrixReduce2x2Shift: - SpvCooperativeMatrixReduceShift_ = 2; -pub const SpvCooperativeMatrixReduceShift__SpvCooperativeMatrixReduceMax: - SpvCooperativeMatrixReduceShift_ = 2147483647; -pub type SpvCooperativeMatrixReduceShift_ = ::std::os::raw::c_int; -pub use self::SpvCooperativeMatrixReduceShift_ as SpvCooperativeMatrixReduceShift; -pub const SpvCooperativeMatrixReduceMask__SpvCooperativeMatrixReduceMaskNone: - SpvCooperativeMatrixReduceMask_ = 0; -pub const SpvCooperativeMatrixReduceMask__SpvCooperativeMatrixReduceRowMask: - SpvCooperativeMatrixReduceMask_ = 1; -pub const SpvCooperativeMatrixReduceMask__SpvCooperativeMatrixReduceColumnMask: - SpvCooperativeMatrixReduceMask_ = 2; -pub const SpvCooperativeMatrixReduceMask__SpvCooperativeMatrixReduce2x2Mask: - SpvCooperativeMatrixReduceMask_ = 4; -pub type SpvCooperativeMatrixReduceMask_ = ::std::os::raw::c_int; -pub use self::SpvCooperativeMatrixReduceMask_ as SpvCooperativeMatrixReduceMask; -pub const SpvTensorClampMode__SpvTensorClampModeUndefined: SpvTensorClampMode_ = 0; -pub const SpvTensorClampMode__SpvTensorClampModeConstant: SpvTensorClampMode_ = 1; -pub const SpvTensorClampMode__SpvTensorClampModeClampToEdge: SpvTensorClampMode_ = 2; -pub const SpvTensorClampMode__SpvTensorClampModeRepeat: SpvTensorClampMode_ = 3; -pub const SpvTensorClampMode__SpvTensorClampModeRepeatMirrored: SpvTensorClampMode_ = 4; -pub const SpvTensorClampMode__SpvTensorClampModeMax: SpvTensorClampMode_ = 2147483647; -pub type SpvTensorClampMode_ = ::std::os::raw::c_int; -pub use self::SpvTensorClampMode_ as SpvTensorClampMode; -pub const SpvTensorAddressingOperandsShift__SpvTensorAddressingOperandsTensorViewShift: - SpvTensorAddressingOperandsShift_ = 0; -pub const SpvTensorAddressingOperandsShift__SpvTensorAddressingOperandsDecodeFuncShift: - SpvTensorAddressingOperandsShift_ = 1; -pub const SpvTensorAddressingOperandsShift__SpvTensorAddressingOperandsMax: - SpvTensorAddressingOperandsShift_ = 2147483647; -pub type SpvTensorAddressingOperandsShift_ = ::std::os::raw::c_int; -pub use self::SpvTensorAddressingOperandsShift_ as SpvTensorAddressingOperandsShift; -pub const SpvTensorAddressingOperandsMask__SpvTensorAddressingOperandsMaskNone: - SpvTensorAddressingOperandsMask_ = 0; -pub const SpvTensorAddressingOperandsMask__SpvTensorAddressingOperandsTensorViewMask: - SpvTensorAddressingOperandsMask_ = 1; -pub const SpvTensorAddressingOperandsMask__SpvTensorAddressingOperandsDecodeFuncMask: - SpvTensorAddressingOperandsMask_ = 2; -pub type SpvTensorAddressingOperandsMask_ = ::std::os::raw::c_int; -pub use self::SpvTensorAddressingOperandsMask_ as SpvTensorAddressingOperandsMask; -pub const SpvTensorOperandsShift__SpvTensorOperandsNontemporalARMShift: SpvTensorOperandsShift_ = 0; -pub const SpvTensorOperandsShift__SpvTensorOperandsOutOfBoundsValueARMShift: - SpvTensorOperandsShift_ = 1; -pub const SpvTensorOperandsShift__SpvTensorOperandsMakeElementAvailableARMShift: - SpvTensorOperandsShift_ = 2; -pub const SpvTensorOperandsShift__SpvTensorOperandsMakeElementVisibleARMShift: - SpvTensorOperandsShift_ = 3; -pub const SpvTensorOperandsShift__SpvTensorOperandsNonPrivateElementARMShift: - SpvTensorOperandsShift_ = 4; -pub const SpvTensorOperandsShift__SpvTensorOperandsMax: SpvTensorOperandsShift_ = 2147483647; -pub type SpvTensorOperandsShift_ = ::std::os::raw::c_int; -pub use self::SpvTensorOperandsShift_ as SpvTensorOperandsShift; -pub const SpvTensorOperandsMask__SpvTensorOperandsMaskNone: SpvTensorOperandsMask_ = 0; -pub const SpvTensorOperandsMask__SpvTensorOperandsNontemporalARMMask: SpvTensorOperandsMask_ = 1; -pub const SpvTensorOperandsMask__SpvTensorOperandsOutOfBoundsValueARMMask: SpvTensorOperandsMask_ = - 2; -pub const SpvTensorOperandsMask__SpvTensorOperandsMakeElementAvailableARMMask: - SpvTensorOperandsMask_ = 4; -pub const SpvTensorOperandsMask__SpvTensorOperandsMakeElementVisibleARMMask: - SpvTensorOperandsMask_ = 8; -pub const SpvTensorOperandsMask__SpvTensorOperandsNonPrivateElementARMMask: SpvTensorOperandsMask_ = - 16; -pub type SpvTensorOperandsMask_ = ::std::os::raw::c_int; -pub use self::SpvTensorOperandsMask_ as SpvTensorOperandsMask; -pub const SpvInitializationModeQualifier__SpvInitializationModeQualifierInitOnDeviceReprogramINTEL : SpvInitializationModeQualifier_ = 0 ; -pub const SpvInitializationModeQualifier__SpvInitializationModeQualifierInitOnDeviceResetINTEL: - SpvInitializationModeQualifier_ = 1; -pub const SpvInitializationModeQualifier__SpvInitializationModeQualifierMax: - SpvInitializationModeQualifier_ = 2147483647; -pub type SpvInitializationModeQualifier_ = ::std::os::raw::c_int; -pub use self::SpvInitializationModeQualifier_ as SpvInitializationModeQualifier; -pub const SpvHostAccessQualifier__SpvHostAccessQualifierNoneINTEL: SpvHostAccessQualifier_ = 0; -pub const SpvHostAccessQualifier__SpvHostAccessQualifierReadINTEL: SpvHostAccessQualifier_ = 1; -pub const SpvHostAccessQualifier__SpvHostAccessQualifierWriteINTEL: SpvHostAccessQualifier_ = 2; -pub const SpvHostAccessQualifier__SpvHostAccessQualifierReadWriteINTEL: SpvHostAccessQualifier_ = 3; -pub const SpvHostAccessQualifier__SpvHostAccessQualifierMax: SpvHostAccessQualifier_ = 2147483647; -pub type SpvHostAccessQualifier_ = ::std::os::raw::c_int; -pub use self::SpvHostAccessQualifier_ as SpvHostAccessQualifier; -pub const SpvLoadCacheControl__SpvLoadCacheControlUncachedINTEL: SpvLoadCacheControl_ = 0; -pub const SpvLoadCacheControl__SpvLoadCacheControlCachedINTEL: SpvLoadCacheControl_ = 1; -pub const SpvLoadCacheControl__SpvLoadCacheControlStreamingINTEL: SpvLoadCacheControl_ = 2; -pub const SpvLoadCacheControl__SpvLoadCacheControlInvalidateAfterReadINTEL: SpvLoadCacheControl_ = - 3; -pub const SpvLoadCacheControl__SpvLoadCacheControlConstCachedINTEL: SpvLoadCacheControl_ = 4; -pub const SpvLoadCacheControl__SpvLoadCacheControlMax: SpvLoadCacheControl_ = 2147483647; -pub type SpvLoadCacheControl_ = ::std::os::raw::c_int; -pub use self::SpvLoadCacheControl_ as SpvLoadCacheControl; -pub const SpvStoreCacheControl__SpvStoreCacheControlUncachedINTEL: SpvStoreCacheControl_ = 0; -pub const SpvStoreCacheControl__SpvStoreCacheControlWriteThroughINTEL: SpvStoreCacheControl_ = 1; -pub const SpvStoreCacheControl__SpvStoreCacheControlWriteBackINTEL: SpvStoreCacheControl_ = 2; -pub const SpvStoreCacheControl__SpvStoreCacheControlStreamingINTEL: SpvStoreCacheControl_ = 3; -pub const SpvStoreCacheControl__SpvStoreCacheControlMax: SpvStoreCacheControl_ = 2147483647; -pub type SpvStoreCacheControl_ = ::std::os::raw::c_int; -pub use self::SpvStoreCacheControl_ as SpvStoreCacheControl; -pub const SpvNamedMaximumNumberOfRegisters__SpvNamedMaximumNumberOfRegistersAutoINTEL: - SpvNamedMaximumNumberOfRegisters_ = 0; -pub const SpvNamedMaximumNumberOfRegisters__SpvNamedMaximumNumberOfRegistersMax: - SpvNamedMaximumNumberOfRegisters_ = 2147483647; -pub type SpvNamedMaximumNumberOfRegisters_ = ::std::os::raw::c_int; -pub use self::SpvNamedMaximumNumberOfRegisters_ as SpvNamedMaximumNumberOfRegisters; -pub const SpvMatrixMultiplyAccumulateOperandsShift__SpvMatrixMultiplyAccumulateOperandsMatrixASignedComponentsINTELShift : SpvMatrixMultiplyAccumulateOperandsShift_ = 0 ; -pub const SpvMatrixMultiplyAccumulateOperandsShift__SpvMatrixMultiplyAccumulateOperandsMatrixBSignedComponentsINTELShift : SpvMatrixMultiplyAccumulateOperandsShift_ = 1 ; -pub const SpvMatrixMultiplyAccumulateOperandsShift__SpvMatrixMultiplyAccumulateOperandsMatrixCBFloat16INTELShift : SpvMatrixMultiplyAccumulateOperandsShift_ = 2 ; -pub const SpvMatrixMultiplyAccumulateOperandsShift__SpvMatrixMultiplyAccumulateOperandsMatrixResultBFloat16INTELShift : SpvMatrixMultiplyAccumulateOperandsShift_ = 3 ; -pub const SpvMatrixMultiplyAccumulateOperandsShift__SpvMatrixMultiplyAccumulateOperandsMatrixAPackedInt8INTELShift : SpvMatrixMultiplyAccumulateOperandsShift_ = 4 ; -pub const SpvMatrixMultiplyAccumulateOperandsShift__SpvMatrixMultiplyAccumulateOperandsMatrixBPackedInt8INTELShift : SpvMatrixMultiplyAccumulateOperandsShift_ = 5 ; -pub const SpvMatrixMultiplyAccumulateOperandsShift__SpvMatrixMultiplyAccumulateOperandsMatrixAPackedInt4INTELShift : SpvMatrixMultiplyAccumulateOperandsShift_ = 6 ; -pub const SpvMatrixMultiplyAccumulateOperandsShift__SpvMatrixMultiplyAccumulateOperandsMatrixBPackedInt4INTELShift : SpvMatrixMultiplyAccumulateOperandsShift_ = 7 ; -pub const SpvMatrixMultiplyAccumulateOperandsShift__SpvMatrixMultiplyAccumulateOperandsMatrixATF32INTELShift : SpvMatrixMultiplyAccumulateOperandsShift_ = 8 ; -pub const SpvMatrixMultiplyAccumulateOperandsShift__SpvMatrixMultiplyAccumulateOperandsMatrixBTF32INTELShift : SpvMatrixMultiplyAccumulateOperandsShift_ = 9 ; -pub const SpvMatrixMultiplyAccumulateOperandsShift__SpvMatrixMultiplyAccumulateOperandsMatrixAPackedFloat16INTELShift : SpvMatrixMultiplyAccumulateOperandsShift_ = 10 ; -pub const SpvMatrixMultiplyAccumulateOperandsShift__SpvMatrixMultiplyAccumulateOperandsMatrixBPackedFloat16INTELShift : SpvMatrixMultiplyAccumulateOperandsShift_ = 11 ; -pub const SpvMatrixMultiplyAccumulateOperandsShift__SpvMatrixMultiplyAccumulateOperandsMatrixAPackedBFloat16INTELShift : SpvMatrixMultiplyAccumulateOperandsShift_ = 12 ; -pub const SpvMatrixMultiplyAccumulateOperandsShift__SpvMatrixMultiplyAccumulateOperandsMatrixBPackedBFloat16INTELShift : SpvMatrixMultiplyAccumulateOperandsShift_ = 13 ; -pub const SpvMatrixMultiplyAccumulateOperandsShift__SpvMatrixMultiplyAccumulateOperandsMax: - SpvMatrixMultiplyAccumulateOperandsShift_ = 2147483647; -pub type SpvMatrixMultiplyAccumulateOperandsShift_ = ::std::os::raw::c_int; -pub use self::SpvMatrixMultiplyAccumulateOperandsShift_ as SpvMatrixMultiplyAccumulateOperandsShift; -pub const SpvMatrixMultiplyAccumulateOperandsMask__SpvMatrixMultiplyAccumulateOperandsMaskNone: - SpvMatrixMultiplyAccumulateOperandsMask_ = 0; -pub const SpvMatrixMultiplyAccumulateOperandsMask__SpvMatrixMultiplyAccumulateOperandsMatrixASignedComponentsINTELMask : SpvMatrixMultiplyAccumulateOperandsMask_ = 1 ; -pub const SpvMatrixMultiplyAccumulateOperandsMask__SpvMatrixMultiplyAccumulateOperandsMatrixBSignedComponentsINTELMask : SpvMatrixMultiplyAccumulateOperandsMask_ = 2 ; -pub const SpvMatrixMultiplyAccumulateOperandsMask__SpvMatrixMultiplyAccumulateOperandsMatrixCBFloat16INTELMask : SpvMatrixMultiplyAccumulateOperandsMask_ = 4 ; -pub const SpvMatrixMultiplyAccumulateOperandsMask__SpvMatrixMultiplyAccumulateOperandsMatrixResultBFloat16INTELMask : SpvMatrixMultiplyAccumulateOperandsMask_ = 8 ; -pub const SpvMatrixMultiplyAccumulateOperandsMask__SpvMatrixMultiplyAccumulateOperandsMatrixAPackedInt8INTELMask : SpvMatrixMultiplyAccumulateOperandsMask_ = 16 ; -pub const SpvMatrixMultiplyAccumulateOperandsMask__SpvMatrixMultiplyAccumulateOperandsMatrixBPackedInt8INTELMask : SpvMatrixMultiplyAccumulateOperandsMask_ = 32 ; -pub const SpvMatrixMultiplyAccumulateOperandsMask__SpvMatrixMultiplyAccumulateOperandsMatrixAPackedInt4INTELMask : SpvMatrixMultiplyAccumulateOperandsMask_ = 64 ; -pub const SpvMatrixMultiplyAccumulateOperandsMask__SpvMatrixMultiplyAccumulateOperandsMatrixBPackedInt4INTELMask : SpvMatrixMultiplyAccumulateOperandsMask_ = 128 ; -pub const SpvMatrixMultiplyAccumulateOperandsMask__SpvMatrixMultiplyAccumulateOperandsMatrixATF32INTELMask : SpvMatrixMultiplyAccumulateOperandsMask_ = 256 ; -pub const SpvMatrixMultiplyAccumulateOperandsMask__SpvMatrixMultiplyAccumulateOperandsMatrixBTF32INTELMask : SpvMatrixMultiplyAccumulateOperandsMask_ = 512 ; -pub const SpvMatrixMultiplyAccumulateOperandsMask__SpvMatrixMultiplyAccumulateOperandsMatrixAPackedFloat16INTELMask : SpvMatrixMultiplyAccumulateOperandsMask_ = 1024 ; -pub const SpvMatrixMultiplyAccumulateOperandsMask__SpvMatrixMultiplyAccumulateOperandsMatrixBPackedFloat16INTELMask : SpvMatrixMultiplyAccumulateOperandsMask_ = 2048 ; -pub const SpvMatrixMultiplyAccumulateOperandsMask__SpvMatrixMultiplyAccumulateOperandsMatrixAPackedBFloat16INTELMask : SpvMatrixMultiplyAccumulateOperandsMask_ = 4096 ; -pub const SpvMatrixMultiplyAccumulateOperandsMask__SpvMatrixMultiplyAccumulateOperandsMatrixBPackedBFloat16INTELMask : SpvMatrixMultiplyAccumulateOperandsMask_ = 8192 ; -pub type SpvMatrixMultiplyAccumulateOperandsMask_ = ::std::os::raw::c_int; -pub use self::SpvMatrixMultiplyAccumulateOperandsMask_ as SpvMatrixMultiplyAccumulateOperandsMask; -pub const SpvRawAccessChainOperandsShift__SpvRawAccessChainOperandsRobustnessPerComponentNVShift: - SpvRawAccessChainOperandsShift_ = 0; -pub const SpvRawAccessChainOperandsShift__SpvRawAccessChainOperandsRobustnessPerElementNVShift: - SpvRawAccessChainOperandsShift_ = 1; -pub const SpvRawAccessChainOperandsShift__SpvRawAccessChainOperandsMax: - SpvRawAccessChainOperandsShift_ = 2147483647; -pub type SpvRawAccessChainOperandsShift_ = ::std::os::raw::c_int; -pub use self::SpvRawAccessChainOperandsShift_ as SpvRawAccessChainOperandsShift; -pub const SpvRawAccessChainOperandsMask__SpvRawAccessChainOperandsMaskNone: - SpvRawAccessChainOperandsMask_ = 0; -pub const SpvRawAccessChainOperandsMask__SpvRawAccessChainOperandsRobustnessPerComponentNVMask: - SpvRawAccessChainOperandsMask_ = 1; -pub const SpvRawAccessChainOperandsMask__SpvRawAccessChainOperandsRobustnessPerElementNVMask: - SpvRawAccessChainOperandsMask_ = 2; -pub type SpvRawAccessChainOperandsMask_ = ::std::os::raw::c_int; -pub use self::SpvRawAccessChainOperandsMask_ as SpvRawAccessChainOperandsMask; -pub const SpvFPEncoding__SpvFPEncodingBFloat16KHR: SpvFPEncoding_ = 0; -pub const SpvFPEncoding__SpvFPEncodingFloat8E4M3EXT: SpvFPEncoding_ = 4214; -pub const SpvFPEncoding__SpvFPEncodingFloat8E5M2EXT: SpvFPEncoding_ = 4215; -pub const SpvFPEncoding__SpvFPEncodingMax: SpvFPEncoding_ = 2147483647; -pub type SpvFPEncoding_ = ::std::os::raw::c_int; -pub use self::SpvFPEncoding_ as SpvFPEncoding; -pub const SpvCooperativeVectorMatrixLayout__SpvCooperativeVectorMatrixLayoutRowMajorNV: - SpvCooperativeVectorMatrixLayout_ = 0; -pub const SpvCooperativeVectorMatrixLayout__SpvCooperativeVectorMatrixLayoutColumnMajorNV: - SpvCooperativeVectorMatrixLayout_ = 1; -pub const SpvCooperativeVectorMatrixLayout__SpvCooperativeVectorMatrixLayoutInferencingOptimalNV: - SpvCooperativeVectorMatrixLayout_ = 2; -pub const SpvCooperativeVectorMatrixLayout__SpvCooperativeVectorMatrixLayoutTrainingOptimalNV: - SpvCooperativeVectorMatrixLayout_ = 3; -pub const SpvCooperativeVectorMatrixLayout__SpvCooperativeVectorMatrixLayoutMax: - SpvCooperativeVectorMatrixLayout_ = 2147483647; -pub type SpvCooperativeVectorMatrixLayout_ = ::std::os::raw::c_int; -pub use self::SpvCooperativeVectorMatrixLayout_ as SpvCooperativeVectorMatrixLayout; -pub const SpvComponentType__SpvComponentTypeFloat16NV: SpvComponentType_ = 0; -pub const SpvComponentType__SpvComponentTypeFloat32NV: SpvComponentType_ = 1; -pub const SpvComponentType__SpvComponentTypeFloat64NV: SpvComponentType_ = 2; -pub const SpvComponentType__SpvComponentTypeSignedInt8NV: SpvComponentType_ = 3; -pub const SpvComponentType__SpvComponentTypeSignedInt16NV: SpvComponentType_ = 4; -pub const SpvComponentType__SpvComponentTypeSignedInt32NV: SpvComponentType_ = 5; -pub const SpvComponentType__SpvComponentTypeSignedInt64NV: SpvComponentType_ = 6; -pub const SpvComponentType__SpvComponentTypeUnsignedInt8NV: SpvComponentType_ = 7; -pub const SpvComponentType__SpvComponentTypeUnsignedInt16NV: SpvComponentType_ = 8; -pub const SpvComponentType__SpvComponentTypeUnsignedInt32NV: SpvComponentType_ = 9; -pub const SpvComponentType__SpvComponentTypeUnsignedInt64NV: SpvComponentType_ = 10; -pub const SpvComponentType__SpvComponentTypeSignedInt8PackedNV: SpvComponentType_ = 1000491000; -pub const SpvComponentType__SpvComponentTypeUnsignedInt8PackedNV: SpvComponentType_ = 1000491001; -pub const SpvComponentType__SpvComponentTypeFloatE4M3NV: SpvComponentType_ = 1000491002; -pub const SpvComponentType__SpvComponentTypeFloatE5M2NV: SpvComponentType_ = 1000491003; -pub const SpvComponentType__SpvComponentTypeMax: SpvComponentType_ = 2147483647; -pub type SpvComponentType_ = ::std::os::raw::c_int; -pub use self::SpvComponentType_ as SpvComponentType; -pub const SpvOp__SpvOpNop: SpvOp_ = 0; -pub const SpvOp__SpvOpUndef: SpvOp_ = 1; -pub const SpvOp__SpvOpSourceContinued: SpvOp_ = 2; -pub const SpvOp__SpvOpSource: SpvOp_ = 3; -pub const SpvOp__SpvOpSourceExtension: SpvOp_ = 4; -pub const SpvOp__SpvOpName: SpvOp_ = 5; -pub const SpvOp__SpvOpMemberName: SpvOp_ = 6; -pub const SpvOp__SpvOpString: SpvOp_ = 7; -pub const SpvOp__SpvOpLine: SpvOp_ = 8; -pub const SpvOp__SpvOpExtension: SpvOp_ = 10; -pub const SpvOp__SpvOpExtInstImport: SpvOp_ = 11; -pub const SpvOp__SpvOpExtInst: SpvOp_ = 12; -pub const SpvOp__SpvOpMemoryModel: SpvOp_ = 14; -pub const SpvOp__SpvOpEntryPoint: SpvOp_ = 15; -pub const SpvOp__SpvOpExecutionMode: SpvOp_ = 16; -pub const SpvOp__SpvOpCapability: SpvOp_ = 17; -pub const SpvOp__SpvOpTypeVoid: SpvOp_ = 19; -pub const SpvOp__SpvOpTypeBool: SpvOp_ = 20; -pub const SpvOp__SpvOpTypeInt: SpvOp_ = 21; -pub const SpvOp__SpvOpTypeFloat: SpvOp_ = 22; -pub const SpvOp__SpvOpTypeVector: SpvOp_ = 23; -pub const SpvOp__SpvOpTypeMatrix: SpvOp_ = 24; -pub const SpvOp__SpvOpTypeImage: SpvOp_ = 25; -pub const SpvOp__SpvOpTypeSampler: SpvOp_ = 26; -pub const SpvOp__SpvOpTypeSampledImage: SpvOp_ = 27; -pub const SpvOp__SpvOpTypeArray: SpvOp_ = 28; -pub const SpvOp__SpvOpTypeRuntimeArray: SpvOp_ = 29; -pub const SpvOp__SpvOpTypeStruct: SpvOp_ = 30; -pub const SpvOp__SpvOpTypeOpaque: SpvOp_ = 31; -pub const SpvOp__SpvOpTypePointer: SpvOp_ = 32; -pub const SpvOp__SpvOpTypeFunction: SpvOp_ = 33; -pub const SpvOp__SpvOpTypeEvent: SpvOp_ = 34; -pub const SpvOp__SpvOpTypeDeviceEvent: SpvOp_ = 35; -pub const SpvOp__SpvOpTypeReserveId: SpvOp_ = 36; -pub const SpvOp__SpvOpTypeQueue: SpvOp_ = 37; -pub const SpvOp__SpvOpTypePipe: SpvOp_ = 38; -pub const SpvOp__SpvOpTypeForwardPointer: SpvOp_ = 39; -pub const SpvOp__SpvOpConstantTrue: SpvOp_ = 41; -pub const SpvOp__SpvOpConstantFalse: SpvOp_ = 42; -pub const SpvOp__SpvOpConstant: SpvOp_ = 43; -pub const SpvOp__SpvOpConstantComposite: SpvOp_ = 44; -pub const SpvOp__SpvOpConstantSampler: SpvOp_ = 45; -pub const SpvOp__SpvOpConstantNull: SpvOp_ = 46; -pub const SpvOp__SpvOpSpecConstantTrue: SpvOp_ = 48; -pub const SpvOp__SpvOpSpecConstantFalse: SpvOp_ = 49; -pub const SpvOp__SpvOpSpecConstant: SpvOp_ = 50; -pub const SpvOp__SpvOpSpecConstantComposite: SpvOp_ = 51; -pub const SpvOp__SpvOpSpecConstantOp: SpvOp_ = 52; -pub const SpvOp__SpvOpFunction: SpvOp_ = 54; -pub const SpvOp__SpvOpFunctionParameter: SpvOp_ = 55; -pub const SpvOp__SpvOpFunctionEnd: SpvOp_ = 56; -pub const SpvOp__SpvOpFunctionCall: SpvOp_ = 57; -pub const SpvOp__SpvOpVariable: SpvOp_ = 59; -pub const SpvOp__SpvOpImageTexelPointer: SpvOp_ = 60; -pub const SpvOp__SpvOpLoad: SpvOp_ = 61; -pub const SpvOp__SpvOpStore: SpvOp_ = 62; -pub const SpvOp__SpvOpCopyMemory: SpvOp_ = 63; -pub const SpvOp__SpvOpCopyMemorySized: SpvOp_ = 64; -pub const SpvOp__SpvOpAccessChain: SpvOp_ = 65; -pub const SpvOp__SpvOpInBoundsAccessChain: SpvOp_ = 66; -pub const SpvOp__SpvOpPtrAccessChain: SpvOp_ = 67; -pub const SpvOp__SpvOpArrayLength: SpvOp_ = 68; -pub const SpvOp__SpvOpGenericPtrMemSemantics: SpvOp_ = 69; -pub const SpvOp__SpvOpInBoundsPtrAccessChain: SpvOp_ = 70; -pub const SpvOp__SpvOpDecorate: SpvOp_ = 71; -pub const SpvOp__SpvOpMemberDecorate: SpvOp_ = 72; -pub const SpvOp__SpvOpDecorationGroup: SpvOp_ = 73; -pub const SpvOp__SpvOpGroupDecorate: SpvOp_ = 74; -pub const SpvOp__SpvOpGroupMemberDecorate: SpvOp_ = 75; -pub const SpvOp__SpvOpVectorExtractDynamic: SpvOp_ = 77; -pub const SpvOp__SpvOpVectorInsertDynamic: SpvOp_ = 78; -pub const SpvOp__SpvOpVectorShuffle: SpvOp_ = 79; -pub const SpvOp__SpvOpCompositeConstruct: SpvOp_ = 80; -pub const SpvOp__SpvOpCompositeExtract: SpvOp_ = 81; -pub const SpvOp__SpvOpCompositeInsert: SpvOp_ = 82; -pub const SpvOp__SpvOpCopyObject: SpvOp_ = 83; -pub const SpvOp__SpvOpTranspose: SpvOp_ = 84; -pub const SpvOp__SpvOpSampledImage: SpvOp_ = 86; -pub const SpvOp__SpvOpImageSampleImplicitLod: SpvOp_ = 87; -pub const SpvOp__SpvOpImageSampleExplicitLod: SpvOp_ = 88; -pub const SpvOp__SpvOpImageSampleDrefImplicitLod: SpvOp_ = 89; -pub const SpvOp__SpvOpImageSampleDrefExplicitLod: SpvOp_ = 90; -pub const SpvOp__SpvOpImageSampleProjImplicitLod: SpvOp_ = 91; -pub const SpvOp__SpvOpImageSampleProjExplicitLod: SpvOp_ = 92; -pub const SpvOp__SpvOpImageSampleProjDrefImplicitLod: SpvOp_ = 93; -pub const SpvOp__SpvOpImageSampleProjDrefExplicitLod: SpvOp_ = 94; -pub const SpvOp__SpvOpImageFetch: SpvOp_ = 95; -pub const SpvOp__SpvOpImageGather: SpvOp_ = 96; -pub const SpvOp__SpvOpImageDrefGather: SpvOp_ = 97; -pub const SpvOp__SpvOpImageRead: SpvOp_ = 98; -pub const SpvOp__SpvOpImageWrite: SpvOp_ = 99; -pub const SpvOp__SpvOpImage: SpvOp_ = 100; -pub const SpvOp__SpvOpImageQueryFormat: SpvOp_ = 101; -pub const SpvOp__SpvOpImageQueryOrder: SpvOp_ = 102; -pub const SpvOp__SpvOpImageQuerySizeLod: SpvOp_ = 103; -pub const SpvOp__SpvOpImageQuerySize: SpvOp_ = 104; -pub const SpvOp__SpvOpImageQueryLod: SpvOp_ = 105; -pub const SpvOp__SpvOpImageQueryLevels: SpvOp_ = 106; -pub const SpvOp__SpvOpImageQuerySamples: SpvOp_ = 107; -pub const SpvOp__SpvOpConvertFToU: SpvOp_ = 109; -pub const SpvOp__SpvOpConvertFToS: SpvOp_ = 110; -pub const SpvOp__SpvOpConvertSToF: SpvOp_ = 111; -pub const SpvOp__SpvOpConvertUToF: SpvOp_ = 112; -pub const SpvOp__SpvOpUConvert: SpvOp_ = 113; -pub const SpvOp__SpvOpSConvert: SpvOp_ = 114; -pub const SpvOp__SpvOpFConvert: SpvOp_ = 115; -pub const SpvOp__SpvOpQuantizeToF16: SpvOp_ = 116; -pub const SpvOp__SpvOpConvertPtrToU: SpvOp_ = 117; -pub const SpvOp__SpvOpSatConvertSToU: SpvOp_ = 118; -pub const SpvOp__SpvOpSatConvertUToS: SpvOp_ = 119; -pub const SpvOp__SpvOpConvertUToPtr: SpvOp_ = 120; -pub const SpvOp__SpvOpPtrCastToGeneric: SpvOp_ = 121; -pub const SpvOp__SpvOpGenericCastToPtr: SpvOp_ = 122; -pub const SpvOp__SpvOpGenericCastToPtrExplicit: SpvOp_ = 123; -pub const SpvOp__SpvOpBitcast: SpvOp_ = 124; -pub const SpvOp__SpvOpSNegate: SpvOp_ = 126; -pub const SpvOp__SpvOpFNegate: SpvOp_ = 127; -pub const SpvOp__SpvOpIAdd: SpvOp_ = 128; -pub const SpvOp__SpvOpFAdd: SpvOp_ = 129; -pub const SpvOp__SpvOpISub: SpvOp_ = 130; -pub const SpvOp__SpvOpFSub: SpvOp_ = 131; -pub const SpvOp__SpvOpIMul: SpvOp_ = 132; -pub const SpvOp__SpvOpFMul: SpvOp_ = 133; -pub const SpvOp__SpvOpUDiv: SpvOp_ = 134; -pub const SpvOp__SpvOpSDiv: SpvOp_ = 135; -pub const SpvOp__SpvOpFDiv: SpvOp_ = 136; -pub const SpvOp__SpvOpUMod: SpvOp_ = 137; -pub const SpvOp__SpvOpSRem: SpvOp_ = 138; -pub const SpvOp__SpvOpSMod: SpvOp_ = 139; -pub const SpvOp__SpvOpFRem: SpvOp_ = 140; -pub const SpvOp__SpvOpFMod: SpvOp_ = 141; -pub const SpvOp__SpvOpVectorTimesScalar: SpvOp_ = 142; -pub const SpvOp__SpvOpMatrixTimesScalar: SpvOp_ = 143; -pub const SpvOp__SpvOpVectorTimesMatrix: SpvOp_ = 144; -pub const SpvOp__SpvOpMatrixTimesVector: SpvOp_ = 145; -pub const SpvOp__SpvOpMatrixTimesMatrix: SpvOp_ = 146; -pub const SpvOp__SpvOpOuterProduct: SpvOp_ = 147; -pub const SpvOp__SpvOpDot: SpvOp_ = 148; -pub const SpvOp__SpvOpIAddCarry: SpvOp_ = 149; -pub const SpvOp__SpvOpISubBorrow: SpvOp_ = 150; -pub const SpvOp__SpvOpUMulExtended: SpvOp_ = 151; -pub const SpvOp__SpvOpSMulExtended: SpvOp_ = 152; -pub const SpvOp__SpvOpAny: SpvOp_ = 154; -pub const SpvOp__SpvOpAll: SpvOp_ = 155; -pub const SpvOp__SpvOpIsNan: SpvOp_ = 156; -pub const SpvOp__SpvOpIsInf: SpvOp_ = 157; -pub const SpvOp__SpvOpIsFinite: SpvOp_ = 158; -pub const SpvOp__SpvOpIsNormal: SpvOp_ = 159; -pub const SpvOp__SpvOpSignBitSet: SpvOp_ = 160; -pub const SpvOp__SpvOpLessOrGreater: SpvOp_ = 161; -pub const SpvOp__SpvOpOrdered: SpvOp_ = 162; -pub const SpvOp__SpvOpUnordered: SpvOp_ = 163; -pub const SpvOp__SpvOpLogicalEqual: SpvOp_ = 164; -pub const SpvOp__SpvOpLogicalNotEqual: SpvOp_ = 165; -pub const SpvOp__SpvOpLogicalOr: SpvOp_ = 166; -pub const SpvOp__SpvOpLogicalAnd: SpvOp_ = 167; -pub const SpvOp__SpvOpLogicalNot: SpvOp_ = 168; -pub const SpvOp__SpvOpSelect: SpvOp_ = 169; -pub const SpvOp__SpvOpIEqual: SpvOp_ = 170; -pub const SpvOp__SpvOpINotEqual: SpvOp_ = 171; -pub const SpvOp__SpvOpUGreaterThan: SpvOp_ = 172; -pub const SpvOp__SpvOpSGreaterThan: SpvOp_ = 173; -pub const SpvOp__SpvOpUGreaterThanEqual: SpvOp_ = 174; -pub const SpvOp__SpvOpSGreaterThanEqual: SpvOp_ = 175; -pub const SpvOp__SpvOpULessThan: SpvOp_ = 176; -pub const SpvOp__SpvOpSLessThan: SpvOp_ = 177; -pub const SpvOp__SpvOpULessThanEqual: SpvOp_ = 178; -pub const SpvOp__SpvOpSLessThanEqual: SpvOp_ = 179; -pub const SpvOp__SpvOpFOrdEqual: SpvOp_ = 180; -pub const SpvOp__SpvOpFUnordEqual: SpvOp_ = 181; -pub const SpvOp__SpvOpFOrdNotEqual: SpvOp_ = 182; -pub const SpvOp__SpvOpFUnordNotEqual: SpvOp_ = 183; -pub const SpvOp__SpvOpFOrdLessThan: SpvOp_ = 184; -pub const SpvOp__SpvOpFUnordLessThan: SpvOp_ = 185; -pub const SpvOp__SpvOpFOrdGreaterThan: SpvOp_ = 186; -pub const SpvOp__SpvOpFUnordGreaterThan: SpvOp_ = 187; -pub const SpvOp__SpvOpFOrdLessThanEqual: SpvOp_ = 188; -pub const SpvOp__SpvOpFUnordLessThanEqual: SpvOp_ = 189; -pub const SpvOp__SpvOpFOrdGreaterThanEqual: SpvOp_ = 190; -pub const SpvOp__SpvOpFUnordGreaterThanEqual: SpvOp_ = 191; -pub const SpvOp__SpvOpShiftRightLogical: SpvOp_ = 194; -pub const SpvOp__SpvOpShiftRightArithmetic: SpvOp_ = 195; -pub const SpvOp__SpvOpShiftLeftLogical: SpvOp_ = 196; -pub const SpvOp__SpvOpBitwiseOr: SpvOp_ = 197; -pub const SpvOp__SpvOpBitwiseXor: SpvOp_ = 198; -pub const SpvOp__SpvOpBitwiseAnd: SpvOp_ = 199; -pub const SpvOp__SpvOpNot: SpvOp_ = 200; -pub const SpvOp__SpvOpBitFieldInsert: SpvOp_ = 201; -pub const SpvOp__SpvOpBitFieldSExtract: SpvOp_ = 202; -pub const SpvOp__SpvOpBitFieldUExtract: SpvOp_ = 203; -pub const SpvOp__SpvOpBitReverse: SpvOp_ = 204; -pub const SpvOp__SpvOpBitCount: SpvOp_ = 205; -pub const SpvOp__SpvOpDPdx: SpvOp_ = 207; -pub const SpvOp__SpvOpDPdy: SpvOp_ = 208; -pub const SpvOp__SpvOpFwidth: SpvOp_ = 209; -pub const SpvOp__SpvOpDPdxFine: SpvOp_ = 210; -pub const SpvOp__SpvOpDPdyFine: SpvOp_ = 211; -pub const SpvOp__SpvOpFwidthFine: SpvOp_ = 212; -pub const SpvOp__SpvOpDPdxCoarse: SpvOp_ = 213; -pub const SpvOp__SpvOpDPdyCoarse: SpvOp_ = 214; -pub const SpvOp__SpvOpFwidthCoarse: SpvOp_ = 215; -pub const SpvOp__SpvOpEmitVertex: SpvOp_ = 218; -pub const SpvOp__SpvOpEndPrimitive: SpvOp_ = 219; -pub const SpvOp__SpvOpEmitStreamVertex: SpvOp_ = 220; -pub const SpvOp__SpvOpEndStreamPrimitive: SpvOp_ = 221; -pub const SpvOp__SpvOpControlBarrier: SpvOp_ = 224; -pub const SpvOp__SpvOpMemoryBarrier: SpvOp_ = 225; -pub const SpvOp__SpvOpAtomicLoad: SpvOp_ = 227; -pub const SpvOp__SpvOpAtomicStore: SpvOp_ = 228; -pub const SpvOp__SpvOpAtomicExchange: SpvOp_ = 229; -pub const SpvOp__SpvOpAtomicCompareExchange: SpvOp_ = 230; -pub const SpvOp__SpvOpAtomicCompareExchangeWeak: SpvOp_ = 231; -pub const SpvOp__SpvOpAtomicIIncrement: SpvOp_ = 232; -pub const SpvOp__SpvOpAtomicIDecrement: SpvOp_ = 233; -pub const SpvOp__SpvOpAtomicIAdd: SpvOp_ = 234; -pub const SpvOp__SpvOpAtomicISub: SpvOp_ = 235; -pub const SpvOp__SpvOpAtomicSMin: SpvOp_ = 236; -pub const SpvOp__SpvOpAtomicUMin: SpvOp_ = 237; -pub const SpvOp__SpvOpAtomicSMax: SpvOp_ = 238; -pub const SpvOp__SpvOpAtomicUMax: SpvOp_ = 239; -pub const SpvOp__SpvOpAtomicAnd: SpvOp_ = 240; -pub const SpvOp__SpvOpAtomicOr: SpvOp_ = 241; -pub const SpvOp__SpvOpAtomicXor: SpvOp_ = 242; -pub const SpvOp__SpvOpPhi: SpvOp_ = 245; -pub const SpvOp__SpvOpLoopMerge: SpvOp_ = 246; -pub const SpvOp__SpvOpSelectionMerge: SpvOp_ = 247; -pub const SpvOp__SpvOpLabel: SpvOp_ = 248; -pub const SpvOp__SpvOpBranch: SpvOp_ = 249; -pub const SpvOp__SpvOpBranchConditional: SpvOp_ = 250; -pub const SpvOp__SpvOpSwitch: SpvOp_ = 251; -pub const SpvOp__SpvOpKill: SpvOp_ = 252; -pub const SpvOp__SpvOpReturn: SpvOp_ = 253; -pub const SpvOp__SpvOpReturnValue: SpvOp_ = 254; -pub const SpvOp__SpvOpUnreachable: SpvOp_ = 255; -pub const SpvOp__SpvOpLifetimeStart: SpvOp_ = 256; -pub const SpvOp__SpvOpLifetimeStop: SpvOp_ = 257; -pub const SpvOp__SpvOpGroupAsyncCopy: SpvOp_ = 259; -pub const SpvOp__SpvOpGroupWaitEvents: SpvOp_ = 260; -pub const SpvOp__SpvOpGroupAll: SpvOp_ = 261; -pub const SpvOp__SpvOpGroupAny: SpvOp_ = 262; -pub const SpvOp__SpvOpGroupBroadcast: SpvOp_ = 263; -pub const SpvOp__SpvOpGroupIAdd: SpvOp_ = 264; -pub const SpvOp__SpvOpGroupFAdd: SpvOp_ = 265; -pub const SpvOp__SpvOpGroupFMin: SpvOp_ = 266; -pub const SpvOp__SpvOpGroupUMin: SpvOp_ = 267; -pub const SpvOp__SpvOpGroupSMin: SpvOp_ = 268; -pub const SpvOp__SpvOpGroupFMax: SpvOp_ = 269; -pub const SpvOp__SpvOpGroupUMax: SpvOp_ = 270; -pub const SpvOp__SpvOpGroupSMax: SpvOp_ = 271; -pub const SpvOp__SpvOpReadPipe: SpvOp_ = 274; -pub const SpvOp__SpvOpWritePipe: SpvOp_ = 275; -pub const SpvOp__SpvOpReservedReadPipe: SpvOp_ = 276; -pub const SpvOp__SpvOpReservedWritePipe: SpvOp_ = 277; -pub const SpvOp__SpvOpReserveReadPipePackets: SpvOp_ = 278; -pub const SpvOp__SpvOpReserveWritePipePackets: SpvOp_ = 279; -pub const SpvOp__SpvOpCommitReadPipe: SpvOp_ = 280; -pub const SpvOp__SpvOpCommitWritePipe: SpvOp_ = 281; -pub const SpvOp__SpvOpIsValidReserveId: SpvOp_ = 282; -pub const SpvOp__SpvOpGetNumPipePackets: SpvOp_ = 283; -pub const SpvOp__SpvOpGetMaxPipePackets: SpvOp_ = 284; -pub const SpvOp__SpvOpGroupReserveReadPipePackets: SpvOp_ = 285; -pub const SpvOp__SpvOpGroupReserveWritePipePackets: SpvOp_ = 286; -pub const SpvOp__SpvOpGroupCommitReadPipe: SpvOp_ = 287; -pub const SpvOp__SpvOpGroupCommitWritePipe: SpvOp_ = 288; -pub const SpvOp__SpvOpEnqueueMarker: SpvOp_ = 291; -pub const SpvOp__SpvOpEnqueueKernel: SpvOp_ = 292; -pub const SpvOp__SpvOpGetKernelNDrangeSubGroupCount: SpvOp_ = 293; -pub const SpvOp__SpvOpGetKernelNDrangeMaxSubGroupSize: SpvOp_ = 294; -pub const SpvOp__SpvOpGetKernelWorkGroupSize: SpvOp_ = 295; -pub const SpvOp__SpvOpGetKernelPreferredWorkGroupSizeMultiple: SpvOp_ = 296; -pub const SpvOp__SpvOpRetainEvent: SpvOp_ = 297; -pub const SpvOp__SpvOpReleaseEvent: SpvOp_ = 298; -pub const SpvOp__SpvOpCreateUserEvent: SpvOp_ = 299; -pub const SpvOp__SpvOpIsValidEvent: SpvOp_ = 300; -pub const SpvOp__SpvOpSetUserEventStatus: SpvOp_ = 301; -pub const SpvOp__SpvOpCaptureEventProfilingInfo: SpvOp_ = 302; -pub const SpvOp__SpvOpGetDefaultQueue: SpvOp_ = 303; -pub const SpvOp__SpvOpBuildNDRange: SpvOp_ = 304; -pub const SpvOp__SpvOpImageSparseSampleImplicitLod: SpvOp_ = 305; -pub const SpvOp__SpvOpImageSparseSampleExplicitLod: SpvOp_ = 306; -pub const SpvOp__SpvOpImageSparseSampleDrefImplicitLod: SpvOp_ = 307; -pub const SpvOp__SpvOpImageSparseSampleDrefExplicitLod: SpvOp_ = 308; -pub const SpvOp__SpvOpImageSparseSampleProjImplicitLod: SpvOp_ = 309; -pub const SpvOp__SpvOpImageSparseSampleProjExplicitLod: SpvOp_ = 310; -pub const SpvOp__SpvOpImageSparseSampleProjDrefImplicitLod: SpvOp_ = 311; -pub const SpvOp__SpvOpImageSparseSampleProjDrefExplicitLod: SpvOp_ = 312; -pub const SpvOp__SpvOpImageSparseFetch: SpvOp_ = 313; -pub const SpvOp__SpvOpImageSparseGather: SpvOp_ = 314; -pub const SpvOp__SpvOpImageSparseDrefGather: SpvOp_ = 315; -pub const SpvOp__SpvOpImageSparseTexelsResident: SpvOp_ = 316; -pub const SpvOp__SpvOpNoLine: SpvOp_ = 317; -pub const SpvOp__SpvOpAtomicFlagTestAndSet: SpvOp_ = 318; -pub const SpvOp__SpvOpAtomicFlagClear: SpvOp_ = 319; -pub const SpvOp__SpvOpImageSparseRead: SpvOp_ = 320; -pub const SpvOp__SpvOpSizeOf: SpvOp_ = 321; -pub const SpvOp__SpvOpTypePipeStorage: SpvOp_ = 322; -pub const SpvOp__SpvOpConstantPipeStorage: SpvOp_ = 323; -pub const SpvOp__SpvOpCreatePipeFromPipeStorage: SpvOp_ = 324; -pub const SpvOp__SpvOpGetKernelLocalSizeForSubgroupCount: SpvOp_ = 325; -pub const SpvOp__SpvOpGetKernelMaxNumSubgroups: SpvOp_ = 326; -pub const SpvOp__SpvOpTypeNamedBarrier: SpvOp_ = 327; -pub const SpvOp__SpvOpNamedBarrierInitialize: SpvOp_ = 328; -pub const SpvOp__SpvOpMemoryNamedBarrier: SpvOp_ = 329; -pub const SpvOp__SpvOpModuleProcessed: SpvOp_ = 330; -pub const SpvOp__SpvOpExecutionModeId: SpvOp_ = 331; -pub const SpvOp__SpvOpDecorateId: SpvOp_ = 332; -pub const SpvOp__SpvOpGroupNonUniformElect: SpvOp_ = 333; -pub const SpvOp__SpvOpGroupNonUniformAll: SpvOp_ = 334; -pub const SpvOp__SpvOpGroupNonUniformAny: SpvOp_ = 335; -pub const SpvOp__SpvOpGroupNonUniformAllEqual: SpvOp_ = 336; -pub const SpvOp__SpvOpGroupNonUniformBroadcast: SpvOp_ = 337; -pub const SpvOp__SpvOpGroupNonUniformBroadcastFirst: SpvOp_ = 338; -pub const SpvOp__SpvOpGroupNonUniformBallot: SpvOp_ = 339; -pub const SpvOp__SpvOpGroupNonUniformInverseBallot: SpvOp_ = 340; -pub const SpvOp__SpvOpGroupNonUniformBallotBitExtract: SpvOp_ = 341; -pub const SpvOp__SpvOpGroupNonUniformBallotBitCount: SpvOp_ = 342; -pub const SpvOp__SpvOpGroupNonUniformBallotFindLSB: SpvOp_ = 343; -pub const SpvOp__SpvOpGroupNonUniformBallotFindMSB: SpvOp_ = 344; -pub const SpvOp__SpvOpGroupNonUniformShuffle: SpvOp_ = 345; -pub const SpvOp__SpvOpGroupNonUniformShuffleXor: SpvOp_ = 346; -pub const SpvOp__SpvOpGroupNonUniformShuffleUp: SpvOp_ = 347; -pub const SpvOp__SpvOpGroupNonUniformShuffleDown: SpvOp_ = 348; -pub const SpvOp__SpvOpGroupNonUniformIAdd: SpvOp_ = 349; -pub const SpvOp__SpvOpGroupNonUniformFAdd: SpvOp_ = 350; -pub const SpvOp__SpvOpGroupNonUniformIMul: SpvOp_ = 351; -pub const SpvOp__SpvOpGroupNonUniformFMul: SpvOp_ = 352; -pub const SpvOp__SpvOpGroupNonUniformSMin: SpvOp_ = 353; -pub const SpvOp__SpvOpGroupNonUniformUMin: SpvOp_ = 354; -pub const SpvOp__SpvOpGroupNonUniformFMin: SpvOp_ = 355; -pub const SpvOp__SpvOpGroupNonUniformSMax: SpvOp_ = 356; -pub const SpvOp__SpvOpGroupNonUniformUMax: SpvOp_ = 357; -pub const SpvOp__SpvOpGroupNonUniformFMax: SpvOp_ = 358; -pub const SpvOp__SpvOpGroupNonUniformBitwiseAnd: SpvOp_ = 359; -pub const SpvOp__SpvOpGroupNonUniformBitwiseOr: SpvOp_ = 360; -pub const SpvOp__SpvOpGroupNonUniformBitwiseXor: SpvOp_ = 361; -pub const SpvOp__SpvOpGroupNonUniformLogicalAnd: SpvOp_ = 362; -pub const SpvOp__SpvOpGroupNonUniformLogicalOr: SpvOp_ = 363; -pub const SpvOp__SpvOpGroupNonUniformLogicalXor: SpvOp_ = 364; -pub const SpvOp__SpvOpGroupNonUniformQuadBroadcast: SpvOp_ = 365; -pub const SpvOp__SpvOpGroupNonUniformQuadSwap: SpvOp_ = 366; -pub const SpvOp__SpvOpCopyLogical: SpvOp_ = 400; -pub const SpvOp__SpvOpPtrEqual: SpvOp_ = 401; -pub const SpvOp__SpvOpPtrNotEqual: SpvOp_ = 402; -pub const SpvOp__SpvOpPtrDiff: SpvOp_ = 403; -pub const SpvOp__SpvOpColorAttachmentReadEXT: SpvOp_ = 4160; -pub const SpvOp__SpvOpDepthAttachmentReadEXT: SpvOp_ = 4161; -pub const SpvOp__SpvOpStencilAttachmentReadEXT: SpvOp_ = 4162; -pub const SpvOp__SpvOpTypeTensorARM: SpvOp_ = 4163; -pub const SpvOp__SpvOpTensorReadARM: SpvOp_ = 4164; -pub const SpvOp__SpvOpTensorWriteARM: SpvOp_ = 4165; -pub const SpvOp__SpvOpTensorQuerySizeARM: SpvOp_ = 4166; -pub const SpvOp__SpvOpGraphConstantARM: SpvOp_ = 4181; -pub const SpvOp__SpvOpGraphEntryPointARM: SpvOp_ = 4182; -pub const SpvOp__SpvOpGraphARM: SpvOp_ = 4183; -pub const SpvOp__SpvOpGraphInputARM: SpvOp_ = 4184; -pub const SpvOp__SpvOpGraphSetOutputARM: SpvOp_ = 4185; -pub const SpvOp__SpvOpGraphEndARM: SpvOp_ = 4186; -pub const SpvOp__SpvOpTypeGraphARM: SpvOp_ = 4190; -pub const SpvOp__SpvOpTerminateInvocation: SpvOp_ = 4416; -pub const SpvOp__SpvOpTypeUntypedPointerKHR: SpvOp_ = 4417; -pub const SpvOp__SpvOpUntypedVariableKHR: SpvOp_ = 4418; -pub const SpvOp__SpvOpUntypedAccessChainKHR: SpvOp_ = 4419; -pub const SpvOp__SpvOpUntypedInBoundsAccessChainKHR: SpvOp_ = 4420; -pub const SpvOp__SpvOpSubgroupBallotKHR: SpvOp_ = 4421; -pub const SpvOp__SpvOpSubgroupFirstInvocationKHR: SpvOp_ = 4422; -pub const SpvOp__SpvOpUntypedPtrAccessChainKHR: SpvOp_ = 4423; -pub const SpvOp__SpvOpUntypedInBoundsPtrAccessChainKHR: SpvOp_ = 4424; -pub const SpvOp__SpvOpUntypedArrayLengthKHR: SpvOp_ = 4425; -pub const SpvOp__SpvOpUntypedPrefetchKHR: SpvOp_ = 4426; -pub const SpvOp__SpvOpFmaKHR: SpvOp_ = 4427; -pub const SpvOp__SpvOpSubgroupAllKHR: SpvOp_ = 4428; -pub const SpvOp__SpvOpSubgroupAnyKHR: SpvOp_ = 4429; -pub const SpvOp__SpvOpSubgroupAllEqualKHR: SpvOp_ = 4430; -pub const SpvOp__SpvOpGroupNonUniformRotateKHR: SpvOp_ = 4431; -pub const SpvOp__SpvOpSubgroupReadInvocationKHR: SpvOp_ = 4432; -pub const SpvOp__SpvOpExtInstWithForwardRefsKHR: SpvOp_ = 4433; -pub const SpvOp__SpvOpUntypedGroupAsyncCopyKHR: SpvOp_ = 4434; -pub const SpvOp__SpvOpTraceRayKHR: SpvOp_ = 4445; -pub const SpvOp__SpvOpExecuteCallableKHR: SpvOp_ = 4446; -pub const SpvOp__SpvOpConvertUToAccelerationStructureKHR: SpvOp_ = 4447; -pub const SpvOp__SpvOpIgnoreIntersectionKHR: SpvOp_ = 4448; -pub const SpvOp__SpvOpTerminateRayKHR: SpvOp_ = 4449; -pub const SpvOp__SpvOpSDot: SpvOp_ = 4450; -pub const SpvOp__SpvOpSDotKHR: SpvOp_ = 4450; -pub const SpvOp__SpvOpUDot: SpvOp_ = 4451; -pub const SpvOp__SpvOpUDotKHR: SpvOp_ = 4451; -pub const SpvOp__SpvOpSUDot: SpvOp_ = 4452; -pub const SpvOp__SpvOpSUDotKHR: SpvOp_ = 4452; -pub const SpvOp__SpvOpSDotAccSat: SpvOp_ = 4453; -pub const SpvOp__SpvOpSDotAccSatKHR: SpvOp_ = 4453; -pub const SpvOp__SpvOpUDotAccSat: SpvOp_ = 4454; -pub const SpvOp__SpvOpUDotAccSatKHR: SpvOp_ = 4454; -pub const SpvOp__SpvOpSUDotAccSat: SpvOp_ = 4455; -pub const SpvOp__SpvOpSUDotAccSatKHR: SpvOp_ = 4455; -pub const SpvOp__SpvOpTypeCooperativeMatrixKHR: SpvOp_ = 4456; -pub const SpvOp__SpvOpCooperativeMatrixLoadKHR: SpvOp_ = 4457; -pub const SpvOp__SpvOpCooperativeMatrixStoreKHR: SpvOp_ = 4458; -pub const SpvOp__SpvOpCooperativeMatrixMulAddKHR: SpvOp_ = 4459; -pub const SpvOp__SpvOpCooperativeMatrixLengthKHR: SpvOp_ = 4460; -pub const SpvOp__SpvOpConstantCompositeReplicateEXT: SpvOp_ = 4461; -pub const SpvOp__SpvOpSpecConstantCompositeReplicateEXT: SpvOp_ = 4462; -pub const SpvOp__SpvOpCompositeConstructReplicateEXT: SpvOp_ = 4463; -pub const SpvOp__SpvOpTypeRayQueryKHR: SpvOp_ = 4472; -pub const SpvOp__SpvOpRayQueryInitializeKHR: SpvOp_ = 4473; -pub const SpvOp__SpvOpRayQueryTerminateKHR: SpvOp_ = 4474; -pub const SpvOp__SpvOpRayQueryGenerateIntersectionKHR: SpvOp_ = 4475; -pub const SpvOp__SpvOpRayQueryConfirmIntersectionKHR: SpvOp_ = 4476; -pub const SpvOp__SpvOpRayQueryProceedKHR: SpvOp_ = 4477; -pub const SpvOp__SpvOpRayQueryGetIntersectionTypeKHR: SpvOp_ = 4479; -pub const SpvOp__SpvOpImageSampleWeightedQCOM: SpvOp_ = 4480; -pub const SpvOp__SpvOpImageBoxFilterQCOM: SpvOp_ = 4481; -pub const SpvOp__SpvOpImageBlockMatchSSDQCOM: SpvOp_ = 4482; -pub const SpvOp__SpvOpImageBlockMatchSADQCOM: SpvOp_ = 4483; -pub const SpvOp__SpvOpBitCastArrayQCOM: SpvOp_ = 4497; -pub const SpvOp__SpvOpImageBlockMatchWindowSSDQCOM: SpvOp_ = 4500; -pub const SpvOp__SpvOpImageBlockMatchWindowSADQCOM: SpvOp_ = 4501; -pub const SpvOp__SpvOpImageBlockMatchGatherSSDQCOM: SpvOp_ = 4502; -pub const SpvOp__SpvOpImageBlockMatchGatherSADQCOM: SpvOp_ = 4503; -pub const SpvOp__SpvOpCompositeConstructCoopMatQCOM: SpvOp_ = 4540; -pub const SpvOp__SpvOpCompositeExtractCoopMatQCOM: SpvOp_ = 4541; -pub const SpvOp__SpvOpExtractSubArrayQCOM: SpvOp_ = 4542; -pub const SpvOp__SpvOpGroupIAddNonUniformAMD: SpvOp_ = 5000; -pub const SpvOp__SpvOpGroupFAddNonUniformAMD: SpvOp_ = 5001; -pub const SpvOp__SpvOpGroupFMinNonUniformAMD: SpvOp_ = 5002; -pub const SpvOp__SpvOpGroupUMinNonUniformAMD: SpvOp_ = 5003; -pub const SpvOp__SpvOpGroupSMinNonUniformAMD: SpvOp_ = 5004; -pub const SpvOp__SpvOpGroupFMaxNonUniformAMD: SpvOp_ = 5005; -pub const SpvOp__SpvOpGroupUMaxNonUniformAMD: SpvOp_ = 5006; -pub const SpvOp__SpvOpGroupSMaxNonUniformAMD: SpvOp_ = 5007; -pub const SpvOp__SpvOpFragmentMaskFetchAMD: SpvOp_ = 5011; -pub const SpvOp__SpvOpFragmentFetchAMD: SpvOp_ = 5012; -pub const SpvOp__SpvOpReadClockKHR: SpvOp_ = 5056; -pub const SpvOp__SpvOpAllocateNodePayloadsAMDX: SpvOp_ = 5074; -pub const SpvOp__SpvOpEnqueueNodePayloadsAMDX: SpvOp_ = 5075; -pub const SpvOp__SpvOpTypeNodePayloadArrayAMDX: SpvOp_ = 5076; -pub const SpvOp__SpvOpFinishWritingNodePayloadAMDX: SpvOp_ = 5078; -pub const SpvOp__SpvOpNodePayloadArrayLengthAMDX: SpvOp_ = 5090; -pub const SpvOp__SpvOpIsNodePayloadValidAMDX: SpvOp_ = 5101; -pub const SpvOp__SpvOpConstantStringAMDX: SpvOp_ = 5103; -pub const SpvOp__SpvOpSpecConstantStringAMDX: SpvOp_ = 5104; -pub const SpvOp__SpvOpGroupNonUniformQuadAllKHR: SpvOp_ = 5110; -pub const SpvOp__SpvOpGroupNonUniformQuadAnyKHR: SpvOp_ = 5111; -pub const SpvOp__SpvOpHitObjectRecordHitMotionNV: SpvOp_ = 5249; -pub const SpvOp__SpvOpHitObjectRecordHitWithIndexMotionNV: SpvOp_ = 5250; -pub const SpvOp__SpvOpHitObjectRecordMissMotionNV: SpvOp_ = 5251; -pub const SpvOp__SpvOpHitObjectGetWorldToObjectNV: SpvOp_ = 5252; -pub const SpvOp__SpvOpHitObjectGetObjectToWorldNV: SpvOp_ = 5253; -pub const SpvOp__SpvOpHitObjectGetObjectRayDirectionNV: SpvOp_ = 5254; -pub const SpvOp__SpvOpHitObjectGetObjectRayOriginNV: SpvOp_ = 5255; -pub const SpvOp__SpvOpHitObjectTraceRayMotionNV: SpvOp_ = 5256; -pub const SpvOp__SpvOpHitObjectGetShaderRecordBufferHandleNV: SpvOp_ = 5257; -pub const SpvOp__SpvOpHitObjectGetShaderBindingTableRecordIndexNV: SpvOp_ = 5258; -pub const SpvOp__SpvOpHitObjectRecordEmptyNV: SpvOp_ = 5259; -pub const SpvOp__SpvOpHitObjectTraceRayNV: SpvOp_ = 5260; -pub const SpvOp__SpvOpHitObjectRecordHitNV: SpvOp_ = 5261; -pub const SpvOp__SpvOpHitObjectRecordHitWithIndexNV: SpvOp_ = 5262; -pub const SpvOp__SpvOpHitObjectRecordMissNV: SpvOp_ = 5263; -pub const SpvOp__SpvOpHitObjectExecuteShaderNV: SpvOp_ = 5264; -pub const SpvOp__SpvOpHitObjectGetCurrentTimeNV: SpvOp_ = 5265; -pub const SpvOp__SpvOpHitObjectGetAttributesNV: SpvOp_ = 5266; -pub const SpvOp__SpvOpHitObjectGetHitKindNV: SpvOp_ = 5267; -pub const SpvOp__SpvOpHitObjectGetPrimitiveIndexNV: SpvOp_ = 5268; -pub const SpvOp__SpvOpHitObjectGetGeometryIndexNV: SpvOp_ = 5269; -pub const SpvOp__SpvOpHitObjectGetInstanceIdNV: SpvOp_ = 5270; -pub const SpvOp__SpvOpHitObjectGetInstanceCustomIndexNV: SpvOp_ = 5271; -pub const SpvOp__SpvOpHitObjectGetWorldRayDirectionNV: SpvOp_ = 5272; -pub const SpvOp__SpvOpHitObjectGetWorldRayOriginNV: SpvOp_ = 5273; -pub const SpvOp__SpvOpHitObjectGetRayTMaxNV: SpvOp_ = 5274; -pub const SpvOp__SpvOpHitObjectGetRayTMinNV: SpvOp_ = 5275; -pub const SpvOp__SpvOpHitObjectIsEmptyNV: SpvOp_ = 5276; -pub const SpvOp__SpvOpHitObjectIsHitNV: SpvOp_ = 5277; -pub const SpvOp__SpvOpHitObjectIsMissNV: SpvOp_ = 5278; -pub const SpvOp__SpvOpReorderThreadWithHitObjectNV: SpvOp_ = 5279; -pub const SpvOp__SpvOpReorderThreadWithHintNV: SpvOp_ = 5280; -pub const SpvOp__SpvOpTypeHitObjectNV: SpvOp_ = 5281; -pub const SpvOp__SpvOpImageSampleFootprintNV: SpvOp_ = 5283; -pub const SpvOp__SpvOpTypeCooperativeVectorNV: SpvOp_ = 5288; -pub const SpvOp__SpvOpCooperativeVectorMatrixMulNV: SpvOp_ = 5289; -pub const SpvOp__SpvOpCooperativeVectorOuterProductAccumulateNV: SpvOp_ = 5290; -pub const SpvOp__SpvOpCooperativeVectorReduceSumAccumulateNV: SpvOp_ = 5291; -pub const SpvOp__SpvOpCooperativeVectorMatrixMulAddNV: SpvOp_ = 5292; -pub const SpvOp__SpvOpCooperativeMatrixConvertNV: SpvOp_ = 5293; -pub const SpvOp__SpvOpEmitMeshTasksEXT: SpvOp_ = 5294; -pub const SpvOp__SpvOpSetMeshOutputsEXT: SpvOp_ = 5295; -pub const SpvOp__SpvOpGroupNonUniformPartitionNV: SpvOp_ = 5296; -pub const SpvOp__SpvOpWritePackedPrimitiveIndices4x8NV: SpvOp_ = 5299; -pub const SpvOp__SpvOpFetchMicroTriangleVertexPositionNV: SpvOp_ = 5300; -pub const SpvOp__SpvOpFetchMicroTriangleVertexBarycentricNV: SpvOp_ = 5301; -pub const SpvOp__SpvOpCooperativeVectorLoadNV: SpvOp_ = 5302; -pub const SpvOp__SpvOpCooperativeVectorStoreNV: SpvOp_ = 5303; -pub const SpvOp__SpvOpReportIntersectionKHR: SpvOp_ = 5334; -pub const SpvOp__SpvOpReportIntersectionNV: SpvOp_ = 5334; -pub const SpvOp__SpvOpIgnoreIntersectionNV: SpvOp_ = 5335; -pub const SpvOp__SpvOpTerminateRayNV: SpvOp_ = 5336; -pub const SpvOp__SpvOpTraceNV: SpvOp_ = 5337; -pub const SpvOp__SpvOpTraceMotionNV: SpvOp_ = 5338; -pub const SpvOp__SpvOpTraceRayMotionNV: SpvOp_ = 5339; -pub const SpvOp__SpvOpRayQueryGetIntersectionTriangleVertexPositionsKHR: SpvOp_ = 5340; -pub const SpvOp__SpvOpTypeAccelerationStructureKHR: SpvOp_ = 5341; -pub const SpvOp__SpvOpTypeAccelerationStructureNV: SpvOp_ = 5341; -pub const SpvOp__SpvOpExecuteCallableNV: SpvOp_ = 5344; -pub const SpvOp__SpvOpRayQueryGetClusterIdNV: SpvOp_ = 5345; -pub const SpvOp__SpvOpRayQueryGetIntersectionClusterIdNV: SpvOp_ = 5345; -pub const SpvOp__SpvOpHitObjectGetClusterIdNV: SpvOp_ = 5346; -pub const SpvOp__SpvOpTypeCooperativeMatrixNV: SpvOp_ = 5358; -pub const SpvOp__SpvOpCooperativeMatrixLoadNV: SpvOp_ = 5359; -pub const SpvOp__SpvOpCooperativeMatrixStoreNV: SpvOp_ = 5360; -pub const SpvOp__SpvOpCooperativeMatrixMulAddNV: SpvOp_ = 5361; -pub const SpvOp__SpvOpCooperativeMatrixLengthNV: SpvOp_ = 5362; -pub const SpvOp__SpvOpBeginInvocationInterlockEXT: SpvOp_ = 5364; -pub const SpvOp__SpvOpEndInvocationInterlockEXT: SpvOp_ = 5365; -pub const SpvOp__SpvOpCooperativeMatrixReduceNV: SpvOp_ = 5366; -pub const SpvOp__SpvOpCooperativeMatrixLoadTensorNV: SpvOp_ = 5367; -pub const SpvOp__SpvOpCooperativeMatrixStoreTensorNV: SpvOp_ = 5368; -pub const SpvOp__SpvOpCooperativeMatrixPerElementOpNV: SpvOp_ = 5369; -pub const SpvOp__SpvOpTypeTensorLayoutNV: SpvOp_ = 5370; -pub const SpvOp__SpvOpTypeTensorViewNV: SpvOp_ = 5371; -pub const SpvOp__SpvOpCreateTensorLayoutNV: SpvOp_ = 5372; -pub const SpvOp__SpvOpTensorLayoutSetDimensionNV: SpvOp_ = 5373; -pub const SpvOp__SpvOpTensorLayoutSetStrideNV: SpvOp_ = 5374; -pub const SpvOp__SpvOpTensorLayoutSliceNV: SpvOp_ = 5375; -pub const SpvOp__SpvOpTensorLayoutSetClampValueNV: SpvOp_ = 5376; -pub const SpvOp__SpvOpCreateTensorViewNV: SpvOp_ = 5377; -pub const SpvOp__SpvOpTensorViewSetDimensionNV: SpvOp_ = 5378; -pub const SpvOp__SpvOpTensorViewSetStrideNV: SpvOp_ = 5379; -pub const SpvOp__SpvOpDemoteToHelperInvocation: SpvOp_ = 5380; -pub const SpvOp__SpvOpDemoteToHelperInvocationEXT: SpvOp_ = 5380; -pub const SpvOp__SpvOpIsHelperInvocationEXT: SpvOp_ = 5381; -pub const SpvOp__SpvOpTensorViewSetClipNV: SpvOp_ = 5382; -pub const SpvOp__SpvOpTensorLayoutSetBlockSizeNV: SpvOp_ = 5384; -pub const SpvOp__SpvOpCooperativeMatrixTransposeNV: SpvOp_ = 5390; -pub const SpvOp__SpvOpConvertUToImageNV: SpvOp_ = 5391; -pub const SpvOp__SpvOpConvertUToSamplerNV: SpvOp_ = 5392; -pub const SpvOp__SpvOpConvertImageToUNV: SpvOp_ = 5393; -pub const SpvOp__SpvOpConvertSamplerToUNV: SpvOp_ = 5394; -pub const SpvOp__SpvOpConvertUToSampledImageNV: SpvOp_ = 5395; -pub const SpvOp__SpvOpConvertSampledImageToUNV: SpvOp_ = 5396; -pub const SpvOp__SpvOpSamplerImageAddressingModeNV: SpvOp_ = 5397; -pub const SpvOp__SpvOpRawAccessChainNV: SpvOp_ = 5398; -pub const SpvOp__SpvOpRayQueryGetIntersectionSpherePositionNV: SpvOp_ = 5427; -pub const SpvOp__SpvOpRayQueryGetIntersectionSphereRadiusNV: SpvOp_ = 5428; -pub const SpvOp__SpvOpRayQueryGetIntersectionLSSPositionsNV: SpvOp_ = 5429; -pub const SpvOp__SpvOpRayQueryGetIntersectionLSSRadiiNV: SpvOp_ = 5430; -pub const SpvOp__SpvOpRayQueryGetIntersectionLSSHitValueNV: SpvOp_ = 5431; -pub const SpvOp__SpvOpHitObjectGetSpherePositionNV: SpvOp_ = 5432; -pub const SpvOp__SpvOpHitObjectGetSphereRadiusNV: SpvOp_ = 5433; -pub const SpvOp__SpvOpHitObjectGetLSSPositionsNV: SpvOp_ = 5434; -pub const SpvOp__SpvOpHitObjectGetLSSRadiiNV: SpvOp_ = 5435; -pub const SpvOp__SpvOpHitObjectIsSphereHitNV: SpvOp_ = 5436; -pub const SpvOp__SpvOpHitObjectIsLSSHitNV: SpvOp_ = 5437; -pub const SpvOp__SpvOpRayQueryIsSphereHitNV: SpvOp_ = 5438; -pub const SpvOp__SpvOpRayQueryIsLSSHitNV: SpvOp_ = 5439; -pub const SpvOp__SpvOpSubgroupShuffleINTEL: SpvOp_ = 5571; -pub const SpvOp__SpvOpSubgroupShuffleDownINTEL: SpvOp_ = 5572; -pub const SpvOp__SpvOpSubgroupShuffleUpINTEL: SpvOp_ = 5573; -pub const SpvOp__SpvOpSubgroupShuffleXorINTEL: SpvOp_ = 5574; -pub const SpvOp__SpvOpSubgroupBlockReadINTEL: SpvOp_ = 5575; -pub const SpvOp__SpvOpSubgroupBlockWriteINTEL: SpvOp_ = 5576; -pub const SpvOp__SpvOpSubgroupImageBlockReadINTEL: SpvOp_ = 5577; -pub const SpvOp__SpvOpSubgroupImageBlockWriteINTEL: SpvOp_ = 5578; -pub const SpvOp__SpvOpSubgroupImageMediaBlockReadINTEL: SpvOp_ = 5580; -pub const SpvOp__SpvOpSubgroupImageMediaBlockWriteINTEL: SpvOp_ = 5581; -pub const SpvOp__SpvOpUCountLeadingZerosINTEL: SpvOp_ = 5585; -pub const SpvOp__SpvOpUCountTrailingZerosINTEL: SpvOp_ = 5586; -pub const SpvOp__SpvOpAbsISubINTEL: SpvOp_ = 5587; -pub const SpvOp__SpvOpAbsUSubINTEL: SpvOp_ = 5588; -pub const SpvOp__SpvOpIAddSatINTEL: SpvOp_ = 5589; -pub const SpvOp__SpvOpUAddSatINTEL: SpvOp_ = 5590; -pub const SpvOp__SpvOpIAverageINTEL: SpvOp_ = 5591; -pub const SpvOp__SpvOpUAverageINTEL: SpvOp_ = 5592; -pub const SpvOp__SpvOpIAverageRoundedINTEL: SpvOp_ = 5593; -pub const SpvOp__SpvOpUAverageRoundedINTEL: SpvOp_ = 5594; -pub const SpvOp__SpvOpISubSatINTEL: SpvOp_ = 5595; -pub const SpvOp__SpvOpUSubSatINTEL: SpvOp_ = 5596; -pub const SpvOp__SpvOpIMul32x16INTEL: SpvOp_ = 5597; -pub const SpvOp__SpvOpUMul32x16INTEL: SpvOp_ = 5598; -pub const SpvOp__SpvOpConstantFunctionPointerINTEL: SpvOp_ = 5600; -pub const SpvOp__SpvOpFunctionPointerCallINTEL: SpvOp_ = 5601; -pub const SpvOp__SpvOpAsmTargetINTEL: SpvOp_ = 5609; -pub const SpvOp__SpvOpAsmINTEL: SpvOp_ = 5610; -pub const SpvOp__SpvOpAsmCallINTEL: SpvOp_ = 5611; -pub const SpvOp__SpvOpAtomicFMinEXT: SpvOp_ = 5614; -pub const SpvOp__SpvOpAtomicFMaxEXT: SpvOp_ = 5615; -pub const SpvOp__SpvOpAssumeTrueKHR: SpvOp_ = 5630; -pub const SpvOp__SpvOpExpectKHR: SpvOp_ = 5631; -pub const SpvOp__SpvOpDecorateString: SpvOp_ = 5632; -pub const SpvOp__SpvOpDecorateStringGOOGLE: SpvOp_ = 5632; -pub const SpvOp__SpvOpMemberDecorateString: SpvOp_ = 5633; -pub const SpvOp__SpvOpMemberDecorateStringGOOGLE: SpvOp_ = 5633; -pub const SpvOp__SpvOpVmeImageINTEL: SpvOp_ = 5699; -pub const SpvOp__SpvOpTypeVmeImageINTEL: SpvOp_ = 5700; -pub const SpvOp__SpvOpTypeAvcImePayloadINTEL: SpvOp_ = 5701; -pub const SpvOp__SpvOpTypeAvcRefPayloadINTEL: SpvOp_ = 5702; -pub const SpvOp__SpvOpTypeAvcSicPayloadINTEL: SpvOp_ = 5703; -pub const SpvOp__SpvOpTypeAvcMcePayloadINTEL: SpvOp_ = 5704; -pub const SpvOp__SpvOpTypeAvcMceResultINTEL: SpvOp_ = 5705; -pub const SpvOp__SpvOpTypeAvcImeResultINTEL: SpvOp_ = 5706; -pub const SpvOp__SpvOpTypeAvcImeResultSingleReferenceStreamoutINTEL: SpvOp_ = 5707; -pub const SpvOp__SpvOpTypeAvcImeResultDualReferenceStreamoutINTEL: SpvOp_ = 5708; -pub const SpvOp__SpvOpTypeAvcImeSingleReferenceStreaminINTEL: SpvOp_ = 5709; -pub const SpvOp__SpvOpTypeAvcImeDualReferenceStreaminINTEL: SpvOp_ = 5710; -pub const SpvOp__SpvOpTypeAvcRefResultINTEL: SpvOp_ = 5711; -pub const SpvOp__SpvOpTypeAvcSicResultINTEL: SpvOp_ = 5712; -pub const SpvOp__SpvOpSubgroupAvcMceGetDefaultInterBaseMultiReferencePenaltyINTEL: SpvOp_ = 5713; -pub const SpvOp__SpvOpSubgroupAvcMceSetInterBaseMultiReferencePenaltyINTEL: SpvOp_ = 5714; -pub const SpvOp__SpvOpSubgroupAvcMceGetDefaultInterShapePenaltyINTEL: SpvOp_ = 5715; -pub const SpvOp__SpvOpSubgroupAvcMceSetInterShapePenaltyINTEL: SpvOp_ = 5716; -pub const SpvOp__SpvOpSubgroupAvcMceGetDefaultInterDirectionPenaltyINTEL: SpvOp_ = 5717; -pub const SpvOp__SpvOpSubgroupAvcMceSetInterDirectionPenaltyINTEL: SpvOp_ = 5718; -pub const SpvOp__SpvOpSubgroupAvcMceGetDefaultIntraLumaShapePenaltyINTEL: SpvOp_ = 5719; -pub const SpvOp__SpvOpSubgroupAvcMceGetDefaultInterMotionVectorCostTableINTEL: SpvOp_ = 5720; -pub const SpvOp__SpvOpSubgroupAvcMceGetDefaultHighPenaltyCostTableINTEL: SpvOp_ = 5721; -pub const SpvOp__SpvOpSubgroupAvcMceGetDefaultMediumPenaltyCostTableINTEL: SpvOp_ = 5722; -pub const SpvOp__SpvOpSubgroupAvcMceGetDefaultLowPenaltyCostTableINTEL: SpvOp_ = 5723; -pub const SpvOp__SpvOpSubgroupAvcMceSetMotionVectorCostFunctionINTEL: SpvOp_ = 5724; -pub const SpvOp__SpvOpSubgroupAvcMceGetDefaultIntraLumaModePenaltyINTEL: SpvOp_ = 5725; -pub const SpvOp__SpvOpSubgroupAvcMceGetDefaultNonDcLumaIntraPenaltyINTEL: SpvOp_ = 5726; -pub const SpvOp__SpvOpSubgroupAvcMceGetDefaultIntraChromaModeBasePenaltyINTEL: SpvOp_ = 5727; -pub const SpvOp__SpvOpSubgroupAvcMceSetAcOnlyHaarINTEL: SpvOp_ = 5728; -pub const SpvOp__SpvOpSubgroupAvcMceSetSourceInterlacedFieldPolarityINTEL: SpvOp_ = 5729; -pub const SpvOp__SpvOpSubgroupAvcMceSetSingleReferenceInterlacedFieldPolarityINTEL: SpvOp_ = 5730; -pub const SpvOp__SpvOpSubgroupAvcMceSetDualReferenceInterlacedFieldPolaritiesINTEL: SpvOp_ = 5731; -pub const SpvOp__SpvOpSubgroupAvcMceConvertToImePayloadINTEL: SpvOp_ = 5732; -pub const SpvOp__SpvOpSubgroupAvcMceConvertToImeResultINTEL: SpvOp_ = 5733; -pub const SpvOp__SpvOpSubgroupAvcMceConvertToRefPayloadINTEL: SpvOp_ = 5734; -pub const SpvOp__SpvOpSubgroupAvcMceConvertToRefResultINTEL: SpvOp_ = 5735; -pub const SpvOp__SpvOpSubgroupAvcMceConvertToSicPayloadINTEL: SpvOp_ = 5736; -pub const SpvOp__SpvOpSubgroupAvcMceConvertToSicResultINTEL: SpvOp_ = 5737; -pub const SpvOp__SpvOpSubgroupAvcMceGetMotionVectorsINTEL: SpvOp_ = 5738; -pub const SpvOp__SpvOpSubgroupAvcMceGetInterDistortionsINTEL: SpvOp_ = 5739; -pub const SpvOp__SpvOpSubgroupAvcMceGetBestInterDistortionsINTEL: SpvOp_ = 5740; -pub const SpvOp__SpvOpSubgroupAvcMceGetInterMajorShapeINTEL: SpvOp_ = 5741; -pub const SpvOp__SpvOpSubgroupAvcMceGetInterMinorShapeINTEL: SpvOp_ = 5742; -pub const SpvOp__SpvOpSubgroupAvcMceGetInterDirectionsINTEL: SpvOp_ = 5743; -pub const SpvOp__SpvOpSubgroupAvcMceGetInterMotionVectorCountINTEL: SpvOp_ = 5744; -pub const SpvOp__SpvOpSubgroupAvcMceGetInterReferenceIdsINTEL: SpvOp_ = 5745; -pub const SpvOp__SpvOpSubgroupAvcMceGetInterReferenceInterlacedFieldPolaritiesINTEL: SpvOp_ = 5746; -pub const SpvOp__SpvOpSubgroupAvcImeInitializeINTEL: SpvOp_ = 5747; -pub const SpvOp__SpvOpSubgroupAvcImeSetSingleReferenceINTEL: SpvOp_ = 5748; -pub const SpvOp__SpvOpSubgroupAvcImeSetDualReferenceINTEL: SpvOp_ = 5749; -pub const SpvOp__SpvOpSubgroupAvcImeRefWindowSizeINTEL: SpvOp_ = 5750; -pub const SpvOp__SpvOpSubgroupAvcImeAdjustRefOffsetINTEL: SpvOp_ = 5751; -pub const SpvOp__SpvOpSubgroupAvcImeConvertToMcePayloadINTEL: SpvOp_ = 5752; -pub const SpvOp__SpvOpSubgroupAvcImeSetMaxMotionVectorCountINTEL: SpvOp_ = 5753; -pub const SpvOp__SpvOpSubgroupAvcImeSetUnidirectionalMixDisableINTEL: SpvOp_ = 5754; -pub const SpvOp__SpvOpSubgroupAvcImeSetEarlySearchTerminationThresholdINTEL: SpvOp_ = 5755; -pub const SpvOp__SpvOpSubgroupAvcImeSetWeightedSadINTEL: SpvOp_ = 5756; -pub const SpvOp__SpvOpSubgroupAvcImeEvaluateWithSingleReferenceINTEL: SpvOp_ = 5757; -pub const SpvOp__SpvOpSubgroupAvcImeEvaluateWithDualReferenceINTEL: SpvOp_ = 5758; -pub const SpvOp__SpvOpSubgroupAvcImeEvaluateWithSingleReferenceStreaminINTEL: SpvOp_ = 5759; -pub const SpvOp__SpvOpSubgroupAvcImeEvaluateWithDualReferenceStreaminINTEL: SpvOp_ = 5760; -pub const SpvOp__SpvOpSubgroupAvcImeEvaluateWithSingleReferenceStreamoutINTEL: SpvOp_ = 5761; -pub const SpvOp__SpvOpSubgroupAvcImeEvaluateWithDualReferenceStreamoutINTEL: SpvOp_ = 5762; -pub const SpvOp__SpvOpSubgroupAvcImeEvaluateWithSingleReferenceStreaminoutINTEL: SpvOp_ = 5763; -pub const SpvOp__SpvOpSubgroupAvcImeEvaluateWithDualReferenceStreaminoutINTEL: SpvOp_ = 5764; -pub const SpvOp__SpvOpSubgroupAvcImeConvertToMceResultINTEL: SpvOp_ = 5765; -pub const SpvOp__SpvOpSubgroupAvcImeGetSingleReferenceStreaminINTEL: SpvOp_ = 5766; -pub const SpvOp__SpvOpSubgroupAvcImeGetDualReferenceStreaminINTEL: SpvOp_ = 5767; -pub const SpvOp__SpvOpSubgroupAvcImeStripSingleReferenceStreamoutINTEL: SpvOp_ = 5768; -pub const SpvOp__SpvOpSubgroupAvcImeStripDualReferenceStreamoutINTEL: SpvOp_ = 5769; -pub const SpvOp__SpvOpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeMotionVectorsINTEL: - SpvOp_ = 5770; -pub const SpvOp__SpvOpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeDistortionsINTEL: SpvOp_ = - 5771; -pub const SpvOp__SpvOpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeReferenceIdsINTEL: SpvOp_ = - 5772; -pub const SpvOp__SpvOpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeMotionVectorsINTEL: SpvOp_ = - 5773; -pub const SpvOp__SpvOpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeDistortionsINTEL: SpvOp_ = - 5774; -pub const SpvOp__SpvOpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeReferenceIdsINTEL: SpvOp_ = - 5775; -pub const SpvOp__SpvOpSubgroupAvcImeGetBorderReachedINTEL: SpvOp_ = 5776; -pub const SpvOp__SpvOpSubgroupAvcImeGetTruncatedSearchIndicationINTEL: SpvOp_ = 5777; -pub const SpvOp__SpvOpSubgroupAvcImeGetUnidirectionalEarlySearchTerminationINTEL: SpvOp_ = 5778; -pub const SpvOp__SpvOpSubgroupAvcImeGetWeightingPatternMinimumMotionVectorINTEL: SpvOp_ = 5779; -pub const SpvOp__SpvOpSubgroupAvcImeGetWeightingPatternMinimumDistortionINTEL: SpvOp_ = 5780; -pub const SpvOp__SpvOpSubgroupAvcFmeInitializeINTEL: SpvOp_ = 5781; -pub const SpvOp__SpvOpSubgroupAvcBmeInitializeINTEL: SpvOp_ = 5782; -pub const SpvOp__SpvOpSubgroupAvcRefConvertToMcePayloadINTEL: SpvOp_ = 5783; -pub const SpvOp__SpvOpSubgroupAvcRefSetBidirectionalMixDisableINTEL: SpvOp_ = 5784; -pub const SpvOp__SpvOpSubgroupAvcRefSetBilinearFilterEnableINTEL: SpvOp_ = 5785; -pub const SpvOp__SpvOpSubgroupAvcRefEvaluateWithSingleReferenceINTEL: SpvOp_ = 5786; -pub const SpvOp__SpvOpSubgroupAvcRefEvaluateWithDualReferenceINTEL: SpvOp_ = 5787; -pub const SpvOp__SpvOpSubgroupAvcRefEvaluateWithMultiReferenceINTEL: SpvOp_ = 5788; -pub const SpvOp__SpvOpSubgroupAvcRefEvaluateWithMultiReferenceInterlacedINTEL: SpvOp_ = 5789; -pub const SpvOp__SpvOpSubgroupAvcRefConvertToMceResultINTEL: SpvOp_ = 5790; -pub const SpvOp__SpvOpSubgroupAvcSicInitializeINTEL: SpvOp_ = 5791; -pub const SpvOp__SpvOpSubgroupAvcSicConfigureSkcINTEL: SpvOp_ = 5792; -pub const SpvOp__SpvOpSubgroupAvcSicConfigureIpeLumaINTEL: SpvOp_ = 5793; -pub const SpvOp__SpvOpSubgroupAvcSicConfigureIpeLumaChromaINTEL: SpvOp_ = 5794; -pub const SpvOp__SpvOpSubgroupAvcSicGetMotionVectorMaskINTEL: SpvOp_ = 5795; -pub const SpvOp__SpvOpSubgroupAvcSicConvertToMcePayloadINTEL: SpvOp_ = 5796; -pub const SpvOp__SpvOpSubgroupAvcSicSetIntraLumaShapePenaltyINTEL: SpvOp_ = 5797; -pub const SpvOp__SpvOpSubgroupAvcSicSetIntraLumaModeCostFunctionINTEL: SpvOp_ = 5798; -pub const SpvOp__SpvOpSubgroupAvcSicSetIntraChromaModeCostFunctionINTEL: SpvOp_ = 5799; -pub const SpvOp__SpvOpSubgroupAvcSicSetBilinearFilterEnableINTEL: SpvOp_ = 5800; -pub const SpvOp__SpvOpSubgroupAvcSicSetSkcForwardTransformEnableINTEL: SpvOp_ = 5801; -pub const SpvOp__SpvOpSubgroupAvcSicSetBlockBasedRawSkipSadINTEL: SpvOp_ = 5802; -pub const SpvOp__SpvOpSubgroupAvcSicEvaluateIpeINTEL: SpvOp_ = 5803; -pub const SpvOp__SpvOpSubgroupAvcSicEvaluateWithSingleReferenceINTEL: SpvOp_ = 5804; -pub const SpvOp__SpvOpSubgroupAvcSicEvaluateWithDualReferenceINTEL: SpvOp_ = 5805; -pub const SpvOp__SpvOpSubgroupAvcSicEvaluateWithMultiReferenceINTEL: SpvOp_ = 5806; -pub const SpvOp__SpvOpSubgroupAvcSicEvaluateWithMultiReferenceInterlacedINTEL: SpvOp_ = 5807; -pub const SpvOp__SpvOpSubgroupAvcSicConvertToMceResultINTEL: SpvOp_ = 5808; -pub const SpvOp__SpvOpSubgroupAvcSicGetIpeLumaShapeINTEL: SpvOp_ = 5809; -pub const SpvOp__SpvOpSubgroupAvcSicGetBestIpeLumaDistortionINTEL: SpvOp_ = 5810; -pub const SpvOp__SpvOpSubgroupAvcSicGetBestIpeChromaDistortionINTEL: SpvOp_ = 5811; -pub const SpvOp__SpvOpSubgroupAvcSicGetPackedIpeLumaModesINTEL: SpvOp_ = 5812; -pub const SpvOp__SpvOpSubgroupAvcSicGetIpeChromaModeINTEL: SpvOp_ = 5813; -pub const SpvOp__SpvOpSubgroupAvcSicGetPackedSkcLumaCountThresholdINTEL: SpvOp_ = 5814; -pub const SpvOp__SpvOpSubgroupAvcSicGetPackedSkcLumaSumThresholdINTEL: SpvOp_ = 5815; -pub const SpvOp__SpvOpSubgroupAvcSicGetInterRawSadsINTEL: SpvOp_ = 5816; -pub const SpvOp__SpvOpVariableLengthArrayINTEL: SpvOp_ = 5818; -pub const SpvOp__SpvOpSaveMemoryINTEL: SpvOp_ = 5819; -pub const SpvOp__SpvOpRestoreMemoryINTEL: SpvOp_ = 5820; -pub const SpvOp__SpvOpArbitraryFloatSinCosPiINTEL: SpvOp_ = 5840; -pub const SpvOp__SpvOpArbitraryFloatCastINTEL: SpvOp_ = 5841; -pub const SpvOp__SpvOpArbitraryFloatCastFromIntINTEL: SpvOp_ = 5842; -pub const SpvOp__SpvOpArbitraryFloatCastToIntINTEL: SpvOp_ = 5843; -pub const SpvOp__SpvOpArbitraryFloatAddINTEL: SpvOp_ = 5846; -pub const SpvOp__SpvOpArbitraryFloatSubINTEL: SpvOp_ = 5847; -pub const SpvOp__SpvOpArbitraryFloatMulINTEL: SpvOp_ = 5848; -pub const SpvOp__SpvOpArbitraryFloatDivINTEL: SpvOp_ = 5849; -pub const SpvOp__SpvOpArbitraryFloatGTINTEL: SpvOp_ = 5850; -pub const SpvOp__SpvOpArbitraryFloatGEINTEL: SpvOp_ = 5851; -pub const SpvOp__SpvOpArbitraryFloatLTINTEL: SpvOp_ = 5852; -pub const SpvOp__SpvOpArbitraryFloatLEINTEL: SpvOp_ = 5853; -pub const SpvOp__SpvOpArbitraryFloatEQINTEL: SpvOp_ = 5854; -pub const SpvOp__SpvOpArbitraryFloatRecipINTEL: SpvOp_ = 5855; -pub const SpvOp__SpvOpArbitraryFloatRSqrtINTEL: SpvOp_ = 5856; -pub const SpvOp__SpvOpArbitraryFloatCbrtINTEL: SpvOp_ = 5857; -pub const SpvOp__SpvOpArbitraryFloatHypotINTEL: SpvOp_ = 5858; -pub const SpvOp__SpvOpArbitraryFloatSqrtINTEL: SpvOp_ = 5859; -pub const SpvOp__SpvOpArbitraryFloatLogINTEL: SpvOp_ = 5860; -pub const SpvOp__SpvOpArbitraryFloatLog2INTEL: SpvOp_ = 5861; -pub const SpvOp__SpvOpArbitraryFloatLog10INTEL: SpvOp_ = 5862; -pub const SpvOp__SpvOpArbitraryFloatLog1pINTEL: SpvOp_ = 5863; -pub const SpvOp__SpvOpArbitraryFloatExpINTEL: SpvOp_ = 5864; -pub const SpvOp__SpvOpArbitraryFloatExp2INTEL: SpvOp_ = 5865; -pub const SpvOp__SpvOpArbitraryFloatExp10INTEL: SpvOp_ = 5866; -pub const SpvOp__SpvOpArbitraryFloatExpm1INTEL: SpvOp_ = 5867; -pub const SpvOp__SpvOpArbitraryFloatSinINTEL: SpvOp_ = 5868; -pub const SpvOp__SpvOpArbitraryFloatCosINTEL: SpvOp_ = 5869; -pub const SpvOp__SpvOpArbitraryFloatSinCosINTEL: SpvOp_ = 5870; -pub const SpvOp__SpvOpArbitraryFloatSinPiINTEL: SpvOp_ = 5871; -pub const SpvOp__SpvOpArbitraryFloatCosPiINTEL: SpvOp_ = 5872; -pub const SpvOp__SpvOpArbitraryFloatASinINTEL: SpvOp_ = 5873; -pub const SpvOp__SpvOpArbitraryFloatASinPiINTEL: SpvOp_ = 5874; -pub const SpvOp__SpvOpArbitraryFloatACosINTEL: SpvOp_ = 5875; -pub const SpvOp__SpvOpArbitraryFloatACosPiINTEL: SpvOp_ = 5876; -pub const SpvOp__SpvOpArbitraryFloatATanINTEL: SpvOp_ = 5877; -pub const SpvOp__SpvOpArbitraryFloatATanPiINTEL: SpvOp_ = 5878; -pub const SpvOp__SpvOpArbitraryFloatATan2INTEL: SpvOp_ = 5879; -pub const SpvOp__SpvOpArbitraryFloatPowINTEL: SpvOp_ = 5880; -pub const SpvOp__SpvOpArbitraryFloatPowRINTEL: SpvOp_ = 5881; -pub const SpvOp__SpvOpArbitraryFloatPowNINTEL: SpvOp_ = 5882; -pub const SpvOp__SpvOpLoopControlINTEL: SpvOp_ = 5887; -pub const SpvOp__SpvOpAliasDomainDeclINTEL: SpvOp_ = 5911; -pub const SpvOp__SpvOpAliasScopeDeclINTEL: SpvOp_ = 5912; -pub const SpvOp__SpvOpAliasScopeListDeclINTEL: SpvOp_ = 5913; -pub const SpvOp__SpvOpFixedSqrtINTEL: SpvOp_ = 5923; -pub const SpvOp__SpvOpFixedRecipINTEL: SpvOp_ = 5924; -pub const SpvOp__SpvOpFixedRsqrtINTEL: SpvOp_ = 5925; -pub const SpvOp__SpvOpFixedSinINTEL: SpvOp_ = 5926; -pub const SpvOp__SpvOpFixedCosINTEL: SpvOp_ = 5927; -pub const SpvOp__SpvOpFixedSinCosINTEL: SpvOp_ = 5928; -pub const SpvOp__SpvOpFixedSinPiINTEL: SpvOp_ = 5929; -pub const SpvOp__SpvOpFixedCosPiINTEL: SpvOp_ = 5930; -pub const SpvOp__SpvOpFixedSinCosPiINTEL: SpvOp_ = 5931; -pub const SpvOp__SpvOpFixedLogINTEL: SpvOp_ = 5932; -pub const SpvOp__SpvOpFixedExpINTEL: SpvOp_ = 5933; -pub const SpvOp__SpvOpPtrCastToCrossWorkgroupINTEL: SpvOp_ = 5934; -pub const SpvOp__SpvOpCrossWorkgroupCastToPtrINTEL: SpvOp_ = 5938; -pub const SpvOp__SpvOpReadPipeBlockingINTEL: SpvOp_ = 5946; -pub const SpvOp__SpvOpWritePipeBlockingINTEL: SpvOp_ = 5947; -pub const SpvOp__SpvOpFPGARegINTEL: SpvOp_ = 5949; -pub const SpvOp__SpvOpRayQueryGetRayTMinKHR: SpvOp_ = 6016; -pub const SpvOp__SpvOpRayQueryGetRayFlagsKHR: SpvOp_ = 6017; -pub const SpvOp__SpvOpRayQueryGetIntersectionTKHR: SpvOp_ = 6018; -pub const SpvOp__SpvOpRayQueryGetIntersectionInstanceCustomIndexKHR: SpvOp_ = 6019; -pub const SpvOp__SpvOpRayQueryGetIntersectionInstanceIdKHR: SpvOp_ = 6020; -pub const SpvOp__SpvOpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR: SpvOp_ = - 6021; -pub const SpvOp__SpvOpRayQueryGetIntersectionGeometryIndexKHR: SpvOp_ = 6022; -pub const SpvOp__SpvOpRayQueryGetIntersectionPrimitiveIndexKHR: SpvOp_ = 6023; -pub const SpvOp__SpvOpRayQueryGetIntersectionBarycentricsKHR: SpvOp_ = 6024; -pub const SpvOp__SpvOpRayQueryGetIntersectionFrontFaceKHR: SpvOp_ = 6025; -pub const SpvOp__SpvOpRayQueryGetIntersectionCandidateAABBOpaqueKHR: SpvOp_ = 6026; -pub const SpvOp__SpvOpRayQueryGetIntersectionObjectRayDirectionKHR: SpvOp_ = 6027; -pub const SpvOp__SpvOpRayQueryGetIntersectionObjectRayOriginKHR: SpvOp_ = 6028; -pub const SpvOp__SpvOpRayQueryGetWorldRayDirectionKHR: SpvOp_ = 6029; -pub const SpvOp__SpvOpRayQueryGetWorldRayOriginKHR: SpvOp_ = 6030; -pub const SpvOp__SpvOpRayQueryGetIntersectionObjectToWorldKHR: SpvOp_ = 6031; -pub const SpvOp__SpvOpRayQueryGetIntersectionWorldToObjectKHR: SpvOp_ = 6032; -pub const SpvOp__SpvOpAtomicFAddEXT: SpvOp_ = 6035; -pub const SpvOp__SpvOpTypeBufferSurfaceINTEL: SpvOp_ = 6086; -pub const SpvOp__SpvOpTypeStructContinuedINTEL: SpvOp_ = 6090; -pub const SpvOp__SpvOpConstantCompositeContinuedINTEL: SpvOp_ = 6091; -pub const SpvOp__SpvOpSpecConstantCompositeContinuedINTEL: SpvOp_ = 6092; -pub const SpvOp__SpvOpCompositeConstructContinuedINTEL: SpvOp_ = 6096; -pub const SpvOp__SpvOpConvertFToBF16INTEL: SpvOp_ = 6116; -pub const SpvOp__SpvOpConvertBF16ToFINTEL: SpvOp_ = 6117; -pub const SpvOp__SpvOpControlBarrierArriveINTEL: SpvOp_ = 6142; -pub const SpvOp__SpvOpControlBarrierWaitINTEL: SpvOp_ = 6143; -pub const SpvOp__SpvOpArithmeticFenceEXT: SpvOp_ = 6145; -pub const SpvOp__SpvOpTaskSequenceCreateINTEL: SpvOp_ = 6163; -pub const SpvOp__SpvOpTaskSequenceAsyncINTEL: SpvOp_ = 6164; -pub const SpvOp__SpvOpTaskSequenceGetINTEL: SpvOp_ = 6165; -pub const SpvOp__SpvOpTaskSequenceReleaseINTEL: SpvOp_ = 6166; -pub const SpvOp__SpvOpTypeTaskSequenceINTEL: SpvOp_ = 6199; -pub const SpvOp__SpvOpSubgroupBlockPrefetchINTEL: SpvOp_ = 6221; -pub const SpvOp__SpvOpSubgroup2DBlockLoadINTEL: SpvOp_ = 6231; -pub const SpvOp__SpvOpSubgroup2DBlockLoadTransformINTEL: SpvOp_ = 6232; -pub const SpvOp__SpvOpSubgroup2DBlockLoadTransposeINTEL: SpvOp_ = 6233; -pub const SpvOp__SpvOpSubgroup2DBlockPrefetchINTEL: SpvOp_ = 6234; -pub const SpvOp__SpvOpSubgroup2DBlockStoreINTEL: SpvOp_ = 6235; -pub const SpvOp__SpvOpSubgroupMatrixMultiplyAccumulateINTEL: SpvOp_ = 6237; -pub const SpvOp__SpvOpBitwiseFunctionINTEL: SpvOp_ = 6242; -pub const SpvOp__SpvOpUntypedVariableLengthArrayINTEL: SpvOp_ = 6244; -pub const SpvOp__SpvOpConditionalExtensionINTEL: SpvOp_ = 6248; -pub const SpvOp__SpvOpConditionalEntryPointINTEL: SpvOp_ = 6249; -pub const SpvOp__SpvOpConditionalCapabilityINTEL: SpvOp_ = 6250; -pub const SpvOp__SpvOpSpecConstantTargetINTEL: SpvOp_ = 6251; -pub const SpvOp__SpvOpSpecConstantArchitectureINTEL: SpvOp_ = 6252; -pub const SpvOp__SpvOpSpecConstantCapabilitiesINTEL: SpvOp_ = 6253; -pub const SpvOp__SpvOpConditionalCopyObjectINTEL: SpvOp_ = 6254; -pub const SpvOp__SpvOpGroupIMulKHR: SpvOp_ = 6401; -pub const SpvOp__SpvOpGroupFMulKHR: SpvOp_ = 6402; -pub const SpvOp__SpvOpGroupBitwiseAndKHR: SpvOp_ = 6403; -pub const SpvOp__SpvOpGroupBitwiseOrKHR: SpvOp_ = 6404; -pub const SpvOp__SpvOpGroupBitwiseXorKHR: SpvOp_ = 6405; -pub const SpvOp__SpvOpGroupLogicalAndKHR: SpvOp_ = 6406; -pub const SpvOp__SpvOpGroupLogicalOrKHR: SpvOp_ = 6407; -pub const SpvOp__SpvOpGroupLogicalXorKHR: SpvOp_ = 6408; -pub const SpvOp__SpvOpRoundFToTF32INTEL: SpvOp_ = 6426; -pub const SpvOp__SpvOpMaskedGatherINTEL: SpvOp_ = 6428; -pub const SpvOp__SpvOpMaskedScatterINTEL: SpvOp_ = 6429; -pub const SpvOp__SpvOpConvertHandleToImageINTEL: SpvOp_ = 6529; -pub const SpvOp__SpvOpConvertHandleToSamplerINTEL: SpvOp_ = 6530; -pub const SpvOp__SpvOpConvertHandleToSampledImageINTEL: SpvOp_ = 6531; -pub const SpvOp__SpvOpMax: SpvOp_ = 2147483647; -pub type SpvOp_ = ::std::os::raw::c_int; -pub use self::SpvOp_ as SpvOp; -extern "C" { - pub fn spvc_get_version( - major: *mut ::std::os::raw::c_uint, - minor: *mut ::std::os::raw::c_uint, - patch: *mut ::std::os::raw::c_uint, - ); -} -extern "C" { - pub fn spvc_get_commit_revision_and_timestamp() -> *const ::std::os::raw::c_char; -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct spvc_context_s { - _unused: [u8; 0], -} -pub type spvc_context = *mut spvc_context_s; -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct spvc_parsed_ir_s { - _unused: [u8; 0], -} -pub type spvc_parsed_ir = *mut spvc_parsed_ir_s; -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct spvc_compiler_s { - _unused: [u8; 0], -} -pub type spvc_compiler = *mut spvc_compiler_s; -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct spvc_compiler_options_s { - _unused: [u8; 0], -} -pub type spvc_compiler_options = *mut spvc_compiler_options_s; -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct spvc_resources_s { - _unused: [u8; 0], -} -pub type spvc_resources = *mut spvc_resources_s; -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct spvc_type_s { - _unused: [u8; 0], -} -pub type spvc_type = *const spvc_type_s; -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct spvc_constant_s { - _unused: [u8; 0], -} -pub type spvc_constant = *mut spvc_constant_s; -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct spvc_set_s { - _unused: [u8; 0], -} -pub type spvc_set = *const spvc_set_s; -pub type spvc_type_id = SpvId; -pub type spvc_variable_id = SpvId; -pub type spvc_constant_id = SpvId; -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct spvc_reflected_resource { - pub id: spvc_variable_id, - pub base_type_id: spvc_type_id, - pub type_id: spvc_type_id, - pub name: *const ::std::os::raw::c_char, -} -#[test] -fn bindgen_test_layout_spvc_reflected_resource() { - const UNINIT: ::std::mem::MaybeUninit = - ::std::mem::MaybeUninit::uninit(); - let ptr = UNINIT.as_ptr(); - assert_eq!( - ::std::mem::size_of::(), - 24usize, - concat!("Size of: ", stringify!(spvc_reflected_resource)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(spvc_reflected_resource)) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).id) as usize - ptr as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(spvc_reflected_resource), - "::", - stringify!(id) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).base_type_id) as usize - ptr as usize }, - 4usize, - concat!( - "Offset of field: ", - stringify!(spvc_reflected_resource), - "::", - stringify!(base_type_id) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).type_id) as usize - ptr as usize }, - 8usize, - concat!( - "Offset of field: ", - stringify!(spvc_reflected_resource), - "::", - stringify!(type_id) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).name) as usize - ptr as usize }, - 16usize, - concat!( - "Offset of field: ", - stringify!(spvc_reflected_resource), - "::", - stringify!(name) - ) - ); -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct spvc_reflected_builtin_resource { - pub builtin: SpvBuiltIn, - pub value_type_id: spvc_type_id, - pub resource: spvc_reflected_resource, -} -#[test] -fn bindgen_test_layout_spvc_reflected_builtin_resource() { - const UNINIT: ::std::mem::MaybeUninit = - ::std::mem::MaybeUninit::uninit(); - let ptr = UNINIT.as_ptr(); - assert_eq!( - ::std::mem::size_of::(), - 32usize, - concat!("Size of: ", stringify!(spvc_reflected_builtin_resource)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(spvc_reflected_builtin_resource)) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).builtin) as usize - ptr as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(spvc_reflected_builtin_resource), - "::", - stringify!(builtin) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).value_type_id) as usize - ptr as usize }, - 4usize, - concat!( - "Offset of field: ", - stringify!(spvc_reflected_builtin_resource), - "::", - stringify!(value_type_id) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).resource) as usize - ptr as usize }, - 8usize, - concat!( - "Offset of field: ", - stringify!(spvc_reflected_builtin_resource), - "::", - stringify!(resource) - ) - ); -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct spvc_entry_point { - pub execution_model: SpvExecutionModel, - pub name: *const ::std::os::raw::c_char, -} -#[test] -fn bindgen_test_layout_spvc_entry_point() { - const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); - let ptr = UNINIT.as_ptr(); - assert_eq!( - ::std::mem::size_of::(), - 16usize, - concat!("Size of: ", stringify!(spvc_entry_point)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(spvc_entry_point)) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).execution_model) as usize - ptr as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(spvc_entry_point), - "::", - stringify!(execution_model) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).name) as usize - ptr as usize }, - 8usize, - concat!( - "Offset of field: ", - stringify!(spvc_entry_point), - "::", - stringify!(name) - ) - ); -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct spvc_combined_image_sampler { - pub combined_id: spvc_variable_id, - pub image_id: spvc_variable_id, - pub sampler_id: spvc_variable_id, -} -#[test] -fn bindgen_test_layout_spvc_combined_image_sampler() { - const UNINIT: ::std::mem::MaybeUninit = - ::std::mem::MaybeUninit::uninit(); - let ptr = UNINIT.as_ptr(); - assert_eq!( - ::std::mem::size_of::(), - 12usize, - concat!("Size of: ", stringify!(spvc_combined_image_sampler)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(spvc_combined_image_sampler)) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).combined_id) as usize - ptr as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(spvc_combined_image_sampler), - "::", - stringify!(combined_id) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).image_id) as usize - ptr as usize }, - 4usize, - concat!( - "Offset of field: ", - stringify!(spvc_combined_image_sampler), - "::", - stringify!(image_id) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).sampler_id) as usize - ptr as usize }, - 8usize, - concat!( - "Offset of field: ", - stringify!(spvc_combined_image_sampler), - "::", - stringify!(sampler_id) - ) - ); -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct spvc_specialization_constant { - pub id: spvc_constant_id, - pub constant_id: ::std::os::raw::c_uint, -} -#[test] -fn bindgen_test_layout_spvc_specialization_constant() { - const UNINIT: ::std::mem::MaybeUninit = - ::std::mem::MaybeUninit::uninit(); - let ptr = UNINIT.as_ptr(); - assert_eq!( - ::std::mem::size_of::(), - 8usize, - concat!("Size of: ", stringify!(spvc_specialization_constant)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(spvc_specialization_constant)) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).id) as usize - ptr as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(spvc_specialization_constant), - "::", - stringify!(id) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).constant_id) as usize - ptr as usize }, - 4usize, - concat!( - "Offset of field: ", - stringify!(spvc_specialization_constant), - "::", - stringify!(constant_id) - ) - ); -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct spvc_buffer_range { - pub index: ::std::os::raw::c_uint, - pub offset: usize, - pub range: usize, -} -#[test] -fn bindgen_test_layout_spvc_buffer_range() { - const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); - let ptr = UNINIT.as_ptr(); - assert_eq!( - ::std::mem::size_of::(), - 24usize, - concat!("Size of: ", stringify!(spvc_buffer_range)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(spvc_buffer_range)) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).index) as usize - ptr as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(spvc_buffer_range), - "::", - stringify!(index) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).offset) as usize - ptr as usize }, - 8usize, - concat!( - "Offset of field: ", - stringify!(spvc_buffer_range), - "::", - stringify!(offset) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).range) as usize - ptr as usize }, - 16usize, - concat!( - "Offset of field: ", - stringify!(spvc_buffer_range), - "::", - stringify!(range) - ) - ); -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct spvc_hlsl_root_constants { - pub start: ::std::os::raw::c_uint, - pub end: ::std::os::raw::c_uint, - pub binding: ::std::os::raw::c_uint, - pub space: ::std::os::raw::c_uint, -} -#[test] -fn bindgen_test_layout_spvc_hlsl_root_constants() { - const UNINIT: ::std::mem::MaybeUninit = - ::std::mem::MaybeUninit::uninit(); - let ptr = UNINIT.as_ptr(); - assert_eq!( - ::std::mem::size_of::(), - 16usize, - concat!("Size of: ", stringify!(spvc_hlsl_root_constants)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(spvc_hlsl_root_constants)) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).start) as usize - ptr as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(spvc_hlsl_root_constants), - "::", - stringify!(start) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).end) as usize - ptr as usize }, - 4usize, - concat!( - "Offset of field: ", - stringify!(spvc_hlsl_root_constants), - "::", - stringify!(end) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).binding) as usize - ptr as usize }, - 8usize, - concat!( - "Offset of field: ", - stringify!(spvc_hlsl_root_constants), - "::", - stringify!(binding) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).space) as usize - ptr as usize }, - 12usize, - concat!( - "Offset of field: ", - stringify!(spvc_hlsl_root_constants), - "::", - stringify!(space) - ) - ); -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct spvc_hlsl_vertex_attribute_remap { - pub location: ::std::os::raw::c_uint, - pub semantic: *const ::std::os::raw::c_char, -} -#[test] -fn bindgen_test_layout_spvc_hlsl_vertex_attribute_remap() { - const UNINIT: ::std::mem::MaybeUninit = - ::std::mem::MaybeUninit::uninit(); - let ptr = UNINIT.as_ptr(); - assert_eq!( - ::std::mem::size_of::(), - 16usize, - concat!("Size of: ", stringify!(spvc_hlsl_vertex_attribute_remap)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!( - "Alignment of ", - stringify!(spvc_hlsl_vertex_attribute_remap) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).location) as usize - ptr as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(spvc_hlsl_vertex_attribute_remap), - "::", - stringify!(location) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).semantic) as usize - ptr as usize }, - 8usize, - concat!( - "Offset of field: ", - stringify!(spvc_hlsl_vertex_attribute_remap), - "::", - stringify!(semantic) - ) - ); -} -pub type spvc_bool = ::std::os::raw::c_uchar; -pub const spvc_result_SPVC_SUCCESS: spvc_result = 0; -pub const spvc_result_SPVC_ERROR_INVALID_SPIRV: spvc_result = -1; -pub const spvc_result_SPVC_ERROR_UNSUPPORTED_SPIRV: spvc_result = -2; -pub const spvc_result_SPVC_ERROR_OUT_OF_MEMORY: spvc_result = -3; -pub const spvc_result_SPVC_ERROR_INVALID_ARGUMENT: spvc_result = -4; -pub const spvc_result_SPVC_ERROR_INT_MAX: spvc_result = 2147483647; -pub type spvc_result = ::std::os::raw::c_int; -pub const spvc_capture_mode_SPVC_CAPTURE_MODE_COPY: spvc_capture_mode = 0; -pub const spvc_capture_mode_SPVC_CAPTURE_MODE_TAKE_OWNERSHIP: spvc_capture_mode = 1; -pub const spvc_capture_mode_SPVC_CAPTURE_MODE_INT_MAX: spvc_capture_mode = 2147483647; -pub type spvc_capture_mode = ::std::os::raw::c_int; -pub const spvc_backend_SPVC_BACKEND_NONE: spvc_backend = 0; -pub const spvc_backend_SPVC_BACKEND_GLSL: spvc_backend = 1; -pub const spvc_backend_SPVC_BACKEND_HLSL: spvc_backend = 2; -pub const spvc_backend_SPVC_BACKEND_MSL: spvc_backend = 3; -pub const spvc_backend_SPVC_BACKEND_CPP: spvc_backend = 4; -pub const spvc_backend_SPVC_BACKEND_JSON: spvc_backend = 5; -pub const spvc_backend_SPVC_BACKEND_INT_MAX: spvc_backend = 2147483647; -pub type spvc_backend = ::std::os::raw::c_int; -pub const spvc_resource_type_SPVC_RESOURCE_TYPE_UNKNOWN: spvc_resource_type = 0; -pub const spvc_resource_type_SPVC_RESOURCE_TYPE_UNIFORM_BUFFER: spvc_resource_type = 1; -pub const spvc_resource_type_SPVC_RESOURCE_TYPE_STORAGE_BUFFER: spvc_resource_type = 2; -pub const spvc_resource_type_SPVC_RESOURCE_TYPE_STAGE_INPUT: spvc_resource_type = 3; -pub const spvc_resource_type_SPVC_RESOURCE_TYPE_STAGE_OUTPUT: spvc_resource_type = 4; -pub const spvc_resource_type_SPVC_RESOURCE_TYPE_SUBPASS_INPUT: spvc_resource_type = 5; -pub const spvc_resource_type_SPVC_RESOURCE_TYPE_STORAGE_IMAGE: spvc_resource_type = 6; -pub const spvc_resource_type_SPVC_RESOURCE_TYPE_SAMPLED_IMAGE: spvc_resource_type = 7; -pub const spvc_resource_type_SPVC_RESOURCE_TYPE_ATOMIC_COUNTER: spvc_resource_type = 8; -pub const spvc_resource_type_SPVC_RESOURCE_TYPE_PUSH_CONSTANT: spvc_resource_type = 9; -pub const spvc_resource_type_SPVC_RESOURCE_TYPE_SEPARATE_IMAGE: spvc_resource_type = 10; -pub const spvc_resource_type_SPVC_RESOURCE_TYPE_SEPARATE_SAMPLERS: spvc_resource_type = 11; -pub const spvc_resource_type_SPVC_RESOURCE_TYPE_ACCELERATION_STRUCTURE: spvc_resource_type = 12; -pub const spvc_resource_type_SPVC_RESOURCE_TYPE_RAY_QUERY: spvc_resource_type = 13; -pub const spvc_resource_type_SPVC_RESOURCE_TYPE_SHADER_RECORD_BUFFER: spvc_resource_type = 14; -pub const spvc_resource_type_SPVC_RESOURCE_TYPE_GL_PLAIN_UNIFORM: spvc_resource_type = 15; -pub const spvc_resource_type_SPVC_RESOURCE_TYPE_TENSOR: spvc_resource_type = 16; -pub const spvc_resource_type_SPVC_RESOURCE_TYPE_INT_MAX: spvc_resource_type = 2147483647; -pub type spvc_resource_type = ::std::os::raw::c_int; -pub const spvc_builtin_resource_type_SPVC_BUILTIN_RESOURCE_TYPE_UNKNOWN: - spvc_builtin_resource_type = 0; -pub const spvc_builtin_resource_type_SPVC_BUILTIN_RESOURCE_TYPE_STAGE_INPUT: - spvc_builtin_resource_type = 1; -pub const spvc_builtin_resource_type_SPVC_BUILTIN_RESOURCE_TYPE_STAGE_OUTPUT: - spvc_builtin_resource_type = 2; -pub const spvc_builtin_resource_type_SPVC_BUILTIN_RESOURCE_TYPE_INT_MAX: - spvc_builtin_resource_type = 2147483647; -pub type spvc_builtin_resource_type = ::std::os::raw::c_int; -pub const spvc_basetype_SPVC_BASETYPE_UNKNOWN: spvc_basetype = 0; -pub const spvc_basetype_SPVC_BASETYPE_VOID: spvc_basetype = 1; -pub const spvc_basetype_SPVC_BASETYPE_BOOLEAN: spvc_basetype = 2; -pub const spvc_basetype_SPVC_BASETYPE_INT8: spvc_basetype = 3; -pub const spvc_basetype_SPVC_BASETYPE_UINT8: spvc_basetype = 4; -pub const spvc_basetype_SPVC_BASETYPE_INT16: spvc_basetype = 5; -pub const spvc_basetype_SPVC_BASETYPE_UINT16: spvc_basetype = 6; -pub const spvc_basetype_SPVC_BASETYPE_INT32: spvc_basetype = 7; -pub const spvc_basetype_SPVC_BASETYPE_UINT32: spvc_basetype = 8; -pub const spvc_basetype_SPVC_BASETYPE_INT64: spvc_basetype = 9; -pub const spvc_basetype_SPVC_BASETYPE_UINT64: spvc_basetype = 10; -pub const spvc_basetype_SPVC_BASETYPE_ATOMIC_COUNTER: spvc_basetype = 11; -pub const spvc_basetype_SPVC_BASETYPE_FP16: spvc_basetype = 12; -pub const spvc_basetype_SPVC_BASETYPE_FP32: spvc_basetype = 13; -pub const spvc_basetype_SPVC_BASETYPE_FP64: spvc_basetype = 14; -pub const spvc_basetype_SPVC_BASETYPE_STRUCT: spvc_basetype = 15; -pub const spvc_basetype_SPVC_BASETYPE_IMAGE: spvc_basetype = 16; -pub const spvc_basetype_SPVC_BASETYPE_SAMPLED_IMAGE: spvc_basetype = 17; -pub const spvc_basetype_SPVC_BASETYPE_SAMPLER: spvc_basetype = 18; -pub const spvc_basetype_SPVC_BASETYPE_ACCELERATION_STRUCTURE: spvc_basetype = 19; -pub const spvc_basetype_SPVC_BASETYPE_INT_MAX: spvc_basetype = 2147483647; -pub type spvc_basetype = ::std::os::raw::c_int; -pub const spvc_msl_platform_SPVC_MSL_PLATFORM_IOS: spvc_msl_platform = 0; -pub const spvc_msl_platform_SPVC_MSL_PLATFORM_MACOS: spvc_msl_platform = 1; -pub const spvc_msl_platform_SPVC_MSL_PLATFORM_MAX_INT: spvc_msl_platform = 2147483647; -pub type spvc_msl_platform = ::std::os::raw::c_int; -pub const spvc_msl_index_type_SPVC_MSL_INDEX_TYPE_NONE: spvc_msl_index_type = 0; -pub const spvc_msl_index_type_SPVC_MSL_INDEX_TYPE_UINT16: spvc_msl_index_type = 1; -pub const spvc_msl_index_type_SPVC_MSL_INDEX_TYPE_UINT32: spvc_msl_index_type = 2; -pub const spvc_msl_index_type_SPVC_MSL_INDEX_TYPE_MAX_INT: spvc_msl_index_type = 2147483647; -pub type spvc_msl_index_type = ::std::os::raw::c_int; -pub const spvc_msl_shader_variable_format_SPVC_MSL_SHADER_VARIABLE_FORMAT_OTHER: - spvc_msl_shader_variable_format = 0; -pub const spvc_msl_shader_variable_format_SPVC_MSL_SHADER_VARIABLE_FORMAT_UINT8: - spvc_msl_shader_variable_format = 1; -pub const spvc_msl_shader_variable_format_SPVC_MSL_SHADER_VARIABLE_FORMAT_UINT16: - spvc_msl_shader_variable_format = 2; -pub const spvc_msl_shader_variable_format_SPVC_MSL_SHADER_VARIABLE_FORMAT_ANY16: - spvc_msl_shader_variable_format = 3; -pub const spvc_msl_shader_variable_format_SPVC_MSL_SHADER_VARIABLE_FORMAT_ANY32: - spvc_msl_shader_variable_format = 4; -pub const spvc_msl_shader_variable_format_SPVC_MSL_VERTEX_FORMAT_OTHER: - spvc_msl_shader_variable_format = 0; -pub const spvc_msl_shader_variable_format_SPVC_MSL_VERTEX_FORMAT_UINT8: - spvc_msl_shader_variable_format = 1; -pub const spvc_msl_shader_variable_format_SPVC_MSL_VERTEX_FORMAT_UINT16: - spvc_msl_shader_variable_format = 2; -pub const spvc_msl_shader_variable_format_SPVC_MSL_SHADER_INPUT_FORMAT_OTHER: - spvc_msl_shader_variable_format = 0; -pub const spvc_msl_shader_variable_format_SPVC_MSL_SHADER_INPUT_FORMAT_UINT8: - spvc_msl_shader_variable_format = 1; -pub const spvc_msl_shader_variable_format_SPVC_MSL_SHADER_INPUT_FORMAT_UINT16: - spvc_msl_shader_variable_format = 2; -pub const spvc_msl_shader_variable_format_SPVC_MSL_SHADER_INPUT_FORMAT_ANY16: - spvc_msl_shader_variable_format = 3; -pub const spvc_msl_shader_variable_format_SPVC_MSL_SHADER_INPUT_FORMAT_ANY32: - spvc_msl_shader_variable_format = 4; -pub const spvc_msl_shader_variable_format_SPVC_MSL_SHADER_INPUT_FORMAT_INT_MAX: - spvc_msl_shader_variable_format = 2147483647; -pub type spvc_msl_shader_variable_format = ::std::os::raw::c_int; -pub use self::spvc_msl_shader_variable_format as spvc_msl_shader_input_format; -pub use self::spvc_msl_shader_variable_format as spvc_msl_vertex_format; -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct spvc_msl_vertex_attribute { - pub location: ::std::os::raw::c_uint, - pub msl_buffer: ::std::os::raw::c_uint, - pub msl_offset: ::std::os::raw::c_uint, - pub msl_stride: ::std::os::raw::c_uint, - pub per_instance: spvc_bool, - pub format: spvc_msl_vertex_format, - pub builtin: SpvBuiltIn, -} -#[test] -fn bindgen_test_layout_spvc_msl_vertex_attribute() { - const UNINIT: ::std::mem::MaybeUninit = - ::std::mem::MaybeUninit::uninit(); - let ptr = UNINIT.as_ptr(); - assert_eq!( - ::std::mem::size_of::(), - 28usize, - concat!("Size of: ", stringify!(spvc_msl_vertex_attribute)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(spvc_msl_vertex_attribute)) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).location) as usize - ptr as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(spvc_msl_vertex_attribute), - "::", - stringify!(location) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).msl_buffer) as usize - ptr as usize }, - 4usize, - concat!( - "Offset of field: ", - stringify!(spvc_msl_vertex_attribute), - "::", - stringify!(msl_buffer) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).msl_offset) as usize - ptr as usize }, - 8usize, - concat!( - "Offset of field: ", - stringify!(spvc_msl_vertex_attribute), - "::", - stringify!(msl_offset) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).msl_stride) as usize - ptr as usize }, - 12usize, - concat!( - "Offset of field: ", - stringify!(spvc_msl_vertex_attribute), - "::", - stringify!(msl_stride) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).per_instance) as usize - ptr as usize }, - 16usize, - concat!( - "Offset of field: ", - stringify!(spvc_msl_vertex_attribute), - "::", - stringify!(per_instance) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).format) as usize - ptr as usize }, - 20usize, - concat!( - "Offset of field: ", - stringify!(spvc_msl_vertex_attribute), - "::", - stringify!(format) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).builtin) as usize - ptr as usize }, - 24usize, - concat!( - "Offset of field: ", - stringify!(spvc_msl_vertex_attribute), - "::", - stringify!(builtin) - ) - ); -} -extern "C" { - pub fn spvc_msl_vertex_attribute_init(attr: *mut spvc_msl_vertex_attribute); -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct spvc_msl_shader_interface_var { - pub location: ::std::os::raw::c_uint, - pub format: spvc_msl_vertex_format, - pub builtin: SpvBuiltIn, - pub vecsize: ::std::os::raw::c_uint, -} -#[test] -fn bindgen_test_layout_spvc_msl_shader_interface_var() { - const UNINIT: ::std::mem::MaybeUninit = - ::std::mem::MaybeUninit::uninit(); - let ptr = UNINIT.as_ptr(); - assert_eq!( - ::std::mem::size_of::(), - 16usize, - concat!("Size of: ", stringify!(spvc_msl_shader_interface_var)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(spvc_msl_shader_interface_var)) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).location) as usize - ptr as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(spvc_msl_shader_interface_var), - "::", - stringify!(location) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).format) as usize - ptr as usize }, - 4usize, - concat!( - "Offset of field: ", - stringify!(spvc_msl_shader_interface_var), - "::", - stringify!(format) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).builtin) as usize - ptr as usize }, - 8usize, - concat!( - "Offset of field: ", - stringify!(spvc_msl_shader_interface_var), - "::", - stringify!(builtin) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).vecsize) as usize - ptr as usize }, - 12usize, - concat!( - "Offset of field: ", - stringify!(spvc_msl_shader_interface_var), - "::", - stringify!(vecsize) - ) - ); -} -pub type spvc_msl_shader_input = spvc_msl_shader_interface_var; -extern "C" { - pub fn spvc_msl_shader_interface_var_init(var: *mut spvc_msl_shader_interface_var); -} -extern "C" { - pub fn spvc_msl_shader_input_init(input: *mut spvc_msl_shader_input); -} -pub const spvc_msl_shader_variable_rate_SPVC_MSL_SHADER_VARIABLE_RATE_PER_VERTEX: - spvc_msl_shader_variable_rate = 0; -pub const spvc_msl_shader_variable_rate_SPVC_MSL_SHADER_VARIABLE_RATE_PER_PRIMITIVE: - spvc_msl_shader_variable_rate = 1; -pub const spvc_msl_shader_variable_rate_SPVC_MSL_SHADER_VARIABLE_RATE_PER_PATCH: - spvc_msl_shader_variable_rate = 2; -pub const spvc_msl_shader_variable_rate_SPVC_MSL_SHADER_VARIABLE_RATE_INT_MAX: - spvc_msl_shader_variable_rate = 2147483647; -pub type spvc_msl_shader_variable_rate = ::std::os::raw::c_int; -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct spvc_msl_shader_interface_var_2 { - pub location: ::std::os::raw::c_uint, - pub format: spvc_msl_shader_variable_format, - pub builtin: SpvBuiltIn, - pub vecsize: ::std::os::raw::c_uint, - pub rate: spvc_msl_shader_variable_rate, -} -#[test] -fn bindgen_test_layout_spvc_msl_shader_interface_var_2() { - const UNINIT: ::std::mem::MaybeUninit = - ::std::mem::MaybeUninit::uninit(); - let ptr = UNINIT.as_ptr(); - assert_eq!( - ::std::mem::size_of::(), - 20usize, - concat!("Size of: ", stringify!(spvc_msl_shader_interface_var_2)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(spvc_msl_shader_interface_var_2)) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).location) as usize - ptr as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(spvc_msl_shader_interface_var_2), - "::", - stringify!(location) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).format) as usize - ptr as usize }, - 4usize, - concat!( - "Offset of field: ", - stringify!(spvc_msl_shader_interface_var_2), - "::", - stringify!(format) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).builtin) as usize - ptr as usize }, - 8usize, - concat!( - "Offset of field: ", - stringify!(spvc_msl_shader_interface_var_2), - "::", - stringify!(builtin) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).vecsize) as usize - ptr as usize }, - 12usize, - concat!( - "Offset of field: ", - stringify!(spvc_msl_shader_interface_var_2), - "::", - stringify!(vecsize) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).rate) as usize - ptr as usize }, - 16usize, - concat!( - "Offset of field: ", - stringify!(spvc_msl_shader_interface_var_2), - "::", - stringify!(rate) - ) - ); -} -extern "C" { - pub fn spvc_msl_shader_interface_var_init_2(var: *mut spvc_msl_shader_interface_var_2); -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct spvc_msl_resource_binding { - pub stage: SpvExecutionModel, - pub desc_set: ::std::os::raw::c_uint, - pub binding: ::std::os::raw::c_uint, - pub msl_buffer: ::std::os::raw::c_uint, - pub msl_texture: ::std::os::raw::c_uint, - pub msl_sampler: ::std::os::raw::c_uint, -} -#[test] -fn bindgen_test_layout_spvc_msl_resource_binding() { - const UNINIT: ::std::mem::MaybeUninit = - ::std::mem::MaybeUninit::uninit(); - let ptr = UNINIT.as_ptr(); - assert_eq!( - ::std::mem::size_of::(), - 24usize, - concat!("Size of: ", stringify!(spvc_msl_resource_binding)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(spvc_msl_resource_binding)) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).stage) as usize - ptr as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(spvc_msl_resource_binding), - "::", - stringify!(stage) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).desc_set) as usize - ptr as usize }, - 4usize, - concat!( - "Offset of field: ", - stringify!(spvc_msl_resource_binding), - "::", - stringify!(desc_set) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).binding) as usize - ptr as usize }, - 8usize, - concat!( - "Offset of field: ", - stringify!(spvc_msl_resource_binding), - "::", - stringify!(binding) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).msl_buffer) as usize - ptr as usize }, - 12usize, - concat!( - "Offset of field: ", - stringify!(spvc_msl_resource_binding), - "::", - stringify!(msl_buffer) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).msl_texture) as usize - ptr as usize }, - 16usize, - concat!( - "Offset of field: ", - stringify!(spvc_msl_resource_binding), - "::", - stringify!(msl_texture) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).msl_sampler) as usize - ptr as usize }, - 20usize, - concat!( - "Offset of field: ", - stringify!(spvc_msl_resource_binding), - "::", - stringify!(msl_sampler) - ) - ); -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct spvc_msl_resource_binding_2 { - pub stage: SpvExecutionModel, - pub desc_set: ::std::os::raw::c_uint, - pub binding: ::std::os::raw::c_uint, - pub count: ::std::os::raw::c_uint, - pub msl_buffer: ::std::os::raw::c_uint, - pub msl_texture: ::std::os::raw::c_uint, - pub msl_sampler: ::std::os::raw::c_uint, -} -#[test] -fn bindgen_test_layout_spvc_msl_resource_binding_2() { - const UNINIT: ::std::mem::MaybeUninit = - ::std::mem::MaybeUninit::uninit(); - let ptr = UNINIT.as_ptr(); - assert_eq!( - ::std::mem::size_of::(), - 28usize, - concat!("Size of: ", stringify!(spvc_msl_resource_binding_2)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(spvc_msl_resource_binding_2)) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).stage) as usize - ptr as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(spvc_msl_resource_binding_2), - "::", - stringify!(stage) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).desc_set) as usize - ptr as usize }, - 4usize, - concat!( - "Offset of field: ", - stringify!(spvc_msl_resource_binding_2), - "::", - stringify!(desc_set) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).binding) as usize - ptr as usize }, - 8usize, - concat!( - "Offset of field: ", - stringify!(spvc_msl_resource_binding_2), - "::", - stringify!(binding) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).count) as usize - ptr as usize }, - 12usize, - concat!( - "Offset of field: ", - stringify!(spvc_msl_resource_binding_2), - "::", - stringify!(count) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).msl_buffer) as usize - ptr as usize }, - 16usize, - concat!( - "Offset of field: ", - stringify!(spvc_msl_resource_binding_2), - "::", - stringify!(msl_buffer) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).msl_texture) as usize - ptr as usize }, - 20usize, - concat!( - "Offset of field: ", - stringify!(spvc_msl_resource_binding_2), - "::", - stringify!(msl_texture) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).msl_sampler) as usize - ptr as usize }, - 24usize, - concat!( - "Offset of field: ", - stringify!(spvc_msl_resource_binding_2), - "::", - stringify!(msl_sampler) - ) - ); -} -extern "C" { - pub fn spvc_msl_resource_binding_init(binding: *mut spvc_msl_resource_binding); -} -extern "C" { - pub fn spvc_msl_resource_binding_init_2(binding: *mut spvc_msl_resource_binding_2); -} -extern "C" { - pub fn spvc_msl_get_aux_buffer_struct_version() -> ::std::os::raw::c_uint; -} -pub const spvc_msl_sampler_coord_SPVC_MSL_SAMPLER_COORD_NORMALIZED: spvc_msl_sampler_coord = 0; -pub const spvc_msl_sampler_coord_SPVC_MSL_SAMPLER_COORD_PIXEL: spvc_msl_sampler_coord = 1; -pub const spvc_msl_sampler_coord_SPVC_MSL_SAMPLER_INT_MAX: spvc_msl_sampler_coord = 2147483647; -pub type spvc_msl_sampler_coord = ::std::os::raw::c_int; -pub const spvc_msl_sampler_filter_SPVC_MSL_SAMPLER_FILTER_NEAREST: spvc_msl_sampler_filter = 0; -pub const spvc_msl_sampler_filter_SPVC_MSL_SAMPLER_FILTER_LINEAR: spvc_msl_sampler_filter = 1; -pub const spvc_msl_sampler_filter_SPVC_MSL_SAMPLER_FILTER_INT_MAX: spvc_msl_sampler_filter = - 2147483647; -pub type spvc_msl_sampler_filter = ::std::os::raw::c_int; -pub const spvc_msl_sampler_mip_filter_SPVC_MSL_SAMPLER_MIP_FILTER_NONE: - spvc_msl_sampler_mip_filter = 0; -pub const spvc_msl_sampler_mip_filter_SPVC_MSL_SAMPLER_MIP_FILTER_NEAREST: - spvc_msl_sampler_mip_filter = 1; -pub const spvc_msl_sampler_mip_filter_SPVC_MSL_SAMPLER_MIP_FILTER_LINEAR: - spvc_msl_sampler_mip_filter = 2; -pub const spvc_msl_sampler_mip_filter_SPVC_MSL_SAMPLER_MIP_FILTER_INT_MAX: - spvc_msl_sampler_mip_filter = 2147483647; -pub type spvc_msl_sampler_mip_filter = ::std::os::raw::c_int; -pub const spvc_msl_sampler_address_SPVC_MSL_SAMPLER_ADDRESS_CLAMP_TO_ZERO: - spvc_msl_sampler_address = 0; -pub const spvc_msl_sampler_address_SPVC_MSL_SAMPLER_ADDRESS_CLAMP_TO_EDGE: - spvc_msl_sampler_address = 1; -pub const spvc_msl_sampler_address_SPVC_MSL_SAMPLER_ADDRESS_CLAMP_TO_BORDER: - spvc_msl_sampler_address = 2; -pub const spvc_msl_sampler_address_SPVC_MSL_SAMPLER_ADDRESS_REPEAT: spvc_msl_sampler_address = 3; -pub const spvc_msl_sampler_address_SPVC_MSL_SAMPLER_ADDRESS_MIRRORED_REPEAT: - spvc_msl_sampler_address = 4; -pub const spvc_msl_sampler_address_SPVC_MSL_SAMPLER_ADDRESS_INT_MAX: spvc_msl_sampler_address = - 2147483647; -pub type spvc_msl_sampler_address = ::std::os::raw::c_int; -pub const spvc_msl_sampler_compare_func_SPVC_MSL_SAMPLER_COMPARE_FUNC_NEVER: - spvc_msl_sampler_compare_func = 0; -pub const spvc_msl_sampler_compare_func_SPVC_MSL_SAMPLER_COMPARE_FUNC_LESS: - spvc_msl_sampler_compare_func = 1; -pub const spvc_msl_sampler_compare_func_SPVC_MSL_SAMPLER_COMPARE_FUNC_LESS_EQUAL: - spvc_msl_sampler_compare_func = 2; -pub const spvc_msl_sampler_compare_func_SPVC_MSL_SAMPLER_COMPARE_FUNC_GREATER: - spvc_msl_sampler_compare_func = 3; -pub const spvc_msl_sampler_compare_func_SPVC_MSL_SAMPLER_COMPARE_FUNC_GREATER_EQUAL: - spvc_msl_sampler_compare_func = 4; -pub const spvc_msl_sampler_compare_func_SPVC_MSL_SAMPLER_COMPARE_FUNC_EQUAL: - spvc_msl_sampler_compare_func = 5; -pub const spvc_msl_sampler_compare_func_SPVC_MSL_SAMPLER_COMPARE_FUNC_NOT_EQUAL: - spvc_msl_sampler_compare_func = 6; -pub const spvc_msl_sampler_compare_func_SPVC_MSL_SAMPLER_COMPARE_FUNC_ALWAYS: - spvc_msl_sampler_compare_func = 7; -pub const spvc_msl_sampler_compare_func_SPVC_MSL_SAMPLER_COMPARE_FUNC_INT_MAX: - spvc_msl_sampler_compare_func = 2147483647; -pub type spvc_msl_sampler_compare_func = ::std::os::raw::c_int; -pub const spvc_msl_sampler_border_color_SPVC_MSL_SAMPLER_BORDER_COLOR_TRANSPARENT_BLACK: - spvc_msl_sampler_border_color = 0; -pub const spvc_msl_sampler_border_color_SPVC_MSL_SAMPLER_BORDER_COLOR_OPAQUE_BLACK: - spvc_msl_sampler_border_color = 1; -pub const spvc_msl_sampler_border_color_SPVC_MSL_SAMPLER_BORDER_COLOR_OPAQUE_WHITE: - spvc_msl_sampler_border_color = 2; -pub const spvc_msl_sampler_border_color_SPVC_MSL_SAMPLER_BORDER_COLOR_INT_MAX: - spvc_msl_sampler_border_color = 2147483647; -pub type spvc_msl_sampler_border_color = ::std::os::raw::c_int; -pub const spvc_msl_format_resolution_SPVC_MSL_FORMAT_RESOLUTION_444: spvc_msl_format_resolution = 0; -pub const spvc_msl_format_resolution_SPVC_MSL_FORMAT_RESOLUTION_422: spvc_msl_format_resolution = 1; -pub const spvc_msl_format_resolution_SPVC_MSL_FORMAT_RESOLUTION_420: spvc_msl_format_resolution = 2; -pub const spvc_msl_format_resolution_SPVC_MSL_FORMAT_RESOLUTION_INT_MAX: - spvc_msl_format_resolution = 2147483647; -pub type spvc_msl_format_resolution = ::std::os::raw::c_int; -pub const spvc_msl_chroma_location_SPVC_MSL_CHROMA_LOCATION_COSITED_EVEN: spvc_msl_chroma_location = - 0; -pub const spvc_msl_chroma_location_SPVC_MSL_CHROMA_LOCATION_MIDPOINT: spvc_msl_chroma_location = 1; -pub const spvc_msl_chroma_location_SPVC_MSL_CHROMA_LOCATION_INT_MAX: spvc_msl_chroma_location = - 2147483647; -pub type spvc_msl_chroma_location = ::std::os::raw::c_int; -pub const spvc_msl_component_swizzle_SPVC_MSL_COMPONENT_SWIZZLE_IDENTITY: - spvc_msl_component_swizzle = 0; -pub const spvc_msl_component_swizzle_SPVC_MSL_COMPONENT_SWIZZLE_ZERO: spvc_msl_component_swizzle = - 1; -pub const spvc_msl_component_swizzle_SPVC_MSL_COMPONENT_SWIZZLE_ONE: spvc_msl_component_swizzle = 2; -pub const spvc_msl_component_swizzle_SPVC_MSL_COMPONENT_SWIZZLE_R: spvc_msl_component_swizzle = 3; -pub const spvc_msl_component_swizzle_SPVC_MSL_COMPONENT_SWIZZLE_G: spvc_msl_component_swizzle = 4; -pub const spvc_msl_component_swizzle_SPVC_MSL_COMPONENT_SWIZZLE_B: spvc_msl_component_swizzle = 5; -pub const spvc_msl_component_swizzle_SPVC_MSL_COMPONENT_SWIZZLE_A: spvc_msl_component_swizzle = 6; -pub const spvc_msl_component_swizzle_SPVC_MSL_COMPONENT_SWIZZLE_INT_MAX: - spvc_msl_component_swizzle = 2147483647; -pub type spvc_msl_component_swizzle = ::std::os::raw::c_int; -pub const spvc_msl_sampler_ycbcr_model_conversion_SPVC_MSL_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY : spvc_msl_sampler_ycbcr_model_conversion = 0 ; -pub const spvc_msl_sampler_ycbcr_model_conversion_SPVC_MSL_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_IDENTITY : spvc_msl_sampler_ycbcr_model_conversion = 1 ; -pub const spvc_msl_sampler_ycbcr_model_conversion_SPVC_MSL_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_BT_709 : spvc_msl_sampler_ycbcr_model_conversion = 2 ; -pub const spvc_msl_sampler_ycbcr_model_conversion_SPVC_MSL_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_BT_601 : spvc_msl_sampler_ycbcr_model_conversion = 3 ; -pub const spvc_msl_sampler_ycbcr_model_conversion_SPVC_MSL_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_BT_2020 : spvc_msl_sampler_ycbcr_model_conversion = 4 ; -pub const spvc_msl_sampler_ycbcr_model_conversion_SPVC_MSL_SAMPLER_YCBCR_MODEL_CONVERSION_INT_MAX : spvc_msl_sampler_ycbcr_model_conversion = 2147483647 ; -pub type spvc_msl_sampler_ycbcr_model_conversion = ::std::os::raw::c_int; -pub const spvc_msl_sampler_ycbcr_range_SPVC_MSL_SAMPLER_YCBCR_RANGE_ITU_FULL: - spvc_msl_sampler_ycbcr_range = 0; -pub const spvc_msl_sampler_ycbcr_range_SPVC_MSL_SAMPLER_YCBCR_RANGE_ITU_NARROW: - spvc_msl_sampler_ycbcr_range = 1; -pub const spvc_msl_sampler_ycbcr_range_SPVC_MSL_SAMPLER_YCBCR_RANGE_INT_MAX: - spvc_msl_sampler_ycbcr_range = 2147483647; -pub type spvc_msl_sampler_ycbcr_range = ::std::os::raw::c_int; -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct spvc_msl_constexpr_sampler { - pub coord: spvc_msl_sampler_coord, - pub min_filter: spvc_msl_sampler_filter, - pub mag_filter: spvc_msl_sampler_filter, - pub mip_filter: spvc_msl_sampler_mip_filter, - pub s_address: spvc_msl_sampler_address, - pub t_address: spvc_msl_sampler_address, - pub r_address: spvc_msl_sampler_address, - pub compare_func: spvc_msl_sampler_compare_func, - pub border_color: spvc_msl_sampler_border_color, - pub lod_clamp_min: f32, - pub lod_clamp_max: f32, - pub max_anisotropy: ::std::os::raw::c_int, - pub compare_enable: spvc_bool, - pub lod_clamp_enable: spvc_bool, - pub anisotropy_enable: spvc_bool, -} -#[test] -fn bindgen_test_layout_spvc_msl_constexpr_sampler() { - const UNINIT: ::std::mem::MaybeUninit = - ::std::mem::MaybeUninit::uninit(); - let ptr = UNINIT.as_ptr(); - assert_eq!( - ::std::mem::size_of::(), - 52usize, - concat!("Size of: ", stringify!(spvc_msl_constexpr_sampler)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(spvc_msl_constexpr_sampler)) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).coord) as usize - ptr as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(spvc_msl_constexpr_sampler), - "::", - stringify!(coord) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).min_filter) as usize - ptr as usize }, - 4usize, - concat!( - "Offset of field: ", - stringify!(spvc_msl_constexpr_sampler), - "::", - stringify!(min_filter) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).mag_filter) as usize - ptr as usize }, - 8usize, - concat!( - "Offset of field: ", - stringify!(spvc_msl_constexpr_sampler), - "::", - stringify!(mag_filter) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).mip_filter) as usize - ptr as usize }, - 12usize, - concat!( - "Offset of field: ", - stringify!(spvc_msl_constexpr_sampler), - "::", - stringify!(mip_filter) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).s_address) as usize - ptr as usize }, - 16usize, - concat!( - "Offset of field: ", - stringify!(spvc_msl_constexpr_sampler), - "::", - stringify!(s_address) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).t_address) as usize - ptr as usize }, - 20usize, - concat!( - "Offset of field: ", - stringify!(spvc_msl_constexpr_sampler), - "::", - stringify!(t_address) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).r_address) as usize - ptr as usize }, - 24usize, - concat!( - "Offset of field: ", - stringify!(spvc_msl_constexpr_sampler), - "::", - stringify!(r_address) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).compare_func) as usize - ptr as usize }, - 28usize, - concat!( - "Offset of field: ", - stringify!(spvc_msl_constexpr_sampler), - "::", - stringify!(compare_func) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).border_color) as usize - ptr as usize }, - 32usize, - concat!( - "Offset of field: ", - stringify!(spvc_msl_constexpr_sampler), - "::", - stringify!(border_color) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).lod_clamp_min) as usize - ptr as usize }, - 36usize, - concat!( - "Offset of field: ", - stringify!(spvc_msl_constexpr_sampler), - "::", - stringify!(lod_clamp_min) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).lod_clamp_max) as usize - ptr as usize }, - 40usize, - concat!( - "Offset of field: ", - stringify!(spvc_msl_constexpr_sampler), - "::", - stringify!(lod_clamp_max) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).max_anisotropy) as usize - ptr as usize }, - 44usize, - concat!( - "Offset of field: ", - stringify!(spvc_msl_constexpr_sampler), - "::", - stringify!(max_anisotropy) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).compare_enable) as usize - ptr as usize }, - 48usize, - concat!( - "Offset of field: ", - stringify!(spvc_msl_constexpr_sampler), - "::", - stringify!(compare_enable) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).lod_clamp_enable) as usize - ptr as usize }, - 49usize, - concat!( - "Offset of field: ", - stringify!(spvc_msl_constexpr_sampler), - "::", - stringify!(lod_clamp_enable) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).anisotropy_enable) as usize - ptr as usize }, - 50usize, - concat!( - "Offset of field: ", - stringify!(spvc_msl_constexpr_sampler), - "::", - stringify!(anisotropy_enable) - ) - ); -} -extern "C" { - pub fn spvc_msl_constexpr_sampler_init(sampler: *mut spvc_msl_constexpr_sampler); -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct spvc_msl_sampler_ycbcr_conversion { - pub planes: ::std::os::raw::c_uint, - pub resolution: spvc_msl_format_resolution, - pub chroma_filter: spvc_msl_sampler_filter, - pub x_chroma_offset: spvc_msl_chroma_location, - pub y_chroma_offset: spvc_msl_chroma_location, - pub swizzle: [spvc_msl_component_swizzle; 4usize], - pub ycbcr_model: spvc_msl_sampler_ycbcr_model_conversion, - pub ycbcr_range: spvc_msl_sampler_ycbcr_range, - pub bpc: ::std::os::raw::c_uint, -} -#[test] -fn bindgen_test_layout_spvc_msl_sampler_ycbcr_conversion() { - const UNINIT: ::std::mem::MaybeUninit = - ::std::mem::MaybeUninit::uninit(); - let ptr = UNINIT.as_ptr(); - assert_eq!( - ::std::mem::size_of::(), - 48usize, - concat!("Size of: ", stringify!(spvc_msl_sampler_ycbcr_conversion)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!( - "Alignment of ", - stringify!(spvc_msl_sampler_ycbcr_conversion) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).planes) as usize - ptr as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(spvc_msl_sampler_ycbcr_conversion), - "::", - stringify!(planes) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).resolution) as usize - ptr as usize }, - 4usize, - concat!( - "Offset of field: ", - stringify!(spvc_msl_sampler_ycbcr_conversion), - "::", - stringify!(resolution) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).chroma_filter) as usize - ptr as usize }, - 8usize, - concat!( - "Offset of field: ", - stringify!(spvc_msl_sampler_ycbcr_conversion), - "::", - stringify!(chroma_filter) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).x_chroma_offset) as usize - ptr as usize }, - 12usize, - concat!( - "Offset of field: ", - stringify!(spvc_msl_sampler_ycbcr_conversion), - "::", - stringify!(x_chroma_offset) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).y_chroma_offset) as usize - ptr as usize }, - 16usize, - concat!( - "Offset of field: ", - stringify!(spvc_msl_sampler_ycbcr_conversion), - "::", - stringify!(y_chroma_offset) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).swizzle) as usize - ptr as usize }, - 20usize, - concat!( - "Offset of field: ", - stringify!(spvc_msl_sampler_ycbcr_conversion), - "::", - stringify!(swizzle) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).ycbcr_model) as usize - ptr as usize }, - 36usize, - concat!( - "Offset of field: ", - stringify!(spvc_msl_sampler_ycbcr_conversion), - "::", - stringify!(ycbcr_model) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).ycbcr_range) as usize - ptr as usize }, - 40usize, - concat!( - "Offset of field: ", - stringify!(spvc_msl_sampler_ycbcr_conversion), - "::", - stringify!(ycbcr_range) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).bpc) as usize - ptr as usize }, - 44usize, - concat!( - "Offset of field: ", - stringify!(spvc_msl_sampler_ycbcr_conversion), - "::", - stringify!(bpc) - ) - ); -} -extern "C" { - pub fn spvc_msl_sampler_ycbcr_conversion_init(conv: *mut spvc_msl_sampler_ycbcr_conversion); -} -pub const spvc_hlsl_binding_flag_bits_SPVC_HLSL_BINDING_AUTO_NONE_BIT: spvc_hlsl_binding_flag_bits = - 0; -pub const spvc_hlsl_binding_flag_bits_SPVC_HLSL_BINDING_AUTO_PUSH_CONSTANT_BIT: - spvc_hlsl_binding_flag_bits = 1; -pub const spvc_hlsl_binding_flag_bits_SPVC_HLSL_BINDING_AUTO_CBV_BIT: spvc_hlsl_binding_flag_bits = - 2; -pub const spvc_hlsl_binding_flag_bits_SPVC_HLSL_BINDING_AUTO_SRV_BIT: spvc_hlsl_binding_flag_bits = - 4; -pub const spvc_hlsl_binding_flag_bits_SPVC_HLSL_BINDING_AUTO_UAV_BIT: spvc_hlsl_binding_flag_bits = - 8; -pub const spvc_hlsl_binding_flag_bits_SPVC_HLSL_BINDING_AUTO_SAMPLER_BIT: - spvc_hlsl_binding_flag_bits = 16; -pub const spvc_hlsl_binding_flag_bits_SPVC_HLSL_BINDING_AUTO_ALL: spvc_hlsl_binding_flag_bits = - 2147483647; -pub type spvc_hlsl_binding_flag_bits = ::std::os::raw::c_int; -pub type spvc_hlsl_binding_flags = ::std::os::raw::c_uint; -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct spvc_hlsl_resource_binding_mapping { - pub register_space: ::std::os::raw::c_uint, - pub register_binding: ::std::os::raw::c_uint, -} -#[test] -fn bindgen_test_layout_spvc_hlsl_resource_binding_mapping() { - const UNINIT: ::std::mem::MaybeUninit = - ::std::mem::MaybeUninit::uninit(); - let ptr = UNINIT.as_ptr(); - assert_eq!( - ::std::mem::size_of::(), - 8usize, - concat!("Size of: ", stringify!(spvc_hlsl_resource_binding_mapping)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!( - "Alignment of ", - stringify!(spvc_hlsl_resource_binding_mapping) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).register_space) as usize - ptr as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(spvc_hlsl_resource_binding_mapping), - "::", - stringify!(register_space) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).register_binding) as usize - ptr as usize }, - 4usize, - concat!( - "Offset of field: ", - stringify!(spvc_hlsl_resource_binding_mapping), - "::", - stringify!(register_binding) - ) - ); -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct spvc_hlsl_resource_binding { - pub stage: SpvExecutionModel, - pub desc_set: ::std::os::raw::c_uint, - pub binding: ::std::os::raw::c_uint, - pub cbv: spvc_hlsl_resource_binding_mapping, - pub uav: spvc_hlsl_resource_binding_mapping, - pub srv: spvc_hlsl_resource_binding_mapping, - pub sampler: spvc_hlsl_resource_binding_mapping, -} -#[test] -fn bindgen_test_layout_spvc_hlsl_resource_binding() { - const UNINIT: ::std::mem::MaybeUninit = - ::std::mem::MaybeUninit::uninit(); - let ptr = UNINIT.as_ptr(); - assert_eq!( - ::std::mem::size_of::(), - 44usize, - concat!("Size of: ", stringify!(spvc_hlsl_resource_binding)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(spvc_hlsl_resource_binding)) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).stage) as usize - ptr as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(spvc_hlsl_resource_binding), - "::", - stringify!(stage) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).desc_set) as usize - ptr as usize }, - 4usize, - concat!( - "Offset of field: ", - stringify!(spvc_hlsl_resource_binding), - "::", - stringify!(desc_set) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).binding) as usize - ptr as usize }, - 8usize, - concat!( - "Offset of field: ", - stringify!(spvc_hlsl_resource_binding), - "::", - stringify!(binding) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).cbv) as usize - ptr as usize }, - 12usize, - concat!( - "Offset of field: ", - stringify!(spvc_hlsl_resource_binding), - "::", - stringify!(cbv) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).uav) as usize - ptr as usize }, - 20usize, - concat!( - "Offset of field: ", - stringify!(spvc_hlsl_resource_binding), - "::", - stringify!(uav) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).srv) as usize - ptr as usize }, - 28usize, - concat!( - "Offset of field: ", - stringify!(spvc_hlsl_resource_binding), - "::", - stringify!(srv) - ) - ); - assert_eq!( - unsafe { ::std::ptr::addr_of!((*ptr).sampler) as usize - ptr as usize }, - 36usize, - concat!( - "Offset of field: ", - stringify!(spvc_hlsl_resource_binding), - "::", - stringify!(sampler) - ) - ); -} -extern "C" { - pub fn spvc_hlsl_resource_binding_init(binding: *mut spvc_hlsl_resource_binding); -} -pub const spvc_compiler_option_SPVC_COMPILER_OPTION_UNKNOWN: spvc_compiler_option = 0; -pub const spvc_compiler_option_SPVC_COMPILER_OPTION_FORCE_TEMPORARY: spvc_compiler_option = - 16777217; -pub const spvc_compiler_option_SPVC_COMPILER_OPTION_FLATTEN_MULTIDIMENSIONAL_ARRAYS: - spvc_compiler_option = 16777218; -pub const spvc_compiler_option_SPVC_COMPILER_OPTION_FIXUP_DEPTH_CONVENTION: spvc_compiler_option = - 16777219; -pub const spvc_compiler_option_SPVC_COMPILER_OPTION_FLIP_VERTEX_Y: spvc_compiler_option = 16777220; -pub const spvc_compiler_option_SPVC_COMPILER_OPTION_GLSL_SUPPORT_NONZERO_BASE_INSTANCE: - spvc_compiler_option = 33554437; -pub const spvc_compiler_option_SPVC_COMPILER_OPTION_GLSL_SEPARATE_SHADER_OBJECTS: - spvc_compiler_option = 33554438; -pub const spvc_compiler_option_SPVC_COMPILER_OPTION_GLSL_ENABLE_420PACK_EXTENSION: - spvc_compiler_option = 33554439; -pub const spvc_compiler_option_SPVC_COMPILER_OPTION_GLSL_VERSION: spvc_compiler_option = 33554440; -pub const spvc_compiler_option_SPVC_COMPILER_OPTION_GLSL_ES: spvc_compiler_option = 33554441; -pub const spvc_compiler_option_SPVC_COMPILER_OPTION_GLSL_VULKAN_SEMANTICS: spvc_compiler_option = - 33554442; -pub const spvc_compiler_option_SPVC_COMPILER_OPTION_GLSL_ES_DEFAULT_FLOAT_PRECISION_HIGHP: - spvc_compiler_option = 33554443; -pub const spvc_compiler_option_SPVC_COMPILER_OPTION_GLSL_ES_DEFAULT_INT_PRECISION_HIGHP: - spvc_compiler_option = 33554444; -pub const spvc_compiler_option_SPVC_COMPILER_OPTION_HLSL_SHADER_MODEL: spvc_compiler_option = - 67108877; -pub const spvc_compiler_option_SPVC_COMPILER_OPTION_HLSL_POINT_SIZE_COMPAT: spvc_compiler_option = - 67108878; -pub const spvc_compiler_option_SPVC_COMPILER_OPTION_HLSL_POINT_COORD_COMPAT: spvc_compiler_option = - 67108879; -pub const spvc_compiler_option_SPVC_COMPILER_OPTION_HLSL_SUPPORT_NONZERO_BASE_VERTEX_BASE_INSTANCE : spvc_compiler_option = 67108880 ; -pub const spvc_compiler_option_SPVC_COMPILER_OPTION_MSL_VERSION: spvc_compiler_option = 134217745; -pub const spvc_compiler_option_SPVC_COMPILER_OPTION_MSL_TEXEL_BUFFER_TEXTURE_WIDTH: - spvc_compiler_option = 134217746; -pub const spvc_compiler_option_SPVC_COMPILER_OPTION_MSL_AUX_BUFFER_INDEX: spvc_compiler_option = - 134217747; -pub const spvc_compiler_option_SPVC_COMPILER_OPTION_MSL_SWIZZLE_BUFFER_INDEX: spvc_compiler_option = - 134217747; -pub const spvc_compiler_option_SPVC_COMPILER_OPTION_MSL_INDIRECT_PARAMS_BUFFER_INDEX: - spvc_compiler_option = 134217748; -pub const spvc_compiler_option_SPVC_COMPILER_OPTION_MSL_SHADER_OUTPUT_BUFFER_INDEX: - spvc_compiler_option = 134217749; -pub const spvc_compiler_option_SPVC_COMPILER_OPTION_MSL_SHADER_PATCH_OUTPUT_BUFFER_INDEX: - spvc_compiler_option = 134217750; -pub const spvc_compiler_option_SPVC_COMPILER_OPTION_MSL_SHADER_TESS_FACTOR_OUTPUT_BUFFER_INDEX: - spvc_compiler_option = 134217751; -pub const spvc_compiler_option_SPVC_COMPILER_OPTION_MSL_SHADER_INPUT_WORKGROUP_INDEX: - spvc_compiler_option = 134217752; -pub const spvc_compiler_option_SPVC_COMPILER_OPTION_MSL_ENABLE_POINT_SIZE_BUILTIN: - spvc_compiler_option = 134217753; -pub const spvc_compiler_option_SPVC_COMPILER_OPTION_MSL_DISABLE_RASTERIZATION: - spvc_compiler_option = 134217754; -pub const spvc_compiler_option_SPVC_COMPILER_OPTION_MSL_CAPTURE_OUTPUT_TO_BUFFER: - spvc_compiler_option = 134217755; -pub const spvc_compiler_option_SPVC_COMPILER_OPTION_MSL_SWIZZLE_TEXTURE_SAMPLES: - spvc_compiler_option = 134217756; -pub const spvc_compiler_option_SPVC_COMPILER_OPTION_MSL_PAD_FRAGMENT_OUTPUT_COMPONENTS: - spvc_compiler_option = 134217757; -pub const spvc_compiler_option_SPVC_COMPILER_OPTION_MSL_TESS_DOMAIN_ORIGIN_LOWER_LEFT: - spvc_compiler_option = 134217758; -pub const spvc_compiler_option_SPVC_COMPILER_OPTION_MSL_PLATFORM: spvc_compiler_option = 134217759; -pub const spvc_compiler_option_SPVC_COMPILER_OPTION_MSL_ARGUMENT_BUFFERS: spvc_compiler_option = - 134217760; -pub const spvc_compiler_option_SPVC_COMPILER_OPTION_GLSL_EMIT_PUSH_CONSTANT_AS_UNIFORM_BUFFER: - spvc_compiler_option = 33554465; -pub const spvc_compiler_option_SPVC_COMPILER_OPTION_MSL_TEXTURE_BUFFER_NATIVE: - spvc_compiler_option = 134217762; -pub const spvc_compiler_option_SPVC_COMPILER_OPTION_GLSL_EMIT_UNIFORM_BUFFER_AS_PLAIN_UNIFORMS: - spvc_compiler_option = 33554467; -pub const spvc_compiler_option_SPVC_COMPILER_OPTION_MSL_BUFFER_SIZE_BUFFER_INDEX: - spvc_compiler_option = 134217764; -pub const spvc_compiler_option_SPVC_COMPILER_OPTION_EMIT_LINE_DIRECTIVES: spvc_compiler_option = - 16777253; -pub const spvc_compiler_option_SPVC_COMPILER_OPTION_MSL_MULTIVIEW: spvc_compiler_option = 134217766; -pub const spvc_compiler_option_SPVC_COMPILER_OPTION_MSL_VIEW_MASK_BUFFER_INDEX: - spvc_compiler_option = 134217767; -pub const spvc_compiler_option_SPVC_COMPILER_OPTION_MSL_DEVICE_INDEX: spvc_compiler_option = - 134217768; -pub const spvc_compiler_option_SPVC_COMPILER_OPTION_MSL_VIEW_INDEX_FROM_DEVICE_INDEX: - spvc_compiler_option = 134217769; -pub const spvc_compiler_option_SPVC_COMPILER_OPTION_MSL_DISPATCH_BASE: spvc_compiler_option = - 134217770; -pub const spvc_compiler_option_SPVC_COMPILER_OPTION_MSL_DYNAMIC_OFFSETS_BUFFER_INDEX: - spvc_compiler_option = 134217771; -pub const spvc_compiler_option_SPVC_COMPILER_OPTION_MSL_TEXTURE_1D_AS_2D: spvc_compiler_option = - 134217772; -pub const spvc_compiler_option_SPVC_COMPILER_OPTION_MSL_ENABLE_BASE_INDEX_ZERO: - spvc_compiler_option = 134217773; -pub const spvc_compiler_option_SPVC_COMPILER_OPTION_MSL_IOS_FRAMEBUFFER_FETCH_SUBPASS: - spvc_compiler_option = 134217774; -pub const spvc_compiler_option_SPVC_COMPILER_OPTION_MSL_FRAMEBUFFER_FETCH_SUBPASS: - spvc_compiler_option = 134217774; -pub const spvc_compiler_option_SPVC_COMPILER_OPTION_MSL_INVARIANT_FP_MATH: spvc_compiler_option = - 134217775; -pub const spvc_compiler_option_SPVC_COMPILER_OPTION_MSL_EMULATE_CUBEMAP_ARRAY: - spvc_compiler_option = 134217776; -pub const spvc_compiler_option_SPVC_COMPILER_OPTION_MSL_ENABLE_DECORATION_BINDING: - spvc_compiler_option = 134217777; -pub const spvc_compiler_option_SPVC_COMPILER_OPTION_MSL_FORCE_ACTIVE_ARGUMENT_BUFFER_RESOURCES: - spvc_compiler_option = 134217778; -pub const spvc_compiler_option_SPVC_COMPILER_OPTION_MSL_FORCE_NATIVE_ARRAYS: spvc_compiler_option = - 134217779; -pub const spvc_compiler_option_SPVC_COMPILER_OPTION_ENABLE_STORAGE_IMAGE_QUALIFIER_DEDUCTION: - spvc_compiler_option = 16777268; -pub const spvc_compiler_option_SPVC_COMPILER_OPTION_HLSL_FORCE_STORAGE_BUFFER_AS_UAV: - spvc_compiler_option = 67108917; -pub const spvc_compiler_option_SPVC_COMPILER_OPTION_FORCE_ZERO_INITIALIZED_VARIABLES: - spvc_compiler_option = 16777270; -pub const spvc_compiler_option_SPVC_COMPILER_OPTION_HLSL_NONWRITABLE_UAV_TEXTURE_AS_SRV: - spvc_compiler_option = 67108919; -pub const spvc_compiler_option_SPVC_COMPILER_OPTION_MSL_ENABLE_FRAG_OUTPUT_MASK: - spvc_compiler_option = 134217784; -pub const spvc_compiler_option_SPVC_COMPILER_OPTION_MSL_ENABLE_FRAG_DEPTH_BUILTIN: - spvc_compiler_option = 134217785; -pub const spvc_compiler_option_SPVC_COMPILER_OPTION_MSL_ENABLE_FRAG_STENCIL_REF_BUILTIN: - spvc_compiler_option = 134217786; -pub const spvc_compiler_option_SPVC_COMPILER_OPTION_MSL_ENABLE_CLIP_DISTANCE_USER_VARYING: - spvc_compiler_option = 134217787; -pub const spvc_compiler_option_SPVC_COMPILER_OPTION_HLSL_ENABLE_16BIT_TYPES: spvc_compiler_option = - 67108924; -pub const spvc_compiler_option_SPVC_COMPILER_OPTION_MSL_MULTI_PATCH_WORKGROUP: - spvc_compiler_option = 134217789; -pub const spvc_compiler_option_SPVC_COMPILER_OPTION_MSL_SHADER_INPUT_BUFFER_INDEX: - spvc_compiler_option = 134217790; -pub const spvc_compiler_option_SPVC_COMPILER_OPTION_MSL_SHADER_INDEX_BUFFER_INDEX: - spvc_compiler_option = 134217791; -pub const spvc_compiler_option_SPVC_COMPILER_OPTION_MSL_VERTEX_FOR_TESSELLATION: - spvc_compiler_option = 134217792; -pub const spvc_compiler_option_SPVC_COMPILER_OPTION_MSL_VERTEX_INDEX_TYPE: spvc_compiler_option = - 134217793; -pub const spvc_compiler_option_SPVC_COMPILER_OPTION_GLSL_FORCE_FLATTENED_IO_BLOCKS: - spvc_compiler_option = 33554498; -pub const spvc_compiler_option_SPVC_COMPILER_OPTION_MSL_MULTIVIEW_LAYERED_RENDERING: - spvc_compiler_option = 134217795; -pub const spvc_compiler_option_SPVC_COMPILER_OPTION_MSL_ARRAYED_SUBPASS_INPUT: - spvc_compiler_option = 134217796; -pub const spvc_compiler_option_SPVC_COMPILER_OPTION_MSL_R32UI_LINEAR_TEXTURE_ALIGNMENT: - spvc_compiler_option = 134217797; -pub const spvc_compiler_option_SPVC_COMPILER_OPTION_MSL_R32UI_ALIGNMENT_CONSTANT_ID: - spvc_compiler_option = 134217798; -pub const spvc_compiler_option_SPVC_COMPILER_OPTION_HLSL_FLATTEN_MATRIX_VERTEX_INPUT_SEMANTICS: - spvc_compiler_option = 67108935; -pub const spvc_compiler_option_SPVC_COMPILER_OPTION_MSL_IOS_USE_SIMDGROUP_FUNCTIONS: - spvc_compiler_option = 134217800; -pub const spvc_compiler_option_SPVC_COMPILER_OPTION_MSL_EMULATE_SUBGROUPS: spvc_compiler_option = - 134217801; -pub const spvc_compiler_option_SPVC_COMPILER_OPTION_MSL_FIXED_SUBGROUP_SIZE: spvc_compiler_option = - 134217802; -pub const spvc_compiler_option_SPVC_COMPILER_OPTION_MSL_FORCE_SAMPLE_RATE_SHADING: - spvc_compiler_option = 134217803; -pub const spvc_compiler_option_SPVC_COMPILER_OPTION_MSL_IOS_SUPPORT_BASE_VERTEX_INSTANCE: - spvc_compiler_option = 134217804; -pub const spvc_compiler_option_SPVC_COMPILER_OPTION_GLSL_OVR_MULTIVIEW_VIEW_COUNT: - spvc_compiler_option = 33554509; -pub const spvc_compiler_option_SPVC_COMPILER_OPTION_RELAX_NAN_CHECKS: spvc_compiler_option = - 16777294; -pub const spvc_compiler_option_SPVC_COMPILER_OPTION_MSL_RAW_BUFFER_TESE_INPUT: - spvc_compiler_option = 134217807; -pub const spvc_compiler_option_SPVC_COMPILER_OPTION_MSL_SHADER_PATCH_INPUT_BUFFER_INDEX: - spvc_compiler_option = 134217808; -pub const spvc_compiler_option_SPVC_COMPILER_OPTION_MSL_MANUAL_HELPER_INVOCATION_UPDATES: - spvc_compiler_option = 134217809; -pub const spvc_compiler_option_SPVC_COMPILER_OPTION_MSL_CHECK_DISCARDED_FRAG_STORES: - spvc_compiler_option = 134217810; -pub const spvc_compiler_option_SPVC_COMPILER_OPTION_GLSL_ENABLE_ROW_MAJOR_LOAD_WORKAROUND: - spvc_compiler_option = 33554515; -pub const spvc_compiler_option_SPVC_COMPILER_OPTION_MSL_ARGUMENT_BUFFERS_TIER: - spvc_compiler_option = 134217812; -pub const spvc_compiler_option_SPVC_COMPILER_OPTION_MSL_SAMPLE_DREF_LOD_ARRAY_AS_GRAD: - spvc_compiler_option = 134217813; -pub const spvc_compiler_option_SPVC_COMPILER_OPTION_MSL_READWRITE_TEXTURE_FENCES: - spvc_compiler_option = 134217814; -pub const spvc_compiler_option_SPVC_COMPILER_OPTION_MSL_REPLACE_RECURSIVE_INPUTS: - spvc_compiler_option = 134217815; -pub const spvc_compiler_option_SPVC_COMPILER_OPTION_MSL_AGX_MANUAL_CUBE_GRAD_FIXUP: - spvc_compiler_option = 134217816; -pub const spvc_compiler_option_SPVC_COMPILER_OPTION_MSL_FORCE_FRAGMENT_WITH_SIDE_EFFECTS_EXECUTION : spvc_compiler_option = 134217817 ; -pub const spvc_compiler_option_SPVC_COMPILER_OPTION_HLSL_USE_ENTRY_POINT_NAME: - spvc_compiler_option = 67108954; -pub const spvc_compiler_option_SPVC_COMPILER_OPTION_HLSL_PRESERVE_STRUCTURED_BUFFERS: - spvc_compiler_option = 67108955; -pub const spvc_compiler_option_SPVC_COMPILER_OPTION_MSL_AUTO_DISABLE_RASTERIZATION: - spvc_compiler_option = 134217820; -pub const spvc_compiler_option_SPVC_COMPILER_OPTION_MSL_ENABLE_POINT_SIZE_DEFAULT: - spvc_compiler_option = 134217821; -pub const spvc_compiler_option_SPVC_COMPILER_OPTION_INT_MAX: spvc_compiler_option = 2147483647; -pub type spvc_compiler_option = ::std::os::raw::c_int; -extern "C" { - pub fn spvc_context_create(context: *mut spvc_context) -> spvc_result; -} -extern "C" { - pub fn spvc_context_destroy(context: spvc_context); -} -extern "C" { - pub fn spvc_context_release_allocations(context: spvc_context); -} -extern "C" { - pub fn spvc_context_get_last_error_string( - context: spvc_context, - ) -> *const ::std::os::raw::c_char; -} -pub type spvc_error_callback = ::std::option::Option< - unsafe extern "C" fn( - userdata: *mut ::std::os::raw::c_void, - error: *const ::std::os::raw::c_char, - ), ->; -extern "C" { - pub fn spvc_context_set_error_callback( - context: spvc_context, - cb: spvc_error_callback, - userdata: *mut ::std::os::raw::c_void, - ); -} -extern "C" { - pub fn spvc_context_parse_spirv( - context: spvc_context, - spirv: *const SpvId, - word_count: usize, - parsed_ir: *mut spvc_parsed_ir, - ) -> spvc_result; -} -extern "C" { - pub fn spvc_context_create_compiler( - context: spvc_context, - backend: spvc_backend, - parsed_ir: spvc_parsed_ir, - mode: spvc_capture_mode, - compiler: *mut spvc_compiler, - ) -> spvc_result; -} -extern "C" { - pub fn spvc_compiler_get_current_id_bound(compiler: spvc_compiler) -> ::std::os::raw::c_uint; -} -extern "C" { - pub fn spvc_compiler_create_compiler_options( - compiler: spvc_compiler, - options: *mut spvc_compiler_options, - ) -> spvc_result; -} -extern "C" { - pub fn spvc_compiler_options_set_bool( - options: spvc_compiler_options, - option: spvc_compiler_option, - value: spvc_bool, - ) -> spvc_result; -} -extern "C" { - pub fn spvc_compiler_options_set_uint( - options: spvc_compiler_options, - option: spvc_compiler_option, - value: ::std::os::raw::c_uint, - ) -> spvc_result; -} -extern "C" { - pub fn spvc_compiler_install_compiler_options( - compiler: spvc_compiler, - options: spvc_compiler_options, - ) -> spvc_result; -} -extern "C" { - pub fn spvc_compiler_compile( - compiler: spvc_compiler, - source: *mut *const ::std::os::raw::c_char, - ) -> spvc_result; -} -extern "C" { - pub fn spvc_compiler_add_header_line( - compiler: spvc_compiler, - line: *const ::std::os::raw::c_char, - ) -> spvc_result; -} -extern "C" { - pub fn spvc_compiler_require_extension( - compiler: spvc_compiler, - ext: *const ::std::os::raw::c_char, - ) -> spvc_result; -} -extern "C" { - pub fn spvc_compiler_get_num_required_extensions(compiler: spvc_compiler) -> usize; -} -extern "C" { - pub fn spvc_compiler_get_required_extension( - compiler: spvc_compiler, - index: usize, - ) -> *const ::std::os::raw::c_char; -} -extern "C" { - pub fn spvc_compiler_flatten_buffer_block( - compiler: spvc_compiler, - id: spvc_variable_id, - ) -> spvc_result; -} -extern "C" { - pub fn spvc_compiler_variable_is_depth_or_compare( - compiler: spvc_compiler, - id: spvc_variable_id, - ) -> spvc_bool; -} -extern "C" { - pub fn spvc_compiler_mask_stage_output_by_location( - compiler: spvc_compiler, - location: ::std::os::raw::c_uint, - component: ::std::os::raw::c_uint, - ) -> spvc_result; -} -extern "C" { - pub fn spvc_compiler_mask_stage_output_by_builtin( - compiler: spvc_compiler, - builtin: SpvBuiltIn, - ) -> spvc_result; -} -extern "C" { - pub fn spvc_compiler_hlsl_set_root_constants_layout( - compiler: spvc_compiler, - constant_info: *const spvc_hlsl_root_constants, - count: usize, - ) -> spvc_result; -} -extern "C" { - pub fn spvc_compiler_hlsl_add_vertex_attribute_remap( - compiler: spvc_compiler, - remap: *const spvc_hlsl_vertex_attribute_remap, - remaps: usize, - ) -> spvc_result; -} -extern "C" { - pub fn spvc_compiler_hlsl_remap_num_workgroups_builtin( - compiler: spvc_compiler, - ) -> spvc_variable_id; -} -extern "C" { - pub fn spvc_compiler_hlsl_set_resource_binding_flags( - compiler: spvc_compiler, - flags: spvc_hlsl_binding_flags, - ) -> spvc_result; -} -extern "C" { - pub fn spvc_compiler_hlsl_add_resource_binding( - compiler: spvc_compiler, - binding: *const spvc_hlsl_resource_binding, - ) -> spvc_result; -} -extern "C" { - pub fn spvc_compiler_hlsl_is_resource_used( - compiler: spvc_compiler, - model: SpvExecutionModel, - set: ::std::os::raw::c_uint, - binding: ::std::os::raw::c_uint, - ) -> spvc_bool; -} -extern "C" { - pub fn spvc_compiler_msl_is_rasterization_disabled(compiler: spvc_compiler) -> spvc_bool; -} -extern "C" { - pub fn spvc_compiler_msl_needs_aux_buffer(compiler: spvc_compiler) -> spvc_bool; -} -extern "C" { - pub fn spvc_compiler_msl_needs_swizzle_buffer(compiler: spvc_compiler) -> spvc_bool; -} -extern "C" { - pub fn spvc_compiler_msl_needs_buffer_size_buffer(compiler: spvc_compiler) -> spvc_bool; -} -extern "C" { - pub fn spvc_compiler_msl_needs_output_buffer(compiler: spvc_compiler) -> spvc_bool; -} -extern "C" { - pub fn spvc_compiler_msl_needs_patch_output_buffer(compiler: spvc_compiler) -> spvc_bool; -} -extern "C" { - pub fn spvc_compiler_msl_needs_input_threadgroup_mem(compiler: spvc_compiler) -> spvc_bool; -} -extern "C" { - pub fn spvc_compiler_msl_add_vertex_attribute( - compiler: spvc_compiler, - attrs: *const spvc_msl_vertex_attribute, - ) -> spvc_result; -} -extern "C" { - pub fn spvc_compiler_msl_add_resource_binding( - compiler: spvc_compiler, - binding: *const spvc_msl_resource_binding, - ) -> spvc_result; -} -extern "C" { - pub fn spvc_compiler_msl_add_resource_binding_2( - compiler: spvc_compiler, - binding: *const spvc_msl_resource_binding_2, - ) -> spvc_result; -} -extern "C" { - pub fn spvc_compiler_msl_add_shader_input( - compiler: spvc_compiler, - input: *const spvc_msl_shader_interface_var, - ) -> spvc_result; -} -extern "C" { - pub fn spvc_compiler_msl_add_shader_input_2( - compiler: spvc_compiler, - input: *const spvc_msl_shader_interface_var_2, - ) -> spvc_result; -} -extern "C" { - pub fn spvc_compiler_msl_add_shader_output( - compiler: spvc_compiler, - output: *const spvc_msl_shader_interface_var, - ) -> spvc_result; -} -extern "C" { - pub fn spvc_compiler_msl_add_shader_output_2( - compiler: spvc_compiler, - output: *const spvc_msl_shader_interface_var_2, - ) -> spvc_result; -} -extern "C" { - pub fn spvc_compiler_msl_add_discrete_descriptor_set( - compiler: spvc_compiler, - desc_set: ::std::os::raw::c_uint, - ) -> spvc_result; -} -extern "C" { - pub fn spvc_compiler_msl_set_argument_buffer_device_address_space( - compiler: spvc_compiler, - desc_set: ::std::os::raw::c_uint, - device_address: spvc_bool, - ) -> spvc_result; -} -extern "C" { - pub fn spvc_compiler_msl_is_vertex_attribute_used( - compiler: spvc_compiler, - location: ::std::os::raw::c_uint, - ) -> spvc_bool; -} -extern "C" { - pub fn spvc_compiler_msl_is_shader_input_used( - compiler: spvc_compiler, - location: ::std::os::raw::c_uint, - ) -> spvc_bool; -} -extern "C" { - pub fn spvc_compiler_msl_is_shader_output_used( - compiler: spvc_compiler, - location: ::std::os::raw::c_uint, - ) -> spvc_bool; -} -extern "C" { - pub fn spvc_compiler_msl_is_resource_used( - compiler: spvc_compiler, - model: SpvExecutionModel, - set: ::std::os::raw::c_uint, - binding: ::std::os::raw::c_uint, - ) -> spvc_bool; -} -extern "C" { - pub fn spvc_compiler_msl_remap_constexpr_sampler( - compiler: spvc_compiler, - id: spvc_variable_id, - sampler: *const spvc_msl_constexpr_sampler, - ) -> spvc_result; -} -extern "C" { - pub fn spvc_compiler_msl_remap_constexpr_sampler_by_binding( - compiler: spvc_compiler, - desc_set: ::std::os::raw::c_uint, - binding: ::std::os::raw::c_uint, - sampler: *const spvc_msl_constexpr_sampler, - ) -> spvc_result; -} -extern "C" { - pub fn spvc_compiler_msl_remap_constexpr_sampler_ycbcr( - compiler: spvc_compiler, - id: spvc_variable_id, - sampler: *const spvc_msl_constexpr_sampler, - conv: *const spvc_msl_sampler_ycbcr_conversion, - ) -> spvc_result; -} -extern "C" { - pub fn spvc_compiler_msl_remap_constexpr_sampler_by_binding_ycbcr( - compiler: spvc_compiler, - desc_set: ::std::os::raw::c_uint, - binding: ::std::os::raw::c_uint, - sampler: *const spvc_msl_constexpr_sampler, - conv: *const spvc_msl_sampler_ycbcr_conversion, - ) -> spvc_result; -} -extern "C" { - pub fn spvc_compiler_msl_set_fragment_output_components( - compiler: spvc_compiler, - location: ::std::os::raw::c_uint, - components: ::std::os::raw::c_uint, - ) -> spvc_result; -} -extern "C" { - pub fn spvc_compiler_msl_get_automatic_resource_binding( - compiler: spvc_compiler, - id: spvc_variable_id, - ) -> ::std::os::raw::c_uint; -} -extern "C" { - pub fn spvc_compiler_msl_get_automatic_resource_binding_secondary( - compiler: spvc_compiler, - id: spvc_variable_id, - ) -> ::std::os::raw::c_uint; -} -extern "C" { - pub fn spvc_compiler_msl_add_dynamic_buffer( - compiler: spvc_compiler, - desc_set: ::std::os::raw::c_uint, - binding: ::std::os::raw::c_uint, - index: ::std::os::raw::c_uint, - ) -> spvc_result; -} -extern "C" { - pub fn spvc_compiler_msl_add_inline_uniform_block( - compiler: spvc_compiler, - desc_set: ::std::os::raw::c_uint, - binding: ::std::os::raw::c_uint, - ) -> spvc_result; -} -extern "C" { - pub fn spvc_compiler_msl_set_combined_sampler_suffix( - compiler: spvc_compiler, - suffix: *const ::std::os::raw::c_char, - ) -> spvc_result; -} -extern "C" { - pub fn spvc_compiler_msl_get_combined_sampler_suffix( - compiler: spvc_compiler, - ) -> *const ::std::os::raw::c_char; -} -extern "C" { - pub fn spvc_compiler_get_active_interface_variables( - compiler: spvc_compiler, - set: *mut spvc_set, - ) -> spvc_result; -} -extern "C" { - pub fn spvc_compiler_set_enabled_interface_variables( - compiler: spvc_compiler, - set: spvc_set, - ) -> spvc_result; -} -extern "C" { - pub fn spvc_compiler_create_shader_resources( - compiler: spvc_compiler, - resources: *mut spvc_resources, - ) -> spvc_result; -} -extern "C" { - pub fn spvc_compiler_create_shader_resources_for_active_variables( - compiler: spvc_compiler, - resources: *mut spvc_resources, - active: spvc_set, - ) -> spvc_result; -} -extern "C" { - pub fn spvc_resources_get_resource_list_for_type( - resources: spvc_resources, - type_: spvc_resource_type, - resource_list: *mut *const spvc_reflected_resource, - resource_size: *mut usize, - ) -> spvc_result; -} -extern "C" { - pub fn spvc_resources_get_builtin_resource_list_for_type( - resources: spvc_resources, - type_: spvc_builtin_resource_type, - resource_list: *mut *const spvc_reflected_builtin_resource, - resource_size: *mut usize, - ) -> spvc_result; -} -extern "C" { - pub fn spvc_compiler_set_decoration( - compiler: spvc_compiler, - id: SpvId, - decoration: SpvDecoration, - argument: ::std::os::raw::c_uint, - ); -} -extern "C" { - pub fn spvc_compiler_set_decoration_string( - compiler: spvc_compiler, - id: SpvId, - decoration: SpvDecoration, - argument: *const ::std::os::raw::c_char, - ); -} -extern "C" { - pub fn spvc_compiler_set_name( - compiler: spvc_compiler, - id: SpvId, - argument: *const ::std::os::raw::c_char, - ); -} -extern "C" { - pub fn spvc_compiler_set_member_decoration( - compiler: spvc_compiler, - id: spvc_type_id, - member_index: ::std::os::raw::c_uint, - decoration: SpvDecoration, - argument: ::std::os::raw::c_uint, - ); -} -extern "C" { - pub fn spvc_compiler_set_member_decoration_string( - compiler: spvc_compiler, - id: spvc_type_id, - member_index: ::std::os::raw::c_uint, - decoration: SpvDecoration, - argument: *const ::std::os::raw::c_char, - ); -} -extern "C" { - pub fn spvc_compiler_set_member_name( - compiler: spvc_compiler, - id: spvc_type_id, - member_index: ::std::os::raw::c_uint, - argument: *const ::std::os::raw::c_char, - ); -} -extern "C" { - pub fn spvc_compiler_unset_decoration( - compiler: spvc_compiler, - id: SpvId, - decoration: SpvDecoration, - ); -} -extern "C" { - pub fn spvc_compiler_unset_member_decoration( - compiler: spvc_compiler, - id: spvc_type_id, - member_index: ::std::os::raw::c_uint, - decoration: SpvDecoration, - ); -} -extern "C" { - pub fn spvc_compiler_has_decoration( - compiler: spvc_compiler, - id: SpvId, - decoration: SpvDecoration, - ) -> spvc_bool; -} -extern "C" { - pub fn spvc_compiler_has_member_decoration( - compiler: spvc_compiler, - id: spvc_type_id, - member_index: ::std::os::raw::c_uint, - decoration: SpvDecoration, - ) -> spvc_bool; -} -extern "C" { - pub fn spvc_compiler_get_name( - compiler: spvc_compiler, - id: SpvId, - ) -> *const ::std::os::raw::c_char; -} -extern "C" { - pub fn spvc_compiler_get_decoration( - compiler: spvc_compiler, - id: SpvId, - decoration: SpvDecoration, - ) -> ::std::os::raw::c_uint; -} -extern "C" { - pub fn spvc_compiler_get_decoration_string( - compiler: spvc_compiler, - id: SpvId, - decoration: SpvDecoration, - ) -> *const ::std::os::raw::c_char; -} -extern "C" { - pub fn spvc_compiler_get_member_decoration( - compiler: spvc_compiler, - id: spvc_type_id, - member_index: ::std::os::raw::c_uint, - decoration: SpvDecoration, - ) -> ::std::os::raw::c_uint; -} -extern "C" { - pub fn spvc_compiler_get_member_decoration_string( - compiler: spvc_compiler, - id: spvc_type_id, - member_index: ::std::os::raw::c_uint, - decoration: SpvDecoration, - ) -> *const ::std::os::raw::c_char; -} -extern "C" { - pub fn spvc_compiler_get_member_name( - compiler: spvc_compiler, - id: spvc_type_id, - member_index: ::std::os::raw::c_uint, - ) -> *const ::std::os::raw::c_char; -} -extern "C" { - pub fn spvc_compiler_get_entry_points( - compiler: spvc_compiler, - entry_points: *mut *const spvc_entry_point, - num_entry_points: *mut usize, - ) -> spvc_result; -} -extern "C" { - pub fn spvc_compiler_set_entry_point( - compiler: spvc_compiler, - name: *const ::std::os::raw::c_char, - model: SpvExecutionModel, - ) -> spvc_result; -} -extern "C" { - pub fn spvc_compiler_rename_entry_point( - compiler: spvc_compiler, - old_name: *const ::std::os::raw::c_char, - new_name: *const ::std::os::raw::c_char, - model: SpvExecutionModel, - ) -> spvc_result; -} -extern "C" { - pub fn spvc_compiler_get_cleansed_entry_point_name( - compiler: spvc_compiler, - name: *const ::std::os::raw::c_char, - model: SpvExecutionModel, - ) -> *const ::std::os::raw::c_char; -} -extern "C" { - pub fn spvc_compiler_set_execution_mode(compiler: spvc_compiler, mode: SpvExecutionMode); -} -extern "C" { - pub fn spvc_compiler_unset_execution_mode(compiler: spvc_compiler, mode: SpvExecutionMode); -} -extern "C" { - pub fn spvc_compiler_set_execution_mode_with_arguments( - compiler: spvc_compiler, - mode: SpvExecutionMode, - arg0: ::std::os::raw::c_uint, - arg1: ::std::os::raw::c_uint, - arg2: ::std::os::raw::c_uint, - ); -} -extern "C" { - pub fn spvc_compiler_get_execution_modes( - compiler: spvc_compiler, - modes: *mut *const SpvExecutionMode, - num_modes: *mut usize, - ) -> spvc_result; -} -extern "C" { - pub fn spvc_compiler_get_execution_mode_argument( - compiler: spvc_compiler, - mode: SpvExecutionMode, - ) -> ::std::os::raw::c_uint; -} -extern "C" { - pub fn spvc_compiler_get_execution_mode_argument_by_index( - compiler: spvc_compiler, - mode: SpvExecutionMode, - index: ::std::os::raw::c_uint, - ) -> ::std::os::raw::c_uint; -} -extern "C" { - pub fn spvc_compiler_get_execution_model(compiler: spvc_compiler) -> SpvExecutionModel; -} -extern "C" { - pub fn spvc_compiler_update_active_builtins(compiler: spvc_compiler); -} -extern "C" { - pub fn spvc_compiler_has_active_builtin( - compiler: spvc_compiler, - builtin: SpvBuiltIn, - storage: SpvStorageClass, - ) -> spvc_bool; -} -extern "C" { - pub fn spvc_compiler_get_type_handle(compiler: spvc_compiler, id: spvc_type_id) -> spvc_type; -} -extern "C" { - pub fn spvc_type_get_base_type_id(type_: spvc_type) -> spvc_type_id; -} -extern "C" { - pub fn spvc_type_get_basetype(type_: spvc_type) -> spvc_basetype; -} -extern "C" { - pub fn spvc_type_get_bit_width(type_: spvc_type) -> ::std::os::raw::c_uint; -} -extern "C" { - pub fn spvc_type_get_vector_size(type_: spvc_type) -> ::std::os::raw::c_uint; -} -extern "C" { - pub fn spvc_type_get_columns(type_: spvc_type) -> ::std::os::raw::c_uint; -} -extern "C" { - pub fn spvc_type_get_num_array_dimensions(type_: spvc_type) -> ::std::os::raw::c_uint; -} -extern "C" { - pub fn spvc_type_array_dimension_is_literal( - type_: spvc_type, - dimension: ::std::os::raw::c_uint, - ) -> spvc_bool; -} -extern "C" { - pub fn spvc_type_get_array_dimension( - type_: spvc_type, - dimension: ::std::os::raw::c_uint, - ) -> SpvId; -} -extern "C" { - pub fn spvc_type_get_num_member_types(type_: spvc_type) -> ::std::os::raw::c_uint; -} -extern "C" { - pub fn spvc_type_get_member_type( - type_: spvc_type, - index: ::std::os::raw::c_uint, - ) -> spvc_type_id; -} -extern "C" { - pub fn spvc_type_get_storage_class(type_: spvc_type) -> SpvStorageClass; -} -extern "C" { - pub fn spvc_type_get_image_sampled_type(type_: spvc_type) -> spvc_type_id; -} -extern "C" { - pub fn spvc_type_get_image_dimension(type_: spvc_type) -> SpvDim; -} -extern "C" { - pub fn spvc_type_get_image_is_depth(type_: spvc_type) -> spvc_bool; -} -extern "C" { - pub fn spvc_type_get_image_arrayed(type_: spvc_type) -> spvc_bool; -} -extern "C" { - pub fn spvc_type_get_image_multisampled(type_: spvc_type) -> spvc_bool; -} -extern "C" { - pub fn spvc_type_get_image_is_storage(type_: spvc_type) -> spvc_bool; -} -extern "C" { - pub fn spvc_type_get_image_storage_format(type_: spvc_type) -> SpvImageFormat; -} -extern "C" { - pub fn spvc_type_get_image_access_qualifier(type_: spvc_type) -> SpvAccessQualifier; -} -extern "C" { - pub fn spvc_compiler_get_declared_struct_size( - compiler: spvc_compiler, - struct_type: spvc_type, - size: *mut usize, - ) -> spvc_result; -} -extern "C" { - pub fn spvc_compiler_get_declared_struct_size_runtime_array( - compiler: spvc_compiler, - struct_type: spvc_type, - array_size: usize, - size: *mut usize, - ) -> spvc_result; -} -extern "C" { - pub fn spvc_compiler_get_declared_struct_member_size( - compiler: spvc_compiler, - type_: spvc_type, - index: ::std::os::raw::c_uint, - size: *mut usize, - ) -> spvc_result; -} -extern "C" { - pub fn spvc_compiler_type_struct_member_offset( - compiler: spvc_compiler, - type_: spvc_type, - index: ::std::os::raw::c_uint, - offset: *mut ::std::os::raw::c_uint, - ) -> spvc_result; -} -extern "C" { - pub fn spvc_compiler_type_struct_member_array_stride( - compiler: spvc_compiler, - type_: spvc_type, - index: ::std::os::raw::c_uint, - stride: *mut ::std::os::raw::c_uint, - ) -> spvc_result; -} -extern "C" { - pub fn spvc_compiler_type_struct_member_matrix_stride( - compiler: spvc_compiler, - type_: spvc_type, - index: ::std::os::raw::c_uint, - stride: *mut ::std::os::raw::c_uint, - ) -> spvc_result; -} -extern "C" { - pub fn spvc_compiler_build_dummy_sampler_for_combined_images( - compiler: spvc_compiler, - id: *mut spvc_variable_id, - ) -> spvc_result; -} -extern "C" { - pub fn spvc_compiler_build_combined_image_samplers(compiler: spvc_compiler) -> spvc_result; -} -extern "C" { - pub fn spvc_compiler_get_combined_image_samplers( - compiler: spvc_compiler, - samplers: *mut *const spvc_combined_image_sampler, - num_samplers: *mut usize, - ) -> spvc_result; -} -extern "C" { - pub fn spvc_compiler_get_specialization_constants( - compiler: spvc_compiler, - constants: *mut *const spvc_specialization_constant, - num_constants: *mut usize, - ) -> spvc_result; -} -extern "C" { - pub fn spvc_compiler_get_constant_handle( - compiler: spvc_compiler, - id: spvc_constant_id, - ) -> spvc_constant; -} -extern "C" { - pub fn spvc_compiler_get_work_group_size_specialization_constants( - compiler: spvc_compiler, - x: *mut spvc_specialization_constant, - y: *mut spvc_specialization_constant, - z: *mut spvc_specialization_constant, - ) -> spvc_constant_id; -} -extern "C" { - pub fn spvc_compiler_get_active_buffer_ranges( - compiler: spvc_compiler, - id: spvc_variable_id, - ranges: *mut *const spvc_buffer_range, - num_ranges: *mut usize, - ) -> spvc_result; -} -extern "C" { - pub fn spvc_constant_get_scalar_fp16( - constant: spvc_constant, - column: ::std::os::raw::c_uint, - row: ::std::os::raw::c_uint, - ) -> f32; -} -extern "C" { - pub fn spvc_constant_get_scalar_fp32( - constant: spvc_constant, - column: ::std::os::raw::c_uint, - row: ::std::os::raw::c_uint, - ) -> f32; -} -extern "C" { - pub fn spvc_constant_get_scalar_fp64( - constant: spvc_constant, - column: ::std::os::raw::c_uint, - row: ::std::os::raw::c_uint, - ) -> f64; -} -extern "C" { - pub fn spvc_constant_get_scalar_u32( - constant: spvc_constant, - column: ::std::os::raw::c_uint, - row: ::std::os::raw::c_uint, - ) -> ::std::os::raw::c_uint; -} -extern "C" { - pub fn spvc_constant_get_scalar_i32( - constant: spvc_constant, - column: ::std::os::raw::c_uint, - row: ::std::os::raw::c_uint, - ) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn spvc_constant_get_scalar_u16( - constant: spvc_constant, - column: ::std::os::raw::c_uint, - row: ::std::os::raw::c_uint, - ) -> ::std::os::raw::c_uint; -} -extern "C" { - pub fn spvc_constant_get_scalar_i16( - constant: spvc_constant, - column: ::std::os::raw::c_uint, - row: ::std::os::raw::c_uint, - ) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn spvc_constant_get_scalar_u8( - constant: spvc_constant, - column: ::std::os::raw::c_uint, - row: ::std::os::raw::c_uint, - ) -> ::std::os::raw::c_uint; -} -extern "C" { - pub fn spvc_constant_get_scalar_i8( - constant: spvc_constant, - column: ::std::os::raw::c_uint, - row: ::std::os::raw::c_uint, - ) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn spvc_constant_get_subconstants( - constant: spvc_constant, - constituents: *mut *const spvc_constant_id, - count: *mut usize, - ); -} -extern "C" { - pub fn spvc_constant_get_scalar_u64( - constant: spvc_constant, - column: ::std::os::raw::c_uint, - row: ::std::os::raw::c_uint, - ) -> ::std::os::raw::c_ulonglong; -} -extern "C" { - pub fn spvc_constant_get_scalar_i64( - constant: spvc_constant, - column: ::std::os::raw::c_uint, - row: ::std::os::raw::c_uint, - ) -> ::std::os::raw::c_longlong; -} -extern "C" { - pub fn spvc_constant_get_type(constant: spvc_constant) -> spvc_type_id; -} -extern "C" { - pub fn spvc_constant_set_scalar_fp16( - constant: spvc_constant, - column: ::std::os::raw::c_uint, - row: ::std::os::raw::c_uint, - value: ::std::os::raw::c_ushort, - ); -} -extern "C" { - pub fn spvc_constant_set_scalar_fp32( - constant: spvc_constant, - column: ::std::os::raw::c_uint, - row: ::std::os::raw::c_uint, - value: f32, - ); -} -extern "C" { - pub fn spvc_constant_set_scalar_fp64( - constant: spvc_constant, - column: ::std::os::raw::c_uint, - row: ::std::os::raw::c_uint, - value: f64, - ); -} -extern "C" { - pub fn spvc_constant_set_scalar_u32( - constant: spvc_constant, - column: ::std::os::raw::c_uint, - row: ::std::os::raw::c_uint, - value: ::std::os::raw::c_uint, - ); -} -extern "C" { - pub fn spvc_constant_set_scalar_i32( - constant: spvc_constant, - column: ::std::os::raw::c_uint, - row: ::std::os::raw::c_uint, - value: ::std::os::raw::c_int, - ); -} -extern "C" { - pub fn spvc_constant_set_scalar_u64( - constant: spvc_constant, - column: ::std::os::raw::c_uint, - row: ::std::os::raw::c_uint, - value: ::std::os::raw::c_ulonglong, - ); -} -extern "C" { - pub fn spvc_constant_set_scalar_i64( - constant: spvc_constant, - column: ::std::os::raw::c_uint, - row: ::std::os::raw::c_uint, - value: ::std::os::raw::c_longlong, - ); -} -extern "C" { - pub fn spvc_constant_set_scalar_u16( - constant: spvc_constant, - column: ::std::os::raw::c_uint, - row: ::std::os::raw::c_uint, - value: ::std::os::raw::c_ushort, - ); -} -extern "C" { - pub fn spvc_constant_set_scalar_i16( - constant: spvc_constant, - column: ::std::os::raw::c_uint, - row: ::std::os::raw::c_uint, - value: ::std::os::raw::c_short, - ); -} -extern "C" { - pub fn spvc_constant_set_scalar_u8( - constant: spvc_constant, - column: ::std::os::raw::c_uint, - row: ::std::os::raw::c_uint, - value: ::std::os::raw::c_uchar, - ); -} -extern "C" { - pub fn spvc_constant_set_scalar_i8( - constant: spvc_constant, - column: ::std::os::raw::c_uint, - row: ::std::os::raw::c_uint, - value: ::std::os::raw::c_schar, - ); -} -extern "C" { - pub fn spvc_compiler_get_binary_offset_for_decoration( - compiler: spvc_compiler, - id: spvc_variable_id, - decoration: SpvDecoration, - word_offset: *mut ::std::os::raw::c_uint, - ) -> spvc_bool; -} -extern "C" { - pub fn spvc_compiler_buffer_is_hlsl_counter_buffer( - compiler: spvc_compiler, - id: spvc_variable_id, - ) -> spvc_bool; -} -extern "C" { - pub fn spvc_compiler_buffer_get_hlsl_counter_buffer( - compiler: spvc_compiler, - id: spvc_variable_id, - counter_id: *mut spvc_variable_id, - ) -> spvc_bool; -} -extern "C" { - pub fn spvc_compiler_get_declared_capabilities( - compiler: spvc_compiler, - capabilities: *mut *const SpvCapability, - num_capabilities: *mut usize, - ) -> spvc_result; -} -extern "C" { - pub fn spvc_compiler_get_declared_extensions( - compiler: spvc_compiler, - extensions: *mut *mut *const ::std::os::raw::c_char, - num_extensions: *mut usize, - ) -> spvc_result; -} -extern "C" { - pub fn spvc_compiler_get_remapped_declared_block_name( - compiler: spvc_compiler, - id: spvc_variable_id, - ) -> *const ::std::os::raw::c_char; -} -extern "C" { - pub fn spvc_compiler_get_buffer_block_decorations( - compiler: spvc_compiler, - id: spvc_variable_id, - decorations: *mut *const SpvDecoration, - num_decorations: *mut usize, - ) -> spvc_result; -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct __crt_locale_data { - pub _address: u8, -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct __crt_multibyte_data { - pub _address: u8, -} diff --git a/crates/htwv/third_party/SPIRV-Cross b/crates/htwv/third_party/SPIRV-Cross deleted file mode 160000 index 7bfcf72a..00000000 --- a/crates/htwv/third_party/SPIRV-Cross +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 7bfcf72ad28d1429deddff6c71b71c81b40b7063 diff --git a/hotline-data b/hotline-data index 26dfb2c6..61602f53 160000 --- a/hotline-data +++ b/hotline-data @@ -1 +1 @@ -Subproject commit 26dfb2c6a49275eac101f92f4f354ba473a62bb6 +Subproject commit 61602f53670155a0d3e4a8a48dcb31c6a21aa3ae From 4baab3cd4fb4754edcd1853238b85ac13ad79cc1 Mon Sep 17 00:00:00 2001 From: polymonster Date: Mon, 18 May 2026 13:13:29 +0200 Subject: [PATCH 43/62] - supress cargo clippy warning --- hotline-data | 2 +- src/gfx/mtl.rs | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/hotline-data b/hotline-data index 61602f53..b5b27064 160000 --- a/hotline-data +++ b/hotline-data @@ -1 +1 @@ -Subproject commit 61602f53670155a0d3e4a8a48dcb31c6a21aa3ae +Subproject commit b5b2706478f2dce413ebdb60b2328627c398a98b diff --git a/src/gfx/mtl.rs b/src/gfx/mtl.rs index 60baacd5..5d41346c 100644 --- a/src/gfx/mtl.rs +++ b/src/gfx/mtl.rs @@ -1,4 +1,7 @@ #![cfg(target_os = "macos")] +// objc 0.2.x's sel_impl macro uses cfg(cargo-clippy) which is not a valid identifier +// so it cannot be declared via check-cfg; suppress the lint for this file. +#![allow(unexpected_cfgs)] use crate::os_platform; use crate::os::Window; @@ -1300,6 +1303,7 @@ impl Device { let heap_descriptor = metal::HeapDescriptor::new(); heap_descriptor.set_storage_mode(metal::MTLStorageMode::Shared); heap_descriptor.set_size(heap_size); + // Enable hazard tracking so Metal automatically synchronizes heap-allocated // textures across command buffers (by default heaps are MTLHazardTrackingModeUntracked) unsafe { let _: () = msg_send![&*heap_descriptor, setHazardTrackingMode: metal::MTLHazardTrackingMode::Tracked]; }; From 7d606df8486c9cb5aeceffbe8ffe9239f2edc6b9 Mon Sep 17 00:00:00 2001 From: polymonster Date: Mon, 18 May 2026 14:02:41 +0200 Subject: [PATCH 44/62] - improve handling of bindings --- LIGHTS_BUG.md | 91 -------------------------------------------------- src/gfx/mtl.rs | 35 +++++++++++++++++-- todo.txt | 29 ++++++++++------ 3 files changed, 51 insertions(+), 104 deletions(-) delete mode 100644 LIGHTS_BUG.md diff --git a/LIGHTS_BUG.md b/LIGHTS_BUG.md deleted file mode 100644 index fc379215..00000000 --- a/LIGHTS_BUG.md +++ /dev/null @@ -1,91 +0,0 @@ -# Metal Light Buffer Strobing — Root Cause - -## What we confirmed - -- CPU always sends correct count (eprintln verified, sentinel shader confirmed solid cyan) -- GPU receives the push constants correctly — `world_buffer_info` arrives intact -- Orange/black flicker = GPU reads zero data from some ring-buffer slots - -## Root cause - -The MSL generated by spirv-cross for `ps_mesh_lit` has: - -```metal -struct spvDescriptorSetBuffer3 // bound at [[buffer(3)]] -{ - spvDescriptor<...> point_lights [[id(0)]][1]; // starts at slot 0 - spvDescriptor<...> spot_lights [[id(1)]][1]; // starts at slot 1 -}; -``` - -`spvDescriptorArray::operator[]` is: -```metal -const device T& operator [] (size_t i) const { return ptr[i]; } -// ptr points to the start of spot_lights array, which is [[id(1)]] -``` - -So `spot_lights[spot_lights_id]` reads argument-buffer slot **`1 + spot_lights_id`**. - -But in Rust, `encode_buffer(heap_index, buf)` puts the buffer at slot `heap_index`. - -**Mismatch:** For heap index 7, the buffer is at slot 7. The shader reads slot `1+7 = 8` — which is the *next* ring-buffer slot's buffer, or an empty slot. - -With 3 ring-buffer slots at heap indices 7, 8, 9: - -| Frame | bb | heap_idx | shader reads slot | what's there | -|-------|----|----------|-------------------|--------------| -| 0 | 0 | 7 | 1+7 = 8 | previous frame's bb=1 data (orange, stale) | -| 1 | 1 | 8 | 1+8 = 9 | previous frame's bb=2 data (orange, stale) | -| 2 | 2 | 9 | 1+9 = 10 | EMPTY (never written) → black | - -This explains the 2-orange/1-black cycle that looks like "flickering orange and black". - -## Why it only affects spot/directional lights, not point lights - -`point_lights [[id(0)]]` — starts at slot 0. -`point_lights[point_lights_id]` → reads slot `0 + point_lights_id = point_lights_id`. -`encode_buffer(heap_index, buf)` → buf at slot `heap_index`. -These match → point lights work. - -## Where the id offsets come from - -`htwv/src/macos_impl.rs` assigns `binding_sub_offset` sequentially for each named binding in the pipeline layout. In `ecs_examples.json`, `mesh_lit` pipeline has: -``` -[0] point_lights → binding_sub_offset=0 → id(0) -[1] spot_lights → binding_sub_offset=1 → id(1) -``` - -`directional_lights` is **not** in the pipeline layout bindings, so it retains its original SPIRV descriptor set from DXC and lands in a separate argument buffer. Its id offset is likely 0 within its own buffer — but this needs to be verified by compiling a shader that includes the directional lights loop before the return. - -## The fix - -For each bindless structured-buffer type, the shader-side index sent in `world_buffer_info` must be `heap_index - id_offset`, where `id_offset` is the `[[id(N)]]` value that spirv-cross assigns to that type's array in its descriptor set buffer. - -**Option A — Adjust index in `get_world_buffer_info()`** (minimal change): -```rust -WorldBufferInfo { - point_light: self.point_light.get_lookup(), // offset 0, no change - spot_light: self.spot_light.get_lookup_with_id_offset(1), // subtract 1 - directional_light: self.directional_light.get_lookup(), // verify offset first - .. -} -``` - -Add `get_lookup_with_id_offset(offset: u32)` to `DynamicBuffer`: -```rust -pub fn get_lookup_with_id_offset(&self, id_offset: u32) -> GpuBufferLookup { - GpuBufferLookup { - index: self.get_index() as u32 - id_offset, - count: self.len as u32, - } -} -``` - -**Option B — Longer-term fix**: track `id_offset` as a field on `DynamicBuffer`, set at allocation time from the pipeline layout, so `get_lookup()` always returns the correct index automatically. - -## Next steps - -1. Verify directional_lights id offset: restore the directional lights loop in `ps_mesh_lit` and recompile, then look at the generated `.psc.metal` for `directional_lights [[id(?)]]`. -2. Apply the fix (Option A is quick, Option B is cleaner). -3. Remove all debug code from `batch_lights`, `render_meshes_bindless`, the shader, and `spot_lights.rs`. -4. Re-enable animation for both spot and directional lights. diff --git a/src/gfx/mtl.rs b/src/gfx/mtl.rs index 5d41346c..80b8f6f8 100644 --- a/src/gfx/mtl.rs +++ b/src/gfx/mtl.rs @@ -435,8 +435,12 @@ impl CmdBuf { }; // Bind push constants using setVertexBytes/setFragmentBytes (zero allocations) + // Skip binders that have not changed since the last draw for b in binder.values() { if let PipelineStageBinder::PushConstants(pc) = b { + if !pc.dirty { + continue; + } let data_size = (pc.num_32_bit_constants * 4) as u64; let data_ptr = pc.data.as_ptr() as *const std::ffi::c_void; @@ -452,16 +456,17 @@ impl CmdBuf { } } - // Group resource bindings by buffer_index + // Group resource bindings by buffer_index, skipping groups where nothing is dirty let mut groups: HashMap> = HashMap::new(); for b in binder.values() { if let PipelineStageBinder::Resource(rb) = b { - if rb.bound_resource.is_some() { + if rb.bound_resource.is_some() && rb.dirty { groups.entry(rb.buffer_index).or_default().push(rb); } } } + // TODO: move to to_mtl_stage function + implement the others let render_stage = match stage { super::ShaderType::Vertex => metal::MTLRenderStages::Vertex, super::ShaderType::Fragment => metal::MTLRenderStages::Fragment, @@ -527,6 +532,20 @@ impl CmdBuf { self.allocate_stage_bindings(&vertex_binder, super::ShaderType::Vertex); self.allocate_stage_bindings(&fragment_binder, super::ShaderType::Fragment); + + // Clear dirty flags on originals now that encoding is done + for b in self.vertex_binder.values_mut() { + match b { + PipelineStageBinder::PushConstants(pc) => pc.dirty = false, + PipelineStageBinder::Resource(rb) => rb.dirty = false, + } + } + for b in self.fragment_binder.values_mut() { + match b { + PipelineStageBinder::PushConstants(pc) => pc.dirty = false, + PipelineStageBinder::Resource(rb) => rb.dirty = false, + } + } } } @@ -743,6 +762,7 @@ impl super::CmdBuf for CmdBuf { if let Some(binder) = self.vertex_binder.get_mut(&key) { if let PipelineStageBinder::Resource(ref mut rb) = binder { rb.bound_resource = Some(ResourceBinding { heap_ptr, offset }); + rb.dirty = true; } } @@ -750,6 +770,7 @@ impl super::CmdBuf for CmdBuf { if let Some(binder) = self.fragment_binder.get_mut(&key) { if let PipelineStageBinder::Resource(ref mut rb) = binder { rb.bound_resource = Some(ResourceBinding { heap_ptr, offset }); + rb.dirty = true; } } @@ -778,6 +799,7 @@ impl super::CmdBuf for CmdBuf { let dest_end = dest_start + data_size_dwords; if dest_end <= pc.data.len() { pc.data[dest_start..dest_end].copy_from_slice(data_u32); + pc.dirty = true; } result = Some(()); } @@ -788,6 +810,7 @@ impl super::CmdBuf for CmdBuf { let dest_end = dest_start + data_size_dwords; if dest_end <= pc.data.len() { pc.data[dest_start..dest_end].copy_from_slice(data_u32); + pc.dirty = true; } result = Some(()); } @@ -993,6 +1016,7 @@ struct PushConstantsBinder { pub data: Vec, pub num_32_bit_constants: u32, pub buffer_index: u32, + pub dirty: bool, } #[derive(Clone, Copy)] @@ -1008,6 +1032,7 @@ struct ResourceBinder { pub data_type: metal::MTLDataType, pub array_length: u64, pub bound_resource: Option, + pub dirty: bool, } #[derive(Clone)] @@ -1484,6 +1509,7 @@ impl Device { data: vec![0u32; push_constant.num_values as usize], num_32_bit_constants: push_constant.num_values, buffer_index, + dirty: true, })); }, ShaderVisibility::Fragment => { @@ -1494,6 +1520,7 @@ impl Device { data: vec![0u32; push_constant.num_values as usize], num_32_bit_constants: push_constant.num_values, buffer_index, + dirty: true, })); }, ShaderVisibility::All => { @@ -1506,12 +1533,14 @@ impl Device { data: vec![0u32; push_constant.num_values as usize], num_32_bit_constants: push_constant.num_values, buffer_index: v_buffer_index, + dirty: true, })); fragment_binder.insert(key, PipelineStageBinder::PushConstants(PushConstantsBinder { data: vec![0u32; push_constant.num_values as usize], num_32_bit_constants: push_constant.num_values, buffer_index: f_buffer_index, + dirty: true, })); }, _ => {}, @@ -1561,6 +1590,7 @@ impl Device { data_type, array_length, bound_resource: None, + dirty: true, })); } } @@ -1574,6 +1604,7 @@ impl Device { data_type, array_length, bound_resource: None, + dirty: true, })); } } diff --git a/todo.txt b/todo.txt index 1c39cece..4dfd293c 100644 --- a/todo.txt +++ b/todo.txt @@ -1,5 +1,20 @@ // TODO: +macos +- perf issues push constants +- draw indirect +- cbuffer instanced causes hugh perf issues (should be structured tbh) +- tangent space normal map is black +- bindless material +- RW texture +- MRT +- shadow map is black +- omni shadow is black +- material ibl +- dynamic cubemap +- MSAA +- mip downsample + // issues // - swap between dynamic cube and PBR causes inconsitency in the cubemap texture @@ -14,21 +29,14 @@ // - area light // - disney brdf -// platforms -// - bring across macos shader compilation -// - integrate macos changes and fixup win32/d3d12 -// - try update windows-rs - // engine // - reverse depth // - visibility buffer // - mesh shader -// - hello triangle (ray tracing) // - HDR pipeline // - glft // - set name on resources // - lazy init print function -// - example triangle culling via execute indirect // gfx // - Alpha to coverage @@ -36,14 +44,13 @@ // - API for fence // ui / debug -// - per demo settings // - thread stats // - view menu + saving state // - imgui not tracked within draw call stats -// build - // DONE: +// x per demo settings +// x hello triangle (ray tracing) // x create tlas with heap? // x raytraced triangle // x test shader compilation with mac changes @@ -158,7 +165,7 @@ // x fix issues with crash when a return happens between begin/end render pass // x gfx::buffer should need to be mut for update // x propagate sample mask?? -// x Draw Instanced +// x Draw Instanced // x draw instanced // x pmfx v2 docs (view) // x batch vertex instance buffer From fbed5609a5b2e59fb371e559a8320dbeee0ad952 Mon Sep 17 00:00:00 2001 From: polymonster Date: Tue, 19 May 2026 10:22:48 +0200 Subject: [PATCH 45/62] - fix window pos restore, improve shader error output --- .vscode/settings.json | 3 +- build.rs | 3 - plugins/ecs_examples/src/spot_lights.rs | 16 ++-- src/gfx/mtl.rs | 114 ++++++++++++++++++++++-- src/os/macos.rs | 30 +++++-- todo.txt | 17 ++-- 6 files changed, 155 insertions(+), 28 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index b4e98008..c1ba8593 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -63,5 +63,6 @@ "xtree": "cpp", "xutility": "cpp" }, - "rust-analyzer.showUnlinkedFileNotification": false + "rust-analyzer.showUnlinkedFileNotification": false, + "rust-analyzer.checkOnSave": false } \ No newline at end of file diff --git a/build.rs b/build.rs index ba3d27bc..171216ef 100644 --- a/build.rs +++ b/build.rs @@ -24,10 +24,7 @@ fn main() { fn main() { use std::path::Path; - // Rerun when source shaders change println!("cargo:rerun-if-changed=shaders"); - println!("cargo:rerun-if-changed=target/data/shaders"); - println!("cargo:rerun-if-changed=target/temp/shaders"); if std::env::var("CARGO_FEATURE_BUILD_DATA").is_ok() { let output_dir = Path::new("target/data/shaders"); diff --git a/plugins/ecs_examples/src/spot_lights.rs b/plugins/ecs_examples/src/spot_lights.rs index 61401bfa..7c372dad 100644 --- a/plugins/ecs_examples/src/spot_lights.rs +++ b/plugins/ecs_examples/src/spot_lights.rs @@ -114,7 +114,7 @@ pub fn setup_spot_lights( let size = 10.0; let height = 50.0; - let half_size = size * 0.5; + let half_size = size * 0.5; let step = size * half_size; let half_extent = (rc-1.0) * step * 0.5; let start_pos = vec3f(-half_extent, size, -half_extent); @@ -146,12 +146,12 @@ pub fn setup_spot_lights( #[export_update_fn] pub fn animate_spot_lights( - time: Res, + time: Res, mut light_query: Query<&mut Position, With>) -> Result<(), hotline_rs::Error> { - + let t = time.accumulated; let rot0 = t; - + let mut i = 0; for mut position in &mut light_query { if i < 16 { @@ -161,7 +161,7 @@ pub fn animate_spot_lights( let ss = 300.0 * ts; position.x = sin(fi * f32::two_pi()) * f32::tau() * ss; position.z = cos(fi * f32::two_pi()) * f32::tau() * ss; - + let pr = rotate_2d(position.xz(), rot0); position.set_xz(pr); } @@ -172,7 +172,7 @@ pub fn animate_spot_lights( let ss = 300.0 * ts; position.x = -sin(fi * f32::two_pi()) * f32::tau() * ss; position.z = cos(fi * f32::two_pi()) * f32::tau() * ss; - + let pr = rotate_2d(position.xz(), -rot0); position.set_xz(pr); } @@ -183,7 +183,7 @@ pub fn animate_spot_lights( let ss = 300.0 * ts; position.x = sin(fi * f32::two_pi()) * f32::tau() * ss; position.z = -cos(fi * f32::two_pi()) * f32::tau() * ss; - + let pr = rotate_2d(position.xz(), -rot0); position.set_xz(pr); } @@ -194,7 +194,7 @@ pub fn animate_spot_lights( let ss = 300.0 * ts; position.x = -sin(fi * f32::two_pi()) * f32::tau() * ss; position.z = -cos(fi * f32::two_pi()) * f32::tau() * ss; - + let pr = rotate_2d(position.xz(), rot0); position.set_xz(pr); } diff --git a/src/gfx/mtl.rs b/src/gfx/mtl.rs index 80b8f6f8..4c200ab7 100644 --- a/src/gfx/mtl.rs +++ b/src/gfx/mtl.rs @@ -326,7 +326,7 @@ impl super::SwapChain for SwapChain { } fn get_frame_fence_value(&self) -> u64 { - 0 + self.frame_value } fn update(&mut self, device: &mut Device, window: &A::Window, cmd: &mut CmdBuf) -> bool { @@ -600,12 +600,51 @@ impl super::CmdBuf for CmdBuf { } fn begin_event(&mut self, colour: u32, name: &str) { + if let Some(enc) = self.render_encoder.as_ref() { + enc.push_debug_group(name); + } else if let Some(enc) = self.compute_encoder.as_ref() { + enc.push_debug_group(name); + } else if let Some(cmd) = self.cmd.as_ref() { + cmd.push_debug_group(name); + } } fn end_event(&mut self) { + if let Some(enc) = self.render_encoder.as_ref() { + enc.pop_debug_group(); + } else if let Some(enc) = self.compute_encoder.as_ref() { + enc.pop_debug_group(); + } else if let Some(cmd) = self.cmd.as_ref() { + cmd.pop_debug_group(); + } } fn timestamp_query(&mut self, heap: &mut QueryHeap, resolve_buffer: &mut Buffer) { + if let Some(sample_buf) = heap.sample_buffer.as_ref() { + let idx = heap.alloc_index; + heap.alloc_index += 1; + resolve_buffer.counter_sample_buffer = Some(sample_buf.to_owned()); + resolve_buffer.counter_sample_index = idx; + resolve_buffer.counter_cmd = self.cmd.clone(); + if let Some(enc) = self.render_encoder.as_ref() { + // mid-pass: counter buffer must have been pre-registered in the render pass + // descriptor to call sampleCountersInBuffer — skip silently if not configured + let _ = enc; + } else if let Some(enc) = self.compute_encoder.as_ref() { + let _ = enc; + } else if let Some(cmd) = self.cmd.as_ref() { + // Between encoders: use a blit pass descriptor with the counter buffer + // registered so Metal accepts the sample call. + let blit_desc = metal::BlitPassDescriptor::new(); + if let Some(attachment) = blit_desc.sample_buffer_attachments().object_at(0) { + attachment.set_sample_buffer(sample_buf); + attachment.set_start_of_encoder_sample_index(idx as _); + attachment.set_end_of_encoder_sample_index(NSUInteger::MAX); + } + let blit = cmd.blit_command_encoder_with_descriptor(blit_desc); + blit.end_encoding(); + } + } } fn begin_query(&mut self, heap: &mut QueryHeap, query_type: QueryType) -> usize { @@ -948,6 +987,10 @@ pub struct Buffer { srv_index: Option, uav_index: Option, cbv_index: Option, + counter_sample_buffer: Option, + counter_sample_index: usize, + // Metal substitute for a D3D12 GPU fence: wait_until_completed before resolving counter data + counter_cmd: Option, } impl super::Buffer for Buffer { @@ -1262,11 +1305,15 @@ impl super::Heap for Heap { } pub struct QueryHeap { - + heap_type: super::QueryType, + sample_buffer: Option, + alloc_index: usize, + capacity: usize, } impl super::QueryHeap for QueryHeap { fn reset(&mut self) { + self.alloc_index = 0; } } @@ -1679,8 +1726,24 @@ impl super::Device for Device { } fn create_query_heap(&self, info: &QueryHeapInfo) -> QueryHeap { + let sample_buffer = if info.heap_type == super::QueryType::Timestamp { + let counter_sets = self.metal_device.counter_sets(); + let ts_set = counter_sets.iter().find(|cs| cs.name().eq_ignore_ascii_case("timestamp")); + ts_set.and_then(|cs| { + let desc = metal::CounterSampleBufferDescriptor::new(); + desc.set_counter_set(cs); + desc.set_sample_count(info.num_queries as _); + desc.set_storage_mode(metal::MTLStorageMode::Shared); + self.metal_device.new_counter_sample_buffer_with_descriptor(&desc).ok() + }) + } else { + None + }; QueryHeap { - + heap_type: info.heap_type, + sample_buffer, + alloc_index: 0, + capacity: info.num_queries, } } @@ -2096,7 +2159,10 @@ impl super::Device for Device { element_stride: info.stride, srv_index, uav_index, - cbv_index + cbv_index, + counter_sample_buffer: None, + counter_sample_index: 0, + counter_cmd: None, }) }) } @@ -2155,7 +2221,10 @@ impl super::Device for Device { element_stride: size, srv_index: None, uav_index: None, - cbv_index: None + cbv_index: None, + counter_sample_buffer: None, + counter_sample_index: 0, + counter_cmd: None, }) }) } @@ -2445,6 +2514,39 @@ impl super::Device for Device { } fn read_timestamps(&self, swap_chain: &SwapChain, buffer: &Self::Buffer, size_bytes: usize, frame_written_fence: u64) -> Vec { + if let Some(sample_buf) = &buffer.counter_sample_buffer { + // Metal has no GPU-signalled fence; wait for the recording command buffer to finish + // before resolving counter data (equivalent to D3D12's GPU fence check). + if let Some(cmd) = &buffer.counter_cmd { + cmd.wait_until_completed(); + } + let elem_size = std::mem::size_of::(); + let count = (size_bytes / elem_size).max(1); + unsafe { + let range = metal::NSRange { + location: buffer.counter_sample_index as _, + length: count as _, + }; + let ns_data: *mut objc::runtime::Object = + msg_send![sample_buf.as_ref(), resolveCounterRange: range]; + if !ns_data.is_null() { + let bytes: *const u8 = msg_send![ns_data, bytes]; + let len: usize = msg_send![ns_data, length]; + let mut results = Vec::new(); + for i in 0..count { + let offset = i * elem_size; + if offset + elem_size <= len { + let nanos = (bytes.add(offset) as *const u64).read_unaligned(); + // MTLCounterResultTimestamp.timestamp is nanoseconds on Apple Silicon + results.push(nanos as f64 / 1_000_000_000.0); + } + } + if !results.is_empty() { + return results; + } + } + } + } vec![] } @@ -2453,7 +2555,7 @@ impl super::Device for Device { } fn get_timestamp_size_bytes() -> usize { - 0 + 8 // u64; matches D3D12 — Metal uses CounterSampleBuffer, not this backing store } fn get_pipeline_statistics_size_bytes() -> usize { diff --git a/src/os/macos.rs b/src/os/macos.rs index 50657176..f7832d09 100644 --- a/src/os/macos.rs +++ b/src/os/macos.rs @@ -9,7 +9,7 @@ use std::sync::Arc; use std::sync::RwLock; use winit::{ - dpi::{LogicalPosition, LogicalSize}, + dpi::{PhysicalPosition, PhysicalSize}, event::{WindowEvent, ElementState}, event_loop::ActiveEventLoop, keyboard::{Key, PhysicalKey, KeyCode}, @@ -313,8 +313,8 @@ impl super::App for App { let window = self.event_loop.read().unwrap() .create_window( winit::window::Window::default_attributes() - .with_inner_size(winit::dpi::LogicalSize::new(info.rect.width, info.rect.height)) - .with_position(winit::dpi::LogicalPosition::new(info.rect.x, info.rect.y)) + .with_inner_size(PhysicalSize::new(info.rect.width, info.rect.height)) + .with_position(PhysicalPosition::new(info.rect.x, info.rect.y)) .with_title(info.title) ) .unwrap(); @@ -460,6 +460,26 @@ impl super::App for App { } fn enumerate_display_monitors(&self) -> Vec { + { + let cached = self.monitors.read().unwrap(); + if !cached.is_empty() { + return cached.clone(); + } + } + // Monitors aren't populated until the first pump_app_events triggers `resumed`. + // Pump once here so the cache gets filled before the caller needs it. + let mut dummy_resume = true; + let mut handler = FrameHandler { + resume: &mut dummy_resume, + input_state: self.input_state.clone(), + monitors: self.monitors.clone(), + window_sizes: self.window_sizes.clone(), + }; + let _ = self.event_loop.write().and_then(|mut event_loop| { + use winit::platform::pump_events::EventLoopExtPumpEvents; + event_loop.pump_app_events(Some(Duration::ZERO), &mut handler); + Ok(()) + }); self.monitors.read().unwrap().clone() } @@ -554,7 +574,7 @@ impl super::Window for Window { /// Set window position in screen space fn set_pos(&self, pos: super::Point) { - self.winit_window.set_outer_position(LogicalPosition { + self.winit_window.set_outer_position(PhysicalPosition { x: pos.x, y: pos.y }); @@ -562,7 +582,7 @@ impl super::Window for Window { /// Set window size in screen coordinates fn set_size(&self, size: super::Size) { - self.winit_window.request_inner_size(LogicalSize::new(size.x, size.y)); + self.winit_window.request_inner_size(PhysicalSize::new(size.x, size.y)); } /// Returns the screen position for the top-left corner of the window diff --git a/todo.txt b/todo.txt index 4dfd293c..d2cc928e 100644 --- a/todo.txt +++ b/todo.txt @@ -1,19 +1,26 @@ // TODO: macos -- perf issues push constants +x perf issues push constants +x hot reload +x window pos restore +x shader errors don't properly display +- gpu timestamp ??? + - draw indirect -- cbuffer instanced causes hugh perf issues (should be structured tbh) - tangent space normal map is black -- bindless material -- RW texture +- RW texture + better demo - MRT - shadow map is black - omni shadow is black - material ibl - dynamic cubemap -- MSAA + - mip downsample +- MSAA + +- bindless material +- cbuffer instanced causes hugh perf issues (should be structured tbh) // issues // - swap between dynamic cube and PBR causes inconsitency in the cubemap texture From 62ffc19ba4482547f3a8db2922d688c949dc6df2 Mon Sep 17 00:00:00 2001 From: polymonster Date: Tue, 19 May 2026 10:23:47 +0200 Subject: [PATCH 46/62] - update submodule --- hotline-data | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hotline-data b/hotline-data index b5b27064..351bd3ef 160000 --- a/hotline-data +++ b/hotline-data @@ -1 +1 @@ -Subproject commit b5b2706478f2dce413ebdb60b2328627c398a98b +Subproject commit 351bd3efabcb5af374b56968b9eb513d19b73cb1 From d55d26ad039b236c0902ab28cc29ba6cfa1445c3 Mon Sep 17 00:00:00 2001 From: polymonster Date: Wed, 20 May 2026 11:54:39 +0200 Subject: [PATCH 47/62] - all shaders compiling, cleanup shader console spew, dynamic cubemap working --- .cargo/config.toml | 2 +- hotline-data | 2 +- .../ecs_examples/src/bindless_material_ibl.rs | 5 +- shaders/ecs.hlsl | 14 ++-- shaders/util.hlsl | 4 ++ src/gfx/mtl.rs | 72 ++++++++++--------- todo.txt | 12 ++-- 7 files changed, 61 insertions(+), 50 deletions(-) diff --git a/.cargo/config.toml b/.cargo/config.toml index 26422587..559ff712 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -1,5 +1,5 @@ [build] rustflags = ["-A", "unused"] -[build.env] +[env] MACOSX_DEPLOYMENT_TARGET = "15.0" \ No newline at end of file diff --git a/hotline-data b/hotline-data index 351bd3ef..f236a202 160000 --- a/hotline-data +++ b/hotline-data @@ -1 +1 @@ -Subproject commit 351bd3efabcb5af374b56968b9eb513d19b73cb1 +Subproject commit f236a20215a8845a1783707b729b62443038866c diff --git a/plugins/ecs_examples/src/bindless_material_ibl.rs b/plugins/ecs_examples/src/bindless_material_ibl.rs index 7f9ef7f7..49b8fb0b 100644 --- a/plugins/ecs_examples/src/bindless_material_ibl.rs +++ b/plugins/ecs_examples/src/bindless_material_ibl.rs @@ -1,9 +1,6 @@ /// /// Bindless Material IBL /// -/// 10 PBR materials × 4 mesh types arranged in a curated 10×4 grid, -/// lit by image-based lighting (cubemap + BRDF LUT) instead of point lights. -/// use crate::prelude::*; @@ -104,7 +101,7 @@ pub fn setup_bindless_material_ibl( let x = -x_offset + col as f32 * cell; let z = -z_offset + row as f32 * cell; - + let pos = vec3f(x, 0.0, z); commands.spawn(( diff --git a/shaders/ecs.hlsl b/shaders/ecs.hlsl index 2472dc98..8026b314 100644 --- a/shaders/ecs.hlsl +++ b/shaders/ecs.hlsl @@ -130,9 +130,9 @@ struct extent_data { } // structures of arrays for indriect / bindless lookups -StructuredBuffer draws[1024] : register(t0, space0); -StructuredBuffer extents[1024] : register(t0, space1); -StructuredBuffer materials[1024] : register(t0, space2); +StructuredBuffer draws[] : register(t0, space0); +StructuredBuffer extents[] : register(t0, space1); +StructuredBuffer materials[] : register(t0, space2); StructuredBuffer point_lights[] : register(t0, space3); StructuredBuffer spot_lights[] : register(t0, space4); StructuredBuffer directional_lights[] : register(t0, space5); @@ -146,17 +146,17 @@ Texture2DArray texture_arrays[] : register(t0, space10); Texture3D volume_textures[] : register(t0, space11); // tlas -RaytracingAccelerationStructure scene_tlas[1024] : register(t0, space12); +RaytracingAccelerationStructure scene_tlas[] : register(t0, space12); // uav textures -RWTexture2D rw_textures[1024] : register(u0, space0); -RWTexture3D rw_volume_textures[1024] : register(u0, space1); +RWTexture2D rw_textures[] : register(u0, space0); +RWTexture3D rw_volume_textures[] : register(u0, space1); // main constants to obtain the indices of the buffer types ConstantBuffer world_buffer_info : register(b2); // camera data for bindless camera lookups -ConstantBuffer cameras[1024] : register(b3); +ConstantBuffer cameras[] : register(b3); // samplers SamplerState sampler0 : register(s0); diff --git a/shaders/util.hlsl b/shaders/util.hlsl index cc0649f3..2b3fdb4d 100644 --- a/shaders/util.hlsl +++ b/shaders/util.hlsl @@ -2,6 +2,7 @@ // utilties to compile into the core hotline engine // +/* cbuffer mip_info : register(b0) { uint read; uint write; @@ -9,9 +10,11 @@ cbuffer mip_info : register(b0) { RWTexture2D rw_texture[] : register(u0, space0); groupshared uint4 group_accumulated[5]; +*/ [numthreads(32, 32, 1)] void cs_mip_chain_texture2d(uint2 did: SV_DispatchThreadID) { + /* uint2 offsets[9]; offsets[0] = uint2( 0, 0); offsets[1] = uint2(-1, -1); @@ -32,6 +35,7 @@ void cs_mip_chain_texture2d(uint2 did: SV_DispatchThreadID) { } rw_texture[write][did.xy] = level_up / 9.0; + */ } // diff --git a/src/gfx/mtl.rs b/src/gfx/mtl.rs index 4c200ab7..d9bc43df 100644 --- a/src/gfx/mtl.rs +++ b/src/gfx/mtl.rs @@ -170,6 +170,30 @@ fn to_mtl_compare_func(func: super::ComparisonFunc) -> metal::MTLCompareFunction } } +fn to_mtl_sampler_address_mode(mode: super::SamplerAddressMode) -> metal::MTLSamplerAddressMode { + match mode { + super::SamplerAddressMode::Wrap => metal::MTLSamplerAddressMode::Repeat, + super::SamplerAddressMode::Mirror => metal::MTLSamplerAddressMode::MirrorRepeat, + super::SamplerAddressMode::Clamp => metal::MTLSamplerAddressMode::ClampToEdge, + super::SamplerAddressMode::Border => metal::MTLSamplerAddressMode::ClampToBorderColor, + super::SamplerAddressMode::MirrorOnce => metal::MTLSamplerAddressMode::MirrorClampToEdge, + } +} + +fn to_mtl_sampler_min_mag_filter(filter: super::SamplerFilter) -> metal::MTLSamplerMinMagFilter { + match filter { + super::SamplerFilter::Point => metal::MTLSamplerMinMagFilter::Nearest, + super::SamplerFilter::Linear | super::SamplerFilter::Anisotropic => metal::MTLSamplerMinMagFilter::Linear, + } +} + +fn to_mtl_sampler_mip_filter(filter: super::SamplerFilter) -> metal::MTLSamplerMipFilter { + match filter { + super::SamplerFilter::Point => metal::MTLSamplerMipFilter::Nearest, + super::SamplerFilter::Linear | super::SamplerFilter::Anisotropic => metal::MTLSamplerMipFilter::Linear, + } +} + fn to_mtl_stencil_op(op: super::StencilOp) -> metal::MTLStencilOperation { match op { super::StencilOp::Keep => metal::MTLStencilOperation::Keep, @@ -1153,7 +1177,7 @@ impl super::Texture for Texture { } fn get_uav_index(&self) -> Option { - None + self.uav_index } fn clone_inner(&self) -> Texture { @@ -1980,13 +2004,17 @@ impl super::Device for Device { if let Some(static_samplers) = &info.pipeline_layout.static_samplers { for sampler in static_samplers { + let si = &sampler.sampler_info; let desc = metal::SamplerDescriptor::new(); - desc.set_address_mode_r(metal::MTLSamplerAddressMode::Repeat); - desc.set_address_mode_s(metal::MTLSamplerAddressMode::Repeat); - desc.set_address_mode_t(metal::MTLSamplerAddressMode::Repeat); - desc.set_min_filter(metal::MTLSamplerMinMagFilter::Linear); - desc.set_mag_filter(metal::MTLSamplerMinMagFilter::Linear); - desc.set_mip_filter(metal::MTLSamplerMipFilter::Linear); + desc.set_address_mode_r(to_mtl_sampler_address_mode(si.address_w)); + desc.set_address_mode_s(to_mtl_sampler_address_mode(si.address_u)); + desc.set_address_mode_t(to_mtl_sampler_address_mode(si.address_v)); + desc.set_min_filter(to_mtl_sampler_min_mag_filter(si.filter)); + desc.set_mag_filter(to_mtl_sampler_min_mag_filter(si.filter)); + desc.set_mip_filter(to_mtl_sampler_mip_filter(si.filter)); + if let Some(func) = si.comparison { + desc.set_compare_function(to_mtl_compare_func(func)); + } desc.set_support_argument_buffers(true); pipeline_static_samplers.push(MetalSamplerBinding { @@ -2113,7 +2141,7 @@ impl super::Device for Device { // StorageModeShared: CPU and GPU share the same physical memory — no didModifyRange // needed and no stale-copy hazard. StorageModeManaged has a separate GPU copy that // requires an explicit sync notification after every CPU write; without it the GPU - // reads stale data, which is the source of the world-buffer tearing. + // reads stale data, causing tearing let opt = metal::MTLResourceOptions::CPUCacheModeDefaultCache | metal::MTLResourceOptions::StorageModeShared; @@ -2172,31 +2200,6 @@ impl super::Device for Device { info: &super::BufferInfo, data: Option<&[T]>, ) -> result::Result { - /* - objc::rc::autoreleasepool(|| { - let opt = metal::MTLResourceOptions::CPUCacheModeDefaultCache | - metal::MTLResourceOptions::StorageModeManaged; - - let byte_len = (info.stride * info.num_elements) as NSUInteger; - - let buf = if let Some(data) = data { - let bytes = data.as_ptr() as *const std::ffi::c_void; - self.metal_device.new_buffer_with_data(bytes, byte_len, opt) - } - else { - self.metal_device.new_buffer(byte_len, opt) - }; - - Ok(Buffer{ - metal_buffer: buf, - element_stride: info.stride, - srv_index: None, - uav_index: None, - cbv_index: None - }) - }) - */ - self.create_buffer_with_heap( info, data, @@ -2376,6 +2379,7 @@ impl super::Device for Device { for rt in &info.render_targets { let color_attachment = descriptor.color_attachments().object_at(0).unwrap(); color_attachment.set_texture(Some(&rt.metal_texture)); + color_attachment.set_slice(info.array_slice as u64); if let Some(cc) = info.rt_clear { color_attachment.set_load_action(metal::MTLLoadAction::Clear); @@ -2397,6 +2401,7 @@ impl super::Device for Device { let depth_format = if let Some(ds_texture) = &info.depth_stencil { let depth_attachment = descriptor.depth_attachment().unwrap(); depth_attachment.set_texture(Some(&ds_texture.metal_texture)); + depth_attachment.set_slice(info.array_slice as u64); if let Some(ds_clear) = &info.ds_clear { if let Some(depth_val) = ds_clear.depth { @@ -2416,6 +2421,7 @@ impl super::Device for Device { if has_stencil_component(format) { let stencil_attachment = descriptor.stencil_attachment().unwrap(); stencil_attachment.set_texture(Some(&ds_texture.metal_texture)); + stencil_attachment.set_slice(info.array_slice as u64); if let Some(ds_clear) = &info.ds_clear { if let Some(stencil_val) = ds_clear.stencil { diff --git a/todo.txt b/todo.txt index d2cc928e..fd2edee7 100644 --- a/todo.txt +++ b/todo.txt @@ -5,15 +5,17 @@ x perf issues push constants x hot reload x window pos restore x shader errors don't properly display +x majority shader compilation - gpu timestamp ??? -- draw indirect -- tangent space normal map is black -- RW texture + better demo -- MRT - shadow map is black - omni shadow is black + - material ibl +- tangent space normal map is black + +- RW texture + better demo +- MRT - dynamic cubemap - mip downsample @@ -22,6 +24,8 @@ x shader errors don't properly display - bindless material - cbuffer instanced causes hugh perf issues (should be structured tbh) +- draw indirect + // issues // - swap between dynamic cube and PBR causes inconsitency in the cubemap texture From e4c647deb3d4acd2cb3b9b46d8390c76169ad5c3 Mon Sep 17 00:00:00 2001 From: polymonster Date: Wed, 20 May 2026 13:15:47 +0200 Subject: [PATCH 48/62] - handling null pixel shader case --- src/gfx/mtl.rs | 33 ++++++++++++++++++--------------- todo.txt | 9 ++++----- 2 files changed, 22 insertions(+), 20 deletions(-) diff --git a/src/gfx/mtl.rs b/src/gfx/mtl.rs index d9bc43df..34bf256f 100644 --- a/src/gfx/mtl.rs +++ b/src/gfx/mtl.rs @@ -1935,24 +1935,27 @@ impl super::Device for Device { .object_at(0) .unwrap(); - // Get pixel format from pass, or default to BGRA8Unorm + // Get pixel format from pass; depth-only passes use Invalid (no colour attachment) let pixel_format = info.pass .map(|p| p.pixel_format) .unwrap_or(metal::MTLPixelFormat::BGRA8Unorm); attachment.set_pixel_format(pixel_format); - // Apply blend state from pipeline info - if let Some(b) = info.blend_info.render_target.first() { - attachment.set_blending_enabled(b.blend_enabled); - attachment.set_rgb_blend_operation(to_mtl_blend_op(&b.blend_op)); - attachment.set_alpha_blend_operation(to_mtl_blend_op(&b.blend_op_alpha)); - attachment.set_source_rgb_blend_factor(to_mtl_blend_factor(&b.src_blend)); - attachment.set_source_alpha_blend_factor(to_mtl_blend_factor(&b.src_blend_alpha)); - attachment.set_destination_rgb_blend_factor(to_mtl_blend_factor(&b.dst_blend)); - attachment.set_destination_alpha_blend_factor(to_mtl_blend_factor(&b.dst_blend_alpha)); - attachment.set_write_mask(to_mtl_write_mask(&b.write_mask)); - } else { - attachment.set_blending_enabled(false); + // Only configure blend/write state when there is a colour attachment + if pixel_format != metal::MTLPixelFormat::Invalid { + if let Some(b) = info.blend_info.render_target.first() { + attachment.set_blending_enabled(b.blend_enabled); + attachment.set_rgb_blend_operation(to_mtl_blend_op(&b.blend_op)); + attachment.set_alpha_blend_operation(to_mtl_blend_op(&b.blend_op_alpha)); + attachment.set_source_rgb_blend_factor(to_mtl_blend_factor(&b.src_blend)); + attachment.set_source_alpha_blend_factor(to_mtl_blend_factor(&b.src_blend_alpha)); + attachment.set_destination_rgb_blend_factor(to_mtl_blend_factor(&b.dst_blend)); + attachment.set_destination_alpha_blend_factor(to_mtl_blend_factor(&b.dst_blend_alpha)); + attachment.set_write_mask(to_mtl_write_mask(&b.write_mask)); + } else { + attachment.set_blending_enabled(false); + attachment.set_write_mask(metal::MTLColorWriteMask::all()); + } } // Set depth format on pipeline descriptor if pass has depth @@ -2392,10 +2395,10 @@ impl super::Device for Device { } } - // Get pixel format from first render target + // Get pixel format from first render target; Invalid for depth-only passes let pixel_format = info.render_targets.first() .map(|rt| rt.metal_texture.pixel_format()) - .unwrap_or(metal::MTLPixelFormat::BGRA8Unorm); + .unwrap_or(metal::MTLPixelFormat::Invalid); // Handle depth stencil attachment let depth_format = if let Some(ds_texture) = &info.depth_stencil { diff --git a/todo.txt b/todo.txt index fd2edee7..4d4727b8 100644 --- a/todo.txt +++ b/todo.txt @@ -6,26 +6,25 @@ x hot reload x window pos restore x shader errors don't properly display x majority shader compilation +x dynamic cubemap - gpu timestamp ??? +- pmfx hotreload - shadow map is black - omni shadow is black - - material ibl - tangent space normal map is black - - RW texture + better demo - MRT -- dynamic cubemap - - mip downsample - MSAA - - bindless material - cbuffer instanced causes hugh perf issues (should be structured tbh) - draw indirect +- pmbuild needs universal install into hotline-data + // issues // - swap between dynamic cube and PBR causes inconsitency in the cubemap texture From f10a09f913a6d56d6e626de9b224cfa1eca0e345 Mon Sep 17 00:00:00 2001 From: polymonster Date: Thu, 21 May 2026 12:25:29 +0200 Subject: [PATCH 49/62] - add compute support macos, plus basic example, improve rw texture demo --- Cargo.toml | 4 + examples/compute/main.rs | 177 +++++++ hotline-data | 2 +- plugins/ecs_examples/src/lib.rs | 4 + .../ecs_examples/src/read_write_texture.rs | 14 + shaders/ecs.hlsl | 14 +- shaders/julia.hlsl | 80 +++ shaders/julia.pmfx | 32 ++ shaders/material.hlsl | 2 +- shaders/shadows.hlsl | 48 +- shaders/texture.hlsl | 28 +- src/gfx/mtl.rs | 463 +++++++++++++++--- todo.txt | 22 +- 13 files changed, 771 insertions(+), 119 deletions(-) create mode 100644 examples/compute/main.rs create mode 100644 shaders/julia.hlsl create mode 100644 shaders/julia.pmfx diff --git a/Cargo.toml b/Cargo.toml index 54f730fa..02859c0a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -100,6 +100,10 @@ default = ["build_data", "client"] name = "bindless" crate-type = ["bin"] +[[example]] +name = "compute" +crate-type = ["bin"] + [[example]] name = "imgui_demo" crate-type = ["bin"] diff --git a/examples/compute/main.rs b/examples/compute/main.rs new file mode 100644 index 00000000..51ad2b05 --- /dev/null +++ b/examples/compute/main.rs @@ -0,0 +1,177 @@ +use hotline_rs::{*, prelude::*}; + +use os::{App, Window}; +use gfx::{CmdBuf, Device, SwapChain, RenderPass, Texture}; + +#[repr(C)] +struct Vertex { + position: [f32; 2], + texcoord: [f32; 2], +} + +// matches `julia_constants` in shaders/julia.hlsl (5x 32-bit values) +#[repr(C)] +struct JuliaConstants { + output_index: u32, + width: u32, + height: u32, + cr: f32, + ci: f32, +} + +fn main() -> Result<(), hotline_rs::Error> { + let mut app = os_platform::App::create(os::AppInfo { + name: String::from("compute"), + window: false, + num_buffers: 0, + dpi_aware: true, + }); + + let mut dev = gfx_platform::Device::create(&gfx::DeviceInfo { + adapter_name: None, + shader_heap_size: 100, + render_target_heap_size: 100, + depth_stencil_heap_size: 100, + }); + print!("{}", dev.get_adapter_info()); + + let mut win = app.create_window(os::WindowInfo { + title: String::from("compute - animated julia set"), + rect: os::Rect { x: 100, y: 100, width: 1280, height: 720 }, + style: os::WindowStyleFlags::NONE, + parent_handle: None, + }); + + let swap_chain_info = gfx::SwapChainInfo { + num_buffers: 2, + format: gfx::Format::RGBA8n, + clear_colour: Some(gfx::ClearColour { r: 0.0, g: 0.0, b: 0.0, a: 1.0 }), + }; + let mut swap_chain = dev.create_swap_chain::(&swap_chain_info, &win)?; + let mut cmdbuffer = dev.create_cmd_buf(2); + + // fullscreen quad (NDC) with texcoords flipped so (0,0) is top-left of the image + let vertices = [ + Vertex { position: [-1.0, -1.0], texcoord: [0.0, 1.0] }, + Vertex { position: [-1.0, 1.0], texcoord: [0.0, 0.0] }, + Vertex { position: [ 1.0, 1.0], texcoord: [1.0, 0.0] }, + Vertex { position: [ 1.0, -1.0], texcoord: [1.0, 1.0] }, + ]; + let vertex_buffer = dev.create_buffer(&gfx::BufferInfo { + usage: gfx::BufferUsage::VERTEX, + cpu_access: gfx::CpuAccessFlags::NONE, + format: gfx::Format::Unknown, + stride: std::mem::size_of::(), + num_elements: 4, + initial_state: gfx::ResourceState::VertexConstantBuffer + }, Some(gfx::as_u8_slice(&vertices)))?; + + let indices: [u16; 6] = [0, 1, 2, 0, 2, 3]; + let index_buffer = dev.create_buffer(&gfx::BufferInfo { + usage: gfx::BufferUsage::INDEX, + cpu_access: gfx::CpuAccessFlags::NONE, + format: gfx::Format::R16u, + stride: std::mem::size_of::(), + num_elements: 6, + initial_state: gfx::ResourceState::IndexBuffer + }, Some(gfx::as_u8_slice(&indices)))?; + + // compute output texture - written by the julia kernel, sampled by the blit pass + let vp_rect = win.get_viewport_rect(); + let tex_width = vp_rect.width as u64; + let tex_height = vp_rect.height as u64; + let output_texture = dev.create_texture::(&gfx::TextureInfo { + format: gfx::Format::RGBA8n, + tex_type: gfx::TextureType::Texture2D, + width: tex_width, + height: tex_height, + depth: 1, + array_layers: 1, + mip_levels: 1, + samples: 1, + usage: gfx::TextureUsage::SHADER_RESOURCE | gfx::TextureUsage::UNORDERED_ACCESS, + initial_state: gfx::ResourceState::UnorderedAccess, + }, None)?; + let uav_index = output_texture.get_uav_index().unwrap() as u32; + let srv_index = output_texture.get_srv_index().unwrap() as u32; + + // load shaders and create the compute + blit pipelines via pmfx + let mut pmfx : pmfx::Pmfx = pmfx::Pmfx::create(&mut dev, 0); + pmfx.load(&hotline_rs::get_data_path("shaders/julia"))?; + pmfx.create_compute_pipeline(&dev, "julia")?; + pmfx.create_render_pipeline(&dev, "blit", swap_chain.get_backbuffer_pass())?; + + let blit_fmt = swap_chain.get_backbuffer_pass().get_format_hash(); + + let mut frame = 0u32; + while app.run() { + win.update(&mut app); + swap_chain.update::(&mut dev, &win, &mut cmdbuffer); + cmdbuffer.reset(&swap_chain); + + // animate the complex constant around a circle for a classic morphing julia set + let theta = frame as f32 * 0.0125; + let radius = 0.7885; + let constants = JuliaConstants { + output_index: uav_index, + width: tex_width as u32, + height: tex_height as u32, + cr: radius * theta.cos(), + ci: radius * theta.sin(), + }; + + // compute pass - dispatch the julia kernel into the rw texture + cmdbuffer.begin_event(0xff00ff00, "Julia Compute"); + let julia = pmfx.get_compute_pipeline("julia")?; + cmdbuffer.set_compute_pipeline(julia); + cmdbuffer.set_heap(julia, dev.get_shader_heap()); + cmdbuffer.push_compute_constants(julia, 0, 0, 5, 0, gfx::as_u8_slice(&constants)); + cmdbuffer.dispatch( + gfx::Size3 { x: (tex_width as u32 + 7) / 8, y: (tex_height as u32 + 7) / 8, z: 1 }, + gfx::Size3 { x: 8, y: 8, z: 1 } + ); + cmdbuffer.end_event(); + + // blit pass - draw the compute output to the back buffer + cmdbuffer.begin_event(0xff0000ff, "Blit Pass"); + let vp = gfx::Viewport::from(win.get_viewport_rect()); + let sc = gfx::ScissorRect::from(win.get_viewport_rect()); + + cmdbuffer.transition_barrier(&gfx::TransitionBarrier { + texture: Some(swap_chain.get_backbuffer_texture()), + buffer: None, + state_before: gfx::ResourceState::Present, + state_after: gfx::ResourceState::RenderTarget, + }); + + let blit = pmfx.get_render_pipeline_for_format("blit", blit_fmt)?; + cmdbuffer.begin_render_pass(swap_chain.get_backbuffer_pass_mut()); + cmdbuffer.set_viewport(&vp); + cmdbuffer.set_scissor_rect(&sc); + cmdbuffer.set_render_pipeline(blit); + cmdbuffer.set_heap(blit, dev.get_shader_heap()); + cmdbuffer.set_index_buffer(&index_buffer); + cmdbuffer.set_vertex_buffer(&vertex_buffer, 0); + let srv = [srv_index, 0, 0, 0]; + cmdbuffer.push_render_constants(blit, 0, 0, 4, 0, gfx::as_u8_slice(&srv)); + cmdbuffer.draw_indexed_instanced(6, 1, 0, 0, 0); + cmdbuffer.end_render_pass(); + + cmdbuffer.transition_barrier(&gfx::TransitionBarrier { + texture: Some(swap_chain.get_backbuffer_texture()), + buffer: None, + state_before: gfx::ResourceState::RenderTarget, + state_after: gfx::ResourceState::Present, + }); + cmdbuffer.end_event(); + + cmdbuffer.close()?; + dev.execute(&cmdbuffer); + swap_chain.swap(&mut dev); + frame += 1; + } + + swap_chain.wait_for_last_frame(); + dev.cleanup_dropped_resources(&swap_chain); + Ok(()) +} diff --git a/hotline-data b/hotline-data index f236a202..a93d8f00 160000 --- a/hotline-data +++ b/hotline-data @@ -1 +1 @@ -Subproject commit f236a20215a8845a1783707b729b62443038866c +Subproject commit a93d8f00b1bc62656782fe8fd1db0f968bfc7d9a diff --git a/plugins/ecs_examples/src/lib.rs b/plugins/ecs_examples/src/lib.rs index 403bd874..ee687b67 100644 --- a/plugins/ecs_examples/src/lib.rs +++ b/plugins/ecs_examples/src/lib.rs @@ -536,6 +536,10 @@ pub fn dispatch_compute( ); } + // stash animation time (user_data.x) in the last resource slot (`resources.input7.index`). + // current compute passes use at most 5 of the 8 input slots, so input7 is always free. + cmd_buf.push_compute_constants(pipeline, 0, 1, 1, 7 * 4, gfx::as_u8_slice(&[pmfx.push_constant_user_data[0]])); + cmd_buf.set_heap(pipeline, &pmfx.shader_heap); cmd_buf.dispatch( diff --git a/plugins/ecs_examples/src/read_write_texture.rs b/plugins/ecs_examples/src/read_write_texture.rs index fc515e08..bdb144f9 100644 --- a/plugins/ecs_examples/src/read_write_texture.rs +++ b/plugins/ecs_examples/src/read_write_texture.rs @@ -12,11 +12,25 @@ pub fn read_write_texture(client: &mut Client, + mut pmfx: ResMut) -> Result<(), hotline_rs::Error> { + + // pack accumulated time into user_data so cs_write_texture3d can animate the volume + pmfx.push_constant_user_data[0] = time.accumulated.to_bits(); + + Ok(()) +} + #[export_update_fn] pub fn setup_read_write_texture( mut device: ResMut, diff --git a/shaders/ecs.hlsl b/shaders/ecs.hlsl index 8026b314..b11a9ec9 100644 --- a/shaders/ecs.hlsl +++ b/shaders/ecs.hlsl @@ -139,18 +139,18 @@ StructuredBuffer directional_lights[] : register(t0, spa StructuredBuffer shadow_matrices[] : register(t0, space6); // textures -Texture2D textures[] : register(t0, space7); -Texture2DMS msaa8x_textures[] : register(t0, space8); -TextureCube cubemaps[] : register(t0, space9); -Texture2DArray texture_arrays[] : register(t0, space10); -Texture3D volume_textures[] : register(t0, space11); +Texture2D textures[] : register(t1, space7); +Texture2DMS msaa8x_textures[] : register(t1, space8); +TextureCube cubemaps[] : register(t1, space9); +Texture2DArray texture_arrays[] : register(t1, space10); +Texture3D volume_textures[] : register(t1, space11); // tlas RaytracingAccelerationStructure scene_tlas[] : register(t0, space12); // uav textures -RWTexture2D rw_textures[] : register(u0, space0); -RWTexture3D rw_volume_textures[] : register(u0, space1); +RWTexture2D rw_textures[] : register(u1, space0); +RWTexture3D rw_volume_textures[] : register(u1, space1); // main constants to obtain the indices of the buffer types ConstantBuffer world_buffer_info : register(b2); diff --git a/shaders/julia.hlsl b/shaders/julia.hlsl new file mode 100644 index 00000000..be93cf3f --- /dev/null +++ b/shaders/julia.hlsl @@ -0,0 +1,80 @@ +// +// animated julia set computed into a read-write texture, then blitted to the back buffer +// + +// bindless read-write texture array - the compute kernel writes the fractal here +RWTexture2D rw_texture[] : register(u0, space0); + +cbuffer julia_constants : register(b0) { + uint output_index; // uav index of the rw_texture to write into + uint output_width; + uint output_height; + float cr; // animated complex constant (real) + float ci; // animated complex constant (imaginary) +}; + +// simple hue ramp for colouring iteration counts +float3 palette(float t) { + return 0.5 + 0.5 * cos(6.28318 * (float3(1.0, 1.0, 1.0) * t + float3(0.0, 0.33, 0.67))); +} + +[numthreads(8, 8, 1)] +void cs_julia(uint2 did : SV_DispatchThreadID) { + if(did.x >= output_width || did.y >= output_height) { + return; + } + + // map pixel to complex plane [-1.5, 1.5] x [-1.0, 1.0] + float aspect = float(output_width) / float(output_height); + float2 uv = float2(did.xy) / float2(output_width, output_height); + float2 z; + z.x = (uv.x * 2.0 - 1.0) * 1.5 * aspect; + z.y = (uv.y * 2.0 - 1.0) * 1.5; + + const int max_iter = 256; + int i = 0; + for(; i < max_iter; ++i) { + float x = z.x * z.x - z.y * z.y + cr; + float y = 2.0 * z.x * z.y + ci; + z = float2(x, y); + if(dot(z, z) > 4.0) { + break; + } + } + + float t = float(i) / float(max_iter); + float3 colour = (i == max_iter) ? float3(0.0, 0.0, 0.0) : palette(t); + rw_texture[output_index][did.xy] = float4(colour, 1.0); +} + +// +// fullscreen blit of the compute output to the back buffer (bindless texture sample) +// + +struct vs_input { + float2 position : POSITION; + float2 texcoord : TEXCOORD; +}; + +struct ps_input { + float4 position : SV_POSITION; + float2 texcoord : TEXCOORD; +}; + +cbuffer blit_constants : register(b0) { + int4 blit_srv_index; // srv index of the compute output texture +}; + +Texture2D blit_textures[] : register(t0); +SamplerState blit_sampler : register(s0); + +ps_input vs_blit(vs_input input) { + ps_input output; + output.position = float4(input.position, 0.0, 1.0); + output.texcoord = input.texcoord; + return output; +} + +float4 ps_blit(ps_input input) : SV_Target { + return blit_textures[blit_srv_index[0]].Sample(blit_sampler, input.texcoord); +} diff --git a/shaders/julia.pmfx b/shaders/julia.pmfx new file mode 100644 index 00000000..52ba7b50 --- /dev/null +++ b/shaders/julia.pmfx @@ -0,0 +1,32 @@ +{ + include: [ + "julia.hlsl" + ] + sampler_states: { + linear_clamp: { + filter: "Linear", + address_u: "Clamp", + address_v: "Clamp", + address_w: "Clamp", + } + } + pipelines: { + julia: { + cs: cs_julia, + push_constants: [ + "julia_constants" + ] + } + blit: { + vs: vs_blit, + ps: ps_blit, + push_constants: [ + "blit_constants" + ] + static_samplers: { + blit_sampler: "linear_clamp" + } + topology: "TriangleList" + } + } +} diff --git a/shaders/material.hlsl b/shaders/material.hlsl index 39560a32..6fcc8cb7 100644 --- a/shaders/material.hlsl +++ b/shaders/material.hlsl @@ -86,7 +86,7 @@ vs_output_material vs_mesh_lit(vs_input_mesh input) { ps_output ps_mesh_debug_tangent_space(vs_output_material input) { ps_output output; - output.colour = float4(0.0, 0.0, 0.0, 0.0); + output.colour = float4(0.0, 0.0, 0.0, 1.0); float3 ts_normal = textures[draw_indices.x].Sample(sampler_wrap_linear, input.texcoord.xy).xyz; ts_normal = ts_normal * 2.0 - 1.0; diff --git a/shaders/shadows.hlsl b/shaders/shadows.hlsl index cd3afdd8..8459df8d 100644 --- a/shaders/shadows.hlsl +++ b/shaders/shadows.hlsl @@ -44,7 +44,7 @@ float sample_shadow_pcf_9(float3 sp, uint sm_index, float2 sm_size) { samples[6] = float2(1.0, -1.0) * inv_sm_size; samples[7] = float2(1.0, 0.0) * inv_sm_size; samples[8] = float2(1.0, 1.0) * inv_sm_size; - + float shadow = 0.0; [unroll] @@ -73,7 +73,7 @@ float sample_shadow_cube_pcf_9(float3 cv, float d, uint sm_index, float sm_size) samples[6] = (b2 * 1.0 + t * -1.0) * inv_sm_size; samples[7] = (b2 * 1.0 + t * 0.0) * inv_sm_size; samples[8] = (b2 * 1.0 + t * -1.0) * inv_sm_size; - + float shadow = 0.0; [unroll] @@ -104,7 +104,7 @@ float4 ps_single_directional_shadow(vs_output input) : SV_Target { int shadow_map_index = light.shadow_map.srv_index; float4x4 shadow_matrix = get_shadow_matrix(light.shadow_map.matrix_index); - + // project shadow coord float4 offset_pos = float4(input.world_pos.xyz, 1.0); @@ -113,10 +113,32 @@ float4 ps_single_directional_shadow(vs_output input) : SV_Target { sp.y *= -1.0; sp.xy = sp.xy * 0.5 + 0.5; - float shadow_sample = textures[shadow_map_index].Sample(sampler_clamp_point, sp.xy).r; - float shadow = sp.z >= shadow_sample ? 0.0 : 1.0; + // sample (non cmp) + //float shadow_sample = textures[shadow_map_index].Sample(sampler_clamp_point, sp.xy).r; + //float shadow = sp.z >= shadow_sample ? 0.0 : 1.0; - shadow = sample_shadow_pcf_9(sp, shadow_map_index, float2(4096.0, 4096.0)); + // pcf sample-compare, inlined here rather than calling sample_shadow_pcf_9: passing the + // bindless texture array + comparison sampler through a function call mis-propagates in the + // shader codegen and the comparison resolves to black (the omni path inlines for the same reason) + float2 sm_size = float2(4096.0, 4096.0); + float2 inv_sm_size = 1.0 / sm_size; + float2 pcf_offsets[9]; + pcf_offsets[0] = float2(-1.0, -1.0) * inv_sm_size; + pcf_offsets[1] = float2(-1.0, 0.0) * inv_sm_size; + pcf_offsets[2] = float2(-1.0, 1.0) * inv_sm_size; + pcf_offsets[3] = float2( 0.0, -1.0) * inv_sm_size; + pcf_offsets[4] = float2( 0.0, 0.0) * inv_sm_size; + pcf_offsets[5] = float2( 0.0, 1.0) * inv_sm_size; + pcf_offsets[6] = float2( 1.0, -1.0) * inv_sm_size; + pcf_offsets[7] = float2( 1.0, 0.0) * inv_sm_size; + pcf_offsets[8] = float2( 1.0, 1.0) * inv_sm_size; + + float shadow = 0.0; + [unroll] + for(int s = 0; s < 9; ++s) { + shadow += textures[shadow_map_index].SampleCmp(sampler_shadow_compare, sp.xy + pcf_offsets[s], sp.z); + } + shadow /= 9.0; float3 l = light.dir.xyz; float diffuse = lambert(l, n); @@ -128,12 +150,13 @@ float4 ps_single_directional_shadow(vs_output input) : SV_Target { float4 lit_colour = light.colour * diffuse + light.colour * specular; output = lit_colour * shadow + light.colour * 0.2; + output.a = 1.0; return output; } float4 ps_single_omni_shadow(vs_output input) : SV_Target { - + int i = 0; float ks = 2.0; float roughness = 0.9; @@ -158,7 +181,7 @@ float4 ps_single_omni_shadow(vs_output input) : SV_Target { light.radius, input.world_pos.xyz ); - + output += atteniuation * light.colour * diffuse; output += atteniuation * light.colour * specular; @@ -196,7 +219,7 @@ float4 ps_single_omni_shadow(vs_output input) : SV_Target { samples[6] = (b2 * 1.0 + t * -1.0) * inv_sm_size; samples[7] = (b2 * 1.0 + t * 0.0) * inv_sm_size; samples[8] = (b2 * 1.0 + t * -1.0) * inv_sm_size; - + float shadow = 0.0; [unroll] @@ -208,6 +231,9 @@ float4 ps_single_omni_shadow(vs_output input) : SV_Target { if(dot(n, l) >= 0.0) { shadow = 0.0; } - - return output * shadow; + + output.rgb *= shadow; + output.a = 1.0; + + return output; } \ No newline at end of file diff --git a/shaders/texture.hlsl b/shaders/texture.hlsl index 78a2c511..40414ac6 100644 --- a/shaders/texture.hlsl +++ b/shaders/texture.hlsl @@ -188,24 +188,32 @@ ps_output ps_volume_texture_ray_march(vs_output input) { [numthreads(8, 8, 8)] void cs_write_texture3d(uint3 did : SV_DispatchThreadID) { - float3 dim = float3(64.0, 64.0, 64.0); - float3 grid_pos = did.xyz * 2.0 - float3(64.0, 64.0, 64.0); - - float4 sphere; - float d = 1.0; - - float nxz = voronoise(did.xz / 8.0, 1.0, 0.0); - float nxy = voronoise(did.xy / 8.0, 1.0, 0.0); - float nyz = voronoise(did.yz / 8.0, 1.0, 0.0); + // animated time, packed into the spare resource slot by `dispatch_compute` + float t = asfloat(resources.input7.index); + float3 grid_pos = did.xyz * 2.0 - float3(64.0, 64.0, 64.0); float3 n = normalize(grid_pos); + // scroll the noise fields over time so the volume churns + float2 flow = float2(t * 4.0, sin(t) * 4.0); + float nxz = voronoise(did.xz / 8.0 + flow, 1.0, 0.0); + float nxy = voronoise(did.xy / 8.0 - flow, 1.0, 0.0); + float nyz = voronoise(did.yz / 8.0 + flow.yx, 1.0, 0.0); + float nn = abs(dot(n, float3(0.0, 1.0, 0.0))) * nxz + abs(dot(n, float3(0.0, 0.0, 1.0))) * nxy + abs(dot(n, float3(1.0, 0.0, 0.0))) * nyz; - rw_volume_textures[resources.input0.index][did.xyz] = float4(nn, 0.0, 0.0, nn < 0.9 ? 0.0 : 1.0); + // a travelling spherical shell pulses in and out, carving the surface threshold + float radius = length(grid_pos) / 64.0; + float pulse = 0.6 + 0.35 * sin(t * 1.5 - radius * 4.0); + + // colour shifts through the spectrum over time for a livelier look + float3 colour = 0.5 + 0.5 * cos(t + nn * 6.0 + float3(0.0, 2.094, 4.188)); + + rw_volume_textures[resources.input0.index][did.xyz] = + float4(colour * nn, nn < pulse ? 0.0 : 1.0); } // diff --git a/src/gfx/mtl.rs b/src/gfx/mtl.rs index 34bf256f..82d63163 100644 --- a/src/gfx/mtl.rs +++ b/src/gfx/mtl.rs @@ -304,6 +304,17 @@ fn to_mtl_data_type(resource_type: super::ResourceType) -> metal::MTLDataType { } } +// HLSL register kind ('t', 'u', 'b', 's') for a DescriptorType. Used to group bindings into MSL +// descriptor sets keyed by (kind, register_number) so e.g. t0 and u0 never share a [[buffer(N)]]. +fn descriptor_register_kind(ty: super::DescriptorType) -> char { + match ty { + super::DescriptorType::ShaderResource => 't', + super::DescriptorType::UnorderedAccess => 'u', + super::DescriptorType::ConstantBuffer | super::DescriptorType::PushConstants => 'b', + super::DescriptorType::Sampler => 's', + } +} + #[derive(Clone)] pub struct Device { metal_device: metal::Device, @@ -423,10 +434,12 @@ pub struct CmdBuf { bound_index_buffer: Option, bound_index_stride: usize, bound_render_pipeline: Option<*const RenderPipeline>, + bound_compute_pipeline: Option<*const ComputePipeline>, metal_device: metal::Device, transient_buffers: Vec, vertex_binder: HashMap, fragment_binder: HashMap, + compute_binder: HashMap, } impl Clone for CmdBuf { @@ -439,10 +452,12 @@ impl Clone for CmdBuf { bound_index_buffer: self.bound_index_buffer.clone(), bound_index_stride: self.bound_index_stride, bound_render_pipeline: self.bound_render_pipeline, + bound_compute_pipeline: self.bound_compute_pipeline, metal_device: self.metal_device.clone(), transient_buffers: self.transient_buffers.clone(), vertex_binder: self.vertex_binder.clone(), fragment_binder: self.fragment_binder.clone(), + compute_binder: self.compute_binder.clone(), } } } @@ -571,6 +586,93 @@ impl CmdBuf { } } } + + /// Flush the compute binder state onto the active compute encoder before a dispatch. Push + /// constants go via setBytes; explicitly bound (non-bindless) resources are encoded into a + /// transient argument buffer - bindless heap argument buffers are already bound by `set_heap`. + fn allocate_compute_resources(&mut self) { + let encoder = match self.compute_encoder.as_ref() { + Some(e) => e, + None => return, + }; + let binder = self.compute_binder.clone(); + + // push constants + for b in binder.values() { + if let PipelineStageBinder::PushConstants(pc) = b { + if !pc.dirty { + continue; + } + let data_size = (pc.num_32_bit_constants * 4) as u64; + let data_ptr = pc.data.as_ptr() as *const std::ffi::c_void; + encoder.set_bytes(pc.buffer_index as u64, data_size, data_ptr); + } + } + + // explicitly bound resources, grouped by buffer_index + let mut groups: HashMap> = HashMap::new(); + for b in binder.values() { + if let PipelineStageBinder::Resource(rb) = b { + if rb.bound_resource.is_some() && rb.dirty { + groups.entry(rb.buffer_index).or_default().push(rb); + } + } + } + + for (buffer_index, mut binders) in groups { + binders.sort_by_key(|rb| rb.binding_index); + + let arg_descs: Vec = binders.iter().map(|rb| { + let arg_desc = metal::ArgumentDescriptor::new(); + arg_desc.set_index(rb.binding_index as u64); + arg_desc.set_data_type(rb.data_type); + arg_desc.set_array_length(rb.array_length); + arg_desc.set_access(metal::MTLArgumentAccess::ReadWrite); + arg_desc.to_owned() + }).collect(); + + let arg_encoder = self.metal_device.new_argument_encoder( + metal::Array::from_owned_slice(&arg_descs) + ); + let arg_buffer = self.metal_device.new_buffer( + arg_encoder.encoded_length(), + metal::MTLResourceOptions::StorageModeShared + ); + arg_encoder.set_argument_buffer(&arg_buffer, 0); + + for rb in &binders { + if let Some(ref binding) = rb.bound_resource { + let heap = unsafe { &*binding.heap_ptr }; + encoder.use_heap(&heap.mtl_heap); + + match rb.data_type { + metal::MTLDataType::Texture => { + if let Some(texture) = heap.texture_slots.get(binding.offset).and_then(|t| t.as_ref()) { + arg_encoder.set_texture(rb.binding_index as u64, texture); + } + } + metal::MTLDataType::Pointer => { + if let Some(buffer) = heap.buffer_slots.get(binding.offset).and_then(|b| b.as_ref()) { + arg_encoder.set_buffer(rb.binding_index as u64, buffer, 0); + } + } + _ => {} + } + } + } + + encoder.set_buffer(buffer_index as u64, Some(&arg_buffer), 0); + self.transient_buffers.push(arg_buffer); + } + + // clear dirty flags now encoding is done + for b in self.compute_binder.values_mut() { + match b { + PipelineStageBinder::PushConstants(pc) => pc.dirty = false, + PipelineStageBinder::Resource(rb) => rb.dirty = false, + } + } + } } impl super::CmdBuf for CmdBuf { @@ -588,6 +690,10 @@ impl super::CmdBuf for CmdBuf { fn close(&mut self) -> result::Result<(), super::Error> { objc::rc::autoreleasepool(|| { + // close any open compute encoder before committing + if let Some(enc) = self.compute_encoder.take() { + enc.end_encoding(); + } self.cmd.as_ref().expect("hotline_rs::gfx::mtl expected call to CmdBuf::reset before close").commit(); self.cmd = None; Ok(()) @@ -604,6 +710,11 @@ impl super::CmdBuf for CmdBuf { assert!(self.render_encoder.is_none(), "hotline_rs::gfx::mtl begin_render_pass called without matching CmdBuf::end_render_pass"); + // close any open compute encoder - Metal forbids two live encoders on one cmd buffer + if let Some(enc) = self.compute_encoder.take() { + enc.end_encoding(); + } + // catch mismatched close/reset let render_encoder = self.cmd.as_ref() .expect("hotline_rs::gfx::mtl expected call to CmdBuf::reset after close") @@ -769,7 +880,23 @@ impl super::CmdBuf for CmdBuf { } fn set_compute_pipeline(&mut self, pipeline: &ComputePipeline) { + objc::rc::autoreleasepool(|| { + // open a compute encoder lazily; reused across dispatches until a render pass or close + if self.compute_encoder.is_none() { + let encoder = self.cmd.as_ref() + .expect("hotline_rs::gfx::mtl expected a call to CmdBuf::reset before set_compute_pipeline") + .new_compute_command_encoder() + .to_owned(); + self.compute_encoder = Some(encoder); + } + self.compute_encoder.as_ref().unwrap() + .set_compute_pipeline_state(&pipeline.pipeline_state); + + // store pipeline pointer and clone binder template into command buffer state + self.bound_compute_pipeline = Some(pipeline as *const ComputePipeline); + self.compute_binder = pipeline.compute_binder.clone(); + }); } fn set_raytracing_pipeline(&mut self, pipeline: &RaytracingPipeline) { @@ -777,6 +904,27 @@ impl super::CmdBuf for CmdBuf { } fn set_heap(&mut self, pipeline: &T, heap: &Heap) { + // compute pipelines bind the heap argument buffers on the compute encoder (single stage) + if matches!(T::get_pipeline_type(), super::PipelineType::Compute) { + let encoder = self.compute_encoder + .as_ref() + .expect("hotline_rs::gfx::metal expected a call to set_compute_pipeline before set_heap"); + let cp: &ComputePipeline = unsafe { std::mem::transmute(pipeline) }; + + encoder.use_heap(&heap.mtl_heap); + for (_key, slot) in &cp.compute_binder { + if let PipelineStageBinder::Resource(res) = slot { + let arg_buffer = match res.data_type { + metal::MTLDataType::Texture => heap.get_texture_argument_buffer(), + metal::MTLDataType::Pointer => heap.get_buffer_argument_buffer(), + _ => continue, + }; + encoder.set_buffer(res.buffer_index as u64, Some(arg_buffer), 0); + } + } + return; + } + let encoder = self.render_encoder .as_ref() .expect("hotline_rs::gfx::metal expected a call to begin render pass before using render commands"); @@ -837,6 +985,14 @@ impl super::CmdBuf for CmdBuf { } } + // Write to compute binder if present + if let Some(binder) = self.compute_binder.get_mut(&key) { + if let PipelineStageBinder::Resource(ref mut rb) = binder { + rb.bound_resource = Some(ResourceBinding { heap_ptr, offset }); + rb.dirty = true; + } + } + Some(()) } @@ -881,7 +1037,27 @@ impl super::CmdBuf for CmdBuf { result } - fn push_compute_constants(&mut self, _pipeline: &P, _register: u32, _space: u32, _num_values: u32, _dest_offset: u32, _data: &[T]) -> Option<()> { + fn push_compute_constants(&mut self, _pipeline: &P, register: u32, space: u32, num_values: u32, dest_offset: u32, data: &[T]) -> Option<()> { + let key = (register, space, super::DescriptorType::PushConstants); + + let data_size_dwords = num_values as usize; + let data_u32 = unsafe { + std::slice::from_raw_parts( + data.as_ptr() as *const u32, + data_size_dwords + ) + }; + + if let Some(PipelineStageBinder::PushConstants(ref mut pc)) = self.compute_binder.get_mut(&key) { + let dest_start = dest_offset as usize; + let dest_end = dest_start + data_size_dwords; + if dest_end <= pc.data.len() { + pc.data[dest_start..dest_end].copy_from_slice(data_u32); + pc.dirty = true; + } + return Some(()); + } + None } @@ -945,7 +1121,20 @@ impl super::CmdBuf for CmdBuf { }) } - fn dispatch(&mut self, group_count: Size3, _numthreads: Size3) { + fn dispatch(&mut self, group_count: Size3, numthreads: Size3) { + objc::rc::autoreleasepool(|| { + self.allocate_compute_resources(); + + let threadgroups = metal::MTLSize::new( + group_count.x as u64, group_count.y as u64, group_count.z as u64); + let threads_per_group = metal::MTLSize::new( + numthreads.x as u64, numthreads.y as u64, numthreads.z as u64); + + self.compute_encoder + .as_ref() + .expect("hotline_rs::gfx::metal expected a call to set_compute_pipeline before dispatch") + .dispatch_thread_groups(threadgroups, threads_per_group); + }); } fn execute_indirect( @@ -1238,12 +1427,17 @@ impl super::RenderPass for RenderPass { } pub struct ComputePipeline { - slots: Vec + pipeline_state: metal::ComputePipelineState, + slots: Vec, + /// Unified slot lookup by (register, space, descriptor_type) + slot_lookup: HashMap, + /// Single-stage binders for push constants and resource bindings + compute_binder: HashMap, } impl super::Pipeline for ComputePipeline { fn get_pipeline_slot(&self, register: u32, space: u32, descriptor_type: DescriptorType) -> Option<&super::PipelineSlotInfo> { - None + self.slot_lookup.get(&(register, space, descriptor_type)) } fn get_pipeline_slots(&self) -> &Vec { @@ -1253,6 +1447,13 @@ impl super::Pipeline for ComputePipeline { fn get_pipeline_type() -> PipelineType { super::PipelineType::Compute } + + fn get_sub_binding_offset(&self, register: u32, space: u32, descriptor_type: DescriptorType) -> u32 { + self.slot_lookup + .get(&(register, space, descriptor_type)) + .map(|s| s.sub_offset) + .unwrap_or(0) + } } #[derive(Clone)] @@ -1502,41 +1703,49 @@ impl Device { } } - // Add regular binding slots + // Add regular binding slots, grouped by (register_kind, shader_register) to mirror the + // descriptor-set layout produced by htwv's MSL codegen. Each (kind, register) becomes its + // own MSL [[buffer(N)]] slot so the heap's texture and buffer argument buffers never share + // a slot. sub_offset matches the [[id(N)]] value spirv-cross assigns within the set; + // callers compensate for the unsized-array-hack offset via get_sub_binding_offset. if let Some(bindings) = pipeline_bindings.as_ref() { if !bindings.is_empty() { - // Determine if any binding needs vertex or fragment visibility - let needs_vertex = bindings.iter().any(|b| - matches!(b.visibility, ShaderVisibility::Vertex | ShaderVisibility::All)); - let needs_fragment = bindings.iter().any(|b| - matches!(b.visibility, ShaderVisibility::Fragment | ShaderVisibility::All)); - - // Single buffer index per stage (only increment once, not per binding!) - let vertex_idx = if needs_vertex { - let idx = vertex_binding_offset; - vertex_binding_offset += 1; - Some(idx) - } else { - None - }; - let fragment_idx = if needs_fragment { - let idx = fragment_binding_offset; - fragment_binding_offset += 1; - Some(idx) - } else { - None - }; - let canonical_index = vertex_idx.or(fragment_idx).unwrap_or(0); - - // Each binding gets a slot entry; sub_offset is the position within the group - // matching the [[id(N)]] value spirv-cross assigns in the descriptor set struct - for (sub_offset, binding) in bindings.iter().enumerate() { + // (register_kind, shader_register) -> (buffer_index, next_sub_offset) + let mut v_groups: HashMap<(char, u32), (u32, u32)> = HashMap::new(); + let mut f_groups: HashMap<(char, u32), (u32, u32)> = HashMap::new(); + + for binding in bindings { + let key = (descriptor_register_kind(binding.binding_type), binding.shader_register); + + let v_slot = if matches!(binding.visibility, ShaderVisibility::Vertex | ShaderVisibility::All) { + let entry = v_groups.entry(key).or_insert_with(|| { + let idx = vertex_binding_offset; + vertex_binding_offset += 1; + (idx, 0) + }); + let sub = entry.1; + entry.1 += 1; + Some((entry.0, sub)) + } else { None }; + + let f_slot = if matches!(binding.visibility, ShaderVisibility::Fragment | ShaderVisibility::All) { + let entry = f_groups.entry(key).or_insert_with(|| { + let idx = fragment_binding_offset; + fragment_binding_offset += 1; + (idx, 0) + }); + let sub = entry.1; + entry.1 += 1; + Some((entry.0, sub)) + } else { None }; + + let (canonical_index, sub_offset) = v_slot.or(f_slot).unwrap_or((0, 0)); slot_lookup.insert( (binding.shader_register, binding.register_space, binding.binding_type), PipelineSlotInfo { index: canonical_index, count: binding.num_descriptors, - sub_offset: sub_offset as u32, + sub_offset, } ); } @@ -1619,65 +1828,58 @@ impl Device { } } - // Add resource binders + // Add resource binders, grouped by (register_kind, shader_register). Each (kind, register) + // pair gets its own [[buffer(N)]] slot per stage so the heap's texture and buffer + // argument buffers are bound to distinct slots. Within a group, binding_index is the + // sub_offset that matches the [[id(N)]] value spirv-cross emits in the MSL set struct. if let Some(bindings) = pipeline_bindings.as_ref() { if !bindings.is_empty() { - // Determine if any binding needs vertex or fragment visibility - let needs_vertex = bindings.iter().any(|b| - matches!(b.visibility, ShaderVisibility::Vertex | ShaderVisibility::All)); - let needs_fragment = bindings.iter().any(|b| - matches!(b.visibility, ShaderVisibility::Fragment | ShaderVisibility::All)); - - // Single buffer index per stage (only increment once, not per binding!) - let vertex_idx = if needs_vertex { - let idx = vertex_binding_offset; - vertex_binding_offset += 1; - Some(idx) - } else { - None - }; - let fragment_idx = if needs_fragment { - let idx = fragment_binding_offset; - fragment_binding_offset += 1; - Some(idx) - } else { - None - }; + // (register_kind, shader_register) -> (buffer_index, next_sub_offset) + let mut v_groups: HashMap<(char, u32), (u32, u32)> = HashMap::new(); + let mut f_groups: HashMap<(char, u32), (u32, u32)> = HashMap::new(); - // Create ResourceBinder for each binding - for (i, binding) in bindings.iter().enumerate() { + for binding in bindings { let key: SlotKey = (binding.shader_register, binding.register_space, binding.binding_type); + let group_key = (descriptor_register_kind(binding.binding_type), binding.shader_register); let data_type = to_mtl_data_type( binding.resource_type.expect("hotline_rs::gfx::mtl: requires resource type for binding") ); let array_length = binding.num_descriptors.map(|n| n as u64).unwrap_or(MAX_BINDLESS_TEXTURES); - // Add to vertex binder if visible to vertex stage if matches!(binding.visibility, ShaderVisibility::Vertex | ShaderVisibility::All) { - if let Some(v_idx) = vertex_idx { - vertex_binder.insert(key, PipelineStageBinder::Resource(ResourceBinder { - buffer_index: v_idx, - binding_index: i as u32, - data_type, - array_length, - bound_resource: None, - dirty: true, - })); - } + let entry = v_groups.entry(group_key).or_insert_with(|| { + let idx = vertex_binding_offset; + vertex_binding_offset += 1; + (idx, 0) + }); + let sub = entry.1; + entry.1 += 1; + vertex_binder.insert(key, PipelineStageBinder::Resource(ResourceBinder { + buffer_index: entry.0, + binding_index: sub, + data_type, + array_length, + bound_resource: None, + dirty: true, + })); } - // Add to fragment binder if visible to fragment stage if matches!(binding.visibility, ShaderVisibility::Fragment | ShaderVisibility::All) { - if let Some(f_idx) = fragment_idx { - fragment_binder.insert(key, PipelineStageBinder::Resource(ResourceBinder { - buffer_index: f_idx, - binding_index: i as u32, - data_type, - array_length, - bound_resource: None, - dirty: true, - })); - } + let entry = f_groups.entry(group_key).or_insert_with(|| { + let idx = fragment_binding_offset; + fragment_binding_offset += 1; + (idx, 0) + }); + let sub = entry.1; + entry.1 += 1; + fragment_binder.insert(key, PipelineStageBinder::Resource(ResourceBinder { + buffer_index: entry.0, + binding_index: sub, + data_type, + array_length, + bound_resource: None, + dirty: true, + })); } } } @@ -1685,6 +1887,77 @@ impl Device { (vertex_binder, fragment_binder) } + + /// Build a single-stage binder for a compute pipeline. Mirrors `build_stage_binders` but emits + /// one map: push constants and resource bindings share a single MSL [[buffer(N)]] namespace + /// (no vertex/fragment split). Buffer indices begin at `COMPUTE_BINDING_BASE` which must match + /// the [[buffer(N)]] slots htwv emits for the compute kernel. + fn build_compute_binder( + &self, + pipeline_bindings: &Option>, + pipeline_push_constants: &Option>, + ) -> HashMap { + const MAX_BINDLESS_TEXTURES: u64 = 1024; + // Compute follows the same MSL [[buffer(N)]] layout htwv emits for the fragment stage: + // buffer(0) is reserved for the sampler descriptor set, push constants take buffer(1), and + // space0 resource descriptor sets follow at buffer(2)+. So start binding indices at 1. + const COMPUTE_BINDING_BASE: u32 = 1; + + let mut binder: HashMap = HashMap::new(); + let mut binding_offset: u32 = COMPUTE_BINDING_BASE; + + // Push constants (use setBytes - no ArgumentEncoder) + if let Some(push_constants) = pipeline_push_constants.as_ref() { + for push_constant in push_constants { + let key: SlotKey = ( + push_constant.shader_register, + push_constant.register_space, + DescriptorType::PushConstants, + ); + let buffer_index = binding_offset; + binding_offset += 1; + binder.insert(key, PipelineStageBinder::PushConstants(PushConstantsBinder { + data: vec![0u32; push_constant.num_values as usize], + num_32_bit_constants: push_constant.num_values, + buffer_index, + dirty: true, + })); + } + } + + // Resource bindings grouped by (register_kind, shader_register) - one [[buffer(N)]] per group + if let Some(bindings) = pipeline_bindings.as_ref() { + if !bindings.is_empty() { + let mut groups: HashMap<(char, u32), (u32, u32)> = HashMap::new(); + for binding in bindings { + let key: SlotKey = (binding.shader_register, binding.register_space, binding.binding_type); + let group_key = (descriptor_register_kind(binding.binding_type), binding.shader_register); + let data_type = to_mtl_data_type( + binding.resource_type.expect("hotline_rs::gfx::mtl: requires resource type for binding") + ); + let array_length = binding.num_descriptors.map(|n| n as u64).unwrap_or(MAX_BINDLESS_TEXTURES); + + let entry = groups.entry(group_key).or_insert_with(|| { + let idx = binding_offset; + binding_offset += 1; + (idx, 0) + }); + let sub = entry.1; + entry.1 += 1; + binder.insert(key, PipelineStageBinder::Resource(ResourceBinder { + buffer_index: entry.0, + binding_index: sub, + data_type, + array_length, + bound_resource: None, + dirty: true, + })); + } + } + } + + binder + } } impl super::Device for Device { @@ -1836,10 +2109,12 @@ impl super::Device for Device { bound_index_buffer: None, bound_index_stride: 0, bound_render_pipeline: None, + bound_compute_pipeline: None, metal_device: self.metal_device.clone(), transient_buffers: Vec::new(), vertex_binder: HashMap::new(), fragment_binder: HashMap::new(), + compute_binder: HashMap::new(), } }) } @@ -2477,8 +2752,36 @@ impl super::Device for Device { &self, info: &super::ComputePipelineInfo, ) -> result::Result { - Ok(ComputePipeline{ - slots: Vec::new() + objc::rc::autoreleasepool(|| { + // load the compute kernel function from the shader library + let function = unsafe { + let cs = info.cs; + let lib = self.metal_device.new_library_with_data( + std::slice::from_raw_parts(cs.data, cs.data_size) + )?; + let name = &lib.function_names()[0]; + lib.get_function(name, None).unwrap() + }; + + let pipeline_state = self.metal_device.new_compute_pipeline_state_with_function(&function)?; + + // unified slot lookup + single-stage binder, both keyed by (register, space, type) + let slot_lookup = self.build_slot_lookup( + &info.pipeline_layout.bindings, + &info.pipeline_layout.push_constants, + ); + + let compute_binder = self.build_compute_binder( + &info.pipeline_layout.bindings, + &info.pipeline_layout.push_constants, + ); + + Ok(ComputePipeline { + pipeline_state, + slots: Vec::new(), + slot_lookup, + compute_binder, + }) }) } diff --git a/todo.txt b/todo.txt index 4d4727b8..dc8c4ecd 100644 --- a/todo.txt +++ b/todo.txt @@ -7,23 +7,27 @@ x window pos restore x shader errors don't properly display x majority shader compilation x dynamic cubemap +x tangent space normal map is black +x shadow map is black +x omni shadow is black +x compute pipeline +x RW texture + better demo + - gpu timestamp ??? - pmfx hotreload +- pmbuild needs universal install into hotline-data -- shadow map is black -- omni shadow is black -- material ibl -- tangent space normal map is black -- RW texture + better demo - MRT -- mip downsample - MSAA +- mip downsample + +- sample cmp shadow +- material ibl - bindless material - cbuffer instanced causes hugh perf issues (should be structured tbh) - - draw indirect - -- pmbuild needs universal install into hotline-data +- video player +- resource tests // issues // - swap between dynamic cube and PBR causes inconsitency in the cubemap texture From 152515b07654442a7837f1883ba6f6edcee7ed59 Mon Sep 17 00:00:00 2001 From: polymonster Date: Thu, 21 May 2026 18:44:21 +0200 Subject: [PATCH 50/62] - mrt, msaa and mips working --- shaders/render_targets.hlsl | 4 +- src/gfx/mtl.rs | 310 +++++++++++++++++++++++++++--------- src/os/macos.rs | 42 +++-- todo.txt | 13 +- 4 files changed, 276 insertions(+), 93 deletions(-) diff --git a/shaders/render_targets.hlsl b/shaders/render_targets.hlsl index dad76f20..075bcb0c 100644 --- a/shaders/render_targets.hlsl +++ b/shaders/render_targets.hlsl @@ -12,7 +12,7 @@ vs_output vs_heightmap(vs_input_mesh input) { float height = 200.0; float3 p1 = pos.xyz; - + float h = fbm(p1.xz + fbm(p1.xz + fbm(p1.xz, 6), 6), 6) * height; p1.y += h; @@ -60,7 +60,7 @@ ps_output_mrt ps_heightmap_example_mrt(vs_output input) { void cs_heightmap_mrt_resolve(uint2 did: SV_DispatchThreadID, uint2 group_id: SV_GroupID) { // grab the output dimension from input0 (which we write to) uint2 half_dim = resources.input0.dimension.xy / 2; - + // render into 4 quadrants float4 final = float4(0.0, 0.0, 0.0, 0.0); if(did.x < half_dim.x && did.y < half_dim.y) { diff --git a/src/gfx/mtl.rs b/src/gfx/mtl.rs index 82d63163..c7f54c87 100644 --- a/src/gfx/mtl.rs +++ b/src/gfx/mtl.rs @@ -367,6 +367,7 @@ impl super::SwapChain for SwapChain { fn update(&mut self, device: &mut Device, window: &A::Window, cmd: &mut CmdBuf) -> bool { objc::rc::autoreleasepool(|| { let draw_size = window.get_size(); + self.layer.set_contents_scale(window.get_dpi_scale() as f64); self.layer.set_drawable_size(CGSize::new(draw_size.x as f64, draw_size.y as f64)); let drawable = self.layer.next_drawable() @@ -376,8 +377,11 @@ impl super::SwapChain for SwapChain { self.backbuffer_texture = Texture { metal_texture: drawable.texture().to_owned(), + resolved_texture: None, srv_index: None, + msaa_srv_index: None, uav_index: None, + resolvable: false, heap_id: None }; @@ -440,6 +444,9 @@ pub struct CmdBuf { vertex_binder: HashMap, fragment_binder: HashMap, compute_binder: HashMap, + /// Textures whose mips must be regenerated when the current render pass ends (see + /// RenderPass::generate_mips_textures), set in begin_render_pass and consumed in end_render_pass. + pending_mip_textures: Vec, } impl Clone for CmdBuf { @@ -458,6 +465,7 @@ impl Clone for CmdBuf { vertex_binder: self.vertex_binder.clone(), fragment_binder: self.fragment_binder.clone(), compute_binder: self.compute_binder.clone(), + pending_mip_textures: self.pending_mip_textures.clone(), } } } @@ -722,6 +730,10 @@ impl super::CmdBuf for CmdBuf { // new encoder self.render_encoder = Some(render_encoder); + + // remember any mip-chained targets so we can regenerate their mips once the pass ends + // (and its MSAA resolve has completed) + self.pending_mip_textures = render_pass.generate_mips_textures.clone(); }); } @@ -731,6 +743,20 @@ impl super::CmdBuf for CmdBuf { .expect("hotline_rs::gfx::mtl end_render_pass called without matching begin") .end_encoding(); self.render_encoder = None; + + // regenerate mips for any generate_mips targets now mip 0 has been written/resolved. + // A blit encoder is the only live encoder here, so Metal's ordering guarantees the + // resolve completes first. + if !self.pending_mip_textures.is_empty() { + if let Some(cmd) = self.cmd.as_ref() { + let blit = cmd.new_blit_command_encoder(); + for tex in &self.pending_mip_textures { + blit.generate_mipmaps(tex); + } + blit.end_encoding(); + } + self.pending_mip_textures.clear(); + } }); } @@ -1154,11 +1180,19 @@ impl super::CmdBuf for CmdBuf { }) } - fn resolve_texture_subresource(&mut self, texture: &Texture, subresource: u32) -> result::Result<(), super::Error> { + fn resolve_texture_subresource(&mut self, _texture: &Texture, _subresource: u32) -> result::Result<(), super::Error> { + // No-op on Metal: MSAA resolve is performed at the end of the owning render pass via the + // StoreAndMultisampleResolve store action (see create_render_pass). pmfx records this into a + // barrier command buffer once at graph-setup and re-executes it every frame, but a committed + // Metal command buffer is single-use, so doing the resolve here would only run once. Ok(()) } - fn generate_mip_maps(&mut self, texture: &Texture, device: &Device, heap: &Heap) -> result::Result<(), super::Error> { + fn generate_mip_maps(&mut self, _texture: &Texture, _device: &Device, _heap: &Heap) -> result::Result<(), super::Error> { + // Mips are generated inline at the end of the render pass that targets the resource (see + // end_render_pass / RenderPass::generate_mips_textures). The pmfx barrier mechanism this + // hooks into cannot run per-frame on Metal (device.execute is a no-op and command buffers + // are single-commit), so the work happens where the resolve does instead. Ok(()) } @@ -1347,8 +1381,15 @@ impl super::Pipeline for RenderPipeline { #[derive(Clone)] pub struct Texture { metal_texture: metal::Texture, + /// Single-sample resolve backing for an MSAA texture (samples > 1); also the texture sampled + /// when reading a resolvable target normally + resolved_texture: Option, + /// Bindless index of the resolved / non-MSAA view (returned by `get_srv_index`) srv_index: Option, + /// Bindless index of the MSAA view, for `Texture2DMS` reads (returned by `get_msaa_srv_index`) + msaa_srv_index: Option, uav_index: Option, + resolvable: bool, heap_id: Option } @@ -1362,7 +1403,7 @@ impl super::Texture for Texture { } fn get_msaa_srv_index(&self) -> Option { - None + self.msaa_srv_index } fn get_uav_index(&self) -> Option { @@ -1372,14 +1413,17 @@ impl super::Texture for Texture { fn clone_inner(&self) -> Texture { Texture { metal_texture: self.metal_texture.clone(), + resolved_texture: self.resolved_texture.clone(), srv_index: self.srv_index, + msaa_srv_index: self.msaa_srv_index, uav_index: self.uav_index, + resolvable: self.resolvable, heap_id: self.heap_id } } fn is_resolvable(&self) -> bool { - false + self.resolvable } fn get_shader_heap_id(&self) -> Option { @@ -1416,8 +1460,14 @@ impl super::ReadBackRequest for ReadBackRequest { #[derive(Clone)] pub struct RenderPass { desc: metal::RenderPassDescriptor, - pixel_format: metal::MTLPixelFormat, + /// Colour attachment formats, one per MRT target (index 0 = SV_Target0) + pixel_formats: Vec, depth_format: Option, + /// MSAA sample count shared by all attachments in the pass (1 = no MSAA) + sample_count: u32, + /// Sampled textures (resolve backing or the target itself) with a mip chain that should have + /// their mips regenerated after this pass completes - filled for `generate_mips` targets. + generate_mips_textures: Vec, } impl super::RenderPass for RenderPass { @@ -1563,6 +1613,16 @@ pub struct RaytracingTLAS { } impl Device { + /// Largest texture sample count <= `requested` that this device supports (always >= 1). + /// Apple GPUs commonly cap at 4x, so an 8x request is clamped down rather than asserting. + fn supported_sample_count(&self, requested: u32) -> u32 { + let mut count = requested.max(1); + while count > 1 && !self.metal_device.supports_texture_sample_count(count as NSUInteger) { + count /= 2; + } + count + } + fn create_render_pass_for_swap_chain( &self, texture: &Texture, @@ -1589,16 +1649,22 @@ impl Device { texture_descriptor.set_depth(1); texture_descriptor.set_texture_type(metal::MTLTextureType::D2); texture_descriptor.set_pixel_format(metal::MTLPixelFormat::RGBA8Unorm); - texture_descriptor.set_storage_mode(metal::MTLStorageMode::Shared); + // Private storage: required for MSAA textures (which can't be Shared) and faster for + // GPU sampling on Apple Silicon. Texture data is uploaded via a staging buffer + blit. + texture_descriptor.set_storage_mode(metal::MTLStorageMode::Private); // Determine the size required for the heap for the given descriptor let size_and_align = mtl_device.heap_texture_size_and_align(&texture_descriptor); let texture_size = align_pow2(size_and_align.size, size_and_align.align); - let heap_size = texture_size * info.num_descriptors.max(1) as u64; + // The 512x512 RGBA8 reference (~1MB) underestimates real descriptors: 2k material + // textures, IBL cubemaps and MSAA render targets are far larger. Oversize the heap so + // the bindless descriptor pool doesn't run out of memory when many/large textures load. + const HEAP_OVERSIZE_FACTOR: u64 = 2; + let heap_size = texture_size * info.num_descriptors.max(1) as u64 * HEAP_OVERSIZE_FACTOR; let heap_descriptor = metal::HeapDescriptor::new(); - heap_descriptor.set_storage_mode(metal::MTLStorageMode::Shared); + heap_descriptor.set_storage_mode(metal::MTLStorageMode::Private); heap_descriptor.set_size(heap_size); // Enable hazard tracking so Metal automatically synchronizes heap-allocated @@ -2064,6 +2130,7 @@ impl super::Device for Device { view.setLayer(std::mem::transmute(layer.as_ref())); let draw_size = win.get_size(); + layer.set_contents_scale(win.get_dpi_scale() as f64); layer.set_drawable_size(CGSize::new(draw_size.x as f64, draw_size.y as f64)); let drawable = layer.next_drawable() @@ -2071,8 +2138,11 @@ impl super::Device for Device { let backbuffer_texture = Texture { metal_texture: drawable.texture().to_owned(), + resolved_texture: None, srv_index: None, + msaa_srv_index: None, uav_index: None, + resolvable: false, heap_id: None }; let render_pass = self.create_render_pass_for_swap_chain(&backbuffer_texture, info.clear_colour); @@ -2115,6 +2185,7 @@ impl super::Device for Device { vertex_binder: HashMap::new(), fragment_binder: HashMap::new(), compute_binder: HashMap::new(), + pending_mip_textures: Vec::new(), } }) } @@ -2204,21 +2275,28 @@ impl super::Device for Device { pipeline_state_descriptor.set_vertex_descriptor(Some(&vertex_desc)); - // TODO: attachments - let attachment = pipeline_state_descriptor - .color_attachments() - .object_at(0) - .unwrap(); - - // Get pixel format from pass; depth-only passes use Invalid (no colour attachment) - let pixel_format = info.pass - .map(|p| p.pixel_format) - .unwrap_or(metal::MTLPixelFormat::BGRA8Unorm); - attachment.set_pixel_format(pixel_format); - - // Only configure blend/write state when there is a colour attachment - if pixel_format != metal::MTLPixelFormat::Invalid { - if let Some(b) = info.blend_info.render_target.first() { + // colour attachments - one per MRT target from the pass (SV_Target0..N). With no pass + // (eg. depth-only / default) fall back to a single BGRA8 attachment. + let pixel_formats: Vec = info.pass + .map(|p| p.pixel_formats.clone()) + .filter(|f| !f.is_empty()) + .unwrap_or_else(|| vec![metal::MTLPixelFormat::BGRA8Unorm]); + + for (i, &pixel_format) in pixel_formats.iter().enumerate() { + let attachment = pipeline_state_descriptor + .color_attachments() + .object_at(i as u64) + .unwrap(); + attachment.set_pixel_format(pixel_format); + + if pixel_format == metal::MTLPixelFormat::Invalid { + continue; + } + + // per-target blend state (falls back to the first / disabled) + let blend = info.blend_info.render_target.get(i) + .or_else(|| info.blend_info.render_target.first()); + if let Some(b) = blend { attachment.set_blending_enabled(b.blend_enabled); attachment.set_rgb_blend_operation(to_mtl_blend_op(&b.blend_op)); attachment.set_alpha_blend_operation(to_mtl_blend_op(&b.blend_op_alpha)); @@ -2233,7 +2311,7 @@ impl super::Device for Device { } } - // Set depth format on pipeline descriptor if pass has depth + // Set depth format + MSAA sample count on pipeline descriptor to match the pass if let Some(pass) = &info.pass { if let Some(depth_format) = pass.depth_format { pipeline_state_descriptor.set_depth_attachment_pixel_format(depth_format); @@ -2241,6 +2319,7 @@ impl super::Device for Device { pipeline_state_descriptor.set_stencil_attachment_pixel_format(depth_format); } } + pipeline_state_descriptor.set_sample_count(pass.sample_count as NSUInteger); } // Create depth stencil state @@ -2531,18 +2610,26 @@ impl super::Device for Device { objc::rc::autoreleasepool(|| { let desc = TextureDescriptor::new(); - // TODO: - // initial_state + // clamp requested MSAA to what the device supports (eg. 8x -> 4x on most Apple GPUs) + let sample_count = self.supported_sample_count(info.samples); + let msaa = sample_count > 1; // desc desc.set_pixel_format(to_mtl_pixel_format(info.format)); desc.set_width(info.width as NSUInteger); desc.set_height(info.height as NSUInteger); desc.set_depth(info.depth as NSUInteger); - desc.set_mipmap_level_count(info.mip_levels as NSUInteger); + // MSAA textures cannot have a mip chain + desc.set_mipmap_level_count(if msaa { 1 } else { info.mip_levels as NSUInteger }); desc.set_usage(to_mtl_texture_usage(info.usage)); - desc.set_storage_mode(metal::MTLStorageMode::Shared); - desc.set_texture_type(to_mtl_texture_type(info.tex_type)); + // Must match the (Private) heap the texture is allocated from + desc.set_storage_mode(metal::MTLStorageMode::Private); + // MSAA Texture2D uses the D2Multisample type + desc.set_texture_type(if msaa && matches!(info.tex_type, super::TextureType::Texture2D) { + metal::MTLTextureType::D2Multisample + } else { + to_mtl_texture_type(info.tex_type) + }); // For cubemaps, arrayLength must be 1 (6 faces are implicit) // For cube arrays, arrayLength is the number of cubemaps (not faces) @@ -2553,9 +2640,7 @@ impl super::Device for Device { }; desc.set_array_length(array_length as NSUInteger); - // TODO: multi sample - // desc.set_sample_count(info.samples as NSUInteger); - desc.set_sample_count(1); + desc.set_sample_count(sample_count as NSUInteger); // use supplied heap or fallback to the device default let shader_heap = if let Some(shader_heap) = heaps.shader { @@ -2569,12 +2654,29 @@ impl super::Device for Device { let tex = shader_heap.mtl_heap.new_texture(&desc) .expect("hotline_rs::gfx::mtl failed to allocate texture in heap!"); - // upload texture data with support for mips, cubemaps, and array slices + // upload texture data with support for mips, cubemaps, and array slices. + // The heap is Private (not CPU-writable), so stage the bytes in a Shared buffer and + // blit each subresource into the texture on a one-shot command buffer. if let Some(data) = data { let block_size = super::block_size_for_format(info.format) as u64; let tpb = super::texels_per_block_for_format(info.format); - let mut data_offset: usize = 0; + let bytes = unsafe { + std::slice::from_raw_parts( + data.as_ptr() as *const u8, + std::mem::size_of_val(data) + ) + }; + let staging = self.metal_device.new_buffer_with_data( + bytes.as_ptr() as *const std::ffi::c_void, + bytes.len() as NSUInteger, + metal::MTLResourceOptions::StorageModeShared + ); + + let cmd = self.command_queue.new_command_buffer(); + let blit = cmd.new_blit_command_encoder(); + + let mut data_offset: u64 = 0; for a in 0..info.array_layers { let mut mip_w = info.width; let mut mip_h = info.height; @@ -2584,27 +2686,20 @@ impl super::Device for Device { let pitch = block_size * (mip_w / tpb).max(1); let depth_pitch = pitch * (mip_h / tpb).max(1); - let region = metal::MTLRegion { - origin: metal::MTLOrigin { x: 0, y: 0, z: 0 }, - size: metal::MTLSize { - width: mip_w, - height: mip_h, - depth: mip_d, - }, - }; - - let mip_data_ptr = unsafe { (data.as_ptr() as *const u8).add(data_offset) }; - - tex.replace_region_in_slice( - region, - mip as NSUInteger, - a as NSUInteger, - mip_data_ptr as _, + blit.copy_from_buffer_to_texture( + &staging, + data_offset as NSUInteger, pitch as NSUInteger, depth_pitch as NSUInteger, + metal::MTLSize { width: mip_w, height: mip_h, depth: mip_d }, + &tex, + a as NSUInteger, + mip as NSUInteger, + metal::MTLOrigin { x: 0, y: 0, z: 0 }, + metal::MTLBlitOption::empty(), ); - data_offset += (depth_pitch * mip_d.max(1)) as usize; + data_offset += depth_pitch * mip_d.max(1); // halve dimensions for next mip (non-pot safe) mip_w = (mip_w / 2).max(1); @@ -2612,6 +2707,10 @@ impl super::Device for Device { mip_d = (mip_d / 2).max(1); } } + + blit.end_encoding(); + cmd.commit(); + cmd.wait_until_completed(); } // allocate on the heap @@ -2621,14 +2720,9 @@ impl super::Device for Device { // Encode texture into heap's argument buffer for bindless access shader_heap.encode_texture(alloc_index, &tex); - // assign srv or uav - let srv_index = if info.usage.contains(TextureUsage::SHADER_RESOURCE) { - Some(alloc_index) - } - else { - None - }; + let shader_resource = info.usage.contains(TextureUsage::SHADER_RESOURCE); + // UAV only applies to the (non-MSAA) texture let uav_index = if info.usage.contains(TextureUsage::UNORDERED_ACCESS) { Some(alloc_index) } @@ -2636,12 +2730,58 @@ impl super::Device for Device { None }; - Ok(Texture{ - metal_texture: tex, - srv_index, - uav_index, - heap_id: Some(shader_heap.id) - }) + if msaa { + // The primary texture is the MSAA view (read as Texture2DMS via get_msaa_srv_index). + let msaa_srv_index = if shader_resource { Some(alloc_index) } else { None }; + + // Create a single-sample resolve backing so the texture can be read normally and + // resolved via resolve_texture_subresource (matches the D3D12 resolve concept). + let mut resolved_texture = None; + let mut srv_index = None; + if shader_resource { + let rdesc = TextureDescriptor::new(); + rdesc.set_pixel_format(to_mtl_pixel_format(info.format)); + rdesc.set_width(info.width as NSUInteger); + rdesc.set_height(info.height as NSUInteger); + rdesc.set_depth(info.depth as NSUInteger); + rdesc.set_mipmap_level_count(info.mip_levels as NSUInteger); + rdesc.set_usage(to_mtl_texture_usage(info.usage)); + rdesc.set_storage_mode(metal::MTLStorageMode::Private); + rdesc.set_texture_type(to_mtl_texture_type(info.tex_type)); + rdesc.set_array_length(array_length as NSUInteger); + rdesc.set_sample_count(1); + + let resolve_tex = shader_heap.mtl_heap.new_texture(&rdesc) + .expect("hotline_rs::gfx::mtl failed to allocate resolve texture in heap!"); + let resolve_index = shader_heap.allocate(); + shader_heap.texture_slots[resolve_index] = Some(resolve_tex.to_owned()); + shader_heap.encode_texture(resolve_index, &resolve_tex); + srv_index = Some(resolve_index); + resolved_texture = Some(resolve_tex); + } + + Ok(Texture{ + metal_texture: tex, + resolved_texture, + srv_index, + msaa_srv_index, + uav_index, + resolvable: shader_resource, + heap_id: Some(shader_heap.id) + }) + } + else { + let srv_index = if shader_resource { Some(alloc_index) } else { None }; + Ok(Texture{ + metal_texture: tex, + resolved_texture: None, + srv_index, + msaa_srv_index: None, + uav_index, + resolvable: false, + heap_id: Some(shader_heap.id) + }) + } }) } @@ -2653,27 +2793,49 @@ impl super::Device for Device { // new desc let descriptor = metal::RenderPassDescriptor::new(); - // colour attachments - for rt in &info.render_targets { - let color_attachment = descriptor.color_attachments().object_at(0).unwrap(); + // colour attachments - one per MRT target (SV_Target0..N) + let mut pixel_formats = Vec::new(); + let mut generate_mips_textures = Vec::new(); + for (i, rt) in info.render_targets.iter().enumerate() { + let color_attachment = descriptor.color_attachments().object_at(i as u64).unwrap(); color_attachment.set_texture(Some(&rt.metal_texture)); color_attachment.set_slice(info.array_slice as u64); if let Some(cc) = info.rt_clear { color_attachment.set_load_action(metal::MTLLoadAction::Clear); color_attachment.set_clear_color(metal::MTLClearColor::new(cc.r as f64, cc.g as f64, cc.b as f64, 1.0)); - color_attachment.set_store_action(metal::MTLStoreAction::Store); } else { color_attachment.set_load_action(metal::MTLLoadAction::Load); + } + + // For an MSAA target with a resolve backing, resolve at the end of the pass (every + // frame) rather than via a separate resolve command buffer. StoreAndMultisampleResolve + // also keeps the raw MSAA samples so they remain readable as Texture2DMS (ReadMsaa). + if let Some(resolved) = rt.resolved_texture.as_ref() { + color_attachment.set_resolve_texture(Some(resolved)); + color_attachment.set_store_action(metal::MTLStoreAction::StoreAndMultisampleResolve); + } + else { color_attachment.set_store_action(metal::MTLStoreAction::Store); } + + pixel_formats.push(rt.metal_texture.pixel_format()); + + // a target with a mip chain (eg. generate_mips) needs its mips rebuilt from mip 0 + // after the pass writes / resolves into it. Use the sampled texture (resolve backing + // for MSAA, otherwise the target itself). + let sampled = rt.resolved_texture.as_ref().unwrap_or(&rt.metal_texture); + if sampled.mipmap_level_count() > 1 { + generate_mips_textures.push(sampled.to_owned()); + } } - // Get pixel format from first render target; Invalid for depth-only passes - let pixel_format = info.render_targets.first() - .map(|rt| rt.metal_texture.pixel_format()) - .unwrap_or(metal::MTLPixelFormat::Invalid); + // sample count shared by all attachments (read from the first colour/depth target) + let sample_count = info.render_targets.first() + .map(|rt| rt.metal_texture.sample_count() as u32) + .or_else(|| info.depth_stencil.map(|ds| ds.metal_texture.sample_count() as u32)) + .unwrap_or(1); // Handle depth stencil attachment let depth_format = if let Some(ds_texture) = &info.depth_stencil { @@ -2721,8 +2883,10 @@ impl super::Device for Device { Ok(RenderPass{ desc: descriptor.to_owned(), - pixel_format, + pixel_formats, depth_format, + sample_count, + generate_mips_textures, }) }) } diff --git a/src/os/macos.rs b/src/os/macos.rs index f7832d09..310942bc 100644 --- a/src/os/macos.rs +++ b/src/os/macos.rs @@ -81,6 +81,8 @@ pub struct App { windows: Arc>>>, monitors: Arc>>, window_sizes: Arc>>>>>, + /// When false, windows render at 1x (non-retina) for lower GPU cost (eg. with MSAA) + dpi_aware: bool, } unsafe impl Send for App {} @@ -93,6 +95,8 @@ pub struct Window { input_state: Arc>, events: Arc>, cached_size: Arc>>, + /// Inherited from `AppInfo.dpi_aware`; false = render at 1x (logical pixels) + dpi_aware: bool, } unsafe impl Send for Window {} @@ -304,6 +308,7 @@ impl super::App for App { windows: Arc::new(RwLock::new(HashMap::new())), monitors: Arc::new(RwLock::new(Vec::new())), window_sizes: Arc::new(RwLock::new(HashMap::new())), + dpi_aware: info.dpi_aware, } } @@ -334,6 +339,7 @@ impl super::App for App { input_state: self.input_state.clone(), events: Arc::new(RwLock::new(super::WindowEventFlags::NONE)), cached_size, + dpi_aware: self.dpi_aware, } } @@ -511,6 +517,23 @@ impl super::App for App { } } +impl Window { + /// Render-target size for this window: physical pixels when dpi-aware, otherwise the logical + /// 1x size (physical / scale_factor) so retina + MSAA isn't allocated at full backing scale. + fn render_size(&self) -> super::Size { + let size = *self.cached_size.read().unwrap(); + if self.dpi_aware { + super::Size { x: size.width as i32, y: size.height as i32 } + } else { + let scale = self.winit_window.scale_factor().max(1.0); + super::Size { + x: ((size.width as f64 / scale).round() as i32).max(1), + y: ((size.height as f64 / scale).round() as i32).max(1), + } + } + } +} + impl super::Window for Window { /// Bring window to front and draw ontop of all others fn bring_to_front(&self) { @@ -596,22 +619,18 @@ impl super::Window for Window { /// Returns a gfx friendly full window rect to use as `gfx::Viewport` or `gfx::Scissor` fn get_viewport_rect(&self) -> super::Rect { - let size = *self.cached_size.read().unwrap(); + let size = self.render_size(); super::Rect { x: 0, y: 0, - width: size.width as i32, - height: size.height as i32 + width: size.x, + height: size.y } } - /// Returns the screen position for the top-left corner of the window + /// Returns the render size of the window (physical pixels, or logical 1x when !dpi_aware) fn get_size(&self) -> super::Size { - let size = *self.cached_size.read().unwrap(); - super::Size { - x: size.width as i32, - y: size.height as i32 - } + self.render_size() } /// Returns the screen rect of the window screen pos x, y , size x, y. @@ -633,9 +652,10 @@ impl super::Window for Window { self.input_state.read().unwrap().mouse_client_pos } - /// Return the dpi scale for the current monitor the window is on + /// Return the dpi scale for the current monitor the window is on. When the app is not + /// dpi-aware the engine operates entirely in logical (1x) pixels, so the effective scale is 1. fn get_dpi_scale(&self) -> f32 { - self.winit_window.scale_factor() as f32 + if self.dpi_aware { self.winit_window.scale_factor() as f32 } else { 1.0 } } /// Gets the internal native handle diff --git a/todo.txt b/todo.txt index dc8c4ecd..0f97a5d3 100644 --- a/todo.txt +++ b/todo.txt @@ -1,5 +1,3 @@ -// TODO: - macos x perf issues push constants x hot reload @@ -12,19 +10,20 @@ x shadow map is black x omni shadow is black x compute pipeline x RW texture + better demo +x MSAA +x MRT +- mip downsample - gpu timestamp ??? - pmfx hotreload - pmbuild needs universal install into hotline-data -- MRT -- MSAA -- mip downsample - -- sample cmp shadow - material ibl - bindless material + +- sample cmp shadow - cbuffer instanced causes hugh perf issues (should be structured tbh) + - draw indirect - video player - resource tests From 9dd41e773c5890b7ab9032c011361e10b49dc05f Mon Sep 17 00:00:00 2001 From: polymonster Date: Thu, 21 May 2026 18:48:08 +0200 Subject: [PATCH 51/62] - update hotline data --- hotline-data | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hotline-data b/hotline-data index a93d8f00..38e00eae 160000 --- a/hotline-data +++ b/hotline-data @@ -1 +1 @@ -Subproject commit a93d8f00b1bc62656782fe8fd1db0f968bfc7d9a +Subproject commit 38e00eae20db3aed01cdbc3ca9b892efd154b2e2 From 5e5522819026c864890759ba18e4419d3678f755 Mon Sep 17 00:00:00 2001 From: polymonster Date: Thu, 21 May 2026 19:01:19 +0200 Subject: [PATCH 52/62] - move handling of resolve and downsample to be driven by barriers, in line with d3d --- src/gfx/mtl.rs | 135 +++++++++++++++++++++++++++++-------------------- todo.txt | 2 +- 2 files changed, 80 insertions(+), 57 deletions(-) diff --git a/src/gfx/mtl.rs b/src/gfx/mtl.rs index c7f54c87..11292bab 100644 --- a/src/gfx/mtl.rs +++ b/src/gfx/mtl.rs @@ -444,9 +444,27 @@ pub struct CmdBuf { vertex_binder: HashMap, fragment_binder: HashMap, compute_binder: HashMap, - /// Textures whose mips must be regenerated when the current render pass ends (see - /// RenderPass::generate_mips_textures), set in begin_render_pass and consumed in end_render_pass. - pending_mip_textures: Vec, + /// Render-graph barrier work recorded as intent rather than encoded immediately. Metal command + /// buffers are single-commit, so a barrier (which the graph replays every frame via + /// `Device::execute`) cannot be a pre-encoded buffer like it is on D3D12. Instead transition / + /// resolve / generate_mip_maps push ops here and `Device::execute` replays them into a fresh + /// command buffer each frame. + deferred_ops: Vec, +} + +/// A unit of render-graph barrier work to replay each frame on Metal. Transition barriers are +/// absent because Metal tracks hazards automatically for resources in a `Tracked` heap. +#[derive(Clone)] +enum DeferredBarrierOp { + /// Resolve an MSAA texture into its single-sample resolve backing via a load/no-clear pass. + Resolve { + msaa: metal::Texture, + resolve: metal::Texture, + }, + /// Regenerate the mip chain of a sampled texture from mip 0 with a blit encoder. + GenerateMips { + texture: metal::Texture, + }, } impl Clone for CmdBuf { @@ -465,7 +483,7 @@ impl Clone for CmdBuf { vertex_binder: self.vertex_binder.clone(), fragment_binder: self.fragment_binder.clone(), compute_binder: self.compute_binder.clone(), - pending_mip_textures: self.pending_mip_textures.clone(), + deferred_ops: self.deferred_ops.clone(), } } } @@ -730,10 +748,6 @@ impl super::CmdBuf for CmdBuf { // new encoder self.render_encoder = Some(render_encoder); - - // remember any mip-chained targets so we can regenerate their mips once the pass ends - // (and its MSAA resolve has completed) - self.pending_mip_textures = render_pass.generate_mips_textures.clone(); }); } @@ -743,20 +757,6 @@ impl super::CmdBuf for CmdBuf { .expect("hotline_rs::gfx::mtl end_render_pass called without matching begin") .end_encoding(); self.render_encoder = None; - - // regenerate mips for any generate_mips targets now mip 0 has been written/resolved. - // A blit encoder is the only live encoder here, so Metal's ordering guarantees the - // resolve completes first. - if !self.pending_mip_textures.is_empty() { - if let Some(cmd) = self.cmd.as_ref() { - let blit = cmd.new_blit_command_encoder(); - for tex in &self.pending_mip_textures { - blit.generate_mipmaps(tex); - } - blit.end_encoding(); - } - self.pending_mip_textures.clear(); - } }); } @@ -1180,19 +1180,28 @@ impl super::CmdBuf for CmdBuf { }) } - fn resolve_texture_subresource(&mut self, _texture: &Texture, _subresource: u32) -> result::Result<(), super::Error> { - // No-op on Metal: MSAA resolve is performed at the end of the owning render pass via the - // StoreAndMultisampleResolve store action (see create_render_pass). pmfx records this into a - // barrier command buffer once at graph-setup and re-executes it every frame, but a committed - // Metal command buffer is single-use, so doing the resolve here would only run once. + fn resolve_texture_subresource(&mut self, texture: &Texture, _subresource: u32) -> result::Result<(), super::Error> { + // Record the resolve as deferred barrier work; Device::execute replays it into a fresh + // command buffer each frame (a committed Metal command buffer can't be re-submitted). + if let Some(resolve) = texture.resolved_texture.as_ref() { + self.deferred_ops.push(DeferredBarrierOp::Resolve { + msaa: texture.metal_texture.to_owned(), + resolve: resolve.to_owned(), + }); + } Ok(()) } - fn generate_mip_maps(&mut self, _texture: &Texture, _device: &Device, _heap: &Heap) -> result::Result<(), super::Error> { - // Mips are generated inline at the end of the render pass that targets the resource (see - // end_render_pass / RenderPass::generate_mips_textures). The pmfx barrier mechanism this - // hooks into cannot run per-frame on Metal (device.execute is a no-op and command buffers - // are single-commit), so the work happens where the resolve does instead. + fn generate_mip_maps(&mut self, texture: &Texture, _device: &Device, _heap: &Heap) -> result::Result<(), super::Error> { + // Record mip generation as deferred barrier work (replayed per-frame by Device::execute). + // Generate on the texture shaders actually sample: the resolve backing for an MSAA target + // (its mip 0 is filled by the preceding resolve op), otherwise the texture itself. + let target = texture.resolved_texture.as_ref().unwrap_or(&texture.metal_texture); + if target.mipmap_level_count() > 1 { + self.deferred_ops.push(DeferredBarrierOp::GenerateMips { + texture: target.to_owned(), + }); + } Ok(()) } @@ -1465,9 +1474,6 @@ pub struct RenderPass { depth_format: Option, /// MSAA sample count shared by all attachments in the pass (1 = no MSAA) sample_count: u32, - /// Sampled textures (resolve backing or the target itself) with a mip chain that should have - /// their mips regenerated after this pass completes - filled for `generate_mips` targets. - generate_mips_textures: Vec, } impl super::RenderPass for RenderPass { @@ -2185,7 +2191,7 @@ impl super::Device for Device { vertex_binder: HashMap::new(), fragment_binder: HashMap::new(), compute_binder: HashMap::new(), - pending_mip_textures: Vec::new(), + deferred_ops: Vec::new(), } }) } @@ -2795,7 +2801,6 @@ impl super::Device for Device { // colour attachments - one per MRT target (SV_Target0..N) let mut pixel_formats = Vec::new(); - let mut generate_mips_textures = Vec::new(); for (i, rt) in info.render_targets.iter().enumerate() { let color_attachment = descriptor.color_attachments().object_at(i as u64).unwrap(); color_attachment.set_texture(Some(&rt.metal_texture)); @@ -2809,26 +2814,13 @@ impl super::Device for Device { color_attachment.set_load_action(metal::MTLLoadAction::Load); } - // For an MSAA target with a resolve backing, resolve at the end of the pass (every - // frame) rather than via a separate resolve command buffer. StoreAndMultisampleResolve - // also keeps the raw MSAA samples so they remain readable as Texture2DMS (ReadMsaa). - if let Some(resolved) = rt.resolved_texture.as_ref() { - color_attachment.set_resolve_texture(Some(resolved)); - color_attachment.set_store_action(metal::MTLStoreAction::StoreAndMultisampleResolve); - } - else { - color_attachment.set_store_action(metal::MTLStoreAction::Store); - } + // Keep the rendered (MSAA) samples. The MSAA resolve and any mip downsample are + // driven by the render graph barriers (see resolve_texture_subresource / + // generate_mip_maps), not baked into every pass, so the barrier can decide when they + // happen (eg. only after the last of several passes that target the same resource). + color_attachment.set_store_action(metal::MTLStoreAction::Store); pixel_formats.push(rt.metal_texture.pixel_format()); - - // a target with a mip chain (eg. generate_mips) needs its mips rebuilt from mip 0 - // after the pass writes / resolves into it. Use the sampled texture (resolve backing - // for MSAA, otherwise the target itself). - let sampled = rt.resolved_texture.as_ref().unwrap_or(&rt.metal_texture); - if sampled.mipmap_level_count() > 1 { - generate_mips_textures.push(sampled.to_owned()); - } } // sample count shared by all attachments (read from the first colour/depth target) @@ -2886,7 +2878,6 @@ impl super::Device for Device { pixel_formats, depth_format, sample_count, - generate_mips_textures, }) }) } @@ -2958,7 +2949,39 @@ impl super::Device for Device { } fn execute(&mut self, cmd: &CmdBuf) { + // Pass command buffers commit themselves in CmdBuf::close, so there is nothing to submit + // here for them. Barrier command buffers instead carry deferred ops (transition / resolve / + // generate mips) which we replay into a fresh command buffer every frame, mirroring how + // D3D12 re-executes a pre-recorded barrier command list. + if cmd.deferred_ops.is_empty() { + return; + } + objc::rc::autoreleasepool(|| { + let metal_cmd = self.command_queue.new_command_buffer(); + for op in &cmd.deferred_ops { + match op { + DeferredBarrierOp::Resolve { msaa, resolve } => { + // a load/no-clear pass with a MultisampleResolve store action resolves the + // MSAA samples into the single-sample backing without drawing anything. + let descriptor = metal::RenderPassDescriptor::new(); + let attachment = descriptor.color_attachments().object_at(0).unwrap(); + attachment.set_texture(Some(msaa)); + attachment.set_resolve_texture(Some(resolve)); + attachment.set_load_action(metal::MTLLoadAction::Load); + attachment.set_store_action(metal::MTLStoreAction::StoreAndMultisampleResolve); + let encoder = metal_cmd.new_render_command_encoder(&descriptor); + encoder.end_encoding(); + } + DeferredBarrierOp::GenerateMips { texture } => { + let blit = metal_cmd.new_blit_command_encoder(); + blit.generate_mipmaps(texture); + blit.end_encoding(); + } + } + } + metal_cmd.commit(); + }); } fn report_live_objects(&self) -> result::Result<(), super::Error> { diff --git a/todo.txt b/todo.txt index 0f97a5d3..5e4dbf0d 100644 --- a/todo.txt +++ b/todo.txt @@ -12,7 +12,7 @@ x compute pipeline x RW texture + better demo x MSAA x MRT -- mip downsample +x mip downsample - gpu timestamp ??? - pmfx hotreload From 6cded14832293e85472ddcf78ced2b015a75db56 Mon Sep 17 00:00:00 2001 From: polymonster Date: Fri, 22 May 2026 11:22:44 +0200 Subject: [PATCH 53/62] - gpu timestamps, fix validation MSAA resolve depth stencil --- shaders/material.hlsl | 3 +- src/gfx/mtl.rs | 188 ++++++++++++++++++++++++++++-------------- src/pmfx.rs | 14 ++-- todo.txt | 4 +- 4 files changed, 140 insertions(+), 69 deletions(-) diff --git a/shaders/material.hlsl b/shaders/material.hlsl index 6fcc8cb7..85ff2a22 100644 --- a/shaders/material.hlsl +++ b/shaders/material.hlsl @@ -207,7 +207,8 @@ float4 ps_mesh_material_instanced_ibl(vs_output_material input) : SV_TARGET { float2 brdf = textures[lut_idx].Sample(sampler_wrap_linear, float2(saturate(dot(n, v)), roughness)).rg; float3 specular = prefilter * (f * brdf.x + brdf.y); - return float4(kd * max(diffuse, 0.0) + max(specular, 0.0), 1.0); + float4 o = float4(kd * max(diffuse, 0.0) + max(specular, 0.0), 1.0) * 0.0001; + return o + float4(n, 1.0); } ps_output ps_mesh_lit(vs_output input) { diff --git a/src/gfx/mtl.rs b/src/gfx/mtl.rs index 11292bab..707184ce 100644 --- a/src/gfx/mtl.rs +++ b/src/gfx/mtl.rs @@ -213,6 +213,14 @@ fn has_stencil_component(format: metal::MTLPixelFormat) -> bool { ) } +fn is_depth_format(format: metal::MTLPixelFormat) -> bool { + matches!(format, + metal::MTLPixelFormat::Depth32Float_Stencil8 + | metal::MTLPixelFormat::Depth32Float + | metal::MTLPixelFormat::Depth16Unorm + ) +} + fn to_mtl_cull_mode(cull_mode: super::CullMode) -> metal::MTLCullMode { match cull_mode { super::CullMode::None => metal::MTLCullMode::None, @@ -322,8 +330,17 @@ pub struct Device { shader_heap: Heap, adapter_info: AdapterInfo, heap_alloc_id: u16, + /// True when the GPU can sample timestamp counters at encoder stage boundaries, which lets us + /// take real per-encoder GPU timestamps. When false we fall back to MTLCommandBuffer's whole-CB + /// GPUStartTime / GPUEndTime (see timestamp_query / read_timestamps). + supports_stage_boundary_timestamps: bool, } +/// MTLCounterSamplingPoint::atStageBoundary — sampling at the boundary between encoder stages. +const MTL_COUNTER_SAMPLING_POINT_AT_STAGE_BOUNDARY: NSUInteger = 0; +/// MTLCounterDontSample sentinel: a stage index that should not record a timestamp. +const MTL_COUNTER_DONT_SAMPLE: NSUInteger = NSUInteger::MAX; + #[derive(Clone)] pub struct SwapChain { layer: metal::MetalLayer, @@ -444,12 +461,8 @@ pub struct CmdBuf { vertex_binder: HashMap, fragment_binder: HashMap, compute_binder: HashMap, - /// Render-graph barrier work recorded as intent rather than encoded immediately. Metal command - /// buffers are single-commit, so a barrier (which the graph replays every frame via - /// `Device::execute`) cannot be a pre-encoded buffer like it is on D3D12. Instead transition / - /// resolve / generate_mip_maps push ops here and `Device::execute` replays them into a fresh - /// command buffer each frame. deferred_ops: Vec, + pending_timestamp: Option<(metal::CounterSampleBuffer, NSUInteger)>, } /// A unit of render-graph barrier work to replay each frame on Metal. Transition barriers are @@ -484,6 +497,7 @@ impl Clone for CmdBuf { fragment_binder: self.fragment_binder.clone(), compute_binder: self.compute_binder.clone(), deferred_ops: self.deferred_ops.clone(), + pending_timestamp: self.pending_timestamp.clone(), } } } @@ -741,6 +755,19 @@ impl super::CmdBuf for CmdBuf { enc.end_encoding(); } + // if a timestamp pair is armed, sample the GPU clock at this encoder's stage boundaries: + // start_of_vertex = pass start, end_of_fragment = pass end (the inner boundaries are left + // as MTLCounterDontSample). Set on the descriptor before the encoder is created. + if let Some((sample_buffer, start)) = self.pending_timestamp.take() { + if let Some(att) = render_pass.desc.sample_buffer_attachments().object_at(0) { + att.set_sample_buffer(&sample_buffer); + att.set_start_of_vertex_sample_index(start); + att.set_end_of_vertex_sample_index(MTL_COUNTER_DONT_SAMPLE); + att.set_start_of_fragment_sample_index(MTL_COUNTER_DONT_SAMPLE); + att.set_end_of_fragment_sample_index(start + 1); + } + } + // catch mismatched close/reset let render_encoder = self.cmd.as_ref() .expect("hotline_rs::gfx::mtl expected call to CmdBuf::reset after close") @@ -781,31 +808,24 @@ impl super::CmdBuf for CmdBuf { } fn timestamp_query(&mut self, heap: &mut QueryHeap, resolve_buffer: &mut Buffer) { - if let Some(sample_buf) = heap.sample_buffer.as_ref() { - let idx = heap.alloc_index; - heap.alloc_index += 1; - resolve_buffer.counter_sample_buffer = Some(sample_buf.to_owned()); - resolve_buffer.counter_sample_index = idx; - resolve_buffer.counter_cmd = self.cmd.clone(); - if let Some(enc) = self.render_encoder.as_ref() { - // mid-pass: counter buffer must have been pre-registered in the render pass - // descriptor to call sampleCountersInBuffer — skip silently if not configured - let _ = enc; - } else if let Some(enc) = self.compute_encoder.as_ref() { - let _ = enc; - } else if let Some(cmd) = self.cmd.as_ref() { - // Between encoders: use a blit pass descriptor with the counter buffer - // registered so Metal accepts the sample call. - let blit_desc = metal::BlitPassDescriptor::new(); - if let Some(attachment) = blit_desc.sample_buffer_attachments().object_at(0) { - attachment.set_sample_buffer(sample_buf); - attachment.set_start_of_encoder_sample_index(idx as _); - attachment.set_end_of_encoder_sample_index(NSUInteger::MAX); - } - let blit = cmd.blit_command_encoder_with_descriptor(blit_desc); - blit.end_encoding(); + let idx = heap.alloc_index; + heap.alloc_index += 1; + resolve_buffer.counter_sample_index = idx; + resolve_buffer.counter_cmd = self.cmd.clone(); + + if let Some(sample_buffer) = heap.sample_buffer.as_ref() { + // counter-sampling path: tag the buffer so read_timestamps resolves the counter, and on + // the start sample of a pair arm the next encoder to record both stage-boundary samples + // ([idx, idx + 1]). Multiple start/end pairs in one CB each arm their own encoder. + resolve_buffer.counter_sample_buffer = Some(sample_buffer.to_owned()); + if idx % 2 == 0 { + self.pending_timestamp = Some((sample_buffer.to_owned(), idx as NSUInteger)); } } + else { + // fallback path: no counter buffer, read GPUStartTime / GPUEndTime of the pass CB. + resolve_buffer.counter_sample_buffer = None; + } } fn begin_query(&mut self, heap: &mut QueryHeap, query_type: QueryType) -> usize { @@ -909,10 +929,21 @@ impl super::CmdBuf for CmdBuf { objc::rc::autoreleasepool(|| { // open a compute encoder lazily; reused across dispatches until a render pass or close if self.compute_encoder.is_none() { - let encoder = self.cmd.as_ref() - .expect("hotline_rs::gfx::mtl expected a call to CmdBuf::reset before set_compute_pipeline") - .new_compute_command_encoder() - .to_owned(); + let cmd = self.cmd.as_ref() + .expect("hotline_rs::gfx::mtl expected a call to CmdBuf::reset before set_compute_pipeline"); + // if a timestamp pair is armed, sample the GPU clock at this encoder's boundaries + let encoder = if let Some((sample_buffer, start)) = self.pending_timestamp.take() { + let desc = metal::ComputePassDescriptor::new(); + if let Some(att) = desc.sample_buffer_attachments().object_at(0) { + att.set_sample_buffer(&sample_buffer); + att.set_start_of_encoder_sample_index(start); + att.set_end_of_encoder_sample_index(start + 1); + } + cmd.compute_command_encoder_with_descriptor(desc).to_owned() + } + else { + cmd.new_compute_command_encoder().to_owned() + }; self.compute_encoder = Some(encoder); } @@ -2070,6 +2101,12 @@ impl super::Device for Device { let tier = device.argument_buffers_support(); assert_eq!(metal::MTLArgumentBuffersTier::Tier2, tier); + // Can the GPU sample timestamp counters at encoder stage boundaries? (Apple Silicon + // typically can; older/other GPUs may not, in which case we fall back to whole-CB times.) + let supports_stage_boundary_timestamps: bool = unsafe { + msg_send![&*device, supportsCounterSampling: MTL_COUNTER_SAMPLING_POINT_AT_STAGE_BOUNDARY] + }; + Device { command_queue: command_queue, shader_heap: Self::create_heap_mtl(&device, &HeapInfo{ @@ -2079,7 +2116,8 @@ impl super::Device for Device { }, 1), adapter_info: adapter_info, metal_device: device, - heap_alloc_id: 2 + heap_alloc_id: 2, + supports_stage_boundary_timestamps, } }) } @@ -2095,7 +2133,8 @@ impl super::Device for Device { } fn create_query_heap(&self, info: &QueryHeapInfo) -> QueryHeap { - let sample_buffer = if info.heap_type == super::QueryType::Timestamp { + let sample_buffer = if info.heap_type == super::QueryType::Timestamp + && self.supports_stage_boundary_timestamps { let counter_sets = self.metal_device.counter_sets(); let ts_set = counter_sets.iter().find(|cs| cs.name().eq_ignore_ascii_case("timestamp")); ts_set.and_then(|cs| { @@ -2192,6 +2231,7 @@ impl super::Device for Device { fragment_binder: HashMap::new(), compute_binder: HashMap::new(), deferred_ops: Vec::new(), + pending_timestamp: None, } }) } @@ -2965,11 +3005,30 @@ impl super::Device for Device { // a load/no-clear pass with a MultisampleResolve store action resolves the // MSAA samples into the single-sample backing without drawing anything. let descriptor = metal::RenderPassDescriptor::new(); - let attachment = descriptor.color_attachments().object_at(0).unwrap(); - attachment.set_texture(Some(msaa)); - attachment.set_resolve_texture(Some(resolve)); - attachment.set_load_action(metal::MTLLoadAction::Load); - attachment.set_store_action(metal::MTLStoreAction::StoreAndMultisampleResolve); + // depth/stencil targets must resolve through the depth (and stencil) + // attachments, not a color attachment - a depth format on color + // attachment 0 is "not color renderable" and trips Metal validation, + // blocking GPU captures. + if is_depth_format(msaa.pixel_format()) { + let depth = descriptor.depth_attachment().unwrap(); + depth.set_texture(Some(msaa)); + depth.set_resolve_texture(Some(resolve)); + depth.set_load_action(metal::MTLLoadAction::Load); + depth.set_store_action(metal::MTLStoreAction::MultisampleResolve); + if has_stencil_component(msaa.pixel_format()) { + let stencil = descriptor.stencil_attachment().unwrap(); + stencil.set_texture(Some(msaa)); + stencil.set_resolve_texture(Some(resolve)); + stencil.set_load_action(metal::MTLLoadAction::Load); + stencil.set_store_action(metal::MTLStoreAction::MultisampleResolve); + } + } else { + let attachment = descriptor.color_attachments().object_at(0).unwrap(); + attachment.set_texture(Some(msaa)); + attachment.set_resolve_texture(Some(resolve)); + attachment.set_load_action(metal::MTLLoadAction::Load); + attachment.set_store_action(metal::MTLStoreAction::StoreAndMultisampleResolve); + } let encoder = metal_cmd.new_render_command_encoder(&descriptor); encoder.end_encoding(); } @@ -3012,39 +3071,48 @@ impl super::Device for Device { None } - fn read_timestamps(&self, swap_chain: &SwapChain, buffer: &Self::Buffer, size_bytes: usize, frame_written_fence: u64) -> Vec { - if let Some(sample_buf) = &buffer.counter_sample_buffer { - // Metal has no GPU-signalled fence; wait for the recording command buffer to finish - // before resolving counter data (equivalent to D3D12's GPU fence check). - if let Some(cmd) = &buffer.counter_cmd { - cmd.wait_until_completed(); - } - let elem_size = std::mem::size_of::(); - let count = (size_bytes / elem_size).max(1); + fn read_timestamps(&self, _swap_chain: &SwapChain, buffer: &Self::Buffer, _size_bytes: usize, _frame_written_fence: u64) -> Vec { + // Metal has no GPU-signalled fence; wait for the pass command buffer to finish before reading + // its timestamps (equivalent to D3D12's GPU fence check). + if let Some(cmd) = &buffer.counter_cmd { + cmd.wait_until_completed(); + } + + if let Some(sample_buffer) = &buffer.counter_sample_buffer { + // counter-sampling path: resolve the one timestamp this buffer points at. The GPU + // timestamp is in nanoseconds on Apple Silicon; gather_stats wants seconds. unsafe { let range = metal::NSRange { location: buffer.counter_sample_index as _, - length: count as _, + length: 1, }; let ns_data: *mut objc::runtime::Object = - msg_send![sample_buf.as_ref(), resolveCounterRange: range]; + msg_send![sample_buffer.as_ref(), resolveCounterRange: range]; if !ns_data.is_null() { let bytes: *const u8 = msg_send![ns_data, bytes]; let len: usize = msg_send![ns_data, length]; - let mut results = Vec::new(); - for i in 0..count { - let offset = i * elem_size; - if offset + elem_size <= len { - let nanos = (bytes.add(offset) as *const u64).read_unaligned(); - // MTLCounterResultTimestamp.timestamp is nanoseconds on Apple Silicon - results.push(nanos as f64 / 1_000_000_000.0); + if len >= std::mem::size_of::() { + let nanos = (bytes as *const u64).read_unaligned(); + // MTLCounterErrorValue marks a sample the GPU could not record - treat as none + if nanos != u64::MAX { + return vec![nanos as f64 / 1_000_000_000.0]; } } - if !results.is_empty() { - return results; - } } } + return vec![]; + } + + // fallback path: whole-CB timing. index 0 = start of pass, index 1 = end of pass. + if let Some(cmd) = &buffer.counter_cmd { + let seconds: f64 = unsafe { + if buffer.counter_sample_index == 0 { + msg_send![cmd.as_ref(), GPUStartTime] + } else { + msg_send![cmd.as_ref(), GPUEndTime] + } + }; + return vec![seconds]; } vec![] } diff --git a/src/pmfx.rs b/src/pmfx.rs index d1085a35..6f82c864 100644 --- a/src/pmfx.rs +++ b/src/pmfx.rs @@ -2875,21 +2875,23 @@ impl ReloadResponder for PmfxReloadResponder { } fn build(&mut self) -> std::process::ExitStatus { + // Shader/data compilation is hooked into the crate's build.rs (under the `build_data` + // feature), so reuse that single path here. `cargo build --lib` re-runs the build script - + // which recompiles the data - while skipping the example/bin targets; when only files under + // `shaders/` changed cargo leaves the crate artifacts untouched, so this rebuilds data only. let hotline_path = super::get_data_path("../.."); - let pmbuild = super::get_data_path("../../hotline-data/pmbuild.cmd"); - let output = std::process::Command::new(pmbuild) + let output = std::process::Command::new("cargo") .current_dir(hotline_path) - .arg("win32-data") - .arg("-pmfx") + .args(["build", "--lib"]) .output() .expect("hotline::hot_lib:: hot pmfx failed to compile!"); if !output.stdout.is_empty() { - println!("{}", String::from_utf8(output.stdout).unwrap()); + println!("{}", String::from_utf8_lossy(&output.stdout)); } if !output.stderr.is_empty() { - println!("{}", String::from_utf8(output.stderr).unwrap()); + println!("{}", String::from_utf8_lossy(&output.stderr)); } if output.status.success() { diff --git a/todo.txt b/todo.txt index 5e4dbf0d..17956c28 100644 --- a/todo.txt +++ b/todo.txt @@ -13,8 +13,8 @@ x RW texture + better demo x MSAA x MRT x mip downsample +x gpu timestamp -- gpu timestamp ??? - pmfx hotreload - pmbuild needs universal install into hotline-data @@ -22,7 +22,7 @@ x mip downsample - bindless material - sample cmp shadow -- cbuffer instanced causes hugh perf issues (should be structured tbh) +- cbuffer instanced causes huge perf issues (should be structured tbh) - draw indirect - video player From dc9f44ae496b8d0c6eed794f80fad6c25198c22a Mon Sep 17 00:00:00 2001 From: polymonster Date: Fri, 22 May 2026 17:52:58 +0200 Subject: [PATCH 54/62] - bindless materials working and rolled back to 1 spv descriptor set per binding --- docs/binding-architecture.md | 250 ++++++++++++++++++ .../ecs_examples/src/bindless_material_ibl.rs | 2 +- .../ecs_examples/src/gpu_frustum_culling.rs | 4 +- plugins/ecs_examples/src/lib.rs | 2 +- .../ecs_examples/src/raytracing_pipeline.rs | 2 +- shaders/material.hlsl | 6 +- src/gfx.rs | 8 - src/gfx/d3d12.rs | 2 - src/gfx/mtl.rs | 143 +++++----- src/pmfx.rs | 47 +--- todo.txt | 8 +- 11 files changed, 349 insertions(+), 125 deletions(-) create mode 100644 docs/binding-architecture.md diff --git a/docs/binding-architecture.md b/docs/binding-architecture.md new file mode 100644 index 00000000..23a92b98 --- /dev/null +++ b/docs/binding-architecture.md @@ -0,0 +1,250 @@ +# Bindless binding architecture: D3D12 ↔ Metal + +Reference notes on how hotline maps a single bindless shader-resource model onto two very +different GPU binding APIs — D3D12 descriptor heaps and Metal argument buffers — and the two +approaches we went through to make Metal behave like D3D12. Written as background for a blog post. + +--- + +## 1. The goal + +Author shaders **once** in HLSL using bindless resource arrays, and run them on both D3D12 and +Metal with identical CPU-side code. A shader looks like this (`shaders/ecs.hlsl`): + +```hlsl +// all bindless arrays share register t1, separated by space +Texture2D textures[] : register(t1, space7); +TextureCube cubemaps[] : register(t1, space9); +Texture2DArray texture_arrays[] : register(t1, space10); +Texture3D volume_textures[] : register(t1, space11); + +StructuredBuffer draws : register(t0, space0); +StructuredBuffer materials : register(t0, space2); + +SamplerState sampler_wrap_linear : register(s1); +``` + +The CPU stores **global indices** into these arrays (e.g. a material stores the heap slot of its +albedo texture and the scene's IBL cubemap), and the shader does `textures[material.albedo_id]` +or `cubemaps[ibl_id]`. There is one global resource pool; the index is the only thing that crosses +the CPU/GPU boundary. + +--- + +## 2. Two GPU binding models + +### D3D12 — descriptor heaps +A `ID3D12DescriptorHeap` is a flat array of descriptors. The shader-visible CBV/SRV/UAV heap is +bound once; shaders index it directly (`ResourceDescriptorHeap[i]` in SM6.6, or unbounded +descriptor-table ranges pre-6.6). The **heap slot is the global index** — exactly the model above, +natively. A root signature maps each HLSL `register`/`space` to a descriptor-table range or root +constants. + +### Metal — argument buffers +Metal has no shader-visible descriptor heap that you index with an arbitrary integer (pre-Metal 3 +bindless). Instead you build an **argument buffer**: a GPU buffer whose layout is described by an +`MTLArgumentEncoder`, holding texture/buffer/sampler handles at fixed `[[id(N)]]` slots. A shader +receives argument buffers as `[[buffer(N)]]` parameters. An `MTLHeap` backs the actual resources so +they're resident; the argument buffer holds references into it. + +So the porting problem is: **make a flat, integer-indexed global pool work on top of Metal argument +buffers**, where each shader only sees the argument buffers (descriptor sets) it actually uses. + +--- + +## 3. Hotline's abstraction + +- `gfx::PipelineLayout` carries `bindings: Vec`, `push_constants`, and + `static_samplers`. Each `DescriptorBinding` records `shader_register`, `register_space`, + `binding_type` (SRV/UAV/CBV/Sampler) and `num_descriptors` (None = unbounded/bindless). +- `gfx::PipelineSlotInfo { index, count }` is the resolved location for a binding key + `(register, space, descriptor_type)`. +- A single bindless `Heap` holds all textures and all buffers. + +The two backends implement `gfx::Device::create_render_pipeline` / `set_heap` / `set_binding` +differently from here. + +--- + +## 4. D3D12 mapping (the reference) + +`src/gfx/d3d12.rs` builds a root signature from the pipeline layout. Each binding/space becomes a +descriptor-table range or root parameter; the resolved `PipelineSlotInfo.index` is the **heap +index / root slot**, used directly. There is no per-binding offset fix-up — the global index *is* +the descriptor index. (This is why `PipelineSlotInfo` carries no offset field, and why D3D12 needed +no special handling.) + +--- + +## 5. Metal mapping via SPIRV-Cross (htwv) + +Shaders are cross-compiled offline: **HLSL → DXC → SPIR-V → SPIRV-Cross → MSL** in the `htwv` crate +(`hotline-data/htwv/src/macos_impl.rs`). DXC encodes HLSL `register(tN, spaceM)` as SPIR-V +decorations `Binding = N`, `DescriptorSet = M`. htwv then **re-decorates** each resource to assign +the Metal descriptor set (`[[buffer(N)]]`) and the slot within it (`[[id(N)]]`), and feeds matching +`spvc_msl_resource_binding` entries to SPIRV-Cross. + +The runtime (`src/gfx/mtl.rs`) must assign the **same** `[[buffer(N)]]` numbering so that +`set_heap` / `set_binding` bind the heap's argument buffers to the slots the MSL expects. This +mirroring is the crux: `build_slot_lookup`, `build_stage_binders` and `build_compute_binder` in +`mtl.rs` reproduce, byte-for-byte, the grouping htwv used in codegen. + +The `Heap` keeps **two argument buffers** — one array of all textures, one of all buffer pointers +(`get_texture_argument_buffer` / `get_buffer_argument_buffer`) — each a flat array based at id 0, +indexed by global slot. Samplers live in their own argument buffer at fragment `buffer(0)`. Push +constants are *discrete* descriptor sets (no argument buffer) so they can use +`setVertexBytes`/`setFragmentBytes`. + +The open question that produced two approaches: **how do you group HLSL bindings into Metal +descriptor sets?** + +--- + +## 6. Approach 1 — group by `(kind, register)`, compensate with `sub_offset` + +Group bindings by register *kind and number only* (`t0`, `t1`, `u0`, `b0`…). All arrays sharing a +register — regardless of space — landed in **one** descriptor set, packed at consecutive ids: + +``` +descriptor set for t1: + textures -> [[id(0)]] + cubemaps -> [[id(1)]] + texture_arrays -> [[id(2)]] + volume_textures -> [[id(3)]] +``` + +**Why this was attractive:** SPIRV-Cross hard-limits argument buffers to +`kMaxArgumentBuffers = 8` (`spirv_msl.hpp`, throws *"Descriptor set index is out of range."* past +it). Packing many spaces into one register's set conserves that scarce budget — you could have up +to 8 *registers*, each holding many spaces. + +**The compensation:** with SPIRV-Cross's "unsized array hack", `array[i]` in a packed set lowers to +`arg_buffer[id + i]`. Our heap argument buffer is a flat array based at id 0, so `cubemaps[i]` +(at `id(1)`) actually reads `heap[1 + i]`. To cancel the `+1`, the CPU subtracted the binding's +`sub_offset` from the index it wrote: `index = global_index - sub_offset` (the old +`get_lookup` → `get_sub_binding_offset` path). + +**The fatal flaw:** that compensation only ran for **structured buffers routed through +`get_lookup`**. Texture indices live in *shared material/draw data* and are written as raw global +indices — materials are pipeline-agnostic, so you can't bake a pipeline-specific `sub_offset` into +them. Result: the **second and later texture array in a packed set was off by one**. `cubemaps` +(at `id(1)`) read `heap[ibl_id + 1]` and sampled a neighbouring, unrelated texture as a cube — the +classic "cube samples a flat orange, 2D samples a flat sky-blue" symptom. The first array +(`textures` at `id(0)`) worked by luck because its offset was 0. + +So Approach 1 only ever worked for shaders using a single bindless texture array. + +--- + +## 7. Approach 2 — group by `(kind, register, space)`, one set per binding (current) + +Add **space** to the grouping key. Each `(kind, register, space)` tuple becomes its own descriptor +set, so every bindless array is alone in its set at `[[id(0)]]`: + +``` +buffer(3): textures -> [[id(0)]] +buffer(4): cubemaps -> [[id(0)]] +``` + +Now `textures[i]` and `cubemaps[i]` both lower to `arg_buffer[i]` — no offset, no compensation. +The CPU writes raw global indices and they just work. `sub_offset`, `get_sub_binding_offset`, and +the `get_lookup` subtraction were all removed; with one binding per set they are permanently 0. + +**The cost we accepted:** capacity drops from "8 registers × many spaces" to roughly **8 total +binding groups per stage**, because each binding now consumes a whole descriptor set against +`kMaxArgumentBuffers = 8`. The heaviest current shader (`vs_mesh_material_indirect`) sits at +`buffer(7)` — the last legal slot. To make the ceiling visible instead of cryptic, htwv now emits a +`cargo:warning` when a stage reaches/exceeds the limit (`MAX_DESCRIPTOR_SETS`, kept in sync with +`kMaxArgumentBuffers`; bump it if a future SPIRV-Cross raises the cap). + +The two sides stay in lockstep by keying on `(kind, register, space)` in **both** +`hotline-data/htwv/src/macos_impl.rs` (codegen) and the three `mtl.rs` builders (runtime), iterating +`pipeline_layout.bindings` in the same order. + +--- + +## 8. Side-by-side + +| Concept | D3D12 | Metal (Approach 2) | +|----------------------------|----------------------------------------|-----------------------------------------------------| +| Global pool | Shader-visible descriptor heap | Two `MTLHeap`-backed argument buffers (tex / buf) | +| Index semantics | Heap slot = global index (direct) | `arg_buffer[i]`, base id 0 = global index (direct) | +| HLSL `register`/`space` | Root-sig table range / root param | One MSL descriptor set per `(kind, register, space)`| +| Per-binding offset fix-up | None (`PipelineSlotInfo` has no offset)| None (each binding alone at `[[id(0)]]`) | +| Samplers | Static samplers in root sig | Sampler argument buffer at fragment `buffer(0)` | +| Push constants | Root constants | Discrete set via `setVertex/FragmentBytes` | +| Residency | Implicit (heap is resident when set) | `use_heap` (textures) + `use_resource` (buffers) | +| Hard limit | 1M-entry heaps (effectively unbounded) | `kMaxArgumentBuffers = 8` descriptor sets | + +The design intent: **make Metal's indexing match D3D12's "the index is the index" semantics**, so +shared CPU data (material/draw indices) is correct on both backends with no per-backend fix-up. +Approach 1 broke that for textures; Approach 2 restores it, trading capacity for correctness. + +--- + +## 9. Residency: `use_heap` vs `use_resource` + +Getting the index right only solves *where* the shader looks. On Metal there's a second, separate +problem: the resource the argument buffer points at must be made **GPU-resident**, or the read +returns garbage. Pointing an argument buffer at a resource does *not* make it resident — that's +explicit, and it differs by how the resource was allocated. + +In hotline the two resource classes are allocated differently: + +- **Textures** are allocated *from* the bindless `MTLHeap` (`mtl_heap.new_texture`). One + `encoder.use_heap(&mtl_heap)` in `set_heap` makes the whole heap resident, covering every texture + the bindless argument buffer might index. +- **Structured buffers** (draw/material/light/etc.) are allocated *from the device* + (`device.new_buffer`), **not** from that heap. Two reasons they can't just live in the texture + heap: + 1. **Storage mode.** The texture heap is `Private` (GPU-only, blit-uploaded). The world buffers + are `Shared` + persistently-mapped and rewritten by the CPU every frame. A `Private` heap + can't host CPU-writable buffers, so they'd need a *separate* `Shared` heap. + 2. **Sizing.** `MTLHeap` is fixed-size and can't grow; buffer capacities are dynamic + (`reserve_world_buffers` at runtime, e.g. a 786 KB draw buffer vs a 160 B material buffer). + Sub-allocating dynamically-sized buffers from a fixed heap means over-allocating wildly or + recreating + re-encoding the heap on growth. + +So the buffers are device-allocated and only *referenced* from the heap's buffer argument buffer. +`use_heap` does nothing for them. They must be made resident explicitly with +`encoder.use_resource(buffer, Read|Write)` (mirroring `use_resource_at(..., Vertex|Fragment)` on the +render encoder) for **every** buffer in the pool — because bindless indices are resolved at runtime +in the shader, any buffer could be the one indexed. + +This produced a memorable bug. Without the `use_resource` calls, residency was left to Metal's +implicit heuristics: small/early device allocations happened to stay resident, large ones did not. +Symptoms: + +- One demo (small draw buffer) worked; another with the *same shader* but a large (786 KB) draw + buffer drew nothing — a size-dependent failure, easily mistaken for a CPU-side data difference. +- Hard-coding the world matrix to identity on the CPU **changed nothing** — the decisive clue. If + the data were the problem, identity would draw at the origin. It didn't, because the GPU was + never reading that buffer's memory: it wasn't resident. + +The fix is a few lines in `set_heap`: alongside each `use_heap`/`use_heap_at`, iterate the heap's +`buffer_slots` and `use_resource` each one. D3D12 has no analogue — a shader-visible descriptor heap +is resident for the duration it's set, so residency never surfaces as a separate step. + +--- + +## 10. Lessons / future + +- A compensation that only covers *some* index paths (buffers, not textures) is worse than none — + it hides the bug for the simple case and surfaces it only with a second array. +- The 8-set limit is now the real constraint. Options if a pipeline needs more: raise + `kMaxArgumentBuffers` in a newer SPIRV-Cross; or selectively re-pack **only buffer bindings** + (which *can* be compensated correctly through `get_lookup`, since they don't share CPU data) while + keeping textures one-set-per-binding. +- Keeping codegen (htwv) and runtime (mtl.rs) grouping identical is essential and fragile — any + change to the grouping key must be made in all four places at once. +- Indexing correctness and residency are *separate* problems on Metal. A correct bindless index + still reads garbage if the resource isn't resident — and because failure is residency-heuristic + driven, it looks data-dependent (works small, fails large), which sends you debugging the wrong + layer. "Hard-coding the data changes nothing" is the tell that it's residency, not data. + +### Key files +- `hotline-data/htwv/src/macos_impl.rs` — HLSL→MSL, descriptor-set assignment, limit warning +- `src/gfx/mtl.rs` — `build_slot_lookup`, `build_stage_binders`, `build_compute_binder`, `set_heap` +- `src/gfx/d3d12.rs` — reference root-signature mapping +- `src/pmfx.rs` — `get_lookup` / world-buffer indices +- `shaders/ecs.hlsl` — the bindless array declarations diff --git a/plugins/ecs_examples/src/bindless_material_ibl.rs b/plugins/ecs_examples/src/bindless_material_ibl.rs index 49b8fb0b..a6c91a99 100644 --- a/plugins/ecs_examples/src/bindless_material_ibl.rs +++ b/plugins/ecs_examples/src/bindless_material_ibl.rs @@ -180,7 +180,7 @@ pub fn render_meshes_bindless_ibl( cmd_buf.push_render_constants(pipeline, 0, 0, 4, 16, gfx::as_u8_slice(&camera.view_position)); // bind world buffer info with IBL indices in user_data - let mut world_buffer_info = pmfx.get_world_buffer_info(pipeline); + let mut world_buffer_info = pmfx.get_world_buffer_info(); world_buffer_info.user_data[0] = ibl_data.cubemap_srv; world_buffer_info.user_data[1] = ibl_data.lut_srv; cmd_buf.push_render_constants( diff --git a/plugins/ecs_examples/src/gpu_frustum_culling.rs b/plugins/ecs_examples/src/gpu_frustum_culling.rs index 1fa68776..f4138144 100644 --- a/plugins/ecs_examples/src/gpu_frustum_culling.rs +++ b/plugins/ecs_examples/src/gpu_frustum_culling.rs @@ -364,7 +364,7 @@ pub fn dispatch_compute_frustum_cull( gfx::as_u8_slice(&indirect_draw.arg_buffer.get_srv_index().unwrap())); // world buffer info to lookup matrices and aabb info - let world_buffer_info = pmfx.get_world_buffer_info(pipeline); + let world_buffer_info = pmfx.get_world_buffer_info(); cmd_buf.push_compute_constants( pipeline, 2, 0, gfx::num_32bit_constants(&world_buffer_info), 0, gfx::as_u8_slice(&world_buffer_info)); @@ -405,7 +405,7 @@ pub fn draw_meshes_indirect_culling( cmd_buf.set_render_pipeline(&pipeline); // bind the world buffer info - let world_buffer_info = pmfx.get_world_buffer_info(pipeline); + let world_buffer_info = pmfx.get_world_buffer_info(); cmd_buf.push_render_constants( pipeline, 2, 0, gfx::num_32bit_constants(&world_buffer_info), 0, gfx::as_u8_slice(&world_buffer_info)); diff --git a/plugins/ecs_examples/src/lib.rs b/plugins/ecs_examples/src/lib.rs index ee687b67..3ec5e52a 100644 --- a/plugins/ecs_examples/src/lib.rs +++ b/plugins/ecs_examples/src/lib.rs @@ -261,7 +261,7 @@ pub fn render_meshes_bindless( cmd_buf.push_render_constants(pipeline, 0, 0, 4, 16, gfx::as_u8_slice(&camera.view_position)); // bind the world buffer info - let world_buffer_info = pmfx.get_world_buffer_info(pipeline); + let world_buffer_info = pmfx.get_world_buffer_info(); cmd_buf.push_render_constants(pipeline, 2, 0, gfx::num_32bit_constants(&world_buffer_info), 0, gfx::as_u8_slice(&world_buffer_info)); // bind resource uses diff --git a/plugins/ecs_examples/src/raytracing_pipeline.rs b/plugins/ecs_examples/src/raytracing_pipeline.rs index 41b97fa5..5b00c67e 100644 --- a/plugins/ecs_examples/src/raytracing_pipeline.rs +++ b/plugins/ecs_examples/src/raytracing_pipeline.rs @@ -244,7 +244,7 @@ pub fn render_meshes_raytraced( cmd_buf.push_compute_constants(&raytracing_pipeline.pipeline, 0, 0, 1, 17, gfx::as_u8_slice(&srv0)); // point light info - let world_buffer_info = pmfx.get_world_buffer_info(&raytracing_pipeline.pipeline); + let world_buffer_info = pmfx.get_world_buffer_info(); cmd_buf.push_compute_constants(&raytracing_pipeline.pipeline, 0, 0, 2, 18, gfx::as_u8_slice(&world_buffer_info.point_light)); cmd_buf.set_heap(&raytracing_pipeline.pipeline, &pmfx.shader_heap); diff --git a/shaders/material.hlsl b/shaders/material.hlsl index 85ff2a22..fcb60757 100644 --- a/shaders/material.hlsl +++ b/shaders/material.hlsl @@ -19,6 +19,7 @@ vs_output_material vs_mesh_material(vs_input_mesh input, vs_input_entity_ids ent // get draw call info and transform world matrix draw_data draw = get_draw_data(entity_input.ids[0]); float4 pos = float4(input.position.xyz, 1.0); + pos.xyz = mul(draw.world_matrix, pos); output.position = mul(view_projection_matrix, pos); @@ -156,10 +157,12 @@ ps_output ps_mesh_material(vs_output_material input) { } } + output.colour.a = 1.0; return output; } float4 ps_mesh_material_instanced_ibl(vs_output_material input) : SV_TARGET { + float2 tc = input.texcoord.xy; // albedo @@ -207,8 +210,7 @@ float4 ps_mesh_material_instanced_ibl(vs_output_material input) : SV_TARGET { float2 brdf = textures[lut_idx].Sample(sampler_wrap_linear, float2(saturate(dot(n, v)), roughness)).rg; float3 specular = prefilter * (f * brdf.x + brdf.y); - float4 o = float4(kd * max(diffuse, 0.0) + max(specular, 0.0), 1.0) * 0.0001; - return o + float4(n, 1.0); + return float4(kd * max(diffuse, 0.0) + max(specular, 0.0), 1.0); } ps_output ps_mesh_lit(vs_output input) { diff --git a/src/gfx.rs b/src/gfx.rs index c78e98a5..4a2b4e08 100644 --- a/src/gfx.rs +++ b/src/gfx.rs @@ -688,8 +688,6 @@ pub struct PipelineSlotInfo { pub index: u32, /// The number of descriptors or the number of 32-bit push constant values, if `None` the table is unbounded pub count: Option, - /// Sub-binding offset within the descriptor set (Metal [[id(N)]]); always 0 on D3D12 - pub sub_offset: u32, } /// Input layout describes the layout of vertex buffers bound to the input assembler. @@ -1273,12 +1271,6 @@ pub trait Pipeline { fn get_pipeline_slots(&self) -> &Vec; /// Returns the pipeline type fn get_pipeline_type() -> PipelineType; - /// Returns the sub-binding offset within the descriptor set for the given binding key. - /// On Metal this corresponds to the [[id(N)]] value assigned by spirv-cross. - /// On D3D12 the default impl returns 0 (heap index is used directly). - fn get_sub_binding_offset(&self, _register: u32, _space: u32, _descriptor_type: DescriptorType) -> u32 { - 0 - } } /// A command signature is used to `execute_indirect` commands diff --git a/src/gfx/d3d12.rs b/src/gfx/d3d12.rs index b587e2d7..abe78e2e 100644 --- a/src/gfx/d3d12.rs +++ b/src/gfx/d3d12.rs @@ -1291,7 +1291,6 @@ impl Device { lookup.insert(h, PipelineSlotInfo { index: slot_iter, count: Some(constants.num_values), - sub_offset: 0, }); slot_iter += 1; } @@ -1359,7 +1358,6 @@ impl Device { lookup.entry(h).or_insert(PipelineSlotInfo { index: slot_iter, count: binding.num_descriptors, - sub_offset: 0, }); } slot_iter += 1; diff --git a/src/gfx/mtl.rs b/src/gfx/mtl.rs index 707184ce..cc38de01 100644 --- a/src/gfx/mtl.rs +++ b/src/gfx/mtl.rs @@ -969,6 +969,13 @@ impl super::CmdBuf for CmdBuf { let cp: &ComputePipeline = unsafe { std::mem::transmute(pipeline) }; encoder.use_heap(&heap.mtl_heap); + // Structured buffers are device-allocated (not part of mtl_heap), so use_heap does not + // make them resident - they are reached indirectly through the bindless buffer argument + // buffer, so without this the GPU can read unmapped memory. Textures live in mtl_heap + // and are covered by use_heap above. + for buffer in heap.buffer_slots.iter().flatten() { + encoder.use_resource(buffer, metal::MTLResourceUsage::Read | metal::MTLResourceUsage::Write); + } for (_key, slot) in &cp.compute_binder { if let PipelineStageBinder::Resource(res) = slot { let arg_buffer = match res.data_type { @@ -989,6 +996,18 @@ impl super::CmdBuf for CmdBuf { // Cast pipeline to RenderPipeline to access slot_lookup let rp: &RenderPipeline = unsafe { std::mem::transmute(pipeline) }; + // Structured buffers are device-allocated (not part of mtl_heap), so use_heap_at does not + // make them resident - they are reached indirectly through the bindless buffer argument + // buffer, so without this the GPU can read unmapped memory. Textures live in mtl_heap and + // are covered by use_heap_at below. + for buffer in heap.buffer_slots.iter().flatten() { + encoder.use_resource_at( + buffer, + metal::MTLResourceUsage::Read | metal::MTLResourceUsage::Write, + metal::MTLRenderStages::Vertex | metal::MTLRenderStages::Fragment, + ); + } + // vertex bindings encoder.use_heap_at(&heap.mtl_heap, metal::MTLRenderStages::Vertex); for (key, slot) in &rp.vertex_binder { @@ -1409,13 +1428,6 @@ impl super::Pipeline for RenderPipeline { fn get_pipeline_type() -> PipelineType { super::PipelineType::Render } - - fn get_sub_binding_offset(&self, register: u32, space: u32, descriptor_type: DescriptorType) -> u32 { - self.slot_lookup - .get(&(register, space, descriptor_type)) - .map(|s| s.sub_offset) - .unwrap_or(0) - } } #[derive(Clone)] @@ -1534,13 +1546,6 @@ impl super::Pipeline for ComputePipeline { fn get_pipeline_type() -> PipelineType { super::PipelineType::Compute } - - fn get_sub_binding_offset(&self, register: u32, space: u32, descriptor_type: DescriptorType) -> u32 { - self.slot_lookup - .get(&(register, space, descriptor_type)) - .map(|s| s.sub_offset) - .unwrap_or(0) - } } #[derive(Clone)] @@ -1800,55 +1805,47 @@ impl Device { PipelineSlotInfo { index: canonical_index, count: Some(push_constant.num_values), - sub_offset: 0, }, ); } } - // Add regular binding slots, grouped by (register_kind, shader_register) to mirror the - // descriptor-set layout produced by htwv's MSL codegen. Each (kind, register) becomes its - // own MSL [[buffer(N)]] slot so the heap's texture and buffer argument buffers never share - // a slot. sub_offset matches the [[id(N)]] value spirv-cross assigns within the set; - // callers compensate for the unsized-array-hack offset via get_sub_binding_offset. + // Add regular binding slots, grouped by (register_kind, shader_register, register_space) to + // mirror the descriptor-set layout produced by htwv's MSL codegen. Each (kind, register, + // space) becomes its own MSL [[buffer(N)]] slot so the heap's texture and buffer argument + // buffers never share a slot, and bindless arrays sharing a register but differing by space + // (e.g. textures t1/space7, cubemaps t1/space9) each get their own set at id(0). if let Some(bindings) = pipeline_bindings.as_ref() { if !bindings.is_empty() { - // (register_kind, shader_register) -> (buffer_index, next_sub_offset) - let mut v_groups: HashMap<(char, u32), (u32, u32)> = HashMap::new(); - let mut f_groups: HashMap<(char, u32), (u32, u32)> = HashMap::new(); + // (register_kind, shader_register, register_space) -> buffer_index + let mut v_groups: HashMap<(char, u32, u32), u32> = HashMap::new(); + let mut f_groups: HashMap<(char, u32, u32), u32> = HashMap::new(); for binding in bindings { - let key = (descriptor_register_kind(binding.binding_type), binding.shader_register); + let key = (descriptor_register_kind(binding.binding_type), binding.shader_register, binding.register_space); let v_slot = if matches!(binding.visibility, ShaderVisibility::Vertex | ShaderVisibility::All) { - let entry = v_groups.entry(key).or_insert_with(|| { + Some(*v_groups.entry(key).or_insert_with(|| { let idx = vertex_binding_offset; vertex_binding_offset += 1; - (idx, 0) - }); - let sub = entry.1; - entry.1 += 1; - Some((entry.0, sub)) + idx + })) } else { None }; let f_slot = if matches!(binding.visibility, ShaderVisibility::Fragment | ShaderVisibility::All) { - let entry = f_groups.entry(key).or_insert_with(|| { + Some(*f_groups.entry(key).or_insert_with(|| { let idx = fragment_binding_offset; fragment_binding_offset += 1; - (idx, 0) - }); - let sub = entry.1; - entry.1 += 1; - Some((entry.0, sub)) + idx + })) } else { None }; - let (canonical_index, sub_offset) = v_slot.or(f_slot).unwrap_or((0, 0)); + let canonical_index = v_slot.or(f_slot).unwrap_or(0); slot_lookup.insert( (binding.shader_register, binding.register_space, binding.binding_type), PipelineSlotInfo { index: canonical_index, count: binding.num_descriptors, - sub_offset, } ); } @@ -1931,35 +1928,34 @@ impl Device { } } - // Add resource binders, grouped by (register_kind, shader_register). Each (kind, register) - // pair gets its own [[buffer(N)]] slot per stage so the heap's texture and buffer - // argument buffers are bound to distinct slots. Within a group, binding_index is the - // sub_offset that matches the [[id(N)]] value spirv-cross emits in the MSL set struct. + // Add resource binders, grouped by (register_kind, shader_register, register_space). Each + // (kind, register, space) gets its own [[buffer(N)]] slot per stage so the heap's texture + // and buffer argument buffers are bound to distinct slots, and bindless arrays sharing a + // register but differing by space each get their own set. Each group holds exactly one + // binding, so it always sits at id(0) - binding_index is always 0. if let Some(bindings) = pipeline_bindings.as_ref() { if !bindings.is_empty() { - // (register_kind, shader_register) -> (buffer_index, next_sub_offset) - let mut v_groups: HashMap<(char, u32), (u32, u32)> = HashMap::new(); - let mut f_groups: HashMap<(char, u32), (u32, u32)> = HashMap::new(); + // (register_kind, shader_register, register_space) -> buffer_index + let mut v_groups: HashMap<(char, u32, u32), u32> = HashMap::new(); + let mut f_groups: HashMap<(char, u32, u32), u32> = HashMap::new(); for binding in bindings { let key: SlotKey = (binding.shader_register, binding.register_space, binding.binding_type); - let group_key = (descriptor_register_kind(binding.binding_type), binding.shader_register); + let group_key = (descriptor_register_kind(binding.binding_type), binding.shader_register, binding.register_space); let data_type = to_mtl_data_type( binding.resource_type.expect("hotline_rs::gfx::mtl: requires resource type for binding") ); let array_length = binding.num_descriptors.map(|n| n as u64).unwrap_or(MAX_BINDLESS_TEXTURES); if matches!(binding.visibility, ShaderVisibility::Vertex | ShaderVisibility::All) { - let entry = v_groups.entry(group_key).or_insert_with(|| { + let buffer_index = *v_groups.entry(group_key).or_insert_with(|| { let idx = vertex_binding_offset; vertex_binding_offset += 1; - (idx, 0) + idx }); - let sub = entry.1; - entry.1 += 1; vertex_binder.insert(key, PipelineStageBinder::Resource(ResourceBinder { - buffer_index: entry.0, - binding_index: sub, + buffer_index, + binding_index: 0, data_type, array_length, bound_resource: None, @@ -1968,16 +1964,14 @@ impl Device { } if matches!(binding.visibility, ShaderVisibility::Fragment | ShaderVisibility::All) { - let entry = f_groups.entry(group_key).or_insert_with(|| { + let buffer_index = *f_groups.entry(group_key).or_insert_with(|| { let idx = fragment_binding_offset; fragment_binding_offset += 1; - (idx, 0) + idx }); - let sub = entry.1; - entry.1 += 1; fragment_binder.insert(key, PipelineStageBinder::Resource(ResourceBinder { - buffer_index: entry.0, - binding_index: sub, + buffer_index, + binding_index: 0, data_type, array_length, bound_resource: None, @@ -2028,28 +2022,28 @@ impl Device { } } - // Resource bindings grouped by (register_kind, shader_register) - one [[buffer(N)]] per group + // Resource bindings grouped by (register_kind, shader_register, register_space) - one + // [[buffer(N)]] per group, so arrays sharing a register but differing by space each get + // their own set. Each group holds exactly one binding, so it always sits at id(0). if let Some(bindings) = pipeline_bindings.as_ref() { if !bindings.is_empty() { - let mut groups: HashMap<(char, u32), (u32, u32)> = HashMap::new(); + let mut groups: HashMap<(char, u32, u32), u32> = HashMap::new(); for binding in bindings { let key: SlotKey = (binding.shader_register, binding.register_space, binding.binding_type); - let group_key = (descriptor_register_kind(binding.binding_type), binding.shader_register); + let group_key = (descriptor_register_kind(binding.binding_type), binding.shader_register, binding.register_space); let data_type = to_mtl_data_type( binding.resource_type.expect("hotline_rs::gfx::mtl: requires resource type for binding") ); let array_length = binding.num_descriptors.map(|n| n as u64).unwrap_or(MAX_BINDLESS_TEXTURES); - let entry = groups.entry(group_key).or_insert_with(|| { + let buffer_index = *groups.entry(group_key).or_insert_with(|| { let idx = binding_offset; binding_offset += 1; - (idx, 0) + idx }); - let sub = entry.1; - entry.1 += 1; binder.insert(key, PipelineStageBinder::Resource(ResourceBinder { - buffer_index: entry.0, - binding_index: sub, + buffer_index, + binding_index: 0, data_type, array_length, bound_resource: None, @@ -2401,7 +2395,7 @@ impl super::Device for Device { self.metal_device.new_depth_stencil_state(&ds_desc) }; - // Create static samplers and argument buffer (at buffer(4) per htwv convention) + // Create static samplers and argument buffer (bound at fragment buffer(0)) let mut pipeline_static_samplers = Vec::new(); let mut sampler_argument_buffer = None; @@ -2426,11 +2420,16 @@ impl super::Device for Device { }) } - // Create argument buffer for samplers at buffer(4) + // Create argument buffer for samplers. SPIRV-Cross repacks the samplers actually + // used by a shader into spvDescriptorSetBuffer0 with sequential ids starting at 0 + // (it does NOT preserve the HLSL register, eg. sampler_wrap_linear at s1 becomes + // [[id(0)]]). So encode each sampler at its position in the static_samplers list, + // which matches that packing order. if !pipeline_static_samplers.is_empty() { let arg_desc = metal::ArgumentDescriptor::new(); arg_desc.set_index(0); arg_desc.set_data_type(metal::MTLDataType::Sampler); + arg_desc.set_array_length(pipeline_static_samplers.len() as u64); arg_desc.set_access(metal::MTLArgumentAccess::ReadOnly); let argument_encoder = self.metal_device.new_argument_encoder( @@ -2441,9 +2440,11 @@ impl super::Device for Device { metal::MTLResourceOptions::StorageModeShared ); - // Encode sampler into argument buffer + // Encode each sampler at its packed id (list position) argument_encoder.set_argument_buffer(&arg_buffer, 0); - argument_encoder.set_sampler_state(0, &pipeline_static_samplers[0].sampler); + for (id, s) in pipeline_static_samplers.iter().enumerate() { + argument_encoder.set_sampler_state(id as u64, &s.sampler); + } sampler_argument_buffer = Some(arg_buffer); } diff --git a/src/pmfx.rs b/src/pmfx.rs index 6f82c864..99ae95fb 100644 --- a/src/pmfx.rs +++ b/src/pmfx.rs @@ -445,9 +445,6 @@ pub struct DynamicBuffer { usage: gfx::BufferUsage, bb: usize, num_buffers: usize, - shader_register: u32, - register_space: u32, - binding_type: gfx::DescriptorType, resource_type: std::marker::PhantomData } @@ -461,21 +458,10 @@ impl DynamicBuffer where D: gfx::Device, T: Sized { usage, bb: 0, num_buffers, - shader_register: 0, - register_space: 0, - binding_type: gfx::DescriptorType::ShaderResource, resource_type: std::marker::PhantomData } } - /// Set the shader binding location so `get_lookup` can resolve the Metal sub-binding offset - pub fn with_binding(mut self, register: u32, space: u32, binding_type: gfx::DescriptorType) -> Self { - self.shader_register = register; - self.register_space = space; - self.binding_type = binding_type; - self - } - pub fn get_bb(&self) -> usize { self.bb } /// Swap buffers once a frame for safe CPU writes an GPU in flight reads @@ -574,11 +560,9 @@ impl DynamicBuffer where D: gfx::Device, T: Sized { } } - pub fn get_lookup(&self, pipeline: &P) -> GpuBufferLookup { - let sub_offset = pipeline.get_sub_binding_offset( - self.shader_register, self.register_space, self.binding_type); + pub fn get_lookup(&self) -> GpuBufferLookup { GpuBufferLookup { - index: (self.get_index() as u32).saturating_sub(sub_offset), + index: self.get_index() as u32, count: self.len as u32, } } @@ -609,12 +593,9 @@ impl Default for DynamicWorldBuffers where D: gfx::Device { draw: DynamicBuffer::::new(gfx::BufferUsage::SHADER_RESOURCE, 3), extent: DynamicBuffer::::new(gfx::BufferUsage::SHADER_RESOURCE, 3), material: DynamicBuffer::::new(gfx::BufferUsage::SHADER_RESOURCE, 3), - point_light: DynamicBuffer::::new(gfx::BufferUsage::SHADER_RESOURCE, 3) - .with_binding(0, 3, gfx::DescriptorType::ShaderResource), - spot_light: DynamicBuffer::::new(gfx::BufferUsage::SHADER_RESOURCE, 3) - .with_binding(0, 4, gfx::DescriptorType::ShaderResource), - directional_light: DynamicBuffer::::new(gfx::BufferUsage::SHADER_RESOURCE, 3) - .with_binding(0, 5, gfx::DescriptorType::ShaderResource), + point_light: DynamicBuffer::::new(gfx::BufferUsage::SHADER_RESOURCE, 3), + spot_light: DynamicBuffer::::new(gfx::BufferUsage::SHADER_RESOURCE, 3), + directional_light: DynamicBuffer::::new(gfx::BufferUsage::SHADER_RESOURCE, 3), camera: DynamicBuffer::::new(gfx::BufferUsage::CONSTANT_BUFFER, 3), shadow_matrix: DynamicBuffer::::new(gfx::BufferUsage::SHADER_RESOURCE, 3), } @@ -1067,16 +1048,16 @@ impl Pmfx where D: gfx::Device { /// Retunrs a `WorldBufferInfo` that contains the serv index and count of the various world buffers used /// during rendering - pub fn get_world_buffer_info(&self, pipeline: &P) -> WorldBufferInfo { + pub fn get_world_buffer_info(&self) -> WorldBufferInfo { WorldBufferInfo { - draw: self.world_buffers.draw.get_lookup(pipeline), - extent: self.world_buffers.extent.get_lookup(pipeline), - material: self.world_buffers.material.get_lookup(pipeline), - point_light: self.world_buffers.point_light.get_lookup(pipeline), - spot_light: self.world_buffers.spot_light.get_lookup(pipeline), - directional_light: self.world_buffers.directional_light.get_lookup(pipeline), - camera: self.world_buffers.camera.get_lookup(pipeline), - shadow_matrix: self.world_buffers.shadow_matrix.get_lookup(pipeline), + draw: self.world_buffers.draw.get_lookup(), + extent: self.world_buffers.extent.get_lookup(), + material: self.world_buffers.material.get_lookup(), + point_light: self.world_buffers.point_light.get_lookup(), + spot_light: self.world_buffers.spot_light.get_lookup(), + directional_light: self.world_buffers.directional_light.get_lookup(), + camera: self.world_buffers.camera.get_lookup(), + shadow_matrix: self.world_buffers.shadow_matrix.get_lookup(), user_data: self.push_constant_user_data, } } diff --git a/todo.txt b/todo.txt index 17956c28..17232d0a 100644 --- a/todo.txt +++ b/todo.txt @@ -14,12 +14,12 @@ x MSAA x MRT x mip downsample x gpu timestamp +x pmfx hotreload +x material ibl +x bindless material -- pmfx hotreload -- pmbuild needs universal install into hotline-data -- material ibl -- bindless material +- pmbuild needs universal install into hotline-data - sample cmp shadow - cbuffer instanced causes huge perf issues (should be structured tbh) From d2247517ab97023462edf7040a0a91d0dfc31555 Mon Sep 17 00:00:00 2001 From: polymonster Date: Fri, 22 May 2026 17:54:04 +0200 Subject: [PATCH 55/62] - update hotline data --- hotline-data | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hotline-data b/hotline-data index 38e00eae..c5c8987a 160000 --- a/hotline-data +++ b/hotline-data @@ -1 +1 @@ -Subproject commit 38e00eae20db3aed01cdbc3ca9b892efd154b2e2 +Subproject commit c5c8987a99f23e8f8559f3458c39cb6d9171334a From a147b2949c75df10e9f27c27ab0bd4fcc3451c33 Mon Sep 17 00:00:00 2001 From: polymonster Date: Fri, 22 May 2026 18:31:12 +0200 Subject: [PATCH 56/62] - shadow sampler working --- shaders/shadows.hlsl | 23 +---------------------- todo.txt | 3 +-- 2 files changed, 2 insertions(+), 24 deletions(-) diff --git a/shaders/shadows.hlsl b/shaders/shadows.hlsl index 8459df8d..465c785a 100644 --- a/shaders/shadows.hlsl +++ b/shaders/shadows.hlsl @@ -82,7 +82,6 @@ float sample_shadow_cube_pcf_9(float3 cv, float d, uint sm_index, float sm_size) } shadow /= 9.0; - // shadow = cubemaps[shadow_map_index].SampleCmp(sampler_shadow_compare, cv, d).r; return shadow; } @@ -117,28 +116,8 @@ float4 ps_single_directional_shadow(vs_output input) : SV_Target { //float shadow_sample = textures[shadow_map_index].Sample(sampler_clamp_point, sp.xy).r; //float shadow = sp.z >= shadow_sample ? 0.0 : 1.0; - // pcf sample-compare, inlined here rather than calling sample_shadow_pcf_9: passing the - // bindless texture array + comparison sampler through a function call mis-propagates in the - // shader codegen and the comparison resolves to black (the omni path inlines for the same reason) float2 sm_size = float2(4096.0, 4096.0); - float2 inv_sm_size = 1.0 / sm_size; - float2 pcf_offsets[9]; - pcf_offsets[0] = float2(-1.0, -1.0) * inv_sm_size; - pcf_offsets[1] = float2(-1.0, 0.0) * inv_sm_size; - pcf_offsets[2] = float2(-1.0, 1.0) * inv_sm_size; - pcf_offsets[3] = float2( 0.0, -1.0) * inv_sm_size; - pcf_offsets[4] = float2( 0.0, 0.0) * inv_sm_size; - pcf_offsets[5] = float2( 0.0, 1.0) * inv_sm_size; - pcf_offsets[6] = float2( 1.0, -1.0) * inv_sm_size; - pcf_offsets[7] = float2( 1.0, 0.0) * inv_sm_size; - pcf_offsets[8] = float2( 1.0, 1.0) * inv_sm_size; - - float shadow = 0.0; - [unroll] - for(int s = 0; s < 9; ++s) { - shadow += textures[shadow_map_index].SampleCmp(sampler_shadow_compare, sp.xy + pcf_offsets[s], sp.z); - } - shadow /= 9.0; + float shadow = sample_shadow_pcf_9(sp, shadow_map_index, sm_size); float3 l = light.dir.xyz; float diffuse = lambert(l, n); diff --git a/todo.txt b/todo.txt index 17232d0a..747bbf1b 100644 --- a/todo.txt +++ b/todo.txt @@ -17,11 +17,10 @@ x gpu timestamp x pmfx hotreload x material ibl x bindless material - +x sample cmp shadow - pmbuild needs universal install into hotline-data -- sample cmp shadow - cbuffer instanced causes huge perf issues (should be structured tbh) - draw indirect From 0bc35239911e7ed91e303e425bf2df4682537d73 Mon Sep 17 00:00:00 2001 From: polymonster Date: Sat, 4 Jul 2026 12:45:05 +0100 Subject: [PATCH 57/62] - integration fixes for win32/d3d/hlsl --- config.jsn | 21 +++------------------ shaders/util.hlsl | 4 ---- src/gfx.rs | 4 ++++ src/gfx/mtl.rs | 2 ++ todo.txt | 2 ++ 5 files changed, 11 insertions(+), 22 deletions(-) diff --git a/config.jsn b/config.jsn index 4698d7fc..0bfec5ab 100644 --- a/config.jsn +++ b/config.jsn @@ -3,11 +3,11 @@ tools: { pmfx: "hotline-data/bin/win32/pmfx/pmfx.exe" texturec: "hotline-data/bin/win32/texturec/texturec.exe" - pmfx_dev: "py -3 ../pmfx-shader/pmfx.py" + pmfx_dev: "py -3 hotline-data/pmfx-shader/pmfx.py" } tools: { - pmfx_dev: "python3 ../pmfx-shader/pmfx.py" + pmfx_dev: "python3 hotline-data/pmfx-shader/pmfx.py" texturec: "hotline-data/bin/macos/texturec" } @@ -126,11 +126,10 @@ // windows specific data, will also build (base) win32-data(base): { - pmfx: { + pmfx_dev: { args: [ "-shader_platform hlsl" "-shader_version 6_5" - "-i ${src_shader_dir}/" "-o ${data_dir}/shaders" "-t ${temp_dir}/shaders" @@ -142,20 +141,6 @@ "-Od" ] } - pmfx_dev: { - explicit: true - args: [ - "-shader_platform hlsl" - "-shader_version 6_5" - "-i ${src_shader_dir}/" - "-o ${data_dir}/shaders" - "-t ${temp_dir}/shaders" - "-num_threads 1" - "-f" - "-args" - "-Zpr" - ] - } } mac-data(base): { diff --git a/shaders/util.hlsl b/shaders/util.hlsl index 2b3fdb4d..cc0649f3 100644 --- a/shaders/util.hlsl +++ b/shaders/util.hlsl @@ -2,7 +2,6 @@ // utilties to compile into the core hotline engine // -/* cbuffer mip_info : register(b0) { uint read; uint write; @@ -10,11 +9,9 @@ cbuffer mip_info : register(b0) { RWTexture2D rw_texture[] : register(u0, space0); groupshared uint4 group_accumulated[5]; -*/ [numthreads(32, 32, 1)] void cs_mip_chain_texture2d(uint2 did: SV_DispatchThreadID) { - /* uint2 offsets[9]; offsets[0] = uint2( 0, 0); offsets[1] = uint2(-1, -1); @@ -35,7 +32,6 @@ void cs_mip_chain_texture2d(uint2 did: SV_DispatchThreadID) { } rw_texture[write][did.xy] = level_up / 9.0; - */ } // diff --git a/src/gfx.rs b/src/gfx.rs index 4a2b4e08..3c588dfb 100644 --- a/src/gfx.rs +++ b/src/gfx.rs @@ -596,6 +596,10 @@ pub enum ResourceType { StructuredBuffer, /// Read-write structured buffer (RWStructuredBuffer) RWStructuredBuffer, + /// Append structured buffer (AppendStructuredBuffer) + AppendStructuredBuffer, + /// Consume structured buffer (ConsumeStructuredBuffer) + ConsumeStructuredBuffer, /// Constant buffer (cbuffer/ConstantBuffer) #[serde(alias = "cbuffer")] ConstantBuffer, diff --git a/src/gfx/mtl.rs b/src/gfx/mtl.rs index cc38de01..a8e50518 100644 --- a/src/gfx/mtl.rs +++ b/src/gfx/mtl.rs @@ -304,6 +304,8 @@ fn to_mtl_data_type(resource_type: super::ResourceType) -> metal::MTLDataType { match resource_type { super::ResourceType::StructuredBuffer | super::ResourceType::RWStructuredBuffer | + super::ResourceType::AppendStructuredBuffer | + super::ResourceType::ConsumeStructuredBuffer | super::ResourceType::ConstantBuffer | super::ResourceType::ByteAddressBuffer | super::ResourceType::RWByteAddressBuffer | diff --git a/todo.txt b/todo.txt index 747bbf1b..b41c92df 100644 --- a/todo.txt +++ b/todo.txt @@ -51,6 +51,8 @@ x sample cmp shadow // - lazy init print function // gfx +// - cross platform append/consume buffer (buffer + atomic counter). metal has no +// AppendStructuredBuffer; currently mapped to a plain buffer so counter semantics are lost // - Alpha to coverage // - Stencil Ref / Buffer // - API for fence From dc2fe2cadaba535d4d1074e70d8f8a772e7eb93d Mon Sep 17 00:00:00 2001 From: polymonster Date: Sat, 4 Jul 2026 12:47:51 +0100 Subject: [PATCH 58/62] - cbuffer instancing to structured buffer --- client/main.rs | 17 +++ ...rs => draw_structured_buffer_instanced.rs} | 55 +++++---- plugins/ecs_examples/src/lib.rs | 4 +- shaders/draw_instanced.hlsl | 12 +- shaders/draw_instanced.jsn | 10 +- src/gfx/mtl.rs | 25 +++++ src/os/macos.rs | 104 +++++++++++++++--- tests/tests.rs | 4 +- todo.txt | 6 +- 9 files changed, 178 insertions(+), 59 deletions(-) rename plugins/ecs_examples/src/{draw_cbuffer_instanced.rs => draw_structured_buffer_instanced.rs} (69%) diff --git a/client/main.rs b/client/main.rs index 70642fcc..91ed1370 100644 --- a/client/main.rs +++ b/client/main.rs @@ -1,10 +1,27 @@ use hotline_rs::*; use hotline_rs::prelude::*; +#[cfg(target_os = "macos")] +fn platform_dpi_aware() -> bool { + false +} + +#[cfg(not(target_os = "macos"))] +fn platform_dpi_aware() -> bool { + true +} + fn main() -> Result<(), hotline_rs::Error> { + std::panic::set_hook(Box::new(|info| { + let bt = std::backtrace::Backtrace::force_capture(); + eprintln!("PANIC: {info}\n{bt}"); + std::process::abort(); + })); + // create client let ctx : Client = Client::create(HotlineInfo { + dpi_aware: platform_dpi_aware(), ..Default::default() })?; diff --git a/plugins/ecs_examples/src/draw_cbuffer_instanced.rs b/plugins/ecs_examples/src/draw_structured_buffer_instanced.rs similarity index 69% rename from plugins/ecs_examples/src/draw_cbuffer_instanced.rs rename to plugins/ecs_examples/src/draw_structured_buffer_instanced.rs index ccb98770..66ee7f74 100644 --- a/plugins/ecs_examples/src/draw_cbuffer_instanced.rs +++ b/plugins/ecs_examples/src/draw_structured_buffer_instanced.rs @@ -1,28 +1,28 @@ /// -/// Draw cbuffer Instanced +/// Draw Structured Buffer Instanced /// -use crate::prelude::*; +use crate::prelude::*; -/// Creates a instance batch, where the `InstanceBatch` parent will update a cbuffer containing -/// the cbuffer is created in a separate heap and the matrices and indexed into using the instance id system value semantic +/// Creates an instance batch where the per-instance world matrices live in a `StructuredBuffer` +/// bound as an SRV and indexed by `SV_InstanceID` in the vertex shader. #[no_mangle] -pub fn draw_cbuffer_instanced(client: &mut Client) -> ScheduleInfo { +pub fn draw_structured_buffer_instanced(client: &mut Client) -> ScheduleInfo { client.pmfx.load(&hotline_rs::get_data_path("shaders/ecs_examples").as_str()).unwrap(); ScheduleInfo { setup: systems![ - "setup_draw_cbuffer_instanced" + "setup_draw_structured_buffer_instanced" ], update: systems![ "rotate_meshes", "batch_world_matrix_instances" ], - render_graph: "mesh_draw_cbuffer_instanced" + render_graph: "mesh_draw_structured_buffer_instanced" } } #[export_update_fn] -pub fn setup_draw_cbuffer_instanced( +pub fn setup_draw_structured_buffer_instanced( mut device: bevy_ecs::change_detection::ResMut, mut commands: bevy_ecs::system::Commands) -> Result<(), hotline_rs::Error> { @@ -42,27 +42,29 @@ pub fn setup_draw_cbuffer_instanced( let mut rng = rand::thread_rng(); let size = 2.0; - let num = 32; // max number of bytes in cbuffer is 65536 + let num = 64; let instance_count = (num*num) as u32; let range = size * size * (num as f32); for mesh in meshes { + // Only one descriptor slot is needed: the per-batch instance buffer. instance_count is the + // element count inside that buffer, not the number of heap descriptors. let mut heap = device.create_heap(&gfx::HeapInfo { heap_type: gfx::HeapType::Shader, - num_descriptors: instance_count as usize, + num_descriptors: 1, debug_name: Some("instance_buffer_heap".to_string()) }); let parent = commands.spawn(InstanceBatch { mesh: MeshComponent(mesh.clone()), - pipeline: PipelineComponent("mesh_cbuffer_instanced".to_string()), - instance_buffer: InstanceBuffer { + pipeline: PipelineComponent("mesh_structured_buffer_instanced".to_string()), + instance_buffer: InstanceBuffer { buffer: device.create_buffer_with_heap(&gfx::BufferInfo{ - usage: gfx::BufferUsage::CONSTANT_BUFFER, + usage: gfx::BufferUsage::SHADER_RESOURCE, cpu_access: gfx::CpuAccessFlags::WRITE, format: gfx::Format::Unknown, stride: std::mem::size_of::(), num_elements: instance_count as usize, - initial_state: gfx::ResourceState::VertexConstantBuffer + initial_state: gfx::ResourceState::ShaderResource }, hotline_rs::data![], &mut heap).unwrap(), instance_count, heap: Some(heap) @@ -70,7 +72,7 @@ pub fn setup_draw_cbuffer_instanced( }).id(); for _ in 0..num { for _ in 0..num { - // spawn a bunch of entites with slightly randomised + // spawn a bunch of entites with slightly randomised let pos = vec3f(rng.gen(), rng.gen(), rng.gen()) * splat3f(range) * 2.0 - vec3f(range, 0.0, range); let rot = vec3f(rng.gen(), rng.gen(), rng.gen()) * f32::pi() * 2.0; commands.spawn(Instance { @@ -87,30 +89,35 @@ pub fn setup_draw_cbuffer_instanced( Ok(()) } -/// Renders all scene instance batches with cbuffer instance buffer +/// Renders all scene instance batches, sourcing per-instance world matrices from a StructuredBuffer SRV #[export_render_fn] -pub fn draw_meshes_cbuffer_instanced( +pub fn draw_meshes_structured_buffer_instanced( pmfx: &Res, view: &pmfx::View, cmd_buf: &mut ::CmdBuf, instance_draw_query: Query<(&InstanceBuffer, &MeshComponent, &PipelineComponent)> ) -> Result<(), hotline_rs::Error> { - + let pmfx = &pmfx; let fmt = view.pass.get_format_hash(); let camera = pmfx.get_camera_constants(&view.camera)?; - + for (instance_batch, mesh, pipeline) in &instance_draw_query { // set pipeline per batch let pipeline = pmfx.get_render_pipeline_for_format(&pipeline.0, fmt)?; cmd_buf.set_render_pipeline(pipeline); cmd_buf.push_render_constants(pipeline, 0, 0, 16, 0, gfx::as_u8_slice(&camera.view_projection_matrix)); - // bind the constant buffer (cbv) on the slot for b1, space0 specified in the shader + // set_heap binds the heap's argument buffer and (on metal) calls use_resource_at over + // its buffer_slots so device-allocated buffers like our SRV are made resident on the encoder + let heap = instance_batch.heap.as_ref().unwrap(); + cmd_buf.set_heap(pipeline, heap); + + // bind the structured buffer as an SRV at t0, space0 specified in the shader cmd_buf.set_binding( - pipeline, 1, 0, gfx::DescriptorType::ConstantBuffer, - instance_batch.heap.as_ref().unwrap(), - instance_batch.buffer.get_cbv_index().unwrap() + pipeline, 0, 0, gfx::DescriptorType::ShaderResource, + heap, + instance_batch.buffer.get_srv_index().unwrap() ); // bind vb, ib and draw instanced @@ -120,4 +127,4 @@ pub fn draw_meshes_cbuffer_instanced( } Ok(()) -} \ No newline at end of file +} diff --git a/plugins/ecs_examples/src/lib.rs b/plugins/ecs_examples/src/lib.rs index 3ec5e52a..a468b95a 100644 --- a/plugins/ecs_examples/src/lib.rs +++ b/plugins/ecs_examples/src/lib.rs @@ -6,7 +6,7 @@ mod draw_push_constants; mod draw_indirect; mod geometry_primitives; mod draw_vertex_buffer_instanced; -mod draw_cbuffer_instanced; +mod draw_structured_buffer_instanced; mod bindless_texture; mod tangent_space_normal_maps; mod bindless_material; @@ -644,7 +644,7 @@ pub fn get_demos_ecs_examples() -> Vec { "draw_indirect", "geometry_primitives", "draw_vertex_buffer_instanced", - "draw_cbuffer_instanced", + "draw_structured_buffer_instanced", "bindless_texture", "tangent_space_normal_maps", "bindless_material", diff --git a/shaders/draw_instanced.hlsl b/shaders/draw_instanced.hlsl index c3d7d25f..ef179a36 100644 --- a/shaders/draw_instanced.hlsl +++ b/shaders/draw_instanced.hlsl @@ -29,20 +29,16 @@ vs_output vs_mesh_vertex_buffer_instanced(vs_input_mesh input, vs_input_instance } // -// example using a cbuffer to lookup instance info from SV_InstanceID +// example using a structured buffer to lookup instance info from SV_InstanceID // -struct cbuffer_instance_data { - row_major float3x4 cbuffer_world_matrix[1024]; -}; - -ConstantBuffer cbuffer_instance : register(b1); +StructuredBuffer instance_world_matrices : register(t0); -vs_output vs_mesh_cbuffer_instanced(vs_input_mesh input, uint iid: SV_InstanceID) { +vs_output vs_mesh_structured_buffer_instanced(vs_input_mesh input, uint iid: SV_InstanceID) { vs_output output; float4 pos = float4(input.position.xyz, 1.0); - pos.xyz = mul(cbuffer_instance.cbuffer_world_matrix[iid], pos); + pos.xyz = mul(instance_world_matrices[iid], pos); output.position = mul(view_projection_matrix, pos); output.world_pos = pos; diff --git a/shaders/draw_instanced.jsn b/shaders/draw_instanced.jsn index e583a002..82d36ae9 100644 --- a/shaders/draw_instanced.jsn +++ b/shaders/draw_instanced.jsn @@ -20,8 +20,8 @@ raster_state: cull_back topology: "TriangleList" } - mesh_cbuffer_instanced: { - vs: vs_mesh_cbuffer_instanced + mesh_structured_buffer_instanced: { + vs: vs_mesh_structured_buffer_instanced ps: ps_checkerboard push_constants: [ "view_push_constants" @@ -46,7 +46,7 @@ depends_on: ["debug"] } } - mesh_draw_cbuffer_instanced: { + mesh_draw_structured_buffer_instanced: { debug: { view: "main_view" pipelines: ["imdraw_3d"] @@ -54,8 +54,8 @@ } meshes: { view: "main_view_no_clear" - pipelines: ["mesh_cbuffer_instanced"] - function: "draw_meshes_cbuffer_instanced" + pipelines: ["mesh_structured_buffer_instanced"] + function: "draw_meshes_structured_buffer_instanced" depends_on: ["debug"] } } diff --git a/src/gfx/mtl.rs b/src/gfx/mtl.rs index a8e50518..6180fb9d 100644 --- a/src/gfx/mtl.rs +++ b/src/gfx/mtl.rs @@ -1715,6 +1715,31 @@ impl Device { // textures across command buffers (by default heaps are MTLHazardTrackingModeUntracked) unsafe { let _: () = msg_send![&*heap_descriptor, setHazardTrackingMode: metal::MTLHazardTrackingMode::Tracked]; }; + /* + // newHeapWithDescriptor: returns nil on allocation failure (e.g. requested size + // exceeds what the GPU can back). metal-rs wraps the result without checking, so + // every later deref of a nil heap would trip foreign-types' from_ptr assert with + // no useful context. Probe first via raw msg_send so we can report what was + // actually requested before falling back to metal-rs's wrapper. + let probe_ptr: *mut objc::runtime::Object = unsafe { + msg_send![&*mtl_device, newHeapWithDescriptor: &*heap_descriptor] + }; + assert!( + !probe_ptr.is_null(), + "hotline_rs::gfx::mtl: failed to allocate MTLHeap ({:.1} MB, {} descriptors, storage Private). \ + Requested size = texture_size({} B) * num_descriptors({}) * HEAP_OVERSIZE_FACTOR({}). \ + Reduce num_descriptors in HeapInfo, or use a smaller per-batch heap for buffer-only allocations.", + heap_size as f64 / (1024.0 * 1024.0), + info.num_descriptors, + texture_size, + info.num_descriptors.max(1), + HEAP_OVERSIZE_FACTOR + ); + // probe_ptr is a +1 retained heap; release it and let metal-rs allocate again so + // we keep using its wrapper type without juggling raw pointer ownership. + unsafe { let _: () = msg_send![probe_ptr, release]; } + */ + let heap = mtl_device.new_heap(&heap_descriptor); // Create texture argument encoder for bindless access diff --git a/src/os/macos.rs b/src/os/macos.rs index 310942bc..6fb64f7e 100644 --- a/src/os/macos.rs +++ b/src/os/macos.rs @@ -80,7 +80,12 @@ pub struct App { input_state: Arc>, windows: Arc>>>, monitors: Arc>>, + // Per-window cells, mirrored on `Window`. We cache state that's normally read from winit + // (scale, size, position) because the equivalent winit calls dispatch objc messages + // (`backingScaleFactor`, `frame`) to the wrong receiver on macOS and panic. + window_scales: Arc>>>>, window_sizes: Arc>>>>>, + window_positions: Arc>>>>>, /// When false, windows render at 1x (non-retina) for lower GPU cost (eg. with MSAA) dpi_aware: bool, } @@ -94,7 +99,9 @@ pub struct Window { window_id: winit::window::WindowId, input_state: Arc>, events: Arc>, + cached_scale: Arc>, cached_size: Arc>>, + cached_position: Arc>>, /// Inherited from `AppInfo.dpi_aware`; false = render at 1x (logical pixels) dpi_aware: bool, } @@ -174,15 +181,24 @@ impl App { // Current mouse_pos is computed on-demand in get_mouse_pos() state.mouse_pos_prev = state.mouse_pos; - // Compute current screen position from window + client pos + // Compute current screen position from window + client pos. + // Cached position is physical; mouse_client_pos is already in render-coord units + // (logical when !dpi_aware), so scale position to match. if let Some(window_id) = state.hovered_window_id { - if let Some(window) = self.windows.read().unwrap().get(&window_id) { - if let Ok(pos) = window.outer_position() { - state.mouse_pos = super::Point { - x: pos.x + state.mouse_client_pos.x, - y: pos.y + state.mouse_client_pos.y, - }; - } + if let Some(pos_cell) = self.window_positions.read().unwrap().get(&window_id) { + let pos = *pos_cell.read().unwrap(); + let scale = if self.dpi_aware { + 1.0 + } else { + self.window_scales.read().unwrap() + .get(&window_id) + .map(|s| (*s.read().unwrap()).max(1.0)) + .unwrap_or(1.0) + }; + state.mouse_pos = super::Point { + x: (pos.x as f64 / scale).round() as i32 + state.mouse_client_pos.x, + y: (pos.y as f64 / scale).round() as i32 + state.mouse_client_pos.y, + }; } } @@ -196,7 +212,10 @@ struct FrameHandler<'a> { resume: &'a mut bool, input_state: Arc>, monitors: Arc>>, + window_scales: Arc>>>>, window_sizes: Arc>>>>>, + window_positions: Arc>>>>>, + dpi_aware: bool, } impl winit::application::ApplicationHandler for FrameHandler<'_> { @@ -215,12 +234,24 @@ impl winit::application::ApplicationHandler for FrameHandler<'_> { } fn window_event(&mut self, _elwt: &ActiveEventLoop, window_id: winit::window::WindowId, event: WindowEvent) { + if let WindowEvent::ScaleFactorChanged { scale_factor, .. } = event { + if let Some(scale) = self.window_scales.read().unwrap().get(&window_id) { + *scale.write().unwrap() = scale_factor; + } + return; + } if let WindowEvent::Resized(new_size) = event { if let Some(size) = self.window_sizes.read().unwrap().get(&window_id) { *size.write().unwrap() = new_size; } return; } + if let WindowEvent::Moved(new_pos) = event { + if let Some(pos) = self.window_positions.read().unwrap().get(&window_id) { + *pos.write().unwrap() = new_pos; + } + return; + } let mut state = self.input_state.write().unwrap(); match event { @@ -229,9 +260,19 @@ impl winit::application::ApplicationHandler for FrameHandler<'_> { } WindowEvent::RedrawRequested => {} WindowEvent::CursorMoved { position, .. } => { + // winit reports physical pixels; convert to logical (1x) when !dpi_aware + // so coords match the render size returned to clients. + let scale = if self.dpi_aware { + 1.0 + } else { + self.window_scales.read().unwrap() + .get(&window_id) + .map(|s| (*s.read().unwrap()).max(1.0)) + .unwrap_or(1.0) + }; state.mouse_client_pos = super::Point { - x: position.x as i32, - y: position.y as i32, + x: (position.x / scale).round() as i32, + y: (position.y / scale).round() as i32, }; state.hovered_window_id = Some(window_id); } @@ -307,7 +348,9 @@ impl super::App for App { input_state: Arc::new(RwLock::new(InputState::new())), windows: Arc::new(RwLock::new(HashMap::new())), monitors: Arc::new(RwLock::new(Vec::new())), + window_scales: Arc::new(RwLock::new(HashMap::new())), window_sizes: Arc::new(RwLock::new(HashMap::new())), + window_positions: Arc::new(RwLock::new(HashMap::new())), dpi_aware: info.dpi_aware, } } @@ -329,16 +372,39 @@ impl super::App for App { // Register window for position lookups self.windows.write().unwrap().insert(window_id, winit_window.clone()); - let initial_size = winit_window.inner_size(); - let cached_size = Arc::new(RwLock::new(initial_size)); + // Seed scale from the primary monitor; updated by ScaleFactorChanged events. + // Avoid calling winit_window.scale_factor() here — on macOS it can dispatch + // backingScaleFactor to the application delegate and panic. + let initial_scale = self.monitors.read().unwrap() + .iter() + .find(|m| m.primary) + .map(|m| m.dpi_scale as f64) + .unwrap_or(1.0); + let cached_scale = Arc::new(RwLock::new(initial_scale)); + self.window_scales.write().unwrap().insert(window_id, cached_scale.clone()); + + // Seed size/position from creation info; updated by Resized / Moved events. + // Avoid winit_window.inner_size()/outer_position() — both dispatch `frame` + // through paths that can panic on macOS for the same objc-receiver reason. + let cached_size = Arc::new(RwLock::new(PhysicalSize::new( + info.rect.width.max(0) as u32, + info.rect.height.max(0) as u32, + ))); self.window_sizes.write().unwrap().insert(window_id, cached_size.clone()); + let cached_position = Arc::new(RwLock::new(PhysicalPosition::new( + info.rect.x, info.rect.y, + ))); + self.window_positions.write().unwrap().insert(window_id, cached_position.clone()); + Window { winit_window, window_id, input_state: self.input_state.clone(), events: Arc::new(RwLock::new(super::WindowEventFlags::NONE)), + cached_scale, cached_size, + cached_position, dpi_aware: self.dpi_aware, } } @@ -358,7 +424,10 @@ impl super::App for App { resume: &mut resume, input_state: self.input_state.clone(), monitors: self.monitors.clone(), + window_scales: self.window_scales.clone(), window_sizes: self.window_sizes.clone(), + window_positions: self.window_positions.clone(), + dpi_aware: self.dpi_aware, }; let _ = self.event_loop.write().and_then(|mut event_loop| { @@ -479,7 +548,10 @@ impl super::App for App { resume: &mut dummy_resume, input_state: self.input_state.clone(), monitors: self.monitors.clone(), + window_scales: self.window_scales.clone(), window_sizes: self.window_sizes.clone(), + window_positions: self.window_positions.clone(), + dpi_aware: self.dpi_aware, }; let _ = self.event_loop.write().and_then(|mut event_loop| { use winit::platform::pump_events::EventLoopExtPumpEvents; @@ -525,7 +597,7 @@ impl Window { if self.dpi_aware { super::Size { x: size.width as i32, y: size.height as i32 } } else { - let scale = self.winit_window.scale_factor().max(1.0); + let scale = (*self.cached_scale.read().unwrap()).max(1.0); super::Size { x: ((size.width as f64 / scale).round() as i32).max(1), y: ((size.height as f64 / scale).round() as i32).max(1), @@ -610,7 +682,7 @@ impl super::Window for Window { /// Returns the screen position for the top-left corner of the window fn get_pos(&self) -> super::Point { - let pos = self.winit_window.outer_position().unwrap_or_default(); + let pos = *self.cached_position.read().unwrap(); super::Point { x: pos.x, y: pos.y @@ -635,7 +707,7 @@ impl super::Window for Window { /// Returns the screen rect of the window screen pos x, y , size x, y. fn get_window_rect(&self) -> super::Rect { - let pos = self.winit_window.outer_position().unwrap_or_default(); + let pos = *self.cached_position.read().unwrap(); let size = *self.cached_size.read().unwrap(); super::Rect { x: pos.x, @@ -655,7 +727,7 @@ impl super::Window for Window { /// Return the dpi scale for the current monitor the window is on. When the app is not /// dpi-aware the engine operates entirely in logical (1x) pixels, so the effective scale is 1. fn get_dpi_scale(&self) -> f32 { - if self.dpi_aware { self.winit_window.scale_factor() as f32 } else { 1.0 } + if self.dpi_aware { *self.cached_scale.read().unwrap() as f32 } else { 1.0 } } /// Gets the internal native handle diff --git a/tests/tests.rs b/tests/tests.rs index 305f1ea9..7cf1a5dc 100644 --- a/tests/tests.rs +++ b/tests/tests.rs @@ -677,8 +677,8 @@ fn draw_vertex_buffer_instanced() -> Result<(), hotline_rs::Error> { } #[test] -fn draw_cbuffer_instanced() -> Result<(), hotline_rs::Error> { - boot_client_ecs_plugin_demo("draw_cbuffer_instanced") +fn draw_structured_buffer_instanced() -> Result<(), hotline_rs::Error> { + boot_client_ecs_plugin_demo("draw_structured_buffer_instanced") } #[test] diff --git a/todo.txt b/todo.txt index b41c92df..dc01d74f 100644 --- a/todo.txt +++ b/todo.txt @@ -18,10 +18,12 @@ x pmfx hotreload x material ibl x bindless material x sample cmp shadow +x cbuffer instanced causes huge perf issues (should be structured tbh) -- pmbuild needs universal install into hotline-data +- cleanup mem -- cbuffer instanced causes huge perf issues (should be structured tbh) +- pmbuild needs universal install into hotline-data +- single shader compile, htwv - draw indirect - video player From c8cdebd138feb86ac1abab2982685ff84685ca58 Mon Sep 17 00:00:00 2001 From: polymonster Date: Sat, 4 Jul 2026 14:05:16 +0100 Subject: [PATCH 59/62] - conditional spirv case to omit groupshared in the mip generation shader --- hotline-data | 2 +- shaders/util.hlsl | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/hotline-data b/hotline-data index c5c8987a..c7fbc464 160000 --- a/hotline-data +++ b/hotline-data @@ -1 +1 @@ -Subproject commit c5c8987a99f23e8f8559f3458c39cb6d9171334a +Subproject commit c7fbc46421ae3e011af58d6a62b9c12d95bbb015 diff --git a/shaders/util.hlsl b/shaders/util.hlsl index cc0649f3..6c30fde5 100644 --- a/shaders/util.hlsl +++ b/shaders/util.hlsl @@ -23,7 +23,11 @@ void cs_mip_chain_texture2d(uint2 did: SV_DispatchThreadID) { offsets[7] = uint2( 1, -1); offsets[8] = uint2( 0, -1); +#ifndef __spirv__ + // DXC's SPIR-V backend can't cast a groupshared (address-space 3) lvalue to void, + // which is what pmfx_touch expands to. Skip it on the spirv/metal path for now. pmfx_touch(group_accumulated[0]); +#endif float4 level_up = float4(0.0, 0.0, 0.0, 0.0); From 357f06214e1e6ad17b6d2565dcd9bdc36da87825 Mon Sep 17 00:00:00 2001 From: polymonster Date: Sun, 5 Jul 2026 11:35:44 +0100 Subject: [PATCH 60/62] - change location of pmfx --- config.jsn | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config.jsn b/config.jsn index 0bfec5ab..e94bc24e 100644 --- a/config.jsn +++ b/config.jsn @@ -1,7 +1,7 @@ { // configure build tools tools: { - pmfx: "hotline-data/bin/win32/pmfx/pmfx.exe" + pmfx: "py -3 hotline-data/pmfx-shader/pmfx.py" texturec: "hotline-data/bin/win32/texturec/texturec.exe" pmfx_dev: "py -3 hotline-data/pmfx-shader/pmfx.py" } From e765d418cfa0b9bbcafd6f65cb4a7a747114c275 Mon Sep 17 00:00:00 2001 From: polymonster Date: Sun, 5 Jul 2026 11:52:22 +0100 Subject: [PATCH 61/62] - update hotline-data --- hotline-data | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hotline-data b/hotline-data index c7fbc464..44e76c60 160000 --- a/hotline-data +++ b/hotline-data @@ -1 +1 @@ -Subproject commit c7fbc46421ae3e011af58d6a62b9c12d95bbb015 +Subproject commit 44e76c6066234a06824cb94d3ab46b2d741ba20e From 1ba4fa7cb5c098e0b2ea2a826d86bfad6092ede9 Mon Sep 17 00:00:00 2001 From: polymonster Date: Sun, 5 Jul 2026 12:07:45 +0100 Subject: [PATCH 62/62] - fix pmfx test since macos changes for metal --- tests/tests.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/tests.rs b/tests/tests.rs index 7cf1a5dc..d3659870 100644 --- a/tests/tests.rs +++ b/tests/tests.rs @@ -415,8 +415,8 @@ fn pmfx() -> Result<(), hotline_rs::Error> { let texture_pipeline = ctx.pmfx.get_render_pipeline_for_format("texture2d_array", fmt)?; // texture array pipeline has 2 sets of push constants, so the resources bind onto 2 - // t0, space9 is Texture2DArray - let slots = texture_pipeline.get_pipeline_slot(0, 10, gfx::DescriptorType::ShaderResource); + // t1, space10 is Texture2DArray + let slots = texture_pipeline.get_pipeline_slot(1, 10, gfx::DescriptorType::ShaderResource); assert!(slots.is_some()); if let Some(slots) = slots {