[msl] inline some of the types

This commit is contained in:
Dzmitry Malyshau 2021-04-08 11:00:11 -04:00 committed by Dzmitry Malyshau
parent f1c5e04b89
commit 2774dcb403
9 changed files with 390 additions and 287 deletions

View File

@ -3,7 +3,7 @@ use super::{
TranslationInfo,
};
use crate::{
arena::Handle,
arena::{Arena, Handle},
proc::{EntryPointIndex, NameKey, Namer, TypeResolution},
valid::{FunctionInfo, GlobalUse, ModuleInfo},
FastHashMap,
@ -31,6 +31,154 @@ impl Display for Level {
}
}
struct TypeContext<'a> {
handle: Handle<crate::Type>,
arena: &'a Arena<crate::Type>,
names: &'a FastHashMap<NameKey, String>,
usage: GlobalUse,
access: crate::StorageAccess,
first_time: bool,
}
impl<'a> Display for TypeContext<'a> {
fn fmt(&self, out: &mut Formatter<'_>) -> Result<(), FmtError> {
let ty = &self.arena[self.handle];
if ty.needs_alias() && !self.first_time {
let name = &self.names[&NameKey::Type(self.handle)];
return write!(out, "{}", name);
}
match ty.inner {
// work around Metal toolchain bug with `uint` typedef
crate::TypeInner::Scalar {
kind: crate::ScalarKind::Uint,
..
} => {
write!(out, "metal::uint")
}
crate::TypeInner::Scalar { kind, .. } => {
write!(out, "{}", scalar_kind_string(kind))
}
crate::TypeInner::Vector { size, kind, .. } => {
write!(
out,
"{}::{}{}",
NAMESPACE,
scalar_kind_string(kind),
vector_size_string(size),
)
}
crate::TypeInner::Matrix { columns, rows, .. } => {
write!(
out,
"{}::{}{}x{}",
NAMESPACE,
scalar_kind_string(crate::ScalarKind::Float),
vector_size_string(columns),
vector_size_string(rows),
)
}
crate::TypeInner::Pointer { base, class } => {
let sub = Self {
arena: self.arena,
names: self.names,
handle: base,
usage: self.usage,
access: self.access,
first_time: false,
};
let class_name = match class.get_name(self.usage) {
Some(name) => name,
None => return Ok(()),
};
write!(out, "{} {}*", class_name, sub)
}
crate::TypeInner::ValuePointer {
size: None,
kind,
width: _,
class,
} => {
let class_name = match class.get_name(self.usage) {
Some(name) => name,
None => return Ok(()),
};
write!(out, "{} {}*", class_name, scalar_kind_string(kind),)
}
crate::TypeInner::ValuePointer {
size: Some(size),
kind,
width: _,
class,
} => {
let class_name = match class.get_name(self.usage) {
Some(name) => name,
None => return Ok(()),
};
write!(
out,
"{} {}::{}{}*",
class_name,
NAMESPACE,
scalar_kind_string(kind),
vector_size_string(size),
)
}
crate::TypeInner::Array { .. } | crate::TypeInner::Struct { .. } => unreachable!(),
crate::TypeInner::Image {
dim,
arrayed,
class,
} => {
let dim_str = match dim {
crate::ImageDimension::D1 => "1d",
crate::ImageDimension::D2 => "2d",
crate::ImageDimension::D3 => "3d",
crate::ImageDimension::Cube => "cube",
};
let (texture_str, msaa_str, kind, access) = match class {
crate::ImageClass::Sampled { kind, multi } => {
("texture", if multi { "_ms" } else { "" }, kind, "sample")
}
crate::ImageClass::Depth => ("depth", "", crate::ScalarKind::Float, "sample"),
crate::ImageClass::Storage(format) => {
let access = if self
.access
.contains(crate::StorageAccess::LOAD | crate::StorageAccess::STORE)
{
"read_write"
} else if self.access.contains(crate::StorageAccess::STORE) {
"write"
} else if self.access.contains(crate::StorageAccess::LOAD) {
"read"
} else {
unreachable!("module is not valid")
};
("texture", "", format.into(), access)
}
};
let base_name = scalar_kind_string(kind);
let array_str = if arrayed { "_array" } else { "" };
write!(
out,
"{}::{}{}{}{}<{}, {}::access::{}>",
NAMESPACE,
texture_str,
dim_str,
msaa_str,
array_str,
base_name,
NAMESPACE,
access,
)
}
crate::TypeInner::Sampler { comparison: _ } => {
write!(out, "{}::sampler", NAMESPACE)
}
}
}
}
struct TypedGlobalVariable<'a> {
module: &'a crate::Module,
names: &'a FastHashMap<NameKey, String>,
@ -43,7 +191,14 @@ impl<'a> TypedGlobalVariable<'a> {
fn try_fmt<W: Write>(&self, out: &mut W) -> Result<(), Error> {
let var = &self.module.global_variables[self.handle];
let name = &self.names[&NameKey::GlobalVariable(self.handle)];
let ty_name = &self.names[&NameKey::Type(var.ty)];
let ty_name = TypeContext {
handle: var.ty,
arena: &self.module.types,
names: self.names,
usage: self.usage,
access: var.storage_access,
first_time: false,
};
let (space, access, reference) = match var.class.get_name(self.usage) {
Some(space) if self.reference => {
@ -143,6 +298,25 @@ impl crate::StorageClass {
}
}
impl crate::Type {
// Returns `true` if we need to emit a type alias for this type.
fn needs_alias(&self) -> bool {
use crate::TypeInner as Ti;
match self.inner {
// value types are concise enough, we only alias them if they are named
Ti::Scalar { .. }
| Ti::Vector { .. }
| Ti::Matrix { .. }
| Ti::Pointer { .. }
| Ti::ValuePointer { .. } => self.name.is_some(),
// composite types are better to be aliased, regardless of the name
Ti::Struct { .. } | Ti::Array { .. } => true,
// handle types may be different, depending on the global var access, so we always inline them
Ti::Image { .. } | Ti::Sampler { .. } => false,
}
}
}
enum FunctionOrigin {
Handle(Handle<crate::Function>),
EntryPoint(EntryPointIndex),
@ -830,7 +1004,14 @@ impl<W: Write> Writer<W> {
) -> Result<(), Error> {
match context.info[handle].ty {
TypeResolution::Handle(ty_handle) => {
let ty_name = &self.names[&NameKey::Type(ty_handle)];
let ty_name = TypeContext {
handle: ty_handle,
arena: &context.module.types,
names: &self.names,
usage: GlobalUse::all(),
access: crate::StorageAccess::empty(),
first_time: false,
};
write!(self.out, "{}", ty_name)?;
}
TypeResolution::Value(crate::TypeInner::Scalar { kind, .. }) => {
@ -1096,92 +1277,25 @@ impl<W: Write> Writer<W> {
fn write_type_defs(&mut self, module: &crate::Module) -> Result<(), Error> {
for (handle, ty) in module.types.iter() {
if !ty.needs_alias() {
continue;
}
let name = &self.names[&NameKey::Type(handle)];
let global_use = GlobalUse::all(); //TODO
match ty.inner {
// work around Metal toolchain bug with `uint` typedef
crate::TypeInner::Scalar {
kind: crate::ScalarKind::Uint,
..
} => {
writeln!(self.out, "typedef metal::uint {};", name)?;
}
crate::TypeInner::Scalar { kind, .. } => {
writeln!(self.out, "typedef {} {};", scalar_kind_string(kind), name)?;
}
crate::TypeInner::Vector { size, kind, .. } => {
writeln!(
self.out,
"typedef {}::{}{} {};",
NAMESPACE,
scalar_kind_string(kind),
vector_size_string(size),
name
)?;
}
crate::TypeInner::Matrix { columns, rows, .. } => {
writeln!(
self.out,
"typedef {}::{}{}x{} {};",
NAMESPACE,
scalar_kind_string(crate::ScalarKind::Float),
vector_size_string(columns),
vector_size_string(rows),
name
)?;
}
crate::TypeInner::Pointer { base, class } => {
let base_name = &self.names[&NameKey::Type(base)];
let class_name = match class.get_name(global_use) {
Some(name) => name,
None => continue,
};
writeln!(self.out, "typedef {} {} *{};", class_name, base_name, name)?;
}
crate::TypeInner::ValuePointer {
size: None,
kind,
width: _,
class,
} => {
let class_name = match class.get_name(global_use) {
Some(name) => name,
None => continue,
};
writeln!(
self.out,
"typedef {} {} *{};",
class_name,
scalar_kind_string(kind),
name
)?;
}
crate::TypeInner::ValuePointer {
size: Some(size),
kind,
width: _,
class,
} => {
let class_name = match class.get_name(global_use) {
Some(name) => name,
None => continue,
};
writeln!(
self.out,
"typedef {} {}::{}{} {};",
class_name,
NAMESPACE,
scalar_kind_string(kind),
vector_size_string(size),
name
)?;
}
crate::TypeInner::Array {
base,
size,
stride: _,
} => {
let base_name = &self.names[&NameKey::Type(base)];
let base_name = TypeContext {
handle: base,
arena: &module.types,
names: &self.names,
usage: global_use,
access: crate::StorageAccess::empty(),
first_time: false,
};
let size_str = match size {
crate::ArraySize::Constant(const_handle) => {
&self.names[&NameKey::Constant(const_handle)]
@ -1197,68 +1311,28 @@ impl<W: Write> Writer<W> {
writeln!(self.out, "struct {} {{", name)?;
for (index, member) in members.iter().enumerate() {
let member_name = &self.names[&NameKey::StructMember(handle, index as u32)];
let base_name = &self.names[&NameKey::Type(member.ty)];
let base_name = TypeContext {
handle: member.ty,
arena: &module.types,
names: &self.names,
usage: global_use,
access: crate::StorageAccess::empty(),
first_time: false,
};
writeln!(self.out, "{}{} {};", INDENT, base_name, member_name)?;
}
writeln!(self.out, "}};")?;
}
crate::TypeInner::Image {
dim,
arrayed,
class,
} => {
let dim_str = match dim {
crate::ImageDimension::D1 => "1d",
crate::ImageDimension::D2 => "2d",
crate::ImageDimension::D3 => "3d",
crate::ImageDimension::Cube => "cube",
_ => {
let ty_name = TypeContext {
handle,
arena: &module.types,
names: &self.names,
usage: global_use,
access: crate::StorageAccess::empty(),
first_time: true,
};
let (texture_str, msaa_str, kind, access) = match class {
crate::ImageClass::Sampled { kind, multi } => {
("texture", if multi { "_ms" } else { "" }, kind, "sample")
}
crate::ImageClass::Depth => {
("depth", "", crate::ScalarKind::Float, "sample")
}
crate::ImageClass::Storage(format) => {
let (_, global) = module
.global_variables
.iter()
.find(|&(_, ref var)| var.ty == handle)
.expect("Unable to find a global variable using the image type");
let access = if global
.storage_access
.contains(crate::StorageAccess::LOAD | crate::StorageAccess::STORE)
{
"read_write"
} else if global.storage_access.contains(crate::StorageAccess::STORE) {
"write"
} else if global.storage_access.contains(crate::StorageAccess::LOAD) {
"read"
} else {
return Err(Error::Validation);
};
("texture", "", format.into(), access)
}
};
let base_name = scalar_kind_string(kind);
let array_str = if arrayed { "_array" } else { "" };
writeln!(
self.out,
"typedef {}::{}{}{}{}<{}, {}::access::{}> {};",
NAMESPACE,
texture_str,
dim_str,
msaa_str,
array_str,
base_name,
NAMESPACE,
access,
name
)?;
}
crate::TypeInner::Sampler { comparison: _ } => {
writeln!(self.out, "typedef {}::sampler {};", NAMESPACE, name)?;
writeln!(self.out, "typedef {} {};", ty_name, name)?;
}
}
}
@ -1305,7 +1379,14 @@ impl<W: Write> Writer<W> {
crate::ConstantInner::Scalar { .. } => {}
crate::ConstantInner::Composite { ty, ref components } => {
let name = &self.names[&NameKey::Constant(handle)];
let ty_name = &self.names[&NameKey::Type(ty)];
let ty_name = TypeContext {
handle: ty,
arena: &module.types,
names: &self.names,
usage: GlobalUse::empty(),
access: crate::StorageAccess::empty(),
first_time: false,
};
write!(self.out, "constexpr constant {} {} = {{", ty_name, name,)?;
for (i, &sub_handle) in components.iter().enumerate() {
let separator = if i != 0 { ", " } else { "" };
@ -1415,16 +1496,36 @@ impl<W: Write> Writer<W> {
}
}
writeln!(self.out)?;
let fun_name = &self.names[&NameKey::Function(fun_handle)];
let result_type_name = match fun.result {
Some(ref result) => &self.names[&NameKey::Type(result.ty)],
None => "void",
};
writeln!(self.out, "{} {}(", result_type_name, fun_name)?;
match fun.result {
Some(ref result) => {
let ty_name = TypeContext {
handle: result.ty,
arena: &module.types,
names: &self.names,
usage: GlobalUse::empty(),
access: crate::StorageAccess::empty(),
first_time: false,
};
write!(self.out, "{}", ty_name)?;
}
None => {
write!(self.out, "void")?;
}
}
writeln!(self.out, " {}(", fun_name)?;
for (index, arg) in fun.arguments.iter().enumerate() {
let name = &self.names[&NameKey::FunctionArgument(fun_handle, index as u32)];
let param_type_name = &self.names[&NameKey::Type(arg.ty)];
let param_type_name = TypeContext {
handle: arg.ty,
arena: &module.types,
names: &self.names,
usage: GlobalUse::empty(),
access: crate::StorageAccess::empty(),
first_time: false,
};
let separator =
separate(!pass_through_globals.is_empty() || index + 1 != fun.arguments.len());
writeln!(
@ -1449,7 +1550,14 @@ impl<W: Write> Writer<W> {
writeln!(self.out, ") {{")?;
for (local_handle, local) in fun.local_variables.iter() {
let ty_name = &self.names[&NameKey::Type(local.ty)];
let ty_name = TypeContext {
handle: local.ty,
arena: &module.types,
names: &self.names,
usage: GlobalUse::empty(),
access: crate::StorageAccess::empty(),
first_time: false,
};
let local_name = &self.names[&NameKey::FunctionLocal(fun_handle, local_handle)];
write!(self.out, "{}{} {}", INDENT, ty_name, local_name)?;
if let Some(value) = local.init {
@ -1473,7 +1581,6 @@ impl<W: Write> Writer<W> {
self.named_expressions.clear();
self.put_block(Level(1), &fun.body, &context)?;
writeln!(self.out, "}}")?;
writeln!(self.out)?;
}
let mut info = TranslationInfo {
@ -1503,6 +1610,7 @@ impl<W: Write> Writer<W> {
}
}
writeln!(self.out)?;
let fun_name = &self.names[&NameKey::EntryPoint(ep_index as _)];
info.entry_point_names.push(Ok(fun_name.clone()));
@ -1558,9 +1666,16 @@ impl<W: Write> Writer<W> {
};
varying_count += 1;
let name = &self.names[&name_key];
let type_name = &self.names[&NameKey::Type(ty)];
let ty_name = TypeContext {
handle: ty,
arena: &module.types,
names: &self.names,
usage: GlobalUse::empty(),
access: crate::StorageAccess::empty(),
first_time: false,
};
let resolved = options.resolve_local_binding(binding, in_mode)?;
write!(self.out, "{}{} {}", INDENT, type_name, name)?;
write!(self.out, "{}{} {}", INDENT, ty_name, name)?;
resolved.try_fmt_decorated(&mut self.out, "")?;
writeln!(self.out, ";")?;
}
@ -1592,7 +1707,14 @@ impl<W: Write> Writer<W> {
}
writeln!(self.out, "struct {} {{", stage_out_name)?;
for (name, ty, binding) in result_members {
let type_name = &self.names[&NameKey::Type(ty)];
let ty_name = TypeContext {
handle: ty,
arena: &module.types,
names: &self.names,
usage: GlobalUse::empty(),
access: crate::StorageAccess::empty(),
first_time: false,
};
let binding = binding.ok_or(Error::Validation)?;
if !pipeline_options.allow_point_size
&& *binding == crate::Binding::BuiltIn(crate::BuiltIn::PointSize)
@ -1600,7 +1722,7 @@ impl<W: Write> Writer<W> {
continue;
}
let resolved = options.resolve_local_binding(binding, out_mode)?;
write!(self.out, "{}{} {}", INDENT, type_name, name)?;
write!(self.out, "{}{} {}", INDENT, ty_name, name)?;
resolved.try_fmt_decorated(&mut self.out, "")?;
writeln!(self.out, ";")?;
}
@ -1626,7 +1748,14 @@ impl<W: Write> Writer<W> {
_ => continue,
};
let name = &self.names[&name_key];
let type_name = &self.names[&NameKey::Type(ty)];
let ty_name = TypeContext {
handle: ty,
arena: &module.types,
names: &self.names,
usage: GlobalUse::empty(),
access: crate::StorageAccess::empty(),
first_time: false,
};
let resolved = options.resolve_local_binding(binding, in_mode)?;
let separator = if is_first_argument {
is_first_argument = false;
@ -1634,7 +1763,7 @@ impl<W: Write> Writer<W> {
} else {
','
};
write!(self.out, "{} {} {}", separator, type_name, name)?;
write!(self.out, "{} {} {}", separator, ty_name, name)?;
resolved.try_fmt_decorated(&mut self.out, "\n")?;
}
for (handle, var) in module.global_variables.iter() {
@ -1763,7 +1892,14 @@ impl<W: Write> Writer<W> {
//TODO: we can postpone this till the relevant expressions are emitted
for (local_handle, local) in fun.local_variables.iter() {
let name = &self.names[&NameKey::EntryPointLocal(ep_index as _, local_handle)];
let ty_name = &self.names[&NameKey::Type(local.ty)];
let ty_name = TypeContext {
handle: local.ty,
arena: &module.types,
names: &self.names,
usage: GlobalUse::empty(),
access: crate::StorageAccess::empty(),
first_time: false,
};
write!(self.out, "{}{} {}", INDENT, ty_name, name)?;
if let Some(value) = local.init {
let value_str = &self.names[&NameKey::Constant(value)];

View File

@ -14,46 +14,42 @@ constexpr constant unsigned const_1u = 1u;
constexpr constant float const_1f = 1.0;
constexpr constant float const_0_10f = 0.1;
constexpr constant float const_n1f = -1.0;
typedef metal::uint type;
typedef metal::float2 type1;
struct Particle {
type1 pos;
type1 vel;
metal::float2 pos;
metal::float2 vel;
};
typedef float type2;
struct SimParams {
type2 deltaT;
type2 rule1Distance;
type2 rule2Distance;
type2 rule3Distance;
type2 rule1Scale;
type2 rule2Scale;
type2 rule3Scale;
float deltaT;
float rule1Distance;
float rule2Distance;
float rule3Distance;
float rule1Scale;
float rule2Scale;
float rule3Scale;
};
typedef Particle type3[1];
struct Particles {
type3 particles;
};
typedef metal::uint3 type4;
typedef int type5;
struct main1Input {
};
kernel void main1(
type4 global_invocation_id [[thread_position_in_grid]]
metal::uint3 global_invocation_id [[thread_position_in_grid]]
, constant SimParams& params [[buffer(0)]]
, constant Particles& particlesSrc [[buffer(1)]]
, device Particles& particlesDst [[buffer(2)]]
) {
type1 vPos;
type1 vVel;
type1 cMass;
type1 cVel;
type1 colVel;
type5 cMassCount = const_0i;
type5 cVelCount = const_0i;
type1 pos1;
type1 vel1;
type i = const_0u;
metal::float2 vPos;
metal::float2 vVel;
metal::float2 cMass;
metal::float2 cVel;
metal::float2 colVel;
int cMassCount = const_0i;
int cVelCount = const_0i;
metal::float2 pos1;
metal::float2 vel1;
metal::uint i = const_0u;
if (global_invocation_id.x >= NUM_PARTICLES) {
return;
}

View File

@ -9,17 +9,16 @@ constexpr constant unsigned const_0u = 0u;
constexpr constant unsigned const_1u = 1u;
constexpr constant unsigned const_2u = 2u;
constexpr constant unsigned const_3u = 3u;
typedef metal::uint type;
typedef type type1[1];
typedef metal::uint type1[1];
struct PrimeIndices {
type1 data;
};
typedef metal::uint3 type2;
type collatz_iterations(
type n_base
metal::uint collatz_iterations(
metal::uint n_base
) {
type n;
type i = const_0u;
metal::uint n;
metal::uint i = const_0u;
n = n_base;
while(true) {
if (n <= const_1u) {
@ -38,10 +37,10 @@ type collatz_iterations(
struct main1Input {
};
kernel void main1(
type2 global_id [[thread_position_in_grid]]
metal::uint3 global_id [[thread_position_in_grid]]
, device PrimeIndices& v_indices [[user(fake0)]]
) {
type _expr9 = collatz_iterations(v_indices.data[global_id.x]);
metal::uint _expr9 = collatz_iterations(v_indices.data[global_id.x]);
v_indices.data[global_id.x] = _expr9;
return;
}

View File

@ -5,6 +5,7 @@ expression: msl
#include <metal_stdlib>
#include <simd/simd.h>
kernel void main1(
) {
return;

View File

@ -7,17 +7,13 @@ expression: msl
constexpr constant int const_10i = 10;
constexpr constant int const_20i = 20;
typedef metal::texture2d<uint, metal::access::read> type;
typedef metal::texture1d<uint, metal::access::write> type1;
typedef metal::uint3 type2;
typedef metal::uint2 type3;
typedef metal::int2 type4;
struct main1Input {
};
kernel void main1(
type2 local_id [[thread_position_in_threadgroup]]
, type image_src [[user(fake0)]]
, type1 image_dst [[user(fake0)]]
metal::uint3 local_id [[thread_position_in_threadgroup]]
, metal::texture2d<uint, metal::access::read> image_src [[user(fake0)]]
, metal::texture1d<uint, metal::access::write> image_dst [[user(fake0)]]
) {
metal::int2 _expr12 = (int2(image_src.get_width(), image_src.get_height()) * static_cast<int2>(metal::uint2(local_id.x, local_id.y))) % metal::int2(const_10i, const_20i);
metal::uint4 _expr13 = image_src.read(metal::uint2(_expr12));

View File

@ -13,57 +13,49 @@ constexpr constant unsigned const_1u = 1u;
constexpr constant int const_0i1 = 0;
constexpr constant float const_0f = 0.0;
constexpr constant float const_1f = 1.0;
typedef float type;
typedef metal::float2 type1;
typedef thread type1 *type2;
typedef thread type1 *type3;
typedef metal::float4 type4;
typedef metal::uint type5;
typedef type type6[const_1u];
typedef float type6[const_1u];
struct gl_PerVertex {
type4 gl_Position;
type gl_PointSize;
metal::float4 gl_Position;
float gl_PointSize;
type6 gl_ClipDistance;
type6 gl_CullDistance;
};
typedef thread gl_PerVertex *type7;
typedef int type8;
typedef thread type4 *type9;
struct type10 {
type1 member;
type4 gl_Position1;
type gl_PointSize1;
metal::float2 member;
metal::float4 gl_Position1;
float gl_PointSize1;
type6 gl_ClipDistance1;
};
void main1(
thread type1& v_uv,
thread type1 const& a_uv,
thread metal::float2& v_uv,
thread metal::float2 const& a_uv,
thread gl_PerVertex& _,
thread type1 const& a_pos
thread metal::float2 const& a_pos
) {
v_uv = a_uv;
type1 _expr13 = a_pos;
metal::float2 _expr13 = a_pos;
_.gl_Position = metal::float4(_expr13.x, _expr13.y, const_0f, const_1f);
return;
}
struct main2Input {
type1 a_uv1 [[attribute(1)]];
type1 a_pos1 [[attribute(0)]];
metal::float2 a_uv1 [[attribute(1)]];
metal::float2 a_pos1 [[attribute(0)]];
};
struct main2Output {
type1 member [[user(loc0)]];
type4 gl_Position1 [[position]];
type gl_PointSize1 [[point_size]];
metal::float2 member [[user(loc0)]];
metal::float4 gl_Position1 [[position]];
float gl_PointSize1 [[point_size]];
type6 gl_ClipDistance1 [[clip_distance]];
};
vertex main2Output main2(
main2Input varyings [[stage_in]]
) {
type1 v_uv = {};
type1 a_uv = {};
metal::float2 v_uv = {};
metal::float2 a_uv = {};
gl_PerVertex _ = {};
type1 a_pos = {};
metal::float2 a_pos = {};
const auto a_uv1 = varyings.a_uv1;
const auto a_pos1 = varyings.a_pos1;
a_uv = a_uv1;

View File

@ -8,22 +8,18 @@ expression: msl
constexpr constant float c_scale = 1.2;
constexpr constant float const_0f = 0.0;
constexpr constant float const_1f = 1.0;
typedef float type;
typedef metal::float2 type1;
typedef metal::float4 type2;
struct VertexOutput {
type1 uv;
type2 position;
metal::float2 uv;
metal::float4 position;
};
typedef metal::texture2d<float, metal::access::sample> type3;
typedef metal::sampler type4;
struct main1Input {
type1 pos [[attribute(0)]];
type1 uv1 [[attribute(1)]];
metal::float2 pos [[attribute(0)]];
metal::float2 uv1 [[attribute(1)]];
};
struct main1Output {
type1 uv [[user(loc0)]];
type2 position [[position]];
metal::float2 uv [[user(loc0)]];
metal::float4 position [[position]];
};
vertex main1Output main1(
main1Input varyings [[stage_in]]
@ -37,16 +33,17 @@ vertex main1Output main1(
return main1Output { _tmp.uv, _tmp.position };
}
struct main2Input {
type1 uv2 [[user(loc0)]];
metal::float2 uv2 [[user(loc0)]];
};
struct main2Output {
type2 member1 [[color(0)]];
metal::float4 member1 [[color(0)]];
};
fragment main2Output main2(
main2Input varyings1 [[stage_in]]
, type3 u_texture [[user(fake0)]]
, type4 u_sampler [[user(fake0)]]
, metal::texture2d<float, metal::access::sample> u_texture [[user(fake0)]]
, metal::sampler u_sampler [[user(fake0)]]
) {
const auto uv2 = varyings1.uv2;
metal::float4 _expr4 = u_texture.sample(u_sampler, uv2);

View File

@ -13,33 +13,25 @@ constexpr constant float const_0_05f = 0.05;
constexpr constant unsigned c_max_lights = 10u;
constexpr constant unsigned const_0u = 0u;
constexpr constant unsigned const_1u = 1u;
typedef metal::uint4 type;
struct Globals {
type num_lights;
metal::uint4 num_lights;
};
typedef metal::float4x4 type1;
typedef metal::float4 type2;
struct Light {
type1 proj;
type2 pos;
type2 color;
metal::float4x4 proj;
metal::float4 pos;
metal::float4 color;
};
typedef Light type3[1];
struct Lights {
type3 data;
};
typedef metal::depth2d_array<float, metal::access::sample> type4;
typedef metal::sampler type5;
typedef metal::uint type6;
typedef float type7;
typedef metal::float2 type8;
typedef metal::float3 type9;
constexpr constant type9 c_ambient = {const_0_05f, const_0_05f, const_0_05f};
type7 fetch_shadow(
type6 light_id,
type2 homogeneous_coords,
type4 t_shadow,
type5 sampler_shadow
constexpr constant metal::float3 c_ambient = {const_0_05f, const_0_05f, const_0_05f};
float fetch_shadow(
metal::uint light_id,
metal::float4 homogeneous_coords,
metal::depth2d_array<float, metal::access::sample> t_shadow,
metal::sampler sampler_shadow
) {
if (homogeneous_coords.w <= const_0f) {
return const_1f;
@ -50,23 +42,23 @@ type7 fetch_shadow(
}
struct fs_mainInput {
type9 raw_normal [[user(loc0)]];
type2 position [[user(loc1)]];
metal::float3 raw_normal [[user(loc0)]];
metal::float4 position [[user(loc1)]];
};
struct fs_mainOutput {
type2 member [[color(0)]];
metal::float4 member [[color(0)]];
};
fragment fs_mainOutput fs_main(
fs_mainInput varyings [[stage_in]]
, constant Globals& u_globals [[user(fake0)]]
, constant Lights& s_lights [[user(fake0)]]
, type4 t_shadow [[user(fake0)]]
, type5 sampler_shadow [[user(fake0)]]
, metal::depth2d_array<float, metal::access::sample> t_shadow [[user(fake0)]]
, metal::sampler sampler_shadow [[user(fake0)]]
) {
const auto raw_normal = varyings.raw_normal;
const auto position = varyings.position;
type9 color1 = c_ambient;
type6 i = const_0u;
metal::float3 color1 = c_ambient;
metal::uint i = const_0u;
bool loop_init = true;
while(true) {
if (!loop_init) {
@ -77,7 +69,7 @@ fragment fs_mainOutput fs_main(
break;
}
Light _expr21 = s_lights.data[i];
type7 _expr25 = fetch_shadow(i, _expr21.proj * position, t_shadow, sampler_shadow);
float _expr25 = fetch_shadow(i, _expr21.proj * position, t_shadow, sampler_shadow);
color1 = color1 + ((_expr25 * metal::max(const_0f, metal::dot(metal::normalize(raw_normal), metal::normalize(metal::float3(_expr21.pos.x, _expr21.pos.y, _expr21.pos.z) - metal::float3(position.x, position.y, position.z))))) * metal::float3(_expr21.color.x, _expr21.color.y, _expr21.color.z));
}
return fs_mainOutput { metal::float4(color1, const_1f) };

View File

@ -10,38 +10,31 @@ constexpr constant int const_1i = 1;
constexpr constant float const_4f = 4.0;
constexpr constant float const_1f = 1.0;
constexpr constant float const_0f = 0.0;
typedef metal::float4 type;
typedef metal::float3 type1;
struct VertexOutput {
type position;
type1 uv;
metal::float4 position;
metal::float3 uv;
};
typedef metal::float4x4 type2;
struct Data {
type2 proj_inv;
type2 view;
metal::float4x4 proj_inv;
metal::float4x4 view;
};
typedef metal::uint type3;
typedef int type4;
typedef metal::float3x3 type5;
typedef metal::texturecube<float, metal::access::sample> type6;
typedef metal::sampler type7;
struct vs_mainInput {
};
struct vs_mainOutput {
type position [[position]];
type1 uv [[user(loc0)]];
metal::float4 position [[position]];
metal::float3 uv [[user(loc0)]];
};
vertex vs_mainOutput vs_main(
type3 vertex_index [[vertex_id]]
metal::uint vertex_index [[vertex_id]]
, constant Data& r_data [[buffer(0)]]
) {
type4 tmp1_;
type4 tmp2_;
int tmp1_;
int tmp2_;
VertexOutput out;
tmp1_ = static_cast<int>(vertex_index) / const_2i;
tmp2_ = static_cast<int>(vertex_index) & const_1i;
type _expr24 = metal::float4((static_cast<float>(tmp1_) * const_4f) - const_1f, (static_cast<float>(tmp2_) * const_4f) - const_1f, const_0f, const_1f);
metal::float4 _expr24 = metal::float4((static_cast<float>(tmp1_) * const_4f) - const_1f, (static_cast<float>(tmp2_) * const_4f) - const_1f, const_0f, const_1f);
metal::float4 _expr50 = r_data.proj_inv * _expr24;
out.uv = metal::transpose(metal::float3x3(metal::float3(r_data.view[0].x, r_data.view[0].y, r_data.view[0].z), metal::float3(r_data.view[1].x, r_data.view[1].y, r_data.view[1].z), metal::float3(r_data.view[2].x, r_data.view[2].y, r_data.view[2].z))) * metal::float3(_expr50.x, _expr50.y, _expr50.z);
out.position = _expr24;
@ -49,16 +42,17 @@ vertex vs_mainOutput vs_main(
return vs_mainOutput { _tmp.position, _tmp.uv };
}
struct fs_mainInput {
type1 uv [[user(loc0)]];
metal::float3 uv [[user(loc0)]];
};
struct fs_mainOutput {
type member1 [[color(0)]];
metal::float4 member1 [[color(0)]];
};
fragment fs_mainOutput fs_main(
fs_mainInput varyings1 [[stage_in]]
, type position [[position]]
, type6 r_texture [[texture(0)]]
, metal::float4 position [[position]]
, metal::texturecube<float, metal::access::sample> r_texture [[texture(0)]]
) {
constexpr metal::sampler r_sampler(
metal::s_address::clamp_to_edge,