Skip to content

Commit

Permalink
WIP modf
Browse files Browse the repository at this point in the history
  • Loading branch information
fornwall committed Aug 21, 2023
1 parent 3da9355 commit 8241ae2
Show file tree
Hide file tree
Showing 23 changed files with 283 additions and 63 deletions.
3 changes: 3 additions & 0 deletions src/back/glsl/keywords.rs
Original file line number Diff line number Diff line change
Expand Up @@ -477,4 +477,7 @@ pub const RESERVED_KEYWORDS: &[&str] = &[
// entry point name (should not be shadowed)
//
"main",
// Naga utilities:
super::MODF_FUNCTION,
super::MODF_STRUCT,
];
29 changes: 28 additions & 1 deletion src/back/glsl/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,9 @@ pub const SUPPORTED_ES_VERSIONS: &[u16] = &[300, 310, 320];
/// of detail for bounds checking in `ImageLoad`
const CLAMPED_LOD_SUFFIX: &str = "_clamped_lod";

pub(crate) const MODF_FUNCTION: &str = "naga_modf";
pub(crate) const MODF_STRUCT: &str = "naga_modf_struct";

/// Mapping between resources and bindings.
pub type BindingMap = std::collections::BTreeMap<crate::ResourceBinding, u8>;

Expand Down Expand Up @@ -604,6 +607,22 @@ impl<'a, W: Write> Writer<'a, W> {
}
}

if self.module.special_types.modf_result.is_some() {
writeln!(
self.out,
"struct {MODF_STRUCT} {{
float fract;
float whole;
}};
{MODF_STRUCT} {MODF_FUNCTION}(float arg) {{
float whole;
float fract = modf(arg, whole);
return {MODF_STRUCT}(fract, whole);
}}"
)?;
}

// Write struct types.
//
// This are always ordered because the IR is structured in a way that
Expand Down Expand Up @@ -860,6 +879,7 @@ impl<'a, W: Write> Writer<'a, W> {
| TypeInner::Sampler { .. }
| TypeInner::AccelerationStructure
| TypeInner::RayQuery
| TypeInner::ModfResultF32
| TypeInner::BindingArray { .. } => {
return Err(Error::Custom(format!("Unable to write type {inner:?}")))
}
Expand All @@ -885,6 +905,10 @@ impl<'a, W: Write> Writer<'a, W> {
}
// glsl array has the size separated from the base type
TypeInner::Array { base, .. } => self.write_type(base),
TypeInner::ModfResultF32 => {
write!(self.out, "{MODF_STRUCT}")?;
Ok(())
}
ref other => self.write_value_type(other),
}
}
Expand Down Expand Up @@ -2325,6 +2349,9 @@ impl<'a, W: Write> Writer<'a, W> {
&self.names[&NameKey::StructMember(ty, index)]
)?
}
TypeInner::ModfResultF32 => {
write!(self.out, ".{}", if index == 0 { "fract" } else { "whole " })?
}
ref other => return Err(Error::Custom(format!("Cannot index {other:?}"))),
}
}
Expand Down Expand Up @@ -2985,7 +3012,7 @@ impl<'a, W: Write> Writer<'a, W> {
Mf::Round => "roundEven",
Mf::Fract => "fract",
Mf::Trunc => "trunc",
Mf::Modf => "modf",
Mf::Modf => MODF_FUNCTION,
Mf::Frexp => "frexp",
Mf::Ldexp => "ldexp",
// exponent
Expand Down
26 changes: 26 additions & 0 deletions src/back/hlsl/help.rs
Original file line number Diff line number Diff line change
Expand Up @@ -781,6 +781,32 @@ impl<'a, W: Write> super::Writer<'a, W> {
Ok(())
}

pub(super) fn write_special_functions(&mut self, module: &crate::Module) -> BackendResult {
if module.special_types.modf_result.is_some() {
let function_name = super::writer::MODF_FUNCTION;
let struct_name = super::writer::MODF_STRUCT;
writeln!(
self.out,
"struct {struct_name} {{
float fract;
float whole;
}};
{struct_name} {function_name}(in float arg) {{
float whole;
float fract = modf(arg, whole);
{struct_name} result;
result.whole = whole;
result.fract = fract;
return result;
}}"
)?;
// Write extra new line
writeln!(self.out)?;
}
Ok(())
}

