Skip to content

Commit

Permalink
Refactor Image to accept const generic parameters
Browse files Browse the repository at this point in the history
  • Loading branch information
XAMPPRocky committed Jan 7, 2021
1 parent b8cea94 commit afd1ab8
Show file tree
Hide file tree
Showing 9 changed files with 394 additions and 296 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions crates/rustc_codegen_spirv/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ use-compiled-tools = ["spirv-tools/use-compiled-tools"]
[dependencies]
bimap = "0.5"
indexmap = "1.6.0"
num-traits = "0.2.14"
rspirv = { git = "https://github.com/gfx-rs/rspirv.git", rev = "01ca0d2e5b667a0e4ff1bc1804511e38f9a08759" }
rustc-demangle = "0.1.18"
serde = { version = "1.0", features = ["derive"] }
Expand Down
60 changes: 50 additions & 10 deletions crates/rustc_codegen_spirv/src/abi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use rspirv::spirv::{Capability, StorageClass, Word};
use rustc_middle::bug;
use rustc_middle::ty::layout::{FnAbiExt, TyAndLayout};
use rustc_middle::ty::subst::SubstsRef;
use rustc_middle::ty::{GeneratorSubsts, PolyFnSig, Ty, TyKind, TypeAndMut};
use rustc_middle::ty::{GeneratorSubsts, ParamEnv, PolyFnSig, Ty, TyKind, TypeAndMut};
use rustc_span::Span;
use rustc_target::abi::call::{CastTarget, FnAbi, PassMode, Reg, RegKind};
use rustc_target::abi::{
Expand All @@ -20,6 +20,9 @@ use std::collections::HashMap;
use std::fmt;
use std::fmt::Write;

use num_traits::FromPrimitive;
use rspirv::spirv;

/// If a struct contains a pointer to itself, even indirectly, then doing a naiive recursive walk
/// of the fields will result in an infinite loop. Because pointers are the only thing that are
/// allowed to be recursive, keep track of what pointers we've translated, or are currently in the
Expand Down Expand Up @@ -797,22 +800,59 @@ fn trans_image<'tcx>(
attr: SpirvAttribute,
) -> Option<Word> {
match attr {
SpirvAttribute::Image {
dim,
depth,
arrayed,
multisampled,
sampled,
image_format,
access_qualifier,
} => {
SpirvAttribute::Image => {
// see SpirvType::sizeof
if ty.size != Size::from_bytes(4) {
cx.tcx.sess.err("#[spirv(image)] type must have size 4");
return None;
}

// Hardcode to float for now
let sampled_type = SpirvType::Float(32).def(span, cx);

macro_rules! type_from_variant_discriminant {
($(let $name:ident : $ty:ty = $exp:expr);+ ;) => {
$(let $name = {
let const_ = $exp;
let adt_def = const_.ty.ty_adt_def().unwrap();
assert!(adt_def.is_enum());
let destructured = cx.tcx.destructure_const(ParamEnv::reveal_all().and(const_));
let idx = destructured.variant.unwrap();
let value = const_.ty
.discriminant_for_variant(cx.tcx, idx)
.unwrap()
.val as u64;
<$ty>::from_u64(value).unwrap()
};)+
}
}

type_from_variant_discriminant! {
let dim: spirv::Dim = substs.const_at(0);
let depth: u32 = substs.const_at(1);
let arrayed: u32 = substs.const_at(2);
let multisampled: u32 = substs.const_at(3);
let sampled: u32 = substs.const_at(4);
let image_format: spirv::ImageFormat = substs.const_at(5);
}

let access_qualifier = {
let option = cx
.tcx
.destructure_const(ParamEnv::reveal_all().and(substs.const_at(6)));

match option.variant.map(|i| i.as_u32()).unwrap_or(0) {
0 => None,
1 => {
type_from_variant_discriminant! {
let access_qualifier: spirv::AccessQualifier = option.fields[0];
}
Some(access_qualifier)
}
_ => unreachable!(),
}
};

let ty = SpirvType::Image {
sampled_type,
dim,
Expand Down
160 changes: 3 additions & 157 deletions crates/rustc_codegen_spirv/src/symbols.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
use crate::builder::libm_intrinsics;
use crate::codegen_cx::CodegenCx;
use rspirv::spirv::{
AccessQualifier, BuiltIn, Dim, ExecutionMode, ExecutionModel, ImageFormat, StorageClass,
};
use rspirv::spirv::{BuiltIn, ExecutionMode, ExecutionModel, StorageClass};
use rustc_ast::ast::{AttrKind, Attribute, Lit, LitIntType, LitKind, NestedMetaItem};
use rustc_span::symbol::{Ident, Symbol};
use std::collections::HashMap;
Expand Down Expand Up @@ -33,13 +31,6 @@ pub struct Symbols {
descriptor_set: Symbol,
binding: Symbol,
image: Symbol,
dim: Symbol,
depth: Symbol,
arrayed: Symbol,
multisampled: Symbol,
sampled: Symbol,
image_format: Symbol,
access_qualifier: Symbol,
attributes: HashMap<Symbol, SpirvAttribute>,
execution_modes: HashMap<Symbol, (ExecutionMode, ExecutionModeExtraDim)>,
pub libm_intrinsics: HashMap<Symbol, libm_intrinsics::LibmIntrinsic>,
Expand Down Expand Up @@ -386,13 +377,6 @@ impl Symbols {
descriptor_set: Symbol::intern("descriptor_set"),
binding: Symbol::intern("binding"),
image: Symbol::intern("image"),
dim: Symbol::intern("dim"),
depth: Symbol::intern("depth"),
arrayed: Symbol::intern("arrayed"),
multisampled: Symbol::intern("multisampled"),
sampled: Symbol::intern("sampled"),
image_format: Symbol::intern("image_format"),
access_qualifier: Symbol::intern("access_qualifier"),
attributes,
execution_modes,
libm_intrinsics,
Expand Down Expand Up @@ -445,15 +429,7 @@ pub enum SpirvAttribute {
DescriptorSet(u32),
Binding(u32),
ReallyUnsafeIgnoreBitcasts,
Image {
dim: Dim,
depth: u32,
arrayed: u32,
multisampled: u32,
sampled: u32,
image_format: ImageFormat,
access_qualifier: Option<AccessQualifier>,
},
Image,
Sampler,
SampledImage,
Block,
Expand Down Expand Up @@ -493,7 +469,7 @@ pub fn parse_attrs(
};
args.into_iter().filter_map(move |ref arg| {
if arg.has_name(cx.sym.image) {
parse_image(cx, arg)
Some(SpirvAttribute::Image)
} else if arg.has_name(cx.sym.descriptor_set) {
match parse_attr_int_value(cx, arg) {
Some(x) => Some(SpirvAttribute::DescriptorSet(x)),
Expand Down Expand Up @@ -537,136 +513,6 @@ pub fn parse_attrs(
result.collect::<Vec<_>>().into_iter()
}

fn parse_image(cx: &CodegenCx<'_>, attr: &NestedMetaItem) -> Option<SpirvAttribute> {
let args = match attr.meta_item_list() {
Some(args) => args,
None => {
cx.tcx
.sess
.span_err(attr.span(), "image attribute must have arguments");
return None;
}
};
if args.len() != 6 && args.len() != 7 {
cx.tcx
.sess
.span_err(attr.span(), "image attribute must have 6 or 7 arguments");
return None;
}
let check = |idx: usize, sym: Symbol| -> bool {
if args[idx].has_name(sym) {
false
} else {
cx.tcx.sess.span_err(
args[idx].span(),
&format!("image attribute argument {} must be {}=...", idx + 1, sym),
);
true
}
};
if check(0, cx.sym.dim)
| check(1, cx.sym.depth)
| check(2, cx.sym.arrayed)
| check(3, cx.sym.multisampled)
| check(4, cx.sym.sampled)
| check(5, cx.sym.image_format)
| (args.len() == 7 && check(6, cx.sym.access_qualifier))
{
return None;
}
let arg_values = args
.iter()
.map(
|arg| match arg.meta_item().and_then(|arg| arg.name_value_literal()) {
Some(arg) => Some(arg),
None => {
cx.tcx
.sess
.span_err(arg.span(), "image attribute must be name=value");
None
}
},
)
.collect::<Option<Vec<_>>>()?;
let dim = match arg_values[0].kind {
LitKind::Str(dim, _) => match dim.with(|s| s.parse()) {
Ok(dim) => dim,
Err(()) => {
cx.tcx.sess.span_err(args[0].span(), "invalid dim value");
return None;
}
},
_ => {
cx.tcx
.sess
.span_err(args[0].span(), "dim value must be str");
return None;
}
};
let parse_lit = |idx: usize, name: &str| -> Option<u32> {
match arg_values[idx].kind {
LitKind::Int(v, _) => Some(v as u32),
_ => {
cx.tcx
.sess
.span_err(args[idx].span(), &format!("{} value must be int", name));
None
}
}
};
let depth = parse_lit(1, "depth")?;
let arrayed = parse_lit(2, "arrayed")?;
let multisampled = parse_lit(3, "multisampled")?;
let sampled = parse_lit(4, "sampled")?;
let image_format = match arg_values[5].kind {
LitKind::Str(dim, _) => match dim.with(|s| s.parse()) {
Ok(dim) => dim,
Err(()) => {
cx.tcx
.sess
.span_err(args[5].span(), "invalid image_format value");
return None;
}
},
_ => {
cx.tcx
.sess
.span_err(args[5].span(), "image_format value must be str");
return None;
}
};
let access_qualifier = if args.len() == 7 {
Some(match arg_values[6].kind {
LitKind::Str(dim, _) => match dim.with(|s| s.parse()) {
Ok(dim) => dim,
Err(()) => {
cx.tcx
.sess
.span_err(args[6].span(), "invalid access_qualifier value");
return None;
}
},
_ => {
cx.tcx
.sess
.span_err(args[6].span(), "access_qualifier value must be str");
return None;
}
})
} else {
None
};
Some(SpirvAttribute::Image {
dim,
depth,
arrayed,
multisampled,
sampled,
image_format,
access_qualifier,
})
}

fn parse_attr_int_value(cx: &CodegenCx<'_>, arg: &NestedMetaItem) -> Option<u32> {
let arg = match arg.meta_item() {
Some(arg) => arg,
Expand Down
Loading

0 comments on commit afd1ab8

Please sign in to comment.