Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for spir-v 1.0 #165

Merged
merged 1 commit into from Oct 28, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 3 additions & 1 deletion examples/wgpu-example-runner/build.rs
Expand Up @@ -3,6 +3,8 @@ use std::error::Error;

fn main() -> Result<(), Box<dyn Error>> {
// This will set the env var `wgpu-example-shader.spv` to a spir-v file that can be include!()'d
SpirvBuilder::new("../wgpu-example-shader").build()?;
SpirvBuilder::new("../wgpu-example-shader")
.spirv_version(1, 0)
.build()?;
Ok(())
}
10 changes: 7 additions & 3 deletions rustc_codegen_spirv/src/builder_spirv.rs
Expand Up @@ -71,17 +71,21 @@ pub struct BuilderSpirv {
}

impl BuilderSpirv {
pub fn new(kernel_mode: bool) -> Self {
pub fn new(version: Option<(u8, u8)>, kernel_mode: bool) -> Self {
let mut builder = Builder::new();
// intel-compute-runtime only supports v1.3
builder.set_version(1, 3);
// Default to spir-v 1.3
let version = version.unwrap_or((1, 3));
builder.set_version(version.0, version.1);
if kernel_mode {
builder.capability(Capability::Kernel);
} else {
builder.extension("SPV_KHR_vulkan_memory_model");
builder.capability(Capability::Shader);
builder.capability(Capability::VulkanMemoryModel);
builder.capability(Capability::VariablePointers);
if version < (1, 3) {
builder.extension("SPV_KHR_variable_pointers");
}
}
// The linker will always be ran on this module
builder.capability(Capability::Linkage);
Expand Down
22 changes: 20 additions & 2 deletions rustc_codegen_spirv/src/codegen_cx/mod.rs
Expand Up @@ -63,11 +63,29 @@ pub struct CodegenCx<'tcx> {
impl<'tcx> CodegenCx<'tcx> {
pub fn new(tcx: TyCtxt<'tcx>, codegen_unit: &'tcx CodegenUnit<'tcx>) -> Self {
let sym = Box::new(Symbols::new());
let kernel_mode = tcx.sess.target_features.contains(&sym.kernel);
let mut kernel_mode = false;
let mut spirv_version = None;
for &feature in &tcx.sess.target_features {
if feature == sym.kernel {
kernel_mode = true;
} else if feature == sym.spirv10 {
spirv_version = Some((1, 0));
} else if feature == sym.spirv11 {
spirv_version = Some((1, 1));
} else if feature == sym.spirv12 {
spirv_version = Some((1, 2));
} else if feature == sym.spirv13 {
spirv_version = Some((1, 3));
} else if feature == sym.spirv14 {
spirv_version = Some((1, 4));
} else if feature == sym.spirv15 {
spirv_version = Some((1, 5));
}
}
Self {
tcx,
codegen_unit,
builder: BuilderSpirv::new(kernel_mode),
builder: BuilderSpirv::new(spirv_version, kernel_mode),
instances: Default::default(),
function_parameter_values: Default::default(),
type_cache: Default::default(),
Expand Down
9 changes: 0 additions & 9 deletions rustc_codegen_spirv/src/linker/mod.rs
Expand Up @@ -223,15 +223,6 @@ pub fn link(sess: Option<&Session>, inputs: &mut [&mut Module], opts: &Options)
output.header.as_mut().unwrap().bound = simple_passes::compact_ids(&mut output);
};

output.debugs.push(Instruction::new(
Op::ModuleProcessed,
None,
None,
vec![Operand::LiteralString(
"Linked by rspirv-linker".to_string(),
)],
));

// output the module
Ok(output)
}
14 changes: 4 additions & 10 deletions rustc_codegen_spirv/src/linker/test.rs
Expand Up @@ -138,8 +138,7 @@ fn standard() -> Result<()> {
);

let result = assemble_and_link(&[&a, &b])?;
let expect = r#"OpModuleProcessed "Linked by rspirv-linker"
%1 = OpTypeFloat 32
let expect = r#"%1 = OpTypeFloat 32
%2 = OpVariable %1 Input
%3 = OpConstant %1 42.0
%4 = OpVariable %1 Uniform %3"#;
Expand All @@ -158,8 +157,7 @@ fn not_a_lib_extra_exports() -> Result<()> {
);

let result = assemble_and_link(&[&a])?;
let expect = r#"OpModuleProcessed "Linked by rspirv-linker"
%1 = OpTypeFloat 32
let expect = r#"%1 = OpTypeFloat 32
%2 = OpVariable %1 Uniform"#;
without_header_eq(result, expect);
Ok(())
Expand All @@ -178,8 +176,7 @@ fn lib_extra_exports() -> Result<()> {

let result = assemble_and_link(&[&a])?;

let expect = r#"OpModuleProcessed "Linked by rspirv-linker"
OpDecorate %1 LinkageAttributes "foo" Export
let expect = r#"OpDecorate %1 LinkageAttributes "foo" Export
%2 = OpTypeFloat 32
%1 = OpVariable %2 Uniform"#;
without_header_eq(result, expect);
Expand Down Expand Up @@ -363,8 +360,7 @@ fn func_ctrl() -> Result<()> {

let result = assemble_and_link(&[&a, &b])?;

let expect = r#"OpModuleProcessed "Linked by rspirv-linker"
%1 = OpTypeVoid
let expect = r#"%1 = OpTypeVoid
%2 = OpTypeFunction %1
%3 = OpTypeFloat 32
%4 = OpVariable %3 Uniform
Expand Down Expand Up @@ -417,7 +413,6 @@ fn use_exported_func_param_attr() -> Result<()> {
let result = assemble_and_link(&[&a, &b])?;

let expect = r#"OpCapability Kernel
OpModuleProcessed "Linked by rspirv-linker"
OpDecorate %1 FuncParamAttr Zext
%1 = OpDecorationGroup
OpGroupDecorate %1 %2
Expand Down Expand Up @@ -487,7 +482,6 @@ fn names_and_decorations() -> Result<()> {
let expect = r#"OpCapability Kernel
OpName %1 "foo"
OpName %2 "param"
OpModuleProcessed "Linked by rspirv-linker"
OpDecorate %3 Restrict
OpDecorate %4 NonWritable
%3 = OpDecorationGroup
Expand Down
12 changes: 12 additions & 0 deletions rustc_codegen_spirv/src/symbols.rs
Expand Up @@ -13,6 +13,12 @@ pub struct Symbols {
pub spirv: Symbol,
pub spirv_std: Symbol,
pub kernel: Symbol,
pub spirv10: Symbol,
pub spirv11: Symbol,
pub spirv12: Symbol,
pub spirv13: Symbol,
pub spirv14: Symbol,
pub spirv15: Symbol,
descriptor_set: Symbol,
binding: Symbol,
attributes: HashMap<Symbol, SpirvAttribute>,
Expand Down Expand Up @@ -211,6 +217,12 @@ impl Symbols {
spirv: Symbol::intern("spirv"),
spirv_std: Symbol::intern("spirv_std"),
kernel: Symbol::intern("kernel"),
spirv10: Symbol::intern("spirv1.0"),
spirv11: Symbol::intern("spirv1.1"),
spirv12: Symbol::intern("spirv1.2"),
spirv13: Symbol::intern("spirv1.3"),
spirv14: Symbol::intern("spirv1.4"),
spirv15: Symbol::intern("spirv1.5"),
descriptor_set: Symbol::intern("descriptor_set"),
binding: Symbol::intern("binding"),
attributes,
Expand Down
29 changes: 26 additions & 3 deletions spirv-builder/src/lib.rs
Expand Up @@ -30,12 +30,14 @@ impl Error for SpirvBuilderError {}
pub struct SpirvBuilder {
path_to_crate: PathBuf,
print_metadata: bool,
spirv_version: Option<(u8, u8)>,
}
impl SpirvBuilder {
pub fn new(path_to_crate: impl AsRef<Path>) -> Self {
Self {
path_to_crate: path_to_crate.as_ref().to_owned(),
print_metadata: true,
spirv_version: None,
}
}

Expand All @@ -45,11 +47,20 @@ impl SpirvBuilder {
self
}

pub fn spirv_version(mut self, major: u8, minor: u8) -> Self {
self.spirv_version = Some((major, minor));
self
}

/// Builds the module. Returns the path to the built spir-v file. If print_metadata is true,
/// you usually don't have to inspect the path, as the environment variable will already be
/// set.
pub fn build(self) -> Result<PathBuf, SpirvBuilderError> {
let spirv_module = invoke_rustc(self.path_to_crate.as_ref(), self.print_metadata)?;
let spirv_module = invoke_rustc(
self.path_to_crate.as_ref(),
self.print_metadata,
self.spirv_version,
)?;
let env_var = spirv_module.file_name().unwrap().to_str().unwrap();
if self.print_metadata {
println!("cargo:rustc-env={}={}", env_var, spirv_module.display());
Expand Down Expand Up @@ -90,7 +101,11 @@ fn find_rustc_codegen_spirv() -> PathBuf {
panic!("Could not find {} in library path", filename);
}

fn invoke_rustc(path_to_crate: &Path, print_metadata: bool) -> Result<PathBuf, SpirvBuilderError> {
fn invoke_rustc(
path_to_crate: &Path,
print_metadata: bool,
spirv_version: Option<(u8, u8)>,
) -> Result<PathBuf, SpirvBuilderError> {
// Okay, this is a little bonkers: in a normal world, we'd have the user clone
// rustc_codegen_spirv and pass in the path to it, and then we'd invoke cargo to build it, grab
// the resulting .so, and pass it into -Z codegen-backend. But that's really gross: the user
Expand All @@ -100,7 +115,15 @@ fn invoke_rustc(path_to_crate: &Path, print_metadata: bool) -> Result<PathBuf, S
// rustc expects a full path, instead of a filename looked up via LD_LIBRARY_PATH, so we need
// to copy cargo's understanding of library lookup and find the library and its full path.
let rustc_codegen_spirv = find_rustc_codegen_spirv();
let rustflags = format!("-Z codegen-backend={}", rustc_codegen_spirv.display());
let spirv_version_feture = match spirv_version {
None => "".to_string(),
Some((major, minor)) => format!(" -C target-feature=+spirv{}.{}", major, minor),
};
let rustflags = format!(
"-Z codegen-backend={}{}",
rustc_codegen_spirv.display(),
spirv_version_feture
);
let build = Command::new("cargo")
.args(&[
"build",
Expand Down