/// Helper function that writes compose wrapped functions
pub(super) fn write_wrapped_compose_functions(
&mut self,
Expand Down
3 changes: 3 additions & 0 deletions src/back/hlsl/keywords.rs
Original file line number Diff line number Diff line change
Expand Up @@ -814,6 +814,9 @@ pub const RESERVED: &[&str] = &[
"TextureBuffer",
"ConstantBuffer",
"RayQuery",
// Naga utilities
super::writer::MODF_FUNCTION,
super::writer::MODF_STRUCT,
];

// DXC scalar types, from https://github.com/microsoft/DirectXShaderCompiler/blob/18c9e114f9c314f93e68fbc72ce207d4ed2e65ae/tools/clang/lib/AST/ASTContextHLSL.cpp#L48-L254
Expand Down
15 changes: 14 additions & 1 deletion src/back/hlsl/writer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ const SPECIAL_BASE_VERTEX: &str = "base_vertex";
const SPECIAL_BASE_INSTANCE: &str = "base_instance";
const SPECIAL_OTHER: &str = "other";

pub(crate) const MODF_FUNCTION: &str = "naga_modf";
pub(crate) const MODF_STRUCT: &str = "naga_modf_result";

struct EpStructMember {
name: String,
ty: Handle<crate::Type>,
Expand Down Expand Up @@ -244,6 +247,8 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> {
}
}

self.write_special_functions(module)?;

self.write_wrapped_compose_functions(module, &module.const_expressions)?;

// Write all named constants
Expand Down Expand Up @@ -1058,6 +1063,9 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> {
TypeInner::Array { base, size, .. } | TypeInner::BindingArray { base, size } => {
self.write_array_size(module, base, size)?;
}
TypeInner::ModfResultF32 => {
write!(self.out, "struct {MODF_STRUCT}")?;
}
_ => return Err(Error::Unimplemented(format!("write_value_type {inner:?}"))),
}

Expand Down Expand Up @@ -2276,6 +2284,11 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> {
&writer.names[&NameKey::StructMember(ty, index)]
)?
}
TypeInner::ModfResultF32 => write!(
writer.out,
".{}",
if index == 0 { "fract" } else { "whole" }
)?,
ref other => {
return Err(Error::Custom(format!("Cannot index {other:?}")))
}
Expand Down Expand Up @@ -2665,7 +2678,7 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> {
Mf::Round => Function::Regular("round"),
Mf::Fract => Function::Regular("frac"),
Mf::Trunc => Function::Regular("trunc"),
Mf::Modf => Function::Regular("modf"),
Mf::Modf => Function::Regular(MODF_FUNCTION),
Mf::Frexp => Function::Regular("frexp"),
Mf::Ldexp => Function::Regular("ldexp"),
// exponent
Expand Down
2 changes: 2 additions & 0 deletions src/back/msl/keywords.rs
Original file line number Diff line number Diff line change
Expand Up @@ -214,4 +214,6 @@ pub const RESERVED: &[&str] = &[
// Naga utilities
"DefaultConstructible",
"clamped_lod_e",
super::writer::MODF_FUNCTION,
super::writer::MODF_STRUCT,
];
47 changes: 44 additions & 3 deletions src/back/msl/writer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ const RAY_QUERY_FIELD_INTERSECTION: &str = "intersection";
const RAY_QUERY_FIELD_READY: &str = "ready";
const RAY_QUERY_FUN_MAP_INTERSECTION: &str = "_map_intersection_type";

pub(crate) const MODF_FUNCTION: &str = "naga_modf";
pub(crate) const MODF_STRUCT: &str = "naga_modf_result";

/// Write the Metal name for a Naga numeric type: scalar, vector, or matrix.
///
/// The `sizes` slice determines whether this function writes a
Expand Down Expand Up @@ -140,7 +143,12 @@ impl<'a> Display for TypeContext<'a> {
// so just print the element type here.
write!(out, "{sub}")
}
crate::TypeInner::Struct { .. } => unreachable!(),
crate::TypeInner::Struct { .. } => {
unreachable!()
}
crate::TypeInner::ModfResultF32 { .. } => {
write!(out, "{}", MODF_STRUCT)
}
crate::TypeInner::Image {
dim,
arrayed,
Expand Down Expand Up @@ -452,6 +460,7 @@ impl crate::Type {
| Ti::Sampler { .. }
| Ti::AccelerationStructure
| Ti::RayQuery
| Ti::ModfResultF32
| Ti::BindingArray { .. } => false,
}
}
Expand Down Expand Up @@ -1635,6 +1644,15 @@ impl<W: Write> Writer<W> {
write!(self.out, "{NAMESPACE}::{op}")?;
self.put_call_parameters(iter::once(argument), context)?;
}
crate::Expression::Math {
fun: crate::MathFunction::Modf,
arg,
..
} => {
write!(self.out, "{MODF_FUNCTION}(")?;
self.put_expression(arg, context, false)?;
write!(self.out, ")")?;
}
crate::Expression::Math {
fun,
arg,
Expand All @@ -1644,7 +1662,7 @@ impl<W: Write> Writer<W> {
} => {
use crate::MathFunction as Mf;

let scalar_argument = match *context.resolve_type(arg) {
let scalar_argument: bool = match *context.resolve_type(arg) {
crate::TypeInner::Scalar { .. } => true,
_ => false,
};
Expand Down Expand Up @@ -2018,7 +2036,8 @@ impl<W: Write> Writer<W> {
base_inner = &context.module.types[base].inner;
}
match *base_inner {
crate::TypeInner::Struct { .. } => (base, None),
crate::TypeInner::Struct { .. }
| crate::TypeInner::ModfResultF32 { .. } => (base, None),
_ => (base, Some(index::GuardedIndex::Known(index))),
}
}
Expand Down Expand Up @@ -2133,6 +2152,10 @@ impl<W: Write> Writer<W> {
write!(self.out, ".{}", back::COMPONENTS[index as usize])?;
}
}
crate::TypeInner::ModfResultF32 => {
self.put_access_chain(base, policy, context)?;
write!(self.out, ".{}", if index == 0 { "fract" } else { "whole" })?;
}
_ => {
self.put_subscripted_access_chain(
base,
Expand Down Expand Up @@ -3236,6 +3259,24 @@ impl<W: Write> Writer<W> {
}
}
}

if module.special_types.modf_result.is_some() {
writeln!(
self.out,
"
struct {MODF_STRUCT} {{
float fract;
float whole;
}};
struct {MODF_STRUCT} {MODF_FUNCTION}(float arg) {{
float whole;
float fract = {NAMESPACE}::modf(arg, whole);
return {MODF_STRUCT}{{ fract, whole }};
}};"
)?;
}

Ok(())
}

Expand Down
11 changes: 11 additions & 0 deletions src/back/spv/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -396,6 +396,17 @@ impl<'w> BlockContext<'w> {

load_id
}
crate::TypeInner::ModfResultF32 => {
let id = self.gen_id();
let base_id = self.cached[base];
block.body.push(Instruction::composite_extract(
result_type_id,
id,
base_id,
&[index],
));
id
}
ref other => {
log::error!("Unable to access index of {:?}", other);
return Err(Error::FeatureNotImplemented("access index for type"));
Expand Down
1 change: 1 addition & 0 deletions src/back/spv/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -403,6 +403,7 @@ fn make_local(inner: &crate::TypeInner) -> Option<LocalType> {
crate::TypeInner::RayQuery => LocalType::RayQuery,
crate::TypeInner::Array { .. }
| crate::TypeInner::Struct { .. }
| crate::TypeInner::ModfResultF32
| crate::TypeInner::BindingArray { .. } => return None,
})
}
Expand Down
4 changes: 4 additions & 0 deletions src/back/spv/writer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1024,6 +1024,10 @@ impl Writer {
}
Instruction::type_struct(id, member_ids.as_slice())
}
crate::TypeInner::ModfResultF32 => {
// TODO
Instruction::type_struct(id, &[])
}

