diff --git a/.gitignore b/.gitignore index b39df26..c3f6918 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,4 @@ /target **/*.rs.bk Cargo.lock -.cargo/config \ No newline at end of file +.cargo/config diff --git a/.gitmodules b/.gitmodules index debdb18..4c9dda3 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,3 @@ -[submodule "glslang"] - path = glslang +[submodule "glslang_actual_builder/glslang"] + path = glslang_actual_builder/glslang url = https://github.com/KhronosGroup/glslang.git diff --git a/Cargo.toml b/Cargo.toml index a94a44d..c0780e9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,10 +1,38 @@ [package] name = "bevy-glsl-to-spirv" -version = "0.2.0" -authors = ["Pierre Krieger ", "The vulkano contributors", "Carter Anderson ", "Nicholas Rishel "] +version = "0.2.2" +authors = ["Pierre Krieger ", "The vulkano contributors", "Carter Anderson ", "Nicholas Rishel ", "Martin Krisnanto Putra "] description = "Deprecated. This crate is a temporary measure until native rust shader compilation like https://github.com/gfx-rs/naga lands." repository = "https://github.com/cart/glsl-to-spirv" license = "MIT/Apache-2.0" -build = "build/build.rs" categories = ["rendering::graphics-api"] edition = "2018" + +[dependencies] +# Default panic message handling +glslang_actual_builder = { path = "glslang_actual_builder", default-features = false } + +# Supported Platforms +[target.x86_64-pc-windows-msvc.dependencies] +glslang_actual_builder = { path = "glslang_actual_builder", default-features = false } + +[target.x86_64-unknown-linux-gnu.dependencies] +glslang_actual_builder = { path = "glslang_actual_builder", default-features = false } + +[target.x86_64-apple-darwin.dependencies] +glslang_actual_builder = { path = "glslang_actual_builder", default-features = false } + +[target.aarch64-linux-android.dependencies] +glslang_actual_builder = { path = "glslang_actual_builder", default-features = false } + +[target.armv7-linux-androideabi.dependencies] +glslang_actual_builder = { path = "glslang_actual_builder", default-features = false } + +[target.i686-pc-windows-msvc.dependencies] +glslang_actual_builder = { path = "glslang_actual_builder", features = ["build-from-source"] } + +[target.x86_64-pc-windows-gnu.dependencies] +glslang_actual_builder = { path = "glslang_actual_builder", features = ["build-from-source"] } + +[target.i686-pc-windows-gnu.dependencies] +glslang_actual_builder = { path = "glslang_actual_builder", features = ["build-from-source"] } diff --git a/build/build.rs b/build/build.rs deleted file mode 100644 index 432a45c..0000000 --- a/build/build.rs +++ /dev/null @@ -1,42 +0,0 @@ -use std::env; -use std::path::PathBuf; - -fn main() { - let target = env::var("TARGET").unwrap(); - let mut bin_dir = PathBuf::from(&env::var("CARGO_MANIFEST_DIR").unwrap()); - bin_dir.push("build"); - - if target.contains("x86_64-pc-windows-msvc") { - bin_dir.push("windows"); - } else if target.contains("x86_64-unknown-linux-gnu") { - bin_dir.push("linux"); - } else if target.contains("x86_64-apple-darwin") { - bin_dir.push("osx"); - } else if target.contains("android") { - if target.contains("aarch64") { - bin_dir.push("android-arm64-v8a"); - } else if target.contains("armv7") { - bin_dir.push("android-armeabi-v7a"); - } else { - panic!("Missing Android target support {}", target); - } - } else { - panic!("Missing target support {}", target); - }; - - // Link order matters, make sure dependents are linked before their dependencies. - println!("cargo:rustc-link-search={}", bin_dir.to_str().unwrap()); - println!("cargo:rustc-link-lib=glslang.glsltospirv"); - println!("cargo:rustc-link-lib=HLSL.glsltospirv"); - println!("cargo:rustc-link-lib=OGLCompiler.glsltospirv"); - println!("cargo:rustc-link-lib=OSDependent.glsltospirv"); - println!("cargo:rustc-link-lib=SPIRV.glsltospirv"); - println!("cargo:rustc-link-lib=SPVRemapper.glsltospirv"); - if target.contains("x86_64-unknown-linux-gnu") || target.contains("x86_64-apple-darwin") { - println!("cargo:rustc-link-lib=SPIRV-Tools-opt.glsltospirv"); - println!("cargo:rustc-link-lib=SPIRV-Tools.glsltospirv"); - } - if target.contains("android") { - println!("cargo:rustc-link-lib=c++_shared"); - } -} diff --git a/glslang b/glslang deleted file mode 160000 index bcf6a24..0000000 --- a/glslang +++ /dev/null @@ -1 +0,0 @@ -Subproject commit bcf6a2430e99e8fc24f9f266e99316905e6d5134 diff --git a/glslang_actual_builder/Cargo.toml b/glslang_actual_builder/Cargo.toml new file mode 100644 index 0000000..e007068 --- /dev/null +++ b/glslang_actual_builder/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "glslang_actual_builder" +version = "0.1.0" +authors = ["Pierre Krieger ", "The vulkano contributors", "Carter Anderson ", "Nicholas Rishel ", "Martin Krisnanto Putra "] +description = "Internal builder" +repository = "https://github.com/cart/glsl-to-spirv" +license = "MIT/Apache-2.0" +build = "build.rs" +categories = ["rendering::graphics-api"] +edition = "2018" + +[features] +default = [] +build-from-source = ["cmake", "cc"] + +[build-dependencies] +cmake = { version = "0.1.45", optional = true } +cc = { version = "1.0.66", features = ["parallel"], optional = true } diff --git a/glslang_actual_builder/build.rs b/glslang_actual_builder/build.rs new file mode 100644 index 0000000..b8489b9 --- /dev/null +++ b/glslang_actual_builder/build.rs @@ -0,0 +1,116 @@ +use std::path::Path; + +fn main() { + let target: &str = &std::env::var("TARGET").unwrap(); + let cargo_dir = Path::new(env!("CARGO_MANIFEST_DIR")); + let bin_dir = match target { + "x86_64-pc-windows-msvc" => cargo_dir.join("build").join("windows"), + "x86_64-unknown-linux-gnu" => cargo_dir.join("build").join("linux"), + "x86_64-apple-darwin" => cargo_dir.join("build").join("osx"), + "aarch64-linux-android" => cargo_dir.join("build").join("android-arm64-v8a"), + "armv7-linux-androideabi" => cargo_dir.join("build").join("android-armeabi-v7a"), + "i686-pc-windows-msvc" => build::build_libraries(&target), + "x86_64-pc-windows-gnu" => build::build_libraries(&target), + "i686-pc-windows-gnu" => build::build_libraries(&target), + _ => panic!("Unsupported target {}", target), + }; + + // Link order matters, make sure dependants are linked before their dependencies. + println!("cargo:rustc-link-search={}", bin_dir.to_str().unwrap()); + println!("cargo:rustc-link-lib=glslang.glsltospirv"); + println!("cargo:rustc-link-lib=HLSL.glsltospirv"); + println!("cargo:rustc-link-lib=OGLCompiler.glsltospirv"); + println!("cargo:rustc-link-lib=OSDependent.glsltospirv"); + println!("cargo:rustc-link-lib=SPIRV.glsltospirv"); + println!("cargo:rustc-link-lib=SPVRemapper.glsltospirv"); + if target.contains("x86_64-unknown-linux-gnu") || target.contains("x86_64-apple-darwin") { + println!("cargo:rustc-link-lib=SPIRV-Tools-opt.glsltospirv"); + println!("cargo:rustc-link-lib=SPIRV-Tools.glsltospirv"); + } + if target.contains("android") { + println!("cargo:rustc-link-lib=c++_shared"); + } + if target.ends_with("-pc-windows-gnu") { + println!("cargo:rustc-link-lib=dylib=stdc++"); + } +} + +#[cfg(feature = "build-from-source")] +mod build { + use std::path::Path; + use std::path::PathBuf; + + /// Build target libraries if required, + /// and returns the location of library files + pub fn build_libraries(_target: &str) -> PathBuf { + // Prepare directories + let cargo_dir = Path::new(env!("CARGO_MANIFEST_DIR")); + let source_dir = cargo_dir.join("glslang"); + + let out_dir_env = std::env::var("OUT_DIR").unwrap(); + let out_dir = Path::new(&out_dir_env); + let install_dir = out_dir.join("install"); + let library_dir = install_dir.join("lib"); + + // Re-use libraries if they exist + if let Ok(mut entry) = library_dir.read_dir() { + if entry.next().is_some() { + // a file exists in the path + return library_dir; + } + } + + // Check glslang folder is initialized + let cmakelists = source_dir.join("CMakeLists.txt"); + if !cmakelists.exists() { + panic!("Please make sure the glslang submodule is initialized"); + } + + // Set up "install" subdirectory + match std::fs::create_dir_all(&install_dir) { + Ok(_) => {} + Err(err) => panic!("Unable to create directory: {:?}", err), + } + + // Common configuration + let mut config = cmake::Config::new(&source_dir); + config + .define("CMAKE_INSTALL_PREFIX", &install_dir) + .define("CMAKE_TRY_COMPILE_TARGET_TYPE", "STATIC_LIBRARY") + .define("ENABLE_GLSLANG_BINARIES", "OFF") + .profile("Release") + .build_target("install"); + + // Build config + config.build(); + + // Add vendor suffix to all library names + for path in library_dir + .read_dir() + .expect("Unable to locate compiled glslang libraries") + { + let filename = path.unwrap().path(); + let metadata = std::fs::metadata(&filename).unwrap(); + if metadata.is_file() { + let extension = filename.extension().unwrap().to_str().unwrap(); + let new_extension = format!("glsltospirv.{}", extension); + let new_name = filename.with_extension(new_extension); + std::fs::copy(&filename, &new_name) + .expect("Failed to rename a glslang library for linking"); + } + } + + library_dir + } +} + +#[cfg(not(feature = "build-from-source"))] +mod build { + use std::path::PathBuf; + + /// Build target libraries if required, + /// and returns the location of library files + pub fn build_libraries(target: &str) -> PathBuf { + panic!("Platform {} must build glslang from source.", &target); + } +} diff --git a/build/android-arm64-v8a/libHLSL.glsltospirv.a b/glslang_actual_builder/build/android-arm64-v8a/libHLSL.glsltospirv.a similarity index 100% rename from build/android-arm64-v8a/libHLSL.glsltospirv.a rename to glslang_actual_builder/build/android-arm64-v8a/libHLSL.glsltospirv.a diff --git a/build/android-arm64-v8a/libOGLCompiler.glsltospirv.a b/glslang_actual_builder/build/android-arm64-v8a/libOGLCompiler.glsltospirv.a similarity index 100% rename from build/android-arm64-v8a/libOGLCompiler.glsltospirv.a rename to glslang_actual_builder/build/android-arm64-v8a/libOGLCompiler.glsltospirv.a diff --git a/build/android-arm64-v8a/libOSDependent.glsltospirv.a b/glslang_actual_builder/build/android-arm64-v8a/libOSDependent.glsltospirv.a similarity index 100% rename from build/android-arm64-v8a/libOSDependent.glsltospirv.a rename to glslang_actual_builder/build/android-arm64-v8a/libOSDependent.glsltospirv.a diff --git a/build/android-arm64-v8a/libSPIRV.glsltospirv.a b/glslang_actual_builder/build/android-arm64-v8a/libSPIRV.glsltospirv.a similarity index 100% rename from build/android-arm64-v8a/libSPIRV.glsltospirv.a rename to glslang_actual_builder/build/android-arm64-v8a/libSPIRV.glsltospirv.a diff --git a/build/android-arm64-v8a/libSPVRemapper.glsltospirv.a b/glslang_actual_builder/build/android-arm64-v8a/libSPVRemapper.glsltospirv.a similarity index 100% rename from build/android-arm64-v8a/libSPVRemapper.glsltospirv.a rename to glslang_actual_builder/build/android-arm64-v8a/libSPVRemapper.glsltospirv.a diff --git a/build/android-arm64-v8a/libglslang.glsltospirv.a b/glslang_actual_builder/build/android-arm64-v8a/libglslang.glsltospirv.a similarity index 100% rename from build/android-arm64-v8a/libglslang.glsltospirv.a rename to glslang_actual_builder/build/android-arm64-v8a/libglslang.glsltospirv.a diff --git a/build/android-armeabi-v7a/libHLSL.glsltospirv.a b/glslang_actual_builder/build/android-armeabi-v7a/libHLSL.glsltospirv.a similarity index 100% rename from build/android-armeabi-v7a/libHLSL.glsltospirv.a rename to glslang_actual_builder/build/android-armeabi-v7a/libHLSL.glsltospirv.a diff --git a/build/android-armeabi-v7a/libOGLCompiler.glsltospirv.a b/glslang_actual_builder/build/android-armeabi-v7a/libOGLCompiler.glsltospirv.a similarity index 100% rename from build/android-armeabi-v7a/libOGLCompiler.glsltospirv.a rename to glslang_actual_builder/build/android-armeabi-v7a/libOGLCompiler.glsltospirv.a diff --git a/build/android-armeabi-v7a/libOSDependent.glsltospirv.a b/glslang_actual_builder/build/android-armeabi-v7a/libOSDependent.glsltospirv.a similarity index 100% rename from build/android-armeabi-v7a/libOSDependent.glsltospirv.a rename to glslang_actual_builder/build/android-armeabi-v7a/libOSDependent.glsltospirv.a diff --git a/build/android-armeabi-v7a/libSPIRV.glsltospirv.a b/glslang_actual_builder/build/android-armeabi-v7a/libSPIRV.glsltospirv.a similarity index 100% rename from build/android-armeabi-v7a/libSPIRV.glsltospirv.a rename to glslang_actual_builder/build/android-armeabi-v7a/libSPIRV.glsltospirv.a diff --git a/build/android-armeabi-v7a/libSPVRemapper.glsltospirv.a b/glslang_actual_builder/build/android-armeabi-v7a/libSPVRemapper.glsltospirv.a similarity index 100% rename from build/android-armeabi-v7a/libSPVRemapper.glsltospirv.a rename to glslang_actual_builder/build/android-armeabi-v7a/libSPVRemapper.glsltospirv.a diff --git a/build/android-armeabi-v7a/libglslang.glsltospirv.a b/glslang_actual_builder/build/android-armeabi-v7a/libglslang.glsltospirv.a similarity index 100% rename from build/android-armeabi-v7a/libglslang.glsltospirv.a rename to glslang_actual_builder/build/android-armeabi-v7a/libglslang.glsltospirv.a diff --git a/build/linux/libHLSL.glsltospirv.a b/glslang_actual_builder/build/linux/libHLSL.glsltospirv.a similarity index 100% rename from build/linux/libHLSL.glsltospirv.a rename to glslang_actual_builder/build/linux/libHLSL.glsltospirv.a diff --git a/build/linux/libOGLCompiler.glsltospirv.a b/glslang_actual_builder/build/linux/libOGLCompiler.glsltospirv.a similarity index 100% rename from build/linux/libOGLCompiler.glsltospirv.a rename to glslang_actual_builder/build/linux/libOGLCompiler.glsltospirv.a diff --git a/build/linux/libOSDependent.glsltospirv.a b/glslang_actual_builder/build/linux/libOSDependent.glsltospirv.a similarity index 100% rename from build/linux/libOSDependent.glsltospirv.a rename to glslang_actual_builder/build/linux/libOSDependent.glsltospirv.a diff --git a/build/linux/libSPIRV-Tools-opt.glsltospirv.a b/glslang_actual_builder/build/linux/libSPIRV-Tools-opt.glsltospirv.a similarity index 100% rename from build/linux/libSPIRV-Tools-opt.glsltospirv.a rename to glslang_actual_builder/build/linux/libSPIRV-Tools-opt.glsltospirv.a diff --git a/build/linux/libSPIRV-Tools.glsltospirv.a b/glslang_actual_builder/build/linux/libSPIRV-Tools.glsltospirv.a similarity index 100% rename from build/linux/libSPIRV-Tools.glsltospirv.a rename to glslang_actual_builder/build/linux/libSPIRV-Tools.glsltospirv.a diff --git a/build/linux/libSPIRV.glsltospirv.a b/glslang_actual_builder/build/linux/libSPIRV.glsltospirv.a similarity index 100% rename from build/linux/libSPIRV.glsltospirv.a rename to glslang_actual_builder/build/linux/libSPIRV.glsltospirv.a diff --git a/build/linux/libSPVRemapper.glsltospirv.a b/glslang_actual_builder/build/linux/libSPVRemapper.glsltospirv.a similarity index 100% rename from build/linux/libSPVRemapper.glsltospirv.a rename to glslang_actual_builder/build/linux/libSPVRemapper.glsltospirv.a diff --git a/build/linux/libglslang.glsltospirv.a b/glslang_actual_builder/build/linux/libglslang.glsltospirv.a similarity index 100% rename from build/linux/libglslang.glsltospirv.a rename to glslang_actual_builder/build/linux/libglslang.glsltospirv.a diff --git a/build/osx/libHLSL.glsltospirv.a b/glslang_actual_builder/build/osx/libHLSL.glsltospirv.a similarity index 100% rename from build/osx/libHLSL.glsltospirv.a rename to glslang_actual_builder/build/osx/libHLSL.glsltospirv.a diff --git a/build/osx/libOGLCompiler.glsltospirv.a b/glslang_actual_builder/build/osx/libOGLCompiler.glsltospirv.a similarity index 100% rename from build/osx/libOGLCompiler.glsltospirv.a rename to glslang_actual_builder/build/osx/libOGLCompiler.glsltospirv.a diff --git a/build/osx/libOSDependent.glsltospirv.a b/glslang_actual_builder/build/osx/libOSDependent.glsltospirv.a similarity index 100% rename from build/osx/libOSDependent.glsltospirv.a rename to glslang_actual_builder/build/osx/libOSDependent.glsltospirv.a diff --git a/build/osx/libSPIRV-Tools-opt.glsltospirv.a b/glslang_actual_builder/build/osx/libSPIRV-Tools-opt.glsltospirv.a similarity index 100% rename from build/osx/libSPIRV-Tools-opt.glsltospirv.a rename to glslang_actual_builder/build/osx/libSPIRV-Tools-opt.glsltospirv.a diff --git a/build/osx/libSPIRV-Tools.glsltospirv.a b/glslang_actual_builder/build/osx/libSPIRV-Tools.glsltospirv.a similarity index 100% rename from build/osx/libSPIRV-Tools.glsltospirv.a rename to glslang_actual_builder/build/osx/libSPIRV-Tools.glsltospirv.a diff --git a/build/osx/libSPIRV.glsltospirv.a b/glslang_actual_builder/build/osx/libSPIRV.glsltospirv.a similarity index 100% rename from build/osx/libSPIRV.glsltospirv.a rename to glslang_actual_builder/build/osx/libSPIRV.glsltospirv.a diff --git a/build/osx/libSPVRemapper.glsltospirv.a b/glslang_actual_builder/build/osx/libSPVRemapper.glsltospirv.a similarity index 100% rename from build/osx/libSPVRemapper.glsltospirv.a rename to glslang_actual_builder/build/osx/libSPVRemapper.glsltospirv.a diff --git a/build/osx/libglslang.glsltospirv.a b/glslang_actual_builder/build/osx/libglslang.glsltospirv.a similarity index 100% rename from build/osx/libglslang.glsltospirv.a rename to glslang_actual_builder/build/osx/libglslang.glsltospirv.a diff --git a/build/windows/HLSL.glsltospirv.lib b/glslang_actual_builder/build/windows/HLSL.glsltospirv.lib similarity index 100% rename from build/windows/HLSL.glsltospirv.lib rename to glslang_actual_builder/build/windows/HLSL.glsltospirv.lib diff --git a/build/windows/OGLCompiler.glsltospirv.lib b/glslang_actual_builder/build/windows/OGLCompiler.glsltospirv.lib similarity index 100% rename from build/windows/OGLCompiler.glsltospirv.lib rename to glslang_actual_builder/build/windows/OGLCompiler.glsltospirv.lib diff --git a/build/windows/OSDependent.glsltospirv.lib b/glslang_actual_builder/build/windows/OSDependent.glsltospirv.lib similarity index 100% rename from build/windows/OSDependent.glsltospirv.lib rename to glslang_actual_builder/build/windows/OSDependent.glsltospirv.lib diff --git a/build/windows/SPIRV.glsltospirv.lib b/glslang_actual_builder/build/windows/SPIRV.glsltospirv.lib similarity index 100% rename from build/windows/SPIRV.glsltospirv.lib rename to glslang_actual_builder/build/windows/SPIRV.glsltospirv.lib diff --git a/build/windows/SPVRemapper.glsltospirv.lib b/glslang_actual_builder/build/windows/SPVRemapper.glsltospirv.lib similarity index 100% rename from build/windows/SPVRemapper.glsltospirv.lib rename to glslang_actual_builder/build/windows/SPVRemapper.glsltospirv.lib diff --git a/build/windows/glslang.glsltospirv.lib b/glslang_actual_builder/build/windows/glslang.glsltospirv.lib similarity index 100% rename from build/windows/glslang.glsltospirv.lib rename to glslang_actual_builder/build/windows/glslang.glsltospirv.lib diff --git a/glslang_actual_builder/glslang b/glslang_actual_builder/glslang new file mode 160000 index 0000000..e22e71e --- /dev/null +++ b/glslang_actual_builder/glslang @@ -0,0 +1 @@ +Subproject commit e22e71ed4b53713311dc24bcc54a44b95767cb92 diff --git a/src/glslang_c_interface.rs b/glslang_actual_builder/src/glslang_c_interface.rs similarity index 100% rename from src/glslang_c_interface.rs rename to glslang_actual_builder/src/glslang_c_interface.rs diff --git a/glslang_actual_builder/src/lib.rs b/glslang_actual_builder/src/lib.rs new file mode 100644 index 0000000..fc82d60 --- /dev/null +++ b/glslang_actual_builder/src/lib.rs @@ -0,0 +1,275 @@ +// Copyright (c) 2016 The vulkano developers +// Licensed under the Apache License, Version 2.0 +// or the MIT +// license , +// at your option. All files in the project carrying such +// notice may not be copied, modified, or distributed except +// according to those terms. + +use std::ffi::{CStr, CString}; +use std::os::raw::c_char; + +mod glslang_c_interface; + +use glslang_c_interface::*; + +pub type SpirvOutput = Vec; + +pub fn compile( + code: &str, + ty: ShaderType, + shader_defs: Option<&[String]>, +) -> Result { + compile_inner(Some((code, ty)), shader_defs) +} + +// Eventually the API will look like this, with an iterator for multiple shader stages. +// However for the moment GLSLang doesn't like that, so we only pass one shader at a time. +fn compile_inner<'a, I>(shaders: I, shader_defs: Option<&[String]>) -> Result +where + I: IntoIterator, +{ + let mut preamble = String::new(); + if let Some(defs) = shader_defs { + for def in defs { + preamble.push_str("#define "); + + let mut def = def.clone(); + if let Some(end) = def.find('\n') { + def.truncate(end); + } + + let def = def.replacen('=', " ", 1); + + preamble.push_str(&def); + preamble.push('\n'); + } + } + + let mut data = Vec::new(); + + unsafe { + glslang_initialize_process(); + + for (source, ty) in shaders.into_iter() { + let stage = match ty { + ShaderType::Vertex => glslang_stage_t_GLSLANG_STAGE_VERTEX, + ShaderType::Fragment => glslang_stage_t_GLSLANG_STAGE_FRAGMENT, + ShaderType::Geometry => glslang_stage_t_GLSLANG_STAGE_GEOMETRY, + ShaderType::TessellationControl => glslang_stage_t_GLSLANG_STAGE_TESSCONTROL, + ShaderType::TessellationEvaluation => glslang_stage_t_GLSLANG_STAGE_TESSEVALUATION, + ShaderType::Compute => glslang_stage_t_GLSLANG_STAGE_COMPUTE, + }; + + let mut source = String::from(source); + if shader_defs.is_some() { + if let Some(version) = source.find(r##"#version"##) { + if let Some(newline) = &source[version..].find('\n') { + source.insert_str(version + newline + 1, &preamble); + } + } + } + + let c_str = CString::new(source.as_str()).unwrap(); + let code: *const c_char = c_str.as_ptr(); + + let input = &glslang_input_t { + language: glslang_source_t_GLSLANG_SOURCE_GLSL, + stage, + client: glslang_client_t_GLSLANG_CLIENT_VULKAN, + client_version: glslang_target_client_version_t_GLSLANG_TARGET_VULKAN_1_0, + target_language: glslang_target_language_t_GLSLANG_TARGET_SPV, + target_language_version: glslang_target_language_version_t_GLSLANG_TARGET_SPV_1_0, + code, + default_version: 100, + default_profile: glslang_profile_t_GLSLANG_NO_PROFILE, + force_default_version_and_profile: 0, + forward_compatible: 0, + messages: glslang_messages_t_GLSLANG_MSG_DEFAULT_BIT + | glslang_messages_t_GLSLANG_MSG_SPV_RULES_BIT + | glslang_messages_t_GLSLANG_MSG_VULKAN_RULES_BIT, + resource: DEFAULT_RESOURCE_LIMITS, + }; + + let shader = glslang_shader_create(input); + + if glslang_shader_preprocess(shader, input) == 0 { + let c_info: &CStr = CStr::from_ptr(glslang_shader_get_info_log(shader)); + let c_debug: &CStr = CStr::from_ptr(glslang_shader_get_info_debug_log(shader)); + + let mut error = String::from("glslang_shader_preprocess:\n"); + error.push_str(&format!("Info log:\n{}\n", c_info.to_str().unwrap())); + error.push_str(&format!("Debug log:\n{}\n", c_debug.to_str().unwrap())); + + return Err(error); + } + if glslang_shader_parse(shader, input) == 0 { + let c_info: &CStr = CStr::from_ptr(glslang_shader_get_info_log(shader)); + let c_debug: &CStr = CStr::from_ptr(glslang_shader_get_info_debug_log(shader)); + + let mut error = String::from("glslang_shader_parse:\n"); + error.push_str(&format!("Info log:\n{}\n", c_info.to_str().unwrap())); + error.push_str(&format!("Debug log:\n{}\n", c_debug.to_str().unwrap())); + + return Err(error); + } + + let program = glslang_program_create(); + glslang_program_add_shader(program, shader); + + if glslang_program_link( + program, + glslang_messages_t_GLSLANG_MSG_SPV_RULES_BIT + | glslang_messages_t_GLSLANG_MSG_VULKAN_RULES_BIT, + ) == 0 + { + let c_info: &CStr = CStr::from_ptr(glslang_program_get_info_log(program)); + let c_debug: &CStr = CStr::from_ptr(glslang_program_get_info_debug_log(program)); + + let mut error = String::from("glslang_program_link:\n"); + error.push_str(&format!("Info log:\n{}\n", c_info.to_str().unwrap())); + error.push_str(&format!("Debug log:\n{}\n", c_debug.to_str().unwrap())); + + return Err(error); + } + + glslang_program_SPIRV_generate(program, input.stage); + + if glslang_program_SPIRV_get_messages(program) != std::ptr::null() { + let c_messages: &CStr = CStr::from_ptr(glslang_program_SPIRV_get_messages(program)); + + println!("{:?}", c_messages); + } + + let size = glslang_program_SPIRV_get_size(program) as usize; + let ptr = glslang_program_SPIRV_get_ptr(program) as *mut u32; + data = std::slice::from_raw_parts(ptr, size).to_vec(); + + glslang_program_delete(program); + glslang_shader_delete(shader); + } + + glslang_finalize_process(); + } + + return Ok(data); +} + +/// Type of shader. +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum ShaderType { + Vertex, + Fragment, + Geometry, + TessellationControl, + TessellationEvaluation, + Compute, +} + +// values copied from glslang default resource limits +const DEFAULT_RESOURCE_LIMITS: &glslang_resource_t = &glslang_resource_t { + max_lights: 32, + max_clip_planes: 6, + max_texture_units: 32, + max_texture_coords: 32, + max_vertex_attribs: 64, + max_vertex_uniform_components: 4096, + max_varying_floats: 64, + max_vertex_texture_image_units: 32, + max_combined_texture_image_units: 80, + max_texture_image_units: 32, + max_fragment_uniform_components: 4096, + max_draw_buffers: 32, + max_vertex_uniform_vectors: 128, + max_varying_vectors: 8, + max_fragment_uniform_vectors: 16, + max_vertex_output_vectors: 16, + max_fragment_input_vectors: 15, + min_program_texel_offset: -8, + max_program_texel_offset: 7, + max_clip_distances: 8, + max_compute_work_group_count_x: 65535, + max_compute_work_group_count_y: 65535, + max_compute_work_group_count_z: 65535, + max_compute_work_group_size_x: 1024, + max_compute_work_group_size_y: 1024, + max_compute_work_group_size_z: 64, + max_compute_uniform_components: 1024, + max_compute_texture_image_units: 16, + max_compute_image_uniforms: 8, + max_compute_atomic_counters: 8, + max_compute_atomic_counter_buffers: 1, + max_varying_components: 60, + max_vertex_output_components: 64, + max_geometry_input_components: 64, + max_geometry_output_components: 128, + max_fragment_input_components: 128, + max_image_units: 8, + max_combined_image_units_and_fragment_outputs: 8, + max_combined_shader_output_resources: 8, + max_image_samples: 0, + max_vertex_image_uniforms: 0, + max_tess_control_image_uniforms: 0, + max_tess_evaluation_image_uniforms: 0, + max_geometry_image_uniforms: 0, + max_fragment_image_uniforms: 8, + max_combined_image_uniforms: 8, + max_geometry_texture_image_units: 16, + max_geometry_output_vertices: 256, + max_geometry_total_output_components: 1024, + max_geometry_uniform_components: 1024, + max_geometry_varying_components: 64, + max_tess_control_input_components: 128, + max_tess_control_output_components: 128, + max_tess_control_texture_image_units: 16, + max_tess_control_uniform_components: 1024, + max_tess_control_total_output_components: 4096, + max_tess_evaluation_input_components: 128, + max_tess_evaluation_output_components: 128, + max_tess_evaluation_texture_image_units: 16, + max_tess_evaluation_uniform_components: 1024, + max_tess_patch_components: 120, + max_patch_vertices: 32, + max_tess_gen_level: 64, + max_viewports: 16, + max_vertex_atomic_counters: 0, + max_tess_control_atomic_counters: 0, + max_tess_evaluation_atomic_counters: 0, + max_geometry_atomic_counters: 0, + max_fragment_atomic_counters: 8, + max_combined_atomic_counters: 8, + max_atomic_counter_bindings: 1, + max_vertex_atomic_counter_buffers: 0, + max_tess_control_atomic_counter_buffers: 0, + max_tess_evaluation_atomic_counter_buffers: 0, + max_geometry_atomic_counter_buffers: 0, + max_fragment_atomic_counter_buffers: 1, + max_combined_atomic_counter_buffers: 1, + max_atomic_counter_buffer_size: 16384, + max_transform_feedback_buffers: 4, + max_transform_feedback_interleaved_components: 64, + max_cull_distances: 8, + max_combined_clip_and_cull_distances: 8, + max_samples: 4, + max_mesh_output_vertices_nv: 256, + max_mesh_output_primitives_nv: 512, + max_mesh_work_group_size_x_nv: 32, + max_mesh_work_group_size_y_nv: 1, + max_mesh_work_group_size_z_nv: 1, + max_task_work_group_size_x_nv: 32, + max_task_work_group_size_y_nv: 1, + max_task_work_group_size_z_nv: 1, + max_mesh_view_count_nv: 4, + limits: glslang_limits_s { + non_inductive_for_loops: true, + while_loops: true, + do_while_loops: true, + general_uniform_indexing: true, + general_attribute_matrix_vector_indexing: true, + general_varying_indexing: true, + general_sampler_indexing: true, + general_variable_indexing: true, + general_constant_matrix_vector_indexing: true, + }, +}; diff --git a/readme.md b/readme.md index 8dbec92..3a31e2a 100644 --- a/readme.md +++ b/readme.md @@ -2,3 +2,27 @@ This crate is deprecated please use [shaderc-rs](https://github.com/google/shade BEVY NOTE: This crate is a temporary measure until native rust shader compilation like https://github.com/gfx-rs/naga lands. + +# Targets requiring build-from-source + +`glslang` will be built from source the first time. Compiled libraries are re-used afterwards. + +[cmake](https://cmake.org/download/) is required to build from source. + +The `glslang` submodule is assumed to be initialized. +Run `git submodule update --init` if you're checking out from git. + +NOTE: There is an additional commit not from upstream that changes one file. +This change is what allows gnu toolchains to build. + +## `i686-pc-windows-msvc` +- MSVC Windows host (either 32 or 64-bit) +- [VS C++ Build Tools](https://aka.ms/buildtools) (2017 or higher) + - Select **Visual C++ build tools** + - Make sure **Visual C++ tools for CMake** is ticked on the right + - Restart the computer after installing build tools - will fail to build otherwise + +## `i686-pc-windows-gnu`, `x86_64-pc-windows-gnu` +- MSYS2 or MinGW +- Install the appropriate toolchain (e.g. `pacman -S mingw-w64-x86_64-toolchain mingw-w64-i686-toolchain`) +- Add bin directories to your PATH (e.g. `C:\msys64\mingw64\bin`) diff --git a/src/lib.rs b/src/lib.rs index fc82d60..5c5f405 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,275 +1,3 @@ -// Copyright (c) 2016 The vulkano developers -// Licensed under the Apache License, Version 2.0 -// or the MIT -// license , -// at your option. All files in the project carrying such -// notice may not be copied, modified, or distributed except -// according to those terms. +extern crate glslang_actual_builder; -use std::ffi::{CStr, CString}; -use std::os::raw::c_char; - -mod glslang_c_interface; - -use glslang_c_interface::*; - -pub type SpirvOutput = Vec; - -pub fn compile( - code: &str, - ty: ShaderType, - shader_defs: Option<&[String]>, -) -> Result { - compile_inner(Some((code, ty)), shader_defs) -} - -// Eventually the API will look like this, with an iterator for multiple shader stages. -// However for the moment GLSLang doesn't like that, so we only pass one shader at a time. -fn compile_inner<'a, I>(shaders: I, shader_defs: Option<&[String]>) -> Result -where - I: IntoIterator, -{ - let mut preamble = String::new(); - if let Some(defs) = shader_defs { - for def in defs { - preamble.push_str("#define "); - - let mut def = def.clone(); - if let Some(end) = def.find('\n') { - def.truncate(end); - } - - let def = def.replacen('=', " ", 1); - - preamble.push_str(&def); - preamble.push('\n'); - } - } - - let mut data = Vec::new(); - - unsafe { - glslang_initialize_process(); - - for (source, ty) in shaders.into_iter() { - let stage = match ty { - ShaderType::Vertex => glslang_stage_t_GLSLANG_STAGE_VERTEX, - ShaderType::Fragment => glslang_stage_t_GLSLANG_STAGE_FRAGMENT, - ShaderType::Geometry => glslang_stage_t_GLSLANG_STAGE_GEOMETRY, - ShaderType::TessellationControl => glslang_stage_t_GLSLANG_STAGE_TESSCONTROL, - ShaderType::TessellationEvaluation => glslang_stage_t_GLSLANG_STAGE_TESSEVALUATION, - ShaderType::Compute => glslang_stage_t_GLSLANG_STAGE_COMPUTE, - }; - - let mut source = String::from(source); - if shader_defs.is_some() { - if let Some(version) = source.find(r##"#version"##) { - if let Some(newline) = &source[version..].find('\n') { - source.insert_str(version + newline + 1, &preamble); - } - } - } - - let c_str = CString::new(source.as_str()).unwrap(); - let code: *const c_char = c_str.as_ptr(); - - let input = &glslang_input_t { - language: glslang_source_t_GLSLANG_SOURCE_GLSL, - stage, - client: glslang_client_t_GLSLANG_CLIENT_VULKAN, - client_version: glslang_target_client_version_t_GLSLANG_TARGET_VULKAN_1_0, - target_language: glslang_target_language_t_GLSLANG_TARGET_SPV, - target_language_version: glslang_target_language_version_t_GLSLANG_TARGET_SPV_1_0, - code, - default_version: 100, - default_profile: glslang_profile_t_GLSLANG_NO_PROFILE, - force_default_version_and_profile: 0, - forward_compatible: 0, - messages: glslang_messages_t_GLSLANG_MSG_DEFAULT_BIT - | glslang_messages_t_GLSLANG_MSG_SPV_RULES_BIT - | glslang_messages_t_GLSLANG_MSG_VULKAN_RULES_BIT, - resource: DEFAULT_RESOURCE_LIMITS, - }; - - let shader = glslang_shader_create(input); - - if glslang_shader_preprocess(shader, input) == 0 { - let c_info: &CStr = CStr::from_ptr(glslang_shader_get_info_log(shader)); - let c_debug: &CStr = CStr::from_ptr(glslang_shader_get_info_debug_log(shader)); - - let mut error = String::from("glslang_shader_preprocess:\n"); - error.push_str(&format!("Info log:\n{}\n", c_info.to_str().unwrap())); - error.push_str(&format!("Debug log:\n{}\n", c_debug.to_str().unwrap())); - - return Err(error); - } - if glslang_shader_parse(shader, input) == 0 { - let c_info: &CStr = CStr::from_ptr(glslang_shader_get_info_log(shader)); - let c_debug: &CStr = CStr::from_ptr(glslang_shader_get_info_debug_log(shader)); - - let mut error = String::from("glslang_shader_parse:\n"); - error.push_str(&format!("Info log:\n{}\n", c_info.to_str().unwrap())); - error.push_str(&format!("Debug log:\n{}\n", c_debug.to_str().unwrap())); - - return Err(error); - } - - let program = glslang_program_create(); - glslang_program_add_shader(program, shader); - - if glslang_program_link( - program, - glslang_messages_t_GLSLANG_MSG_SPV_RULES_BIT - | glslang_messages_t_GLSLANG_MSG_VULKAN_RULES_BIT, - ) == 0 - { - let c_info: &CStr = CStr::from_ptr(glslang_program_get_info_log(program)); - let c_debug: &CStr = CStr::from_ptr(glslang_program_get_info_debug_log(program)); - - let mut error = String::from("glslang_program_link:\n"); - error.push_str(&format!("Info log:\n{}\n", c_info.to_str().unwrap())); - error.push_str(&format!("Debug log:\n{}\n", c_debug.to_str().unwrap())); - - return Err(error); - } - - glslang_program_SPIRV_generate(program, input.stage); - - if glslang_program_SPIRV_get_messages(program) != std::ptr::null() { - let c_messages: &CStr = CStr::from_ptr(glslang_program_SPIRV_get_messages(program)); - - println!("{:?}", c_messages); - } - - let size = glslang_program_SPIRV_get_size(program) as usize; - let ptr = glslang_program_SPIRV_get_ptr(program) as *mut u32; - data = std::slice::from_raw_parts(ptr, size).to_vec(); - - glslang_program_delete(program); - glslang_shader_delete(shader); - } - - glslang_finalize_process(); - } - - return Ok(data); -} - -/// Type of shader. -#[derive(Debug, Clone, PartialEq, Eq)] -pub enum ShaderType { - Vertex, - Fragment, - Geometry, - TessellationControl, - TessellationEvaluation, - Compute, -} - -// values copied from glslang default resource limits -const DEFAULT_RESOURCE_LIMITS: &glslang_resource_t = &glslang_resource_t { - max_lights: 32, - max_clip_planes: 6, - max_texture_units: 32, - max_texture_coords: 32, - max_vertex_attribs: 64, - max_vertex_uniform_components: 4096, - max_varying_floats: 64, - max_vertex_texture_image_units: 32, - max_combined_texture_image_units: 80, - max_texture_image_units: 32, - max_fragment_uniform_components: 4096, - max_draw_buffers: 32, - max_vertex_uniform_vectors: 128, - max_varying_vectors: 8, - max_fragment_uniform_vectors: 16, - max_vertex_output_vectors: 16, - max_fragment_input_vectors: 15, - min_program_texel_offset: -8, - max_program_texel_offset: 7, - max_clip_distances: 8, - max_compute_work_group_count_x: 65535, - max_compute_work_group_count_y: 65535, - max_compute_work_group_count_z: 65535, - max_compute_work_group_size_x: 1024, - max_compute_work_group_size_y: 1024, - max_compute_work_group_size_z: 64, - max_compute_uniform_components: 1024, - max_compute_texture_image_units: 16, - max_compute_image_uniforms: 8, - max_compute_atomic_counters: 8, - max_compute_atomic_counter_buffers: 1, - max_varying_components: 60, - max_vertex_output_components: 64, - max_geometry_input_components: 64, - max_geometry_output_components: 128, - max_fragment_input_components: 128, - max_image_units: 8, - max_combined_image_units_and_fragment_outputs: 8, - max_combined_shader_output_resources: 8, - max_image_samples: 0, - max_vertex_image_uniforms: 0, - max_tess_control_image_uniforms: 0, - max_tess_evaluation_image_uniforms: 0, - max_geometry_image_uniforms: 0, - max_fragment_image_uniforms: 8, - max_combined_image_uniforms: 8, - max_geometry_texture_image_units: 16, - max_geometry_output_vertices: 256, - max_geometry_total_output_components: 1024, - max_geometry_uniform_components: 1024, - max_geometry_varying_components: 64, - max_tess_control_input_components: 128, - max_tess_control_output_components: 128, - max_tess_control_texture_image_units: 16, - max_tess_control_uniform_components: 1024, - max_tess_control_total_output_components: 4096, - max_tess_evaluation_input_components: 128, - max_tess_evaluation_output_components: 128, - max_tess_evaluation_texture_image_units: 16, - max_tess_evaluation_uniform_components: 1024, - max_tess_patch_components: 120, - max_patch_vertices: 32, - max_tess_gen_level: 64, - max_viewports: 16, - max_vertex_atomic_counters: 0, - max_tess_control_atomic_counters: 0, - max_tess_evaluation_atomic_counters: 0, - max_geometry_atomic_counters: 0, - max_fragment_atomic_counters: 8, - max_combined_atomic_counters: 8, - max_atomic_counter_bindings: 1, - max_vertex_atomic_counter_buffers: 0, - max_tess_control_atomic_counter_buffers: 0, - max_tess_evaluation_atomic_counter_buffers: 0, - max_geometry_atomic_counter_buffers: 0, - max_fragment_atomic_counter_buffers: 1, - max_combined_atomic_counter_buffers: 1, - max_atomic_counter_buffer_size: 16384, - max_transform_feedback_buffers: 4, - max_transform_feedback_interleaved_components: 64, - max_cull_distances: 8, - max_combined_clip_and_cull_distances: 8, - max_samples: 4, - max_mesh_output_vertices_nv: 256, - max_mesh_output_primitives_nv: 512, - max_mesh_work_group_size_x_nv: 32, - max_mesh_work_group_size_y_nv: 1, - max_mesh_work_group_size_z_nv: 1, - max_task_work_group_size_x_nv: 32, - max_task_work_group_size_y_nv: 1, - max_task_work_group_size_z_nv: 1, - max_mesh_view_count_nv: 4, - limits: glslang_limits_s { - non_inductive_for_loops: true, - while_loops: true, - do_while_loops: true, - general_uniform_indexing: true, - general_attribute_matrix_vector_indexing: true, - general_varying_indexing: true, - general_sampler_indexing: true, - general_variable_indexing: true, - general_constant_matrix_vector_indexing: true, - }, -}; +pub use glslang_actual_builder::*; diff --git a/tests/test.rs b/tests/test.rs index 8ec8be9..660b672 100644 --- a/tests/test.rs +++ b/tests/test.rs @@ -7,7 +7,7 @@ // notice may not be copied, modified, or distributed except // according to those terms. -extern crate glsl_to_spirv; +extern crate bevy_glsl_to_spirv; #[test] fn test1() { @@ -21,5 +21,5 @@ void main() { } "#; - glsl_to_spirv::compile(shader, glsl_to_spirv::ShaderType::Fragment, None).unwrap(); + bevy_glsl_to_spirv::compile(shader, bevy_glsl_to_spirv::ShaderType::Fragment, None).unwrap(); }