[hlsl-out] Implicitly transpose all matrices

This commit is contained in:
Connor Fitzgerald
2021-08-15 19:32:52 -04:00
committed by Dzmitry Malyshau
parent 91ea6e3d83
commit 73be8c7454
6 changed files with 35 additions and 18 deletions

View File

@@ -5,6 +5,17 @@
//! - 5.1
//! - 6.0
//!
//! All matrix construction/deconstruction is row based in HLSL. This means that when
//! we construct a matrix from column vectors, our matrix will be implicitly transposed.
//! The inverse transposition happens when we call `[0]` to get the zeroth column vector.
//!
//! Because all of our matrices are implicitly transposed, we flip arguments to `mul`. `mat * vec`
//! becomes `vec * mat`, etc. This acts as the inverse transpose making the results identical.
//!
//! The only time we don't get this implicit transposition is when reading matrices from Uniforms/Push Constants.
//! To deal with this, we add `row_major` to all declarations of matrices in Uniforms/Push Constants.
//!
//! Finally because all of our matrices are transposed, if you use `mat3x4`, it'll become `float4x3` in HLSL.
mod conv;
mod help;

View File

@@ -1,7 +1,6 @@
//! Logic related to `ByteAddressBuffer` operations.
//!
//! HLSL backend uses byte address buffers for all storage buffers in IR.
//! Matrices have to be transposed, because HLSL syntax implies row majority.
use super::{
super::{FunctionCtx, INDENT},
@@ -122,7 +121,7 @@ impl<W: fmt::Write> super::Writer<'_, W> {
} => {
write!(
self.out,
"transpose({}{}x{}(",
"{}{}x{}(",
crate::ScalarKind::Float.to_hlsl_str(width)?,
rows as u8,
columns as u8,
@@ -144,7 +143,7 @@ impl<W: fmt::Write> super::Writer<'_, W> {
(TypeResolution::Value(ty_inner), i * row_stride)
});
self.write_storage_load_sequence(module, var_handle, iter, func_ctx)?;
write!(self.out, "))")?;
write!(self.out, ")")?;
}
crate::TypeInner::Array {
base,
@@ -267,7 +266,7 @@ impl<W: fmt::Write> super::Writer<'_, W> {
let depth = indent + 1;
write!(
self.out,
"{}{}{}x{} {}{} = transpose(",
"{}{}{}x{} {}{} = ",
INDENT.repeat(indent + 1),
crate::ScalarKind::Float.to_hlsl_str(width)?,
rows as u8,
@@ -276,7 +275,7 @@ impl<W: fmt::Write> super::Writer<'_, W> {
depth,
)?;
self.write_store_value(module, &value, func_ctx)?;
writeln!(self.out, ");")?;
writeln!(self.out, ";")?;
// then iterate the stores
let row_stride = width as u32 * columns as u32;
for i in 0..rows as u32 {

View File

@@ -640,6 +640,10 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> {
}
}
if let TypeInner::Matrix { .. } = module.types[ty].inner {
write!(self.out, "row_major ")?;
}
// Write the member type and name
self.write_type(module, ty)?;
write!(
@@ -700,12 +704,14 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> {
} => {
// The IR supports only float matrix
// https://docs.microsoft.com/en-us/windows/win32/direct3dhlsl/dx-graphics-hlsl-matrix
// Because of the implicit transpose all matrices have in HLSL, we need to tranpose the size as well.
write!(
self.out,
"{}{}x{}",
crate::ScalarKind::Float.to_hlsl_str(width)?,
back::vector_size_str(columns),
back::vector_size_str(rows),
back::vector_size_str(columns),
)?;
}
TypeInner::Image {
@@ -1302,10 +1308,11 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> {
.inner_with(&module.types)
.is_matrix() =>
{
// We intentionally flip the order of multiplication as our matrices are implicitly transposed.
write!(self.out, "mul(")?;
self.write_expr(module, left, func_ctx)?;
write!(self.out, ", ")?;
self.write_expr(module, right, func_ctx)?;
write!(self.out, ", ")?;
self.write_expr(module, left, func_ctx)?;
write!(self.out, ")")?;
}
Expression::Binary { op, left, right } => {