// These all have TypeLocal representations, so they should have been
// handled by `write_type_declaration_local` above.
Expand Down
3 changes: 3 additions & 0 deletions src/back/wgsl/writer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1223,6 +1223,9 @@ impl<W: Write> Writer<W> {
&self.names[&NameKey::StructMember(ty, index)]
)?
}
TypeInner::ModfResultF32 => {
write!(self.out, ".{}", if index == 0 { "fract" } else { "whole" })?
}
ref other => return Err(Error::Custom(format!("Cannot index {other:?}"))),
}
}
Expand Down
18 changes: 18 additions & 0 deletions src/front/type_gen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -311,4 +311,22 @@ impl crate::Module {
self.special_types.ray_intersection = Some(handle);
handle
}

/// Populate this module's [`SpecialTypes::modf_result_f32`] type.
///
/// TODO
pub fn generate_modf_result(&mut self) -> Handle<crate::Type> {
if let Some(handle) = self.special_types.modf_result {
return handle;
}
let handle = self.types.insert(
crate::Type {
name: Some("__naga_modf_result".to_string()),
inner: crate::TypeInner::ModfResultF32,
},
Span::UNDEFINED,
);
self.special_types.modf_result = Some(handle);
handle
}
}
Loading

0 comments on commit 8241ae2

Please sign in to comment.