extern crate shaderc;
use std::env;
use std::io::{Read,Write};
use std::fs::File;
use std::path::{Path,PathBuf};
use std::process::Command;
extern crate vulkan_rs_generator;
#[cfg(all(feature = "VK_USE_PLATFORM_DEFAULT", target_os = "windows"))]
fn enable_default_platform() {
println!("cargo:rustc-cfg=feature=\"VK_USE_PLATFORM_WIN32_KHR\"");
}
#[cfg(all(feature = "VK_USE_PLATFORM_DEFAULT", target_os = "linux"))]
fn enable_default_platform() {
println!("cargo:rustc-cfg=feature=\"VK_USE_PLATFORM_XLIB_KHR\"");
println!("cargo:rustc-cfg=feature=\"VK_USE_PLATFORM_XLIB_XRANDR_EXT\"");
println!("cargo:rustc-cfg=feature=\"VK_USE_PLATFORM_XCB_KHR\"");
println!("cargo:rustc-cfg=feature=\"VK_USE_PLATFORM_WAYLAND_KHR\"");
println!("cargo:rustc-cfg=feature=\"VK_USE_PLATFORM_MIR_KHR\"");
}
#[cfg(all(feature = "VK_USE_PLATFORM_DEFAULT", target_os = "android"))]
fn enable_default_platform() {
println!("cargo:rustc-cfg=feature=\"VK_USE_PLATFORM_ANDROID_KHR\"");
}
#[cfg(all(feature = "VK_USE_PLATFORM_DEFAULT", target_os = "ios"))]
fn enable_default_platform() {
println!("cargo:rustc-cfg=feature=\"VK_USE_PLATFORM_IOS_MVK\"");
}
#[cfg(all(feature = "VK_USE_PLATFORM_DEFAULT", target_os = "macos"))]
fn enable_default_platform() {
println!("cargo:rustc-cfg=feature=\"VK_USE_PLATFORM_MACOS_MVK\"");
}
#[cfg(not(feature = "VK_USE_PLATFORM_DEFAULT"))]
fn enable_default_platform() {}
fn generate_vulkan_bindings() {
use vulkan_rs_generator::registry;
use vulkan_rs_generator::generator::rust as rustgen;
let vkdoc_path = Path::new("vulkan_spec").join("Vulkan-Docs");
let registry_path = vkdoc_path.join("src/spec/vk.xml");
let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap());
if !registry_path.exists() {
let status = Command::new("git")
.arg("submodule")
.arg("update")
.arg("--init")
.arg(vkdoc_path)
.status()
.expect("git submodule update");
if !status.success() {
panic!("`git submodule update init [...]` exited with status code {}", status)
}
}
println!("cargo:rerun-if-changed={}", registry_path.to_str().unwrap());
let registry_file = File::open(registry_path).expect("opening reg");
let registry = registry::RegistryData::read(registry_file).expect("reading reg");
let registry = registry::Registry::new(®istry);
println!("registry: num-types: {}", registry.types.len());
println!("registry: num-enums: {}", registry.enum_groups.len());
println!("registry: num-cmds: {}", registry.commands.len());
println!("registry: num-enum_extensions: {}", registry.enum_extensions.len());
let selection = {
let mut s = registry::Selection::new(®istry);
s.ignore_feature(registry::SelectionNameRef::Type("VK_NULL_HANDLE"));
for f in ®istry.features {
s.select_feature_set(f).expect("selecting feature");
}
for e in ®istry.extensions {
s.select_feature_set(e).expect("selecting extension");
}
s
};
println!("selection: num-selections: {}", selection.selected_set.len());
println!("selection: num-features: {}", selection.features.len());
let style = rustgen::RustCodeStyle {
style: rustgen::CodeStyle {
snake_case_commands: false,
snake_case_fields: false,
},
out_dir: true,
};
{
let mut out_file = File::create(out_dir.join("types.rs")).expect("create types.rs");
let mut gen = rustgen::types::TypesGenerator{ style };
selection.generate(&mut gen, &mut out_file).expect("generate types");
}
{
let mut out_file = File::create(out_dir.join("prelude.rs")).expect("create prelude.rs");
let mut gen = rustgen::alias::AliasGenerator{
strip_api_prefix: false,
use_feature_modules: true,
snake_case_commands: false,
};
selection.generate(&mut gen, &mut out_file).expect("generate prelude");
}
{
let tables = rustgen::cmds::DispatchTablePreprocessor::new(&selection).expect("preprocess table");
let mut out_file = File::create(out_dir.join("cmds_table.rs")).expect("create cmds_table.rs");
tables.generate(&mut rustgen::cmds::DispatchTableWriter::new(), &mut out_file).expect("generate dispatch table");
tables.generate(&mut rustgen::cmds::DispatchTableImplWriter::new(), &mut out_file).expect("generate dispatch table impl");
}
{
let mut out_file = File::create(out_dir.join("cmds_dispatch.rs")).expect("create cmds_dispatch.rs");
let mut gen = rustgen::cmds::DispatchCommandImplWriter{ style };
selection.generate(&mut gen, &mut out_file).expect("generate dispatch cmd impl");
}
{
let mut out_file = File::create(out_dir.join("cmds_safe.rs")).expect("create cmds_safe.rs");
let mut gen = rustgen::cmds::SafeCommandImplWriter{ style };
selection.generate(&mut gen, &mut out_file).expect("generate safe cmd impl");
}
}
const NUM_SHADER_TYPES : usize = 6;
const SHADER_EXTS : [&'static str;NUM_SHADER_TYPES] = ["comp", "frag", "geom", "tesc", "tese", "vert"]; const SHADER_TYPES: [shaderc::ShaderKind;NUM_SHADER_TYPES] = {
use shaderc::ShaderKind::*;
[DefaultCompute, DefaultFragment, DefaultGeometry, DefaultTessControl, DefaultTessEvaluation, DefaultVertex]
};
fn compile_sharers() {
let mut compiler = shaderc::Compiler::new().unwrap();
let out_dir = env::var("OUT_DIR").unwrap();
let out_dir = Path::new(&out_dir);
let shader_path = Path::new("examples");
for src_path in shader_path.read_dir()
.unwrap()
.map(|p| p.unwrap().path())
.filter(|p| p.is_file()) {
let file_ext = src_path.extension().unwrap();
let shader_type = match SHADER_EXTS.binary_search(&file_ext.to_str().unwrap()) {
Err(_) => { continue; },
Ok(i) => SHADER_TYPES[i],
};
println!("cargo:rerun-if-changed={}", src_path.to_str().unwrap());
let rel_path = src_path.strip_prefix(&shader_path).unwrap();
let out_path = out_dir.join(rel_path).with_extension(format!("{}.spv", file_ext.to_str().unwrap()));
::std::fs::create_dir_all(out_path.parent().unwrap()).unwrap();
let mut source = String::new();
{
File::open(&src_path).expect("open source")
.read_to_string(&mut source).expect("reading source");
}
let binary = compiler.compile_into_spirv(
&source,
shader_type,
src_path.to_str().unwrap(),
"main",
None
).expect("compile");
{
let bytes = unsafe { ::std::slice::from_raw_parts(binary.as_binary().as_ptr() as *const u8, binary.len()) };
File::create(&out_path).expect("create file")
.write(bytes).expect("write file");
}
}
}
fn main() {
println!("cargo:rerun-if-changed=build.rs");
enable_default_platform();
generate_vulkan_bindings();
compile_sharers();
}