render: Implement PixelBender Operation::Select (renamed from Loop) (#14503)

This commit is contained in:
Aaron Hill 2024-01-10 20:04:50 -05:00 committed by GitHub
parent aeedec19fa
commit 57f6963133
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 85 additions and 10 deletions

View File

@ -1388,8 +1388,44 @@ impl<'a> ShaderBuilder<'a> {
}
}
}
Operation::Loop { unknown } => {
tracing::warn!("Unimplemented Loop opcode with data: {unknown:?}")
Operation::Select {
src1,
src2,
dst,
condition,
} => {
let src1_expr = self.load_src_register(src1)?;
let src2_expr = self.load_src_register(src2)?;
let expr_zero: Handle<Expression> = match condition.kind {
PixelBenderRegKind::Float => self.zerof32,
PixelBenderRegKind::Int => self.zeroi32,
};
if condition.channels.len() != 1 {
panic!("'Select' condition must be a scalar: {condition:?}");
}
// FIXME - `load_src_register` always gives us a vec4 - ideally, we would
// have a flag to avoid this pointless splat-and-extract.
let cond_expr = self.load_src_register(condition)?;
let first_component = self.evaluate_expr(Expression::AccessIndex {
base: cond_expr,
index: 0,
});
let is_true = self.evaluate_expr(Expression::Binary {
op: BinaryOperator::NotEqual,
left: first_component,
right: expr_zero,
});
let select_expr = self.evaluate_expr(Expression::Select {
condition: is_true,
accept: src1_expr,
reject: src2_expr,
});
self.emit_dest_store(select_expr, dst)?;
}
Operation::Nop => {}
}

View File

@ -199,7 +199,7 @@ pub enum Opcode {
SampleNearest = 0x30,
SampleLinear = 0x31,
LoadIntOrFloat = 0x32,
Loop = 0x33,
Select = 0x33,
If = 0x34,
Else = 0x35,
EndIf = 0x36,
@ -250,8 +250,11 @@ pub enum Operation {
},
Else,
EndIf,
Loop {
unknown: Box<[u8]>,
Select {
src1: PixelBenderReg,
src2: PixelBenderReg,
condition: PixelBenderReg,
dst: PixelBenderReg,
},
}
@ -585,11 +588,29 @@ fn read_op<R: Read>(
_ => unreachable!(),
}
}
Opcode::Loop => {
let mut unknown = vec![0u8; 23];
data.read_exact(&mut unknown)?;
shader.operations.push(Operation::Loop {
unknown: unknown.into(),
Opcode::Select => {
let dst = data.read_u16::<LittleEndian>()?;
let mask = data.read_u8()?;
assert_eq!(mask & 0xF, 0);
let dst_reg = read_dst_reg(dst, mask >> 4)?;
let condition = read_uint24(data)?;
assert_eq!(data.read_u8()?, 0);
let condition_reg = read_src_reg(condition, 1)?;
let src1 = read_uint24(data)?;
assert_eq!(data.read_u8()?, 0);
let src_reg1 = read_src_reg(src1, 1)?;
let src2 = read_uint24(data)?;
assert_eq!(data.read_u8()?, 0);
let src_reg2 = read_src_reg(src2, 1)?;
shader.operations.push(Operation::Select {
condition: condition_reg,
src1: src_reg1,
src2: src_reg2,
dst: dst_reg,
});
}
_ => {

Binary file not shown.

After

Width:  |  Height:  |  Size: 344 KiB

View File

@ -0,0 +1,8 @@
Shader metadata: description Value: Ordered Dithering
Shader parameter: matrixHeight Value: 4
Shader parameter: matrixWidth Value: 4
Shader metadata: name Value: OrderDithering
Shader metadata: namespace Value: YourNamespace
Shader input: src Value: null
Shader metadata: vendor Value: YourVendor
Shader metadata: version Value: 1

Binary file not shown.

View File

@ -0,0 +1,10 @@
# Based on https://github.com/FlashBacks1998/Custom-Pixel-Bender-Example-Ordered-Dithering-
# The prints were sorted to avoid relying on object iteration order
num_ticks = 1
[image_comparisons.output]
tolerance = 1
max_outliers = 19813
[player_options]
with_renderer = { optional = false, sample_count = 1 }