naga-agal: Implement m33 and m34 ops

This commit is contained in:
Mike Welsh 2023-04-06 14:56:55 -07:00 committed by Aaron Hill
parent 35ef04eadc
commit 3257cc44cf
1 changed files with 55 additions and 35 deletions

View File

@ -95,6 +95,10 @@ pub(crate) struct NagaBuilder<'a> {
// The Naga representation of 'vec4f' // The Naga representation of 'vec4f'
vec4f: Handle<Type>, vec4f: Handle<Type>,
// The Naga representation of 'mat3x3f'
matrix3x3f: Handle<Type>,
// The Naga representation of 'mat4x3f'
matrix4x3f: Handle<Type>,
// The Naga representation of 'mat4x4f' // The Naga representation of 'mat4x4f'
matrix4x4f: Handle<Type>, matrix4x4f: Handle<Type>,
// The Naga representation of `texture_2d<f32>` // The Naga representation of `texture_2d<f32>`
@ -351,6 +355,30 @@ impl<'a> NagaBuilder<'a> {
let vec4f = VertexAttributeFormat::Float4.to_naga_type(&mut module); let vec4f = VertexAttributeFormat::Float4.to_naga_type(&mut module);
let matrix3x3f = module.types.insert(
Type {
name: None,
inner: TypeInner::Matrix {
columns: VectorSize::Tri,
rows: VectorSize::Tri,
width: 4,
},
},
Span::UNDEFINED,
);
let matrix4x3f = module.types.insert(
Type {
name: None,
inner: TypeInner::Matrix {
columns: VectorSize::Tri,
rows: VectorSize::Quad,
width: 4,
},
},
Span::UNDEFINED,
);
let matrix4x4f = module.types.insert( let matrix4x4f = module.types.insert(
Type { Type {
name: None, name: None,
@ -563,6 +591,8 @@ impl<'a> NagaBuilder<'a> {
vertex_input_expressions: vec![], vertex_input_expressions: vec![],
varying_pointers: vec![], varying_pointers: vec![],
return_type, return_type,
matrix3x3f,
matrix4x3f,
matrix4x4f, matrix4x4f,
vec4f, vec4f,
constant_registers, constant_registers,
@ -910,7 +940,7 @@ impl<'a> NagaBuilder<'a> {
} }
// This is a no-op swizzle - we can just return the base expression // This is a no-op swizzle - we can just return the base expression
if source.swizzle == SWIZZLE_XYZW { if source.swizzle == SWIZZLE_XYZW && output == VectorSize::Quad {
return Ok(base_expr); return Ok(base_expr);
} }
@ -1066,45 +1096,39 @@ impl<'a> NagaBuilder<'a> {
}); });
self.emit_dest_store(dest, expr)?; self.emit_dest_store(dest, expr)?;
} }
// Perform 'M * v', where M is a 4x4 matrix, and 'v' is a column vector. // Perform 'M * v', where M is a matrix, and 'v' is a column vector.
Opcode::M44 => { Opcode::M33 | Opcode::M34 | Opcode::M44 => {
let source2 = match source2 { let source2 = match source2 {
Source2::SourceField(source2) => source2, Source2::SourceField(source2) => source2,
_ => unreachable!(), _ => unreachable!(),
}; };
let (num_rows, ty, vec_size) = match opcode {
Opcode::M33 => (3, self.matrix3x3f, VectorSize::Tri),
Opcode::M34 => (3, self.matrix4x3f, VectorSize::Quad),
Opcode::M44 => (4, self.matrix4x4f, VectorSize::Quad),
_ => unreachable!(),
};
// Read each row of the matrix // Read each row of the matrix
let source2_row0 = self.emit_source_field_load(source2, false)?; let mut components = Vec::with_capacity(num_rows.into());
let source2_row1 = self.emit_source_field_load( for i in 0..num_rows {
&SourceField { let source2_row = self.emit_source_field_load_with_swizzle_out(
reg_num: source2.reg_num + 1, &SourceField {
..source2.clone() reg_num: source2.reg_num + i,
}, ..source2.clone()
false, },
)?; false,
let source2_row2 = self.emit_source_field_load( vec_size,
&SourceField { )?;
reg_num: source2.reg_num + 2, components.push(source2_row);
..source2.clone() }
},
false,
)?;
let source2_row3 = self.emit_source_field_load(
&SourceField {
reg_num: source2.reg_num + 3,
..source2.clone()
},
false,
)?;
// FIXME - The naga spv backend hits an 'unreachable!' // FIXME - The naga spv backend hits an 'unreachable!'
// if we don't create a Statement::Emit for each of these, // if we don't create a Statement::Emit for each of these,
// even though validation passes. We should investigate this // even though validation passes. We should investigate this
// and report it upstream. // and report it upstream.
let matrix = self.evaluate_expr(Expression::Compose { let matrix = self.evaluate_expr(Expression::Compose { ty, components });
ty: self.matrix4x4f,
components: vec![source2_row0, source2_row1, source2_row2, source2_row3],
});
// Naga interprets each component of the matrix as a *column*. // Naga interprets each component of the matrix as a *column*.
// However, the matrix is stored in memory as a *row*, so we need // However, the matrix is stored in memory as a *row*, so we need
@ -1117,7 +1141,8 @@ impl<'a> NagaBuilder<'a> {
arg3: None, arg3: None,
}); });
let vector = self.emit_source_field_load(source1, true)?; let vector =
self.emit_source_field_load_with_swizzle_out(source1, true, vec_size)?;
let multiply = self.evaluate_expr(Expression::Binary { let multiply = self.evaluate_expr(Expression::Binary {
op: BinaryOperator::Multiply, op: BinaryOperator::Multiply,
@ -1627,11 +1652,6 @@ impl<'a> NagaBuilder<'a> {
reject: Block::new(), reject: Block::new(),
}); });
} }
_ => {
return Err(Error::Unimplemented(format!(
"Unimplemented opcode: {opcode:?}",
)))
}
} }
Ok(()) Ok(())
} }