From e7502d0a9be0313227ebdebb462abf2764553b23 Mon Sep 17 00:00:00 2001 From: Dzmitry Malyshau Date: Mon, 26 Jul 2021 00:24:05 -0400 Subject: [PATCH] hlsl: factor storage logic into a separate module --- src/back/hlsl/help.rs | 2 +- src/back/hlsl/mod.rs | 21 +- src/back/hlsl/storage.rs | 395 +++++++++++++++++++++++++++++++++++ src/back/hlsl/writer.rs | 433 ++------------------------------------- 4 files changed, 433 insertions(+), 418 deletions(-) create mode 100644 src/back/hlsl/storage.rs diff --git a/src/back/hlsl/help.rs b/src/back/hlsl/help.rs index aef71ddb2a..7102319017 100644 --- a/src/back/hlsl/help.rs +++ b/src/back/hlsl/help.rs @@ -21,7 +21,7 @@ // int dim_1d = NagaDimensions1D(image_1d); // ``` -use super::{super::FunctionCtx, writer::BackendResult}; +use super::{super::FunctionCtx, BackendResult}; use crate::arena::Handle; use std::fmt::Write; diff --git a/src/back/hlsl/mod.rs b/src/back/hlsl/mod.rs index 1b5e70b92f..72ec44e3a4 100644 --- a/src/back/hlsl/mod.rs +++ b/src/back/hlsl/mod.rs @@ -9,12 +9,13 @@ mod conv; mod help; mod keywords; +mod storage; mod writer; use std::fmt::Error as FmtError; use thiserror::Error; -pub use writer::Writer; +use crate::proc; #[derive(Clone, Debug, Default, PartialEq, Eq, Hash)] #[cfg_attr(feature = "serialize", derive(serde::Serialize))] @@ -69,6 +70,9 @@ impl crate::ImageDimension { } } +/// Shorthand result used internally by the backend +type BackendResult = Result<(), Error>; + #[derive(Clone, Debug, PartialEq, thiserror::Error)] #[cfg_attr(feature = "serialize", derive(serde::Serialize))] #[cfg_attr(feature = "deserialize", derive(serde::Deserialize))] @@ -138,3 +142,18 @@ pub enum Error { #[error("{0}")] Custom(String), } + +pub struct Writer<'a, W> { + out: W, + names: crate::FastHashMap, + namer: proc::Namer, + /// HLSL backend options + options: &'a Options, + /// Information about entry point arguments wrapped into structure + ep_inputs: Vec>, + /// Set of expressions that have associated temporary variables + named_expressions: crate::NamedExpressions, + wrapped_array_lengths: crate::FastHashSet, + wrapped_image_queries: crate::FastHashSet, + temp_access_chain: Vec, +} diff --git a/src/back/hlsl/storage.rs b/src/back/hlsl/storage.rs new file mode 100644 index 0000000000..033bfcf16b --- /dev/null +++ b/src/back/hlsl/storage.rs @@ -0,0 +1,395 @@ +use super::{ + super::{FunctionCtx, INDENT}, + BackendResult, Error, +}; +use crate::{ + proc::{NameKey, TypeResolution}, + Handle, +}; + +use std::{fmt, mem}; + +const STORE_TEMP_NAME: &str = "_value"; + +pub(super) enum SubAccess { + Offset(u32), + Index { + value: Handle, + stride: u32, + }, +} + +pub(super) enum StoreValue { + Expression(Handle), + TempIndex { + depth: usize, + index: u32, + ty: TypeResolution, + }, + TempAccess { + depth: usize, + base: Handle, + member_index: u32, + }, +} + +impl super::Writer<'_, W> { + fn write_storage_address( + &mut self, + module: &crate::Module, + chain: &[SubAccess], + func_ctx: &FunctionCtx, + ) -> BackendResult { + for (i, access) in chain.iter().enumerate() { + if i != 0 { + write!(self.out, "+")?; + } + match *access { + SubAccess::Offset(offset) => { + write!(self.out, "{}", offset)?; + } + SubAccess::Index { value, stride } => { + self.write_expr(module, value, func_ctx)?; + write!(self.out, "*{}", stride)?; + } + } + } + Ok(()) + } + + fn write_storage_load_sequence>( + &mut self, + module: &crate::Module, + var_handle: Handle, + sequence: I, + func_ctx: &FunctionCtx, + ) -> BackendResult { + for (i, (ty_resolution, offset)) in sequence.enumerate() { + // add the index temporarily + self.temp_access_chain.push(SubAccess::Offset(offset)); + if i != 0 { + write!(self.out, ", ")?; + }; + self.write_storage_load(module, var_handle, ty_resolution, func_ctx)?; + self.temp_access_chain.pop(); + } + Ok(()) + } + + /// Helper function to write down the Load operation on a `ByteAddressBuffer`. + pub(super) fn write_storage_load( + &mut self, + module: &crate::Module, + var_handle: Handle, + result_ty: TypeResolution, + func_ctx: &FunctionCtx, + ) -> BackendResult { + match *result_ty.inner_with(&module.types) { + crate::TypeInner::Scalar { kind, width: _ } => { + // working around the borrow checker in `self.write_expr` + let chain = mem::take(&mut self.temp_access_chain); + let var_name = &self.names[&NameKey::GlobalVariable(var_handle)]; + let cast = kind.to_hlsl_cast(); + write!(self.out, "{}({}.Load(", cast, var_name)?; + self.write_storage_address(module, &chain, func_ctx)?; + write!(self.out, "))")?; + self.temp_access_chain = chain; + } + crate::TypeInner::Vector { + size, + kind, + width: _, + } => { + // working around the borrow checker in `self.write_expr` + let chain = mem::take(&mut self.temp_access_chain); + let var_name = &self.names[&NameKey::GlobalVariable(var_handle)]; + let cast = kind.to_hlsl_cast(); + write!(self.out, "{}({}.Load{}(", cast, var_name, size as u8)?; + self.write_storage_address(module, &chain, func_ctx)?; + write!(self.out, "))")?; + self.temp_access_chain = chain; + } + crate::TypeInner::Matrix { + columns, + rows, + width, + } => { + write!( + self.out, + "{}{}x{}(", + crate::ScalarKind::Float.to_hlsl_str(width)?, + columns as u8, + rows as u8, + )?; + let row_stride = width as u32 * rows as u32; + let iter = (0..columns as u32).map(|i| { + let ty_inner = crate::TypeInner::Vector { + size: rows, + kind: crate::ScalarKind::Float, + width, + }; + (TypeResolution::Value(ty_inner), i * row_stride) + }); + self.write_storage_load_sequence(module, var_handle, iter, func_ctx)?; + write!(self.out, ")")?; + } + crate::TypeInner::Array { + base, + size: crate::ArraySize::Constant(const_handle), + .. + } => { + write!(self.out, "{{")?; + let count = module.constants[const_handle].to_array_length().unwrap(); + let stride = module.types[base].inner.span(&module.constants); + let iter = (0..count).map(|i| (TypeResolution::Handle(base), stride * i)); + self.write_storage_load_sequence(module, var_handle, iter, func_ctx)?; + write!(self.out, "}}")?; + } + crate::TypeInner::Struct { ref members, .. } => { + write!(self.out, "{{")?; + let iter = members + .iter() + .map(|m| (TypeResolution::Handle(m.ty), m.offset)); + self.write_storage_load_sequence(module, var_handle, iter, func_ctx)?; + write!(self.out, "}}")?; + } + _ => unreachable!(), + } + Ok(()) + } + + fn write_store_value( + &mut self, + module: &crate::Module, + value: &StoreValue, + func_ctx: &FunctionCtx, + ) -> BackendResult { + match *value { + StoreValue::Expression(expr) => self.write_expr(module, expr, &func_ctx)?, + StoreValue::TempIndex { + depth, + index, + ty: _, + } => write!(self.out, "{}{}[{}]", STORE_TEMP_NAME, depth, index)?, + StoreValue::TempAccess { + depth, + base, + member_index, + } => { + let name = &self.names[&NameKey::StructMember(base, member_index)]; + write!(self.out, "{}{}.{}", STORE_TEMP_NAME, depth, name)? + } + } + Ok(()) + } + + /// Helper function to write down the Store operation on a `ByteAddressBuffer`. + pub(super) fn write_storage_store( + &mut self, + module: &crate::Module, + var_handle: Handle, + value: StoreValue, + func_ctx: &FunctionCtx, + indent: usize, + ) -> BackendResult { + let temp_resolution; + let ty_resolution = match value { + StoreValue::Expression(expr) => &func_ctx.info[expr].ty, + StoreValue::TempIndex { + depth: _, + index: _, + ref ty, + } => ty, + StoreValue::TempAccess { + depth: _, + base, + member_index, + } => { + let ty_handle = match module.types[base].inner { + crate::TypeInner::Struct { ref members, .. } => { + members[member_index as usize].ty + } + _ => unreachable!(), + }; + temp_resolution = TypeResolution::Handle(ty_handle); + &temp_resolution + } + }; + match *ty_resolution.inner_with(&module.types) { + crate::TypeInner::Scalar { .. } => { + // working around the borrow checker in `self.write_expr` + let chain = mem::take(&mut self.temp_access_chain); + let var_name = &self.names[&NameKey::GlobalVariable(var_handle)]; + write!(self.out, "{}{}.Store(", INDENT.repeat(indent), var_name)?; + self.write_storage_address(module, &chain, func_ctx)?; + write!(self.out, ", asuint(")?; + self.write_store_value(module, &value, func_ctx)?; + writeln!(self.out, "));")?; + self.temp_access_chain = chain; + } + crate::TypeInner::Vector { size, .. } => { + // working around the borrow checker in `self.write_expr` + let chain = mem::take(&mut self.temp_access_chain); + let var_name = &self.names[&NameKey::GlobalVariable(var_handle)]; + write!( + self.out, + "{}{}.Store{}(", + INDENT.repeat(indent), + var_name, + size as u8 + )?; + self.write_storage_address(module, &chain, func_ctx)?; + write!(self.out, ", asuint(")?; + self.write_store_value(module, &value, func_ctx)?; + writeln!(self.out, "));")?; + self.temp_access_chain = chain; + } + crate::TypeInner::Matrix { + columns, + rows, + width, + } => { + // first, assign the value to a temporary + writeln!(self.out, "{}{{", INDENT.repeat(indent))?; + let depth = indent + 1; + write!( + self.out, + "{}{}{}x{} {}{} = ", + INDENT.repeat(indent + 1), + crate::ScalarKind::Float.to_hlsl_str(width)?, + columns as u8, + rows as u8, + STORE_TEMP_NAME, + depth, + )?; + self.write_store_value(module, &value, func_ctx)?; + writeln!(self.out, ";")?; + // then iterate the stores + let row_stride = width as u32 * rows as u32; + for i in 0..columns as u32 { + self.temp_access_chain + .push(SubAccess::Offset(i * row_stride)); + let ty_inner = crate::TypeInner::Vector { + size: rows, + kind: crate::ScalarKind::Float, + width, + }; + let sv = StoreValue::TempIndex { + depth, + index: i, + ty: TypeResolution::Value(ty_inner), + }; + self.write_storage_store(module, var_handle, sv, func_ctx, indent + 1)?; + self.temp_access_chain.pop(); + } + // done + writeln!(self.out, "{}}}", INDENT.repeat(indent))?; + } + crate::TypeInner::Array { + base, + size: crate::ArraySize::Constant(const_handle), + .. + } => { + // first, assign the value to a temporary + writeln!(self.out, "{}{{", INDENT.repeat(indent))?; + write!(self.out, "{}", INDENT.repeat(indent + 1))?; + self.write_value_type(module, &module.types[base].inner)?; + let depth = indent + 1; + write!(self.out, " {}{}", STORE_TEMP_NAME, depth)?; + self.write_array_size(module, crate::ArraySize::Constant(const_handle))?; + write!(self.out, " = ")?; + self.write_store_value(module, &value, func_ctx)?; + writeln!(self.out, ";")?; + // then iterate the stores + let count = module.constants[const_handle].to_array_length().unwrap(); + let stride = module.types[base].inner.span(&module.constants); + for i in 0..count { + self.temp_access_chain.push(SubAccess::Offset(i * stride)); + let sv = StoreValue::TempIndex { + depth, + index: i, + ty: TypeResolution::Handle(base), + }; + self.write_storage_store(module, var_handle, sv, func_ctx, indent + 1)?; + self.temp_access_chain.pop(); + } + // done + writeln!(self.out, "{}}}", INDENT.repeat(indent))?; + } + crate::TypeInner::Struct { ref members, .. } => { + // first, assign the value to a temporary + writeln!(self.out, "{}{{", INDENT.repeat(indent))?; + let depth = indent + 1; + let struct_ty = ty_resolution.handle().unwrap(); + let struct_name = &self.names[&NameKey::Type(struct_ty)]; + write!( + self.out, + "{}{} {}{} = ", + INDENT.repeat(indent + 1), + struct_name, + STORE_TEMP_NAME, + depth + )?; + self.write_store_value(module, &value, func_ctx)?; + writeln!(self.out, ";")?; + // then iterate the stores + for (i, member) in members.iter().enumerate() { + self.temp_access_chain + .push(SubAccess::Offset(member.offset)); + let sv = StoreValue::TempAccess { + depth, + base: struct_ty, + member_index: i as u32, + }; + self.write_storage_store(module, var_handle, sv, func_ctx, indent + 1)?; + self.temp_access_chain.pop(); + } + // done + writeln!(self.out, "{}}}", INDENT.repeat(indent))?; + } + _ => unreachable!(), + } + Ok(()) + } + + pub(super) fn fill_access_chain( + &mut self, + module: &crate::Module, + mut cur_expr: Handle, + func_ctx: &FunctionCtx, + ) -> Result, Error> { + self.temp_access_chain.clear(); + loop { + let stride = func_ctx.info[cur_expr] + .ty + .inner_with(&module.types) + .span(&module.constants); + let (next_expr, sub) = match func_ctx.expressions[cur_expr] { + crate::Expression::GlobalVariable(handle) => return Ok(handle), + crate::Expression::Access { base, index } => ( + base, + SubAccess::Index { + value: index, + stride, + }, + ), + crate::Expression::AccessIndex { base, index } => { + match *func_ctx.info[base].ty.inner_with(&module.types) { + crate::TypeInner::Struct { ref members, .. } => { + (base, SubAccess::Offset(members[index as usize].offset)) + } + _ => (base, SubAccess::Offset(index * stride)), + } + } + ref other => { + return Err(Error::Unimplemented(format!( + "Pointer access of {:?}", + other + ))) + } + }; + self.temp_access_chain.push(sub); + cur_expr = next_expr; + } + } +} diff --git a/src/back/hlsl/writer.rs b/src/back/hlsl/writer.rs index 68841b5475..b331d8c278 100644 --- a/src/back/hlsl/writer.rs +++ b/src/back/hlsl/writer.rs @@ -1,51 +1,20 @@ use super::{ help::{MipLevelCoordinate, WrappedArrayLength, WrappedImageQuery}, - Error, Options, + storage::StoreValue, + BackendResult, Error, Options, }; use crate::{ back, proc::{self, NameKey}, valid, Handle, Module, ShaderStage, TypeInner, }; -use std::{fmt, mem}; +use std::fmt; const LOCATION_SEMANTIC: &str = "LOC"; -const STORE_TEMP_NAME: &str = "_value"; - -/// Shorthand result used internally by the backend -pub(super) type BackendResult = Result<(), Error>; - -#[derive(Copy, Clone, PartialEq)] -enum Io { - Input, - Output, -} - -enum SubAccess { - Offset(u32), - Index { - value: Handle, - stride: u32, - }, -} - -enum StoreValue { - Expression(Handle), - TempIndex { - depth: usize, - index: u32, - ty: proc::TypeResolution, - }, - TempAccess { - depth: usize, - base: Handle, - member_index: u32, - }, -} /// Structure contains information required for generating /// wrapped structure of all entry points arguments -struct EntryPointBinding { +pub(super) struct EntryPointBinding { /// Generated structure name name: String, /// Members of generated structure @@ -53,27 +22,18 @@ struct EntryPointBinding { } struct EpStructMember { - pub name: String, - pub ty: Handle, - pub binding: Option, + name: String, + ty: Handle, + binding: Option, } -pub struct Writer<'a, W> { - pub(super) out: W, - names: crate::FastHashMap, - namer: proc::Namer, - /// HLSL backend options - options: &'a Options, - /// Information about entry point arguments wrapped into structure - ep_inputs: Vec>, - /// Set of expressions that have associated temporary variables - named_expressions: crate::NamedExpressions, - pub(super) wrapped_array_lengths: crate::FastHashSet, - pub(super) wrapped_image_queries: crate::FastHashSet, - temp_access_chain: Vec, +#[derive(Copy, Clone, PartialEq)] +enum Io { + Input, + Output, } -impl<'a, W: fmt::Write> Writer<'a, W> { +impl<'a, W: fmt::Write> super::Writer<'a, W> { pub fn new(out: W, options: &'a Options) -> Self { Self { out, @@ -524,8 +484,11 @@ impl<'a, W: fmt::Write> Writer<'a, W> { Ok(()) } - // copy-paste from glsl-out - fn write_array_size(&mut self, module: &Module, size: crate::ArraySize) -> BackendResult { + pub(super) fn write_array_size( + &mut self, + module: &Module, + size: crate::ArraySize, + ) -> BackendResult { write!(self.out, "[")?; // Write the array size @@ -1788,366 +1751,4 @@ impl<'a, W: fmt::Write> Writer<'a, W> { } Ok(()) } - - fn write_storage_address( - &mut self, - module: &Module, - chain: &[SubAccess], - func_ctx: &back::FunctionCtx<'_>, - ) -> BackendResult { - for (i, access) in chain.iter().enumerate() { - if i != 0 { - write!(self.out, "+")?; - } - match *access { - SubAccess::Offset(offset) => { - write!(self.out, "{}", offset)?; - } - SubAccess::Index { value, stride } => { - self.write_expr(module, value, func_ctx)?; - write!(self.out, "*{}", stride)?; - } - } - } - Ok(()) - } - - fn write_storage_load_sequence>( - &mut self, - module: &Module, - var_handle: Handle, - sequence: I, - func_ctx: &back::FunctionCtx<'_>, - ) -> BackendResult { - for (i, (ty_resolution, offset)) in sequence.enumerate() { - // add the index temporarily - self.temp_access_chain.push(SubAccess::Offset(offset)); - if i != 0 { - write!(self.out, ", ")?; - }; - self.write_storage_load(module, var_handle, ty_resolution, func_ctx)?; - self.temp_access_chain.pop(); - } - Ok(()) - } - - /// Helper function to write down the Load operation on a `ByteAddressBuffer`. - fn write_storage_load( - &mut self, - module: &Module, - var_handle: Handle, - result_ty: proc::TypeResolution, - func_ctx: &back::FunctionCtx<'_>, - ) -> BackendResult { - match *result_ty.inner_with(&module.types) { - TypeInner::Scalar { kind, width: _ } => { - // working around the borrow checker in `self.write_expr` - let chain = mem::take(&mut self.temp_access_chain); - let var_name = &self.names[&NameKey::GlobalVariable(var_handle)]; - let cast = kind.to_hlsl_cast(); - write!(self.out, "{}({}.Load(", cast, var_name)?; - self.write_storage_address(module, &chain, func_ctx)?; - write!(self.out, "))")?; - self.temp_access_chain = chain; - } - TypeInner::Vector { - size, - kind, - width: _, - } => { - // working around the borrow checker in `self.write_expr` - let chain = mem::take(&mut self.temp_access_chain); - let var_name = &self.names[&NameKey::GlobalVariable(var_handle)]; - let cast = kind.to_hlsl_cast(); - write!(self.out, "{}({}.Load{}(", cast, var_name, size as u8)?; - self.write_storage_address(module, &chain, func_ctx)?; - write!(self.out, "))")?; - self.temp_access_chain = chain; - } - TypeInner::Matrix { - columns, - rows, - width, - } => { - write!( - self.out, - "{}{}x{}(", - crate::ScalarKind::Float.to_hlsl_str(width)?, - columns as u8, - rows as u8, - )?; - let row_stride = width as u32 * rows as u32; - let iter = (0..columns as u32).map(|i| { - let ty_inner = TypeInner::Vector { - size: rows, - kind: crate::ScalarKind::Float, - width, - }; - (proc::TypeResolution::Value(ty_inner), i * row_stride) - }); - self.write_storage_load_sequence(module, var_handle, iter, func_ctx)?; - write!(self.out, ")")?; - } - TypeInner::Array { - base, - size: crate::ArraySize::Constant(const_handle), - .. - } => { - write!(self.out, "{{")?; - let count = module.constants[const_handle].to_array_length().unwrap(); - let stride = module.types[base].inner.span(&module.constants); - let iter = (0..count).map(|i| (proc::TypeResolution::Handle(base), stride * i)); - self.write_storage_load_sequence(module, var_handle, iter, func_ctx)?; - write!(self.out, "}}")?; - } - TypeInner::Struct { ref members, .. } => { - write!(self.out, "{{")?; - let iter = members - .iter() - .map(|m| (proc::TypeResolution::Handle(m.ty), m.offset)); - self.write_storage_load_sequence(module, var_handle, iter, func_ctx)?; - write!(self.out, "}}")?; - } - _ => unreachable!(), - } - Ok(()) - } - - fn write_store_value( - &mut self, - module: &Module, - value: &StoreValue, - func_ctx: &back::FunctionCtx, - ) -> BackendResult { - match *value { - StoreValue::Expression(expr) => self.write_expr(module, expr, &func_ctx)?, - StoreValue::TempIndex { - depth, - index, - ty: _, - } => write!(self.out, "{}{}[{}]", STORE_TEMP_NAME, depth, index)?, - StoreValue::TempAccess { - depth, - base, - member_index, - } => { - let name = &self.names[&NameKey::StructMember(base, member_index)]; - write!(self.out, "{}{}.{}", STORE_TEMP_NAME, depth, name)? - } - } - Ok(()) - } - - /// Helper function to write down the Store operation on a `ByteAddressBuffer`. - fn write_storage_store( - &mut self, - module: &Module, - var_handle: Handle, - value: StoreValue, - func_ctx: &back::FunctionCtx<'_>, - indent: usize, - ) -> BackendResult { - let temp_resolution; - let ty_resolution = match value { - StoreValue::Expression(expr) => &func_ctx.info[expr].ty, - StoreValue::TempIndex { - depth: _, - index: _, - ref ty, - } => ty, - StoreValue::TempAccess { - depth: _, - base, - member_index, - } => { - let ty_handle = match module.types[base].inner { - TypeInner::Struct { ref members, .. } => members[member_index as usize].ty, - _ => unreachable!(), - }; - temp_resolution = proc::TypeResolution::Handle(ty_handle); - &temp_resolution - } - }; - match *ty_resolution.inner_with(&module.types) { - TypeInner::Scalar { .. } => { - // working around the borrow checker in `self.write_expr` - let chain = mem::take(&mut self.temp_access_chain); - let var_name = &self.names[&NameKey::GlobalVariable(var_handle)]; - write!( - self.out, - "{}{}.Store(", - back::INDENT.repeat(indent), - var_name - )?; - self.write_storage_address(module, &chain, func_ctx)?; - write!(self.out, ", asuint(")?; - self.write_store_value(module, &value, func_ctx)?; - writeln!(self.out, "));")?; - self.temp_access_chain = chain; - } - TypeInner::Vector { size, .. } => { - // working around the borrow checker in `self.write_expr` - let chain = mem::take(&mut self.temp_access_chain); - let var_name = &self.names[&NameKey::GlobalVariable(var_handle)]; - write!( - self.out, - "{}{}.Store{}(", - back::INDENT.repeat(indent), - var_name, - size as u8 - )?; - self.write_storage_address(module, &chain, func_ctx)?; - write!(self.out, ", asuint(")?; - self.write_store_value(module, &value, func_ctx)?; - writeln!(self.out, "));")?; - self.temp_access_chain = chain; - } - TypeInner::Matrix { - columns, - rows, - width, - } => { - // first, assign the value to a temporary - writeln!(self.out, "{}{{", back::INDENT.repeat(indent))?; - let depth = indent + 1; - write!( - self.out, - "{}{}{}x{} {}{} = ", - back::INDENT.repeat(indent + 1), - crate::ScalarKind::Float.to_hlsl_str(width)?, - columns as u8, - rows as u8, - STORE_TEMP_NAME, - depth, - )?; - self.write_store_value(module, &value, func_ctx)?; - writeln!(self.out, ";")?; - // then iterate the stores - let row_stride = width as u32 * rows as u32; - for i in 0..columns as u32 { - self.temp_access_chain - .push(SubAccess::Offset(i * row_stride)); - let ty_inner = TypeInner::Vector { - size: rows, - kind: crate::ScalarKind::Float, - width, - }; - let sv = StoreValue::TempIndex { - depth, - index: i, - ty: proc::TypeResolution::Value(ty_inner), - }; - self.write_storage_store(module, var_handle, sv, func_ctx, indent + 1)?; - self.temp_access_chain.pop(); - } - // done - writeln!(self.out, "{}}}", back::INDENT.repeat(indent))?; - } - TypeInner::Array { - base, - size: crate::ArraySize::Constant(const_handle), - .. - } => { - // first, assign the value to a temporary - writeln!(self.out, "{}{{", back::INDENT.repeat(indent))?; - write!(self.out, "{}", back::INDENT.repeat(indent + 1))?; - self.write_value_type(module, &module.types[base].inner)?; - let depth = indent + 1; - write!(self.out, " {}{}", STORE_TEMP_NAME, depth)?; - self.write_array_size(module, crate::ArraySize::Constant(const_handle))?; - write!(self.out, " = ")?; - self.write_store_value(module, &value, func_ctx)?; - writeln!(self.out, ";")?; - // then iterate the stores - let count = module.constants[const_handle].to_array_length().unwrap(); - let stride = module.types[base].inner.span(&module.constants); - for i in 0..count { - self.temp_access_chain.push(SubAccess::Offset(i * stride)); - let sv = StoreValue::TempIndex { - depth, - index: i, - ty: proc::TypeResolution::Handle(base), - }; - self.write_storage_store(module, var_handle, sv, func_ctx, indent + 1)?; - self.temp_access_chain.pop(); - } - // done - writeln!(self.out, "{}}}", back::INDENT.repeat(indent))?; - } - TypeInner::Struct { ref members, .. } => { - // first, assign the value to a temporary - writeln!(self.out, "{}{{", back::INDENT.repeat(indent))?; - let depth = indent + 1; - let struct_ty = ty_resolution.handle().unwrap(); - let struct_name = &self.names[&NameKey::Type(struct_ty)]; - write!( - self.out, - "{}{} {}{} = ", - back::INDENT.repeat(indent + 1), - struct_name, - STORE_TEMP_NAME, - depth - )?; - self.write_store_value(module, &value, func_ctx)?; - writeln!(self.out, ";")?; - // then iterate the stores - for (i, member) in members.iter().enumerate() { - self.temp_access_chain - .push(SubAccess::Offset(member.offset)); - let sv = StoreValue::TempAccess { - depth, - base: struct_ty, - member_index: i as u32, - }; - self.write_storage_store(module, var_handle, sv, func_ctx, indent + 1)?; - self.temp_access_chain.pop(); - } - // done - writeln!(self.out, "{}}}", back::INDENT.repeat(indent))?; - } - _ => unreachable!(), - } - Ok(()) - } - - fn fill_access_chain( - &mut self, - module: &Module, - mut cur_expr: Handle, - func_ctx: &back::FunctionCtx<'_>, - ) -> Result, Error> { - self.temp_access_chain.clear(); - loop { - let stride = func_ctx.info[cur_expr] - .ty - .inner_with(&module.types) - .span(&module.constants); - let (next_expr, sub) = match func_ctx.expressions[cur_expr] { - crate::Expression::GlobalVariable(handle) => return Ok(handle), - crate::Expression::Access { base, index } => ( - base, - SubAccess::Index { - value: index, - stride, - }, - ), - crate::Expression::AccessIndex { base, index } => { - match *func_ctx.info[base].ty.inner_with(&module.types) { - TypeInner::Struct { ref members, .. } => { - (base, SubAccess::Offset(members[index as usize].offset)) - } - _ => (base, SubAccess::Offset(index * stride)), - } - } - ref other => { - return Err(Error::Unimplemented(format!( - "Pointer access of {:?}", - other - ))) - } - }; - self.temp_access_chain.push(sub); - cur_expr = next_expr; - } - } }