use {
crate::{
env::VarKind,
generate::{BackendWriter, BlockGenerator, ExprGenerator},
ident::{Ident, IdentPath},
shaderast::*,
span::Span,
swizzle::Swizzle,
ty::{Ty, TyLit},
},
std::cell::Cell,
std::collections::HashSet,
std::fmt::Write,
};
pub fn generate_vertex_shader(shader: &ShaderAst) -> String {
let mut string = String::new();
ShaderGenerator { shader, string: &mut string, backend_writer: &GlslBackendWriter() }.generate_vertex_shader();
string
}
pub fn generate_fragment_shader(shader: &ShaderAst) -> String {
let mut string = String::new();
ShaderGenerator { shader, string: &mut string, backend_writer: &GlslBackendWriter() }.generate_fragment_shader();
string
}
struct ShaderGenerator<'a> {
shader: &'a ShaderAst,
string: &'a mut String,
backend_writer: &'a dyn BackendWriter,
}
impl<'a, 'b> ShaderGenerator<'a> {
fn write_ty_init(&mut self, ty: &Ty) {
write!(
self.string,
"{}",
match ty {
Ty::Bool => "false",
Ty::Int => "0",
Ty::Float => "0.0",
Ty::Bvec2 => "bvec2(0)",
Ty::Bvec3 => "bvec3(0)",
Ty::Bvec4 => "bvec4(0)",
Ty::Ivec2 => "ivec2(0)",
Ty::Ivec3 => "ivec3(0)",
Ty::Ivec4 => "ivec4(0)",
Ty::Vec2 => "vec2(0.0)",
Ty::Vec3 => "vec3(0.0)",
Ty::Vec4 => "vec4(0.0)",
Ty::Mat2 => "mat2(0.0)",
Ty::Mat3 => "mat3(0.0)",
Ty::Mat4 => "mat4(0.0)",
_ => panic!("unexpected as initializeable type"),
}
)
.unwrap()
}
fn generate_vertex_shader(&mut self) {
let packed_geometries_size = self.compute_packed_geometries_size();
let packed_instances_size = self.compute_packed_instances_size();
let packed_varyings_size = self.compute_packed_varyings_size();
self.generate_decls(Some(packed_geometries_size), Some(packed_instances_size), packed_varyings_size);
for decl in &self.shader.decls {
match decl {
Decl::Geometry(decl) => {
self.write_var_decl(false, decl.ident, decl.ty_expr.ty.borrow().as_ref().unwrap());
write!(self.string, "=").unwrap();
self.write_ty_init(decl.ty_expr.ty.borrow().as_ref().unwrap());
writeln!(self.string, ";").unwrap();
}
Decl::Instance(decl) => {
self.write_var_decl(false, decl.ident, decl.ty_expr.ty.borrow().as_ref().unwrap());
write!(self.string, "=").unwrap();
self.write_ty_init(decl.ty_expr.ty.borrow().as_ref().unwrap());
writeln!(self.string, ";").unwrap();
}
Decl::Varying(decl) => {
self.write_var_decl(false, decl.ident, decl.ty_expr.ty.borrow().as_ref().unwrap());
write!(self.string, "=").unwrap();
self.write_ty_init(decl.ty_expr.ty.borrow().as_ref().unwrap());
writeln!(self.string, ";").unwrap();
}
_ => {}
}
}
let vertex_decl = self.shader.find_fn_decl(IdentPath::from_str("vertex")).unwrap();
for &(ty_lit, ref param_tys) in vertex_decl.cons_fn_deps.borrow_mut().as_ref().unwrap() {
self.generate_cons_fn(ty_lit, param_tys);
}
self.generate_fn_decl(vertex_decl, self.backend_writer);
writeln!(self.string, "void main() {{").unwrap();
let mut geometry_unpacker = VarUnpacker::new("mpsc_packed_geometry", packed_geometries_size, self.string);
for decl in &self.shader.decls {
match decl {
Decl::Geometry(decl) => {
geometry_unpacker.unpack_var(decl.ident, decl.ty_expr.ty.borrow().as_ref().unwrap());
}
_ => {}
}
}
let mut instance_unpacker = VarUnpacker::new("mpsc_packed_instance", packed_instances_size, self.string);
for decl in &self.shader.decls {
match decl {
Decl::Instance(decl) => {
instance_unpacker.unpack_var(decl.ident, decl.ty_expr.ty.borrow().as_ref().unwrap());
}
_ => {}
}
}
writeln!(self.string, " gl_Position = vertex();").unwrap();
let mut varying_packer = VarPacker::new("mpsc_packed_varying", packed_varyings_size, self.string);
for decl in &self.shader.decls {
match decl {
Decl::Geometry(decl) if decl.is_used_in_fragment_shader.get().unwrap() => {
varying_packer.pack_var(decl.ident, decl.ty_expr.ty.borrow().as_ref().unwrap());
}
Decl::Instance(decl) if decl.is_used_in_fragment_shader.get().unwrap() => {
varying_packer.pack_var(decl.ident, decl.ty_expr.ty.borrow().as_ref().unwrap());
}
Decl::Varying(decl) => {
varying_packer.pack_var(decl.ident, decl.ty_expr.ty.borrow().as_ref().unwrap());
}
_ => {}
}
}
writeln!(self.string, "}}").unwrap();
}
fn generate_fragment_shader(&mut self) {
let packed_varyings_size = self.compute_packed_varyings_size();
self.generate_decls(None, None, packed_varyings_size);
for decl in &self.shader.decls {
match decl {
Decl::Geometry(decl) if decl.is_used_in_fragment_shader.get().unwrap() => {
self.write_var_decl(false, decl.ident, decl.ty_expr.ty.borrow().as_ref().unwrap());
write!(self.string, "=").unwrap();
self.write_ty_init(decl.ty_expr.ty.borrow().as_ref().unwrap());
writeln!(self.string, ";").unwrap();
}
Decl::Instance(decl) if decl.is_used_in_fragment_shader.get().unwrap() => {
self.write_var_decl(false, decl.ident, decl.ty_expr.ty.borrow().as_ref().unwrap());
write!(self.string, "=").unwrap();
self.write_ty_init(decl.ty_expr.ty.borrow().as_ref().unwrap());
writeln!(self.string, ";").unwrap();
}
Decl::Varying(decl) => {
self.write_var_decl(false, decl.ident, decl.ty_expr.ty.borrow().as_ref().unwrap());
write!(self.string, "=").unwrap();
self.write_ty_init(decl.ty_expr.ty.borrow().as_ref().unwrap());
writeln!(self.string, ";").unwrap();
}
_ => {}
}
}
let pixel_decl = self.shader.find_fn_decl(IdentPath::from_str("pixel")).unwrap();
for &(ty_lit, ref param_tys) in pixel_decl.cons_fn_deps.borrow_mut().as_ref().unwrap() {
self.generate_cons_fn(ty_lit, param_tys);
}
self.generate_fn_decl(pixel_decl, self.backend_writer);
writeln!(self.string, "void main() {{").unwrap();
let mut varying_unpacker = VarUnpacker::new("mpsc_packed_varying", packed_varyings_size, self.string);
for decl in &self.shader.decls {
match decl {
Decl::Geometry(decl) if decl.is_used_in_fragment_shader.get().unwrap() => {
varying_unpacker.unpack_var(decl.ident, decl.ty_expr.ty.borrow().as_ref().unwrap());
}
Decl::Instance(decl) if decl.is_used_in_fragment_shader.get().unwrap() => {
varying_unpacker.unpack_var(decl.ident, decl.ty_expr.ty.borrow().as_ref().unwrap());
}
Decl::Varying(decl) => {
varying_unpacker.unpack_var(decl.ident, decl.ty_expr.ty.borrow().as_ref().unwrap());
}
_ => {}
}
}
writeln!(self.string, " gl_FragColor = pixel();").unwrap();
writeln!(self.string, "}}").unwrap();
}
fn generate_decls(
&mut self,
packed_attributes_size: Option<usize>,
packed_instances_size: Option<usize>,
packed_varyings_size: usize,
) {
for decl in &self.shader.decls {
match decl {
Decl::Struct(decl) => self.generate_struct_decl(decl),
_ => {}
}
}
for decl in &self.shader.decls {
match decl {
Decl::Const(decl) => self.generate_const_decl(decl),
_ => {}
}
}
for decl in &self.shader.decls {
match decl {
Decl::Uniform(decl) => self.generate_uniform_decl(decl),
_ => {}
}
}
for decl in &self.shader.decls {
match decl {
Decl::Texture(decl) => self.generate_texture_decl(decl),
_ => {}
}
}
if let Some(packed_attributes_size) = packed_attributes_size {
self.generate_packed_var_decls("attribute", "mpsc_packed_geometry", packed_attributes_size);
}
if let Some(packed_instances_size) = packed_instances_size {
self.generate_packed_var_decls("attribute", "mpsc_packed_instance", packed_instances_size);
}
self.generate_packed_var_decls("varying", "mpsc_packed_varying", packed_varyings_size);
}
fn generate_struct_decl(&mut self, decl: &StructDecl) {
write!(self.string, "struct {} {{", decl.ident).unwrap();
if !decl.fields.is_empty() {
writeln!(self.string).unwrap();
for field in &decl.fields {
write!(self.string, " ").unwrap();
self.write_var_decl(false, field.ident, field.ty_expr.ty.borrow().as_ref().unwrap());
writeln!(self.string, ";").unwrap();
}
}
writeln!(self.string, "}};").unwrap();
}
fn generate_const_decl(&mut self, decl: &ConstDecl) {
write!(self.string, "const ").unwrap();
self.write_var_decl(false, decl.ident, decl.ty_expr.ty.borrow().as_ref().unwrap());
write!(self.string, " = ").unwrap();
self.generate_expr(&decl.expr);
writeln!(self.string, ";").unwrap();
}
fn generate_uniform_decl(&mut self, decl: &UniformDecl) {
write!(self.string, "uniform ").unwrap();
self.write_var_decl(false, decl.ident, decl.ty_expr.ty.borrow().as_ref().unwrap());
writeln!(self.string, ";").unwrap();
}
fn generate_texture_decl(&mut self, decl: &TextureDecl) {
write!(self.string, "uniform ").unwrap();
self.write_var_decl(false, decl.ident, decl.ty_expr.ty.borrow().as_ref().unwrap());
writeln!(self.string, ";").unwrap();
}
fn compute_packed_geometries_size(&self) -> usize {
let mut packed_attributes_size = 0;
for decl in &self.shader.decls {
packed_attributes_size += match decl {
Decl::Geometry(decl) => decl.ty_expr.ty.borrow().as_ref().unwrap().size(),
_ => 0,
}
}
packed_attributes_size
}
fn compute_packed_instances_size(&self) -> usize {
let mut packed_instances_size = 0;
for decl in &self.shader.decls {
packed_instances_size += match decl {
Decl::Instance(decl) => decl.ty_expr.ty.borrow().as_ref().unwrap().size(),
_ => 0,
}
}
packed_instances_size
}
fn compute_packed_varyings_size(&self) -> usize {
let mut packed_varyings_size = 0;
for decl in &self.shader.decls {
packed_varyings_size += match decl {
Decl::Geometry(decl) if decl.is_used_in_fragment_shader.get().unwrap() => {
decl.ty_expr.ty.borrow().as_ref().unwrap().size()
}
Decl::Instance(decl) if decl.is_used_in_fragment_shader.get().unwrap() => {
decl.ty_expr.ty.borrow().as_ref().unwrap().size()
}
Decl::Varying(decl) => decl.ty_expr.ty.borrow().as_ref().unwrap().size(),
_ => 0,
}
}
packed_varyings_size
}
fn generate_packed_var_decls(
&mut self,
packed_var_qualifier: &'a str,
packed_var_name: &'a str,
mut packed_vars_size: usize,
) {
let mut packed_var_index = 0;
loop {
let packed_var_size = packed_vars_size.min(4);
writeln!(
self.string,
"{} {} {}_{};",
packed_var_qualifier,
match packed_var_size {
0 => break,
1 => "float",
2 => "vec2",
3 => "vec3",
4 => "vec4",
_ => panic!(),
},
packed_var_name,
packed_var_index,
)
.unwrap();
packed_vars_size -= packed_var_size;
packed_var_index += 1;
}
}
fn generate_cons_fn(&mut self, ty_lit: TyLit, param_tys: &[Ty]) {
let mut cons_name = format!("mpsc_{}", ty_lit);
for param_ty in param_tys {
write!(cons_name, "_{}", param_ty).unwrap();
}
if !self.backend_writer.use_cons_fn(&cons_name) {
return;
}
self.write_ty_lit(ty_lit);
write!(self.string, " {}(", cons_name).unwrap();
let mut sep = "";
if param_tys.len() == 1 {
self.write_var_decl(false, Ident::new("x"), ¶m_tys[0])
} else {
for (index, param_ty) in param_tys.iter().enumerate() {
write!(self.string, "{}", sep).unwrap();
self.write_var_decl(false, Ident::new(format!("x{}", index)), param_ty);
sep = ", ";
}
}
writeln!(self.string, ") {{").unwrap();
write!(self.string, " return ").unwrap();
self.write_ty_lit(ty_lit);
write!(self.string, "(").unwrap();
let ty = ty_lit.to_ty();
if param_tys.len() == 1 {
let param_ty = ¶m_tys[0];
match param_ty {
Ty::Bool | Ty::Int | Ty::Float => {
let mut sep = "";
for _ in 0..ty.size() {
write!(self.string, "{}x", sep).unwrap();
sep = ", ";
}
}
Ty::Mat2 | Ty::Mat3 | Ty::Mat4 => {
let dst_size = match ty {
Ty::Mat2 => 2,
Ty::Mat3 => 3,
Ty::Mat4 => 4,
_ => panic!(),
};
let src_size = match param_ty {
Ty::Mat2 => 2,
Ty::Mat3 => 3,
Ty::Mat4 => 4,
_ => panic!(),
};
let mut sep = "";
for col_index in 0..dst_size {
for row_index in 0..dst_size {
if row_index < src_size && col_index < src_size {
write!(self.string, "{}x[{}][{}]", sep, col_index, row_index).unwrap();
} else {
write!(self.string, "{}{}", sep, if col_index == row_index { 1.0 } else { 0.0 }).unwrap();
}
sep = ", ";
}
}
}
_ => panic!(),
}
} else {
let mut sep = "";
for (index_0, param_ty) in param_tys.iter().enumerate() {
if param_ty.size() == 1 {
write!(self.string, "{}x{}", sep, index_0).unwrap();
sep = ", ";
} else {
for index_1 in 0..param_ty.size() {
write!(self.string, "{}x{}[{}]", sep, index_0, index_1).unwrap();
sep = ", ";
}
}
}
}
writeln!(self.string, ");").unwrap();
writeln!(self.string, "}}").unwrap();
}
fn generate_fn_decl(&mut self, decl: &FnDecl, backend_writer: &dyn BackendWriter) {
FnDeclGenerator { shader: self.shader, decl, backend_writer, visited: &mut HashSet::new(), string: self.string }
.generate_fn_decl()
}
fn generate_expr(&mut self, expr: &Expr) {
ExprGenerator {
shader: self.shader,
decl: None,
backend_writer: self.backend_writer,
string: self.string,
}
.generate_expr(expr)
}
fn write_var_decl(&mut self, is_inout: bool, ident: Ident, ty: &Ty) {
self.backend_writer.write_var_decl(self.string, is_inout, false, ident, ty);
}
fn write_ty_lit(&mut self, ty_lit: TyLit) {
self.backend_writer.write_ty_lit(self.string, ty_lit);
}
}
struct FnDeclGenerator<'a> {
shader: &'a ShaderAst,
decl: &'a FnDecl,
visited: &'a mut HashSet<IdentPath>,
string: &'a mut String,
backend_writer: &'a dyn BackendWriter,
}
impl<'a> FnDeclGenerator<'a> {
fn generate_fn_decl(&mut self) {
if self.visited.contains(&self.decl.ident_path) {
return;
}
for &callee in self.decl.callees.borrow().as_ref().unwrap().iter() {
FnDeclGenerator {
shader: self.shader,
decl: self.shader.find_fn_decl(callee).unwrap(),
visited: self.visited,
backend_writer: self.backend_writer,
string: self.string,
}
.generate_fn_decl()
}
self.write_var_decl(
false,
self.decl.ident_path.to_struct_fn_ident(), self.decl.return_ty.borrow().as_ref().unwrap(),
);
write!(self.string, "(").unwrap();
let mut sep = "";
for param in &self.decl.params {
write!(self.string, "{}", sep).unwrap();
self.write_var_decl(param.is_inout, param.ident, param.ty_expr.ty.borrow().as_ref().unwrap());
sep = ", ";
}
write!(self.string, ") ").unwrap();
self.generate_block(&self.decl.block);
writeln!(self.string).unwrap();
self.visited.insert(self.decl.ident_path);
}
fn generate_block(&mut self, block: &Block) {
BlockGenerator {
shader: self.shader,
decl: self.decl,
backend_writer: self.backend_writer,
indent_level: 0,
string: self.string,
}
.generate_block(block)
}
fn write_var_decl(&mut self, is_inout: bool, ident: Ident, ty: &Ty) {
self.backend_writer.write_var_decl(self.string, is_inout, false, ident, ty);
}
}
struct VarPacker<'a> {
packed_var_name: &'a str,
packed_vars_size: usize,
packed_var_index: usize,
packed_var_size: usize,
packed_var_offset: usize,
string: &'a mut String,
}
impl<'a> VarPacker<'a> {
fn new(packed_var_name: &'a str, packed_vars_size: usize, string: &'a mut String) -> VarPacker<'a> {
VarPacker {
packed_var_name,
packed_vars_size,
packed_var_index: 0,
packed_var_size: packed_vars_size.min(4),
packed_var_offset: 0,
string,
}
}
fn pack_var(&mut self, ident: Ident, ty: &Ty) {
let var_size = ty.size();
let mut var_offset = 0;
let mut in_matrix = None;
while var_offset < var_size {
let count = var_size - var_offset;
let packed_count = self.packed_var_size - self.packed_var_offset;
let min_count = if var_size > 4 { 1 } else { count.min(packed_count) };
write!(self.string, " {}_{}", self.packed_var_name, self.packed_var_index).unwrap();
if self.packed_var_size > 1 {
write!(self.string, ".{}", Swizzle::from_range(self.packed_var_offset, self.packed_var_offset + min_count))
.unwrap();
}
write!(self.string, " = {}", ident).unwrap();
if var_size > 1 {
if var_size <= 4 {
in_matrix = None;
write!(self.string, ".{}", Swizzle::from_range(var_offset, var_offset + min_count)).unwrap();
} else {
if let Some(in_matrix) = &mut in_matrix {
*in_matrix += 1;
} else {
in_matrix = Some(0);
}
if let Some(in_matrix) = in_matrix {
write!(self.string, "[{}][{}]", in_matrix >> 2, in_matrix & 3,).unwrap();
}
}
}
writeln!(self.string, ";").unwrap();
self.packed_var_offset += min_count;
if self.packed_var_offset == self.packed_var_size {
self.packed_vars_size -= self.packed_var_size;
self.packed_var_index += 1;
self.packed_var_size = self.packed_vars_size.min(4);
self.packed_var_offset = 0;
}
var_offset += min_count;
}
}
}
struct VarUnpacker<'a> {
packed_var_name: &'a str,
packed_vars_size: usize,
packed_var_index: usize,
packed_var_size: usize,
packed_var_offset: usize,
string: &'a mut String,
}
impl<'a> VarUnpacker<'a> {
fn new(packed_var_name: &'a str, packed_vars_size: usize, string: &'a mut String) -> VarUnpacker<'a> {
VarUnpacker {
packed_var_name,
packed_vars_size,
packed_var_index: 0,
packed_var_size: packed_vars_size.min(4),
packed_var_offset: 0,
string,
}
}
fn unpack_var(&mut self, ident: Ident, ty: &Ty) {
let var_size = ty.size();
let mut var_offset = 0;
let mut in_matrix = None;
while var_offset < var_size {
let count = var_size - var_offset;
let packed_count = self.packed_var_size - self.packed_var_offset;
let min_count = if var_size > 4 { 1 } else { count.min(packed_count) };
write!(self.string, " {}", ident).unwrap();
if var_size > 1 {
if var_size <= 4 {
in_matrix = None;
write!(self.string, ".{}", Swizzle::from_range(var_offset, var_offset + min_count)).unwrap();
} else {
if let Some(in_matrix) = &mut in_matrix {
*in_matrix += 1;
} else {
in_matrix = Some(0);
}
if let Some(in_matrix) = in_matrix {
write!(self.string, "[{}][{}]", in_matrix >> 2, in_matrix & 3,).unwrap();
}
}
}
write!(self.string, " = {}_{}", self.packed_var_name, self.packed_var_index).unwrap();
if self.packed_var_size > 1 {
write!(self.string, ".{}", Swizzle::from_range(self.packed_var_offset, self.packed_var_offset + min_count))
.unwrap();
}
writeln!(self.string, ";").unwrap();
var_offset += min_count;
self.packed_var_offset += min_count;
if self.packed_var_offset == self.packed_var_size {
self.packed_vars_size -= self.packed_var_size;
self.packed_var_index += 1;
self.packed_var_size = self.packed_vars_size.min(4);
self.packed_var_offset = 0;
}
}
}
}
struct GlslBackendWriter();
impl BackendWriter for GlslBackendWriter {
fn write_call_expr_hidden_args(&self, _string: &mut String, _ident_path: IdentPath, _shader: &ShaderAst, _sep: &str) {}
fn generate_var_expr(
&self,
string: &mut String,
_span: Span,
ident_path: IdentPath,
_kind: &Cell<Option<VarKind>>,
_shader: &ShaderAst,
_decl: &FnDecl,
_ty: &Option<Ty>,
) {
self.write_ident(string, ident_path.get_single().expect("unexpected"));
}
fn needs_mul_fn_for_matrix_multiplication(&self) -> bool {
false
}
fn needs_unpack_for_matrix_multiplication(&self) -> bool {
false
}
fn use_cons_fn(&self, _what: &str) -> bool {
false
}
fn write_var_decl(&self, string: &mut String, is_inout: bool, is_packed: bool, ident: Ident, ty: &Ty) {
if is_inout {
write!(string, "inout ").unwrap();
}
match *ty {
Ty::Void => {
write!(string, "void ").unwrap();
self.write_ident(string, ident);
}
Ty::Bool => {
self.write_ty_lit(string, TyLit::Bool);
write!(string, " ").unwrap();
self.write_ident(string, ident);
}
Ty::Int => {
self.write_ty_lit(string, TyLit::Int);
write!(string, " ").unwrap();
self.write_ident(string, ident);
}
Ty::Float => {
self.write_ty_lit(string, TyLit::Float);
write!(string, " ").unwrap();
self.write_ident(string, ident);
}
Ty::Bvec2 => {
self.write_ty_lit(string, TyLit::Bvec2);
write!(string, " ").unwrap();
self.write_ident(string, ident);
}
Ty::Bvec3 => {
self.write_ty_lit(string, TyLit::Bvec3);
write!(string, " ").unwrap();
self.write_ident(string, ident);
}
Ty::Bvec4 => {
self.write_ty_lit(string, TyLit::Bvec4);
write!(string, " ").unwrap();
self.write_ident(string, ident);
}
Ty::Ivec2 => {
self.write_ty_lit(string, TyLit::Ivec2);
write!(string, " ").unwrap();
self.write_ident(string, ident);
}
Ty::Ivec3 => {
self.write_ty_lit(string, TyLit::Ivec3);
write!(string, " ").unwrap();
self.write_ident(string, ident);
}
Ty::Ivec4 => {
self.write_ty_lit(string, TyLit::Ivec4);
write!(string, " ").unwrap();
self.write_ident(string, ident);
}
Ty::Vec2 => {
self.write_ty_lit(string, TyLit::Vec2);
write!(string, " ").unwrap();
self.write_ident(string, ident);
}
Ty::Vec3 => {
self.write_ty_lit(string, TyLit::Vec3);
write!(string, " ").unwrap();
self.write_ident(string, ident);
}
Ty::Vec4 => {
self.write_ty_lit(string, TyLit::Vec4);
write!(string, " ").unwrap();
self.write_ident(string, ident);
}
Ty::Mat2 => {
self.write_ty_lit(string, TyLit::Mat2);
write!(string, " ").unwrap();
self.write_ident(string, ident);
}
Ty::Mat3 => {
self.write_ty_lit(string, TyLit::Mat3);
write!(string, " ").unwrap();
self.write_ident(string, ident);
}
Ty::Mat4 => {
self.write_ty_lit(string, TyLit::Mat4);
write!(string, " ").unwrap();
self.write_ident(string, ident);
}
Ty::Texture2D => {
self.write_ty_lit(string, TyLit::Texture2D);
write!(string, " ").unwrap();
self.write_ident(string, ident);
}
Ty::Array { ref elem_ty, len } => {
self.write_var_decl(string, is_inout, is_packed, ident, elem_ty);
write!(string, "[{}]", len).unwrap();
}
Ty::Struct { ident: struct_ident } => {
write!(string, "{} ", struct_ident).unwrap();
self.write_ident(string, ident);
}
}
}
fn write_ty_lit(&self, string: &mut String, ty_lit: TyLit) {
write!(
string,
"{}",
match ty_lit {
TyLit::Bool => "bool",
TyLit::Int => "int",
TyLit::Float => "float",
TyLit::Bvec2 => "bvec2",
TyLit::Bvec3 => "bvec3",
TyLit::Bvec4 => "bvec4",
TyLit::Ivec2 => "ivec2",
TyLit::Ivec3 => "ivec3",
TyLit::Ivec4 => "ivec4",
TyLit::Vec2 => "vec2",
TyLit::Vec3 => "vec3",
TyLit::Vec4 => "vec4",
TyLit::Mat2 => "mat2",
TyLit::Mat3 => "mat3",
TyLit::Mat4 => "mat4",
TyLit::Texture2D => "sampler2D",
}
)
.unwrap();
}
fn write_call_ident(&self, string: &mut String, ident: Ident, _arg_exprs: &[Expr]) {
self.write_ident(string, ident);
}
fn write_ident(&self, string: &mut String, ident: Ident) {
ident.with(|ident_string| {
write!(
string,
"{}",
match ident_string {
"union" => "mpsc_union",
"texture" => "mpsc_texture",
_ => ident_string,
}
)
.unwrap()
})
}
}