[GPU] Fix scalar ALU swizzles with three-source vector ops
This commit is contained in:
committed by
Radosław Gliński
parent
ec5c875122
commit
92ada8ebc0
@@ -620,7 +620,8 @@ void ShaderInterpreter::ExecuteAluInstruction(ucode::AluInstruction instr) {
|
||||
bool scalar_src_absolute = false;
|
||||
switch (scalar_opcode_info.operand_count) {
|
||||
case 1: {
|
||||
// r#/c#.w or r#/c#.wx.
|
||||
// r#/c#.w, or r#/c#.wx unless the paired vector opcode has three
|
||||
// operands, in which case r#/c#.wz.
|
||||
const float* scalar_src_ptr;
|
||||
uint32_t scalar_src_register = instr.src_reg(3);
|
||||
std::array<float, 4> scalar_src_float_constant;
|
||||
@@ -640,9 +641,11 @@ void ShaderInterpreter::ExecuteAluInstruction(ucode::AluInstruction instr) {
|
||||
scalar_operand_component_count =
|
||||
scalar_opcode_info.single_operand_is_two_component ? 2 : 1;
|
||||
for (uint32_t i = 0; i < scalar_operand_component_count; ++i) {
|
||||
uint32_t source_component =
|
||||
i == 0 ? 3 : (vector_opcode_info.GetOperandCount() == 3 ? 2 : 0);
|
||||
scalar_operands[i] =
|
||||
scalar_src_ptr[ucode::AluInstruction::GetSwizzledComponentIndex(
|
||||
scalar_src_swizzle, (3 + i) & 3)];
|
||||
scalar_src_swizzle, source_component)];
|
||||
}
|
||||
} break;
|
||||
case 2: {
|
||||
|
||||
@@ -1213,7 +1213,8 @@ uint32_t ParsedTextureFetchInstruction::GetNonZeroResultComponents() const {
|
||||
|
||||
static void ParseAluInstructionOperand(const AluInstruction& op, uint32_t i,
|
||||
uint32_t swizzle_component_count,
|
||||
InstructionOperand& out_op) {
|
||||
InstructionOperand& out_op,
|
||||
uint32_t scalar_second_component = 0) {
|
||||
out_op.is_negated = op.src_negate(i);
|
||||
uint32_t reg = op.src_reg(i);
|
||||
if (op.src_is_temp(i)) {
|
||||
@@ -1247,9 +1248,10 @@ static void ParseAluInstructionOperand(const AluInstruction& op, uint32_t i,
|
||||
// Scalar `a` (W).
|
||||
out_op.components[0] = GetSwizzledAluSourceComponent(swizzle, 3);
|
||||
} else if (swizzle_component_count == 2) {
|
||||
// Scalar left-hand `a` (W) and right-hand `b` (X).
|
||||
// Scalar left-hand `a` (W) and right-hand `b` (X or Z).
|
||||
out_op.components[0] = GetSwizzledAluSourceComponent(swizzle, 3);
|
||||
out_op.components[1] = GetSwizzledAluSourceComponent(swizzle, 0);
|
||||
out_op.components[1] =
|
||||
GetSwizzledAluSourceComponent(swizzle, scalar_second_component);
|
||||
} else if (swizzle_component_count == 3) {
|
||||
assert_always();
|
||||
} else if (swizzle_component_count == 4) {
|
||||
@@ -1421,9 +1423,13 @@ void ParseAluInstruction(const AluInstruction& op,
|
||||
instr.scalar_operand_count = scalar_opcode_info.operand_count;
|
||||
if (instr.scalar_operand_count) {
|
||||
if (instr.scalar_operand_count == 1) {
|
||||
// The scalar operation shares source 3 with the vector operation. If the
|
||||
// vector operation uses source 3, the scalar `b` component is Z;
|
||||
// otherwise it is X.
|
||||
ParseAluInstructionOperand(
|
||||
op, 3, scalar_opcode_info.single_operand_is_two_component ? 2 : 1,
|
||||
instr.scalar_operands[0]);
|
||||
instr.scalar_operands[0],
|
||||
vector_opcode_info.GetOperandCount() == 3 ? 2 : 0);
|
||||
} else {
|
||||
// Constant and temporary register.
|
||||
|
||||
|
||||
@@ -942,10 +942,13 @@ static_assert_size(FetchInstruction, sizeof(uint32_t) * 3);
|
||||
// - All temporary registers are vec4s.
|
||||
// - Most scalar ALU operations work with one or two components of the source
|
||||
// register or the float constant passed as the third operand of the whole
|
||||
// co-issued ALU operation, denoted by `a` (the left-hand operand) and `b`
|
||||
// (the right-hand operand).
|
||||
// ALU instruction, denoted by `a` (the left-hand operand) and `b` (the
|
||||
// right-hand operand).
|
||||
// `a` is the [(3 + src3_swizzle[6:7]) & 3] component (W - alpha).
|
||||
// `b` is the [(0 + src3_swizzle[0:1]) & 3] component (X - red).
|
||||
// For single-source two-component scalar operations, `b` is the
|
||||
// [(0 + src3_swizzle[0:1]) & 3] component (X - red), or the
|
||||
// [(2 + src3_swizzle[4:5]) & 3] component (Z - blue) if the vector operation
|
||||
// uses source 3.
|
||||
// - mulsc, addsc, subsc scalar ALU operations accept two operands - a float
|
||||
// constant with the `a` (W) swizzle (addressed by the third operand index and
|
||||
// addressing mode) being the left-hand operand, and a temporary register with
|
||||
@@ -1330,11 +1333,12 @@ enum class AluScalarOpcode : uint32_t {
|
||||
struct AluScalarOpcodeInfo {
|
||||
const char* name;
|
||||
// 0 - no operands.
|
||||
// 1 - one single-component (W) or two-component (WX) r# or c#.
|
||||
// 1 - one single-component (W) or two-component (WX, or WZ if the vector
|
||||
// operation uses source 3) r# or c#.
|
||||
// 2 - c#.w and r#.x.
|
||||
uint32_t operand_count;
|
||||
// If operand_count is 1, whether both W and X of the operand are used rather
|
||||
// than only W.
|
||||
// If operand_count is 1, whether two components of the operand are used
|
||||
// rather than only W.
|
||||
bool single_operand_is_two_component;
|
||||
// Note that all scalar instructions except for retain_prev modify the
|
||||
// previous scalar register, so they must be executed even if they don't write
|
||||
|
||||
Reference in New Issue
Block a user