mirror of
https://github.com/gfx-rs/wgpu.git
synced 2026-04-22 03:02:01 -04:00
hlsl: storage writes
This commit is contained in:
committed by
Dzmitry Malyshau
parent
4b6846d5da
commit
284cfcce47
@@ -10,6 +10,7 @@ use crate::{
|
||||
use std::{fmt, mem};
|
||||
|
||||
const LOCATION_SEMANTIC: &str = "LOC";
|
||||
const STORE_TEMP_NAME: &str = "_value";
|
||||
|
||||
/// Shorthand result used internally by the backend
|
||||
pub(super) type BackendResult = Result<(), Error>;
|
||||
@@ -28,6 +29,20 @@ enum SubAccess {
|
||||
},
|
||||
}
|
||||
|
||||
enum StoreValue {
|
||||
Expression(Handle<crate::Expression>),
|
||||
TempIndex {
|
||||
depth: usize,
|
||||
index: u32,
|
||||
ty: proc::TypeResolution,
|
||||
},
|
||||
TempAccess {
|
||||
depth: usize,
|
||||
base: Handle<crate::Type>,
|
||||
member_index: u32,
|
||||
},
|
||||
}
|
||||
|
||||
/// Structure contains information required for generating
|
||||
/// wrapped structure of all entry points arguments
|
||||
struct EntryPointBinding {
|
||||
@@ -521,11 +536,7 @@ impl<'a, W: fmt::Write> Writer<'a, W> {
|
||||
let size = module.constants[const_handle].to_array_length().unwrap();
|
||||
write!(self.out, "{}", size)?;
|
||||
}
|
||||
crate::ArraySize::Dynamic => {
|
||||
//TODO: https://github.com/gfx-rs/naga/issues/1127
|
||||
log::warn!("Dynamically sized arrays are not properly supported yet");
|
||||
write!(self.out, "1")?;
|
||||
}
|
||||
crate::ArraySize::Dynamic => unreachable!(),
|
||||
}
|
||||
|
||||
write!(self.out, "]")?;
|
||||
@@ -965,7 +976,14 @@ impl<'a, W: fmt::Write> Writer<'a, W> {
|
||||
.pointer_class()
|
||||
== Some(crate::StorageClass::Storage)
|
||||
{
|
||||
return Err(Error::Unimplemented("Storage stores".to_string()));
|
||||
let var_handle = self.fill_access_chain(module, pointer, func_ctx)?;
|
||||
self.write_storage_store(
|
||||
module,
|
||||
var_handle,
|
||||
StoreValue::Expression(value),
|
||||
func_ctx,
|
||||
indent,
|
||||
)?;
|
||||
} else if let Some((const_handle, base_ty)) = array_info {
|
||||
let size = module.constants[const_handle].to_array_length().unwrap();
|
||||
writeln!(self.out, "{}{{", INDENT.repeat(indent))?;
|
||||
@@ -1813,7 +1831,7 @@ impl<'a, W: fmt::Write> Writer<'a, W> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Helper function to write down the load operation on a `ByteAddressBuffer`.
|
||||
/// Helper function to write down the Load operation on a `ByteAddressBuffer`.
|
||||
fn write_storage_load(
|
||||
&mut self,
|
||||
module: &Module,
|
||||
@@ -1895,6 +1913,203 @@ impl<'a, W: fmt::Write> Writer<'a, W> {
|
||||
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<crate::GlobalVariable>,
|
||||
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,
|
||||
|
||||
Reference in New Issue
Block a user