use glslang::SpirvVersion::{SPIRV1_0, SPIRV1_1, SPIRV1_6};
use glslang::{
CompilerOptions, OpenGlVersion, ShaderInput, ShaderSource, ShaderStage, Target, VulkanVersion,
};
use spirv_cross2::reflect::TypeInner;
use spirv_cross2::SpirvCrossError;
use spirv_cross2::{Compiler, Module};
#[test]
pub fn spec_constant() -> Result<(), SpirvCrossError> {
const SHADER: &str = r##"#version 450
layout (local_size_x_id = 0, local_size_y = 1, local_size_z = 1) in;
layout(set = 0, binding = 0) uniform Config{
mat4 transform;
int matrixCount;
} opData;
layout(set = 0, binding = 1) readonly buffer InputBuffer{
mat4 matrices[];
} sourceData;
layout(set = 0, binding = 2) buffer OutputBuffer{
mat4 matrices[];
} outputData;
void main()
{
//grab global ID
uint gID = gl_GlobalInvocationID.x;
//make sure we don't access past the buffer size
if(gID < opData.matrixCount)
{
// do math
outputData.matrices[gID] = sourceData.matrices[gID] * opData.transform;
}
}
"##;
let glslang = glslang::Compiler::acquire().unwrap();
let src = ShaderSource::from(SHADER);
let mut opts = CompilerOptions::default();
opts.target = Target::Vulkan {
version: VulkanVersion::Vulkan1_3,
spirv_version: SPIRV1_6,
};
let shader = ShaderInput::new(&src, ShaderStage::Compute, &opts, None, None).unwrap();
let spv = glslang.create_shader(shader).unwrap().compile().unwrap();
let mut compiler = Compiler::<spirv_cross2::targets::None>::new(Module::from_words(&spv))?;
let spec_workgroup = compiler.work_group_size_specialization_constants();
eprintln!("{:?}", spec_workgroup);
let Some(args) = compiler.execution_mode_arguments(spirv::ExecutionMode::LocalSize)? else {
panic!("unexpected")
};
let id = spec_workgroup.x.unwrap().id;
compiler.set_specialization_constant_value(id, 4u32)?;
let id = compiler.specialization_constant_value::<u32>(id)?;
eprintln!("{:?}", args);
eprintln!("{:?}", id);
Ok(())
}
#[test]
pub fn workgroup_size() -> Result<(), SpirvCrossError> {
const SHADER: &str = r##"#version 450
layout (local_size_x_id = 0, local_size_y = 1, local_size_z = 1) in;
layout(set = 0, binding = 0) uniform Config{
mat4 transform;
int matrixCount;
} opData;
layout(set = 0, binding = 1) readonly buffer InputBuffer{
mat4 matrices[];
} sourceData;
layout(set = 0, binding = 2) buffer OutputBuffer{
mat4 matrices[];
} outputData;
void main()
{
//grab global ID
uint gID = gl_GlobalInvocationID.x;
//make sure we don't access past the buffer size
if(gID < opData.matrixCount)
{
// do math
outputData.matrices[gID] = sourceData.matrices[gID] * opData.transform;
}
}
"##;
let glslang = glslang::Compiler::acquire().unwrap();
let src = ShaderSource::from(SHADER);
let mut opts = CompilerOptions::default();
opts.target = Target::Vulkan {
version: VulkanVersion::Vulkan1_3,
spirv_version: SPIRV1_6,
};
let shader = ShaderInput::new(&src, ShaderStage::Compute, &opts, None, None).unwrap();
let spv = glslang.create_shader(shader).unwrap().compile().unwrap();
let compiler = Compiler::<spirv_cross2::targets::None>::new(Module::from_words(&spv))?;
let spec_workgroup = compiler.work_group_size_specialization_constants();
eprintln!("{:?}", spec_workgroup);
let Some(args) = compiler.execution_mode_arguments(spirv::ExecutionMode::LocalSize)? else {
panic!("unexpected")
};
let id = spec_workgroup.x.unwrap().id;
let id = compiler.specialization_constant_scalar::<u32>(id, 0, 0)?;
eprintln!("{:?}", args);
eprintln!("{:?}", id);
Ok(())
}
#[test]
pub fn sandbox() -> Result<(), SpirvCrossError> {
const SHADER: &str = r##"#version 450
layout(binding = 0) uniform UBO
{
float value;
};
layout(location = 0) out vec4 color;
layout(binding = 1) uniform sampler2D tex;
void main() {
color = texture(tex, vec2(value));
}"##;
let glslang = glslang::Compiler::acquire().unwrap();
let src = ShaderSource::from(SHADER);
let mut opts = CompilerOptions::default();
opts.target = Target::Vulkan {
version: VulkanVersion::Vulkan1_0,
spirv_version: SPIRV1_0,
};
let shader = ShaderInput::new(&src, ShaderStage::Vertex, &opts, None, None).unwrap();
let spv = glslang.create_shader(shader).unwrap().compile().unwrap();
let compiler = Compiler::<spirv_cross2::targets::None>::new(Module::from_words(&spv))?;
let res = compiler.shader_resources()?.all_resources()?;
let counter = &res.uniform_buffers[0];
let ranges = compiler.active_buffer_ranges(counter.id)?;
eprintln!("{:?}", ranges);
Ok(())
}
#[test]
pub fn runtime_size_array() -> Result<(), SpirvCrossError> {
const SHADER: &str = r##"#version 450
layout(std430, binding = 0) buffer SSBO
{
float data[];
};
layout(location = 0) out vec4 color;
layout(binding = 1) uniform sampler2D tex;
void main() {
color = texture(tex, vec2(0.0));
}"##;
let glslang = glslang::Compiler::acquire().unwrap();
let src = ShaderSource::from(SHADER);
let mut opts = CompilerOptions::default();
opts.target = Target::Vulkan {
version: VulkanVersion::Vulkan1_0,
spirv_version: SPIRV1_0,
};
let shader = ShaderInput::new(&src, ShaderStage::Vertex, &opts, None, None).unwrap();
let spv = glslang.create_shader(shader).unwrap().compile().unwrap();
let compiler = Compiler::<spirv_cross2::targets::None>::new(Module::from_words(&spv))?;
let res = compiler.shader_resources()?.all_resources()?;
eprintln!("{:?}", res.builtin_inputs);
let counter = &res.storage_buffers[0];
let TypeInner::Struct(struct_ty) = compiler.type_description(counter.base_type_id)?.inner
else {
panic!("unknown type")
};
eprintln!("{:?}", struct_ty);
Ok(())
}
#[test]
pub fn image_type_sandbox() -> Result<(), SpirvCrossError> {
const SHADER: &str = r##"#version 450
layout (constant_id = 0) const int SSAO_KERNEL_SIZE = 13;
layout(set = 0, binding = 0, std140) uniform UBO
{
float data[SSAO_KERNEL_SIZE];
mat4 matrix;
vec2 vec;
};
layout(location = 0) out vec4[SSAO_KERNEL_SIZE] color;
layout(binding = 1) uniform sampler2D tex;
layout(binding = 1, rgba32f) writeonly uniform image3D threeD;
layout(binding = 2) uniform texture2DMSArray texArrayMs[4];
layout(binding = 3, rgba32f) uniform readonly imageBuffer arrayBuf;
layout(binding = 3) uniform samplerBuffer arrayBufA;
layout(binding = 3, rgba32f) uniform readonly imageBuffer arrayBufAS;
layout(binding = 3) uniform samplerCubeArrayShadow depth;
void main() {
color[0] = texture(tex, vec2(0.0));
}"##;
let glslang = glslang::Compiler::acquire().unwrap();
let src = ShaderSource::from(SHADER);
let mut opts = CompilerOptions::default();
opts.target = Target::Vulkan {
version: VulkanVersion::Vulkan1_0,
spirv_version: SPIRV1_0,
};
let shader = ShaderInput::new(&src, ShaderStage::Vertex, &opts, None, None).unwrap();
let spv = glslang.create_shader(shader).unwrap().compile().unwrap();
let compiler = Compiler::<spirv_cross2::targets::None>::new(Module::from_words(&spv))?;
let res = compiler.shader_resources()?.all_resources()?;
let counter = &res.uniform_buffers[0];
let TypeInner::Struct(stru) = compiler.type_description(counter.base_type_id)?.inner else {
panic!("unexpected")
};
eprintln!("{:#?}", stru);
let arrdesc = compiler.type_description(stru.members[1].id)?;
eprintln!("{:?}", arrdesc);
Ok(())
}
#[test]
pub fn const_id_array_dim() -> Result<(), SpirvCrossError> {
const SHADER: &str = r##"#version 450
layout (constant_id = 0) const int SSAO_KERNEL_SIZE = 2;
layout(location = 0) out vec4[SSAO_KERNEL_SIZE][4] color;
layout(binding = 1) uniform sampler2D tex;
void main() {
color[0][0] = texture(tex, vec2(0.0));
}"##;
let glslang = glslang::Compiler::acquire().unwrap();
let src = ShaderSource::from(SHADER);
let mut opts = CompilerOptions::default();
opts.target = Target::Vulkan {
version: VulkanVersion::Vulkan1_0,
spirv_version: SPIRV1_0,
};
let shader = ShaderInput::new(&src, ShaderStage::Vertex, &opts, None, None).unwrap();
let spv = glslang.create_shader(shader).unwrap().compile().unwrap();
let compiler = Compiler::<spirv_cross2::targets::None>::new(Module::from_words(&spv))?;
let res = compiler.shader_resources()?.all_resources()?;
let counter = &res.stage_outputs[0];
eprintln!("{:?}", compiler.type_description(counter.type_id));
Ok(())
}
#[test]
pub fn atomic_counters() -> Result<(), SpirvCrossError> {
const SHADER: &str = r##"#version 450
layout(binding = 0) uniform atomic_uint one;
layout(location = 0) out vec4 color;
layout(binding = 1) uniform sampler2D tex;
void main() {
color = texture(tex, vec2(0.0));
}"##;
let glslang = glslang::Compiler::acquire().unwrap();
let src = ShaderSource::from(SHADER);
let mut opts = CompilerOptions::default();
opts.target = Target::OpenGL {
version: OpenGlVersion::OpenGL4_5,
spirv_version: Some(SPIRV1_1),
};
let shader = ShaderInput::new(&src, ShaderStage::Vertex, &opts, None, None).unwrap();
let spv = glslang.create_shader(shader).unwrap().compile().unwrap();
let compiler = Compiler::<spirv_cross2::targets::None>::new(Module::from_words(&spv))?;
let res = compiler.shader_resources()?.all_resources()?;
let counter = &res.atomic_counters[0];
eprintln!("{:?}", compiler.type_description(counter.base_type_id));
Ok(())
}