shader: reuse SPIR-V helpers and memory resources

This commit is contained in:
nmzik
2026-09-08 13:33:18 +04:00
parent fde550ef66
commit 9f49ac8249
7 changed files with 139 additions and 195 deletions
@@ -10,26 +10,6 @@ struct Pair {
uint32_t high = 0;
};
uint32_t NewUnary(EmitterState& state, uint32_t opcode, uint32_t type, uint32_t value) {
const auto result = state.builder.AllocateId();
state.builder.AddFunction({opcode, type, result, value});
return result;
}
uint32_t NewBinary(EmitterState& state, uint32_t opcode, uint32_t type, uint32_t lhs,
uint32_t rhs) {
const auto result = state.builder.AllocateId();
state.builder.AddFunction({opcode, type, result, lhs, rhs});
return result;
}
uint32_t NewSelect(EmitterState& state, uint32_t type, uint32_t condition, uint32_t true_value,
uint32_t false_value) {
const auto result = state.builder.AllocateId();
state.builder.AddFunction({OpSelect, type, result, condition, true_value, false_value});
return result;
}
Pair ExtractPair(EmitterState& state, uint32_t value) {
Pair result {state.builder.AllocateId(), state.builder.AllocateId()};
state.builder.AddFunction({OpCompositeExtract, TypeU32(state), result.low, value, 0});
@@ -45,20 +25,20 @@ uint32_t MakePair(EmitterState& state, uint32_t low, uint32_t high) {
uint32_t CompareEqual64(EmitterState& state, uint32_t lhs_value, uint32_t rhs_value,
bool not_equal) {
const auto compare = NewBinary(state, not_equal ? OpINotEqual : OpIEqual,
const auto compare = Binary(state, not_equal ? OpINotEqual : OpIEqual,
TypeBoolVector(state, 2), lhs_value, rhs_value);
return NewUnary(state, not_equal ? OpAny : OpAll, TypeBool(state), compare);
return Unary(state, not_equal ? OpAny : OpAll, TypeBool(state), compare);
}
uint32_t CompareOrdered64(EmitterState& state, uint32_t lhs_value, uint32_t rhs_value,
uint32_t high_compare, uint32_t low_compare) {
const auto lhs = ExtractPair(state, lhs_value);
const auto rhs = ExtractPair(state, rhs_value);
const auto high_equal = NewBinary(state, OpIEqual, TypeBool(state), lhs.high, rhs.high);
const auto high_result = NewBinary(state, high_compare, TypeBool(state), lhs.high, rhs.high);
const auto low_result = NewBinary(state, low_compare, TypeBool(state), lhs.low, rhs.low);
const auto low_path = NewBinary(state, OpLogicalAnd, TypeBool(state), high_equal, low_result);
return NewBinary(state, OpLogicalOr, TypeBool(state), high_result, low_path);
const auto high_equal = Binary(state, OpIEqual, TypeBool(state), lhs.high, rhs.high);
const auto high_result = Binary(state, high_compare, TypeBool(state), lhs.high, rhs.high);
const auto low_result = Binary(state, low_compare, TypeBool(state), lhs.low, rhs.low);
const auto low_path = Binary(state, OpLogicalAnd, TypeBool(state), high_equal, low_result);
return Binary(state, OpLogicalOr, TypeBool(state), high_result, low_path);
}
uint32_t EmitAdd64(EmitterState& state, uint32_t lhs_value, uint32_t rhs_value) {
@@ -70,20 +50,20 @@ uint32_t EmitAdd64(EmitterState& state, uint32_t lhs_value, uint32_t rhs_value)
state.builder.AddFunction({OpIAddCarry, TypeU32Pair(state), low_pair, lhs.low, rhs.low});
state.builder.AddFunction({OpCompositeExtract, TypeU32(state), low, low_pair, 0});
state.builder.AddFunction({OpCompositeExtract, TypeU32(state), carry, low_pair, 1});
const auto high0 = NewBinary(state, OpIAdd, TypeU32(state), lhs.high, rhs.high);
const auto high = NewBinary(state, OpIAdd, TypeU32(state), high0, carry);
const auto high0 = Binary(state, OpIAdd, TypeU32(state), lhs.high, rhs.high);
const auto high = Binary(state, OpIAdd, TypeU32(state), high0, carry);
return MakePair(state, low, high);
}
uint32_t EmitSub64(EmitterState& state, uint32_t lhs_value, uint32_t rhs_value) {
const auto lhs = ExtractPair(state, lhs_value);
const auto rhs = ExtractPair(state, rhs_value);
const auto low = NewBinary(state, OpISub, TypeU32(state), lhs.low, rhs.low);
const auto borrow = NewBinary(state, OpULessThan, TypeBool(state), lhs.low, rhs.low);
const auto low = Binary(state, OpISub, TypeU32(state), lhs.low, rhs.low);
const auto borrow = Binary(state, OpULessThan, TypeBool(state), lhs.low, rhs.low);
const auto borrow_u32 =
NewSelect(state, TypeU32(state), borrow, ConstantU32(state, 1), ConstantU32(state, 0));
const auto high0 = NewBinary(state, OpISub, TypeU32(state), lhs.high, rhs.high);
const auto high = NewBinary(state, OpISub, TypeU32(state), high0, borrow_u32);
Select(state, TypeU32(state), borrow, ConstantU32(state, 1), ConstantU32(state, 0));
const auto high0 = Binary(state, OpISub, TypeU32(state), lhs.high, rhs.high);
const auto high = Binary(state, OpISub, TypeU32(state), high0, borrow_u32);
return MakePair(state, low, high);
}
@@ -93,27 +73,27 @@ uint32_t EmitMulHigh(EmitterState& state, uint32_t lhs, uint32_t rhs, bool signe
uint32_t lhs_operand = lhs;
uint32_t rhs_operand = rhs;
if (signed_value) {
lhs_operand = NewUnary(state, OpBitcast, TypeI32(state), lhs);
rhs_operand = NewUnary(state, OpBitcast, TypeI32(state), rhs);
lhs_operand = Unary(state, OpBitcast, TypeI32(state), lhs);
rhs_operand = Unary(state, OpBitcast, TypeI32(state), rhs);
}
const auto extended = state.builder.AllocateId();
state.builder.AddFunction({signed_value ? OpSMulExtended : OpUMulExtended, pair_type, extended,
lhs_operand, rhs_operand});
const auto high = state.builder.AllocateId();
state.builder.AddFunction({OpCompositeExtract, operand_type, high, extended, 1});
return signed_value ? NewUnary(state, OpBitcast, TypeU32(state), high) : high;
return signed_value ? Unary(state, OpBitcast, TypeU32(state), high) : high;
}
uint32_t EmitMul64(EmitterState& state, uint32_t lhs_value, uint32_t rhs_value) {
const auto lhs = ExtractPair(state, lhs_value);
const auto rhs = ExtractPair(state, rhs_value);
const auto low = NewBinary(state, OpIMul, TypeU32(state), lhs.low, rhs.low);
const auto low = Binary(state, OpIMul, TypeU32(state), lhs.low, rhs.low);
const auto high0 = EmitMulHigh(state, lhs.low, rhs.low, false);
const auto high1 = NewBinary(state, OpIMul, TypeU32(state), lhs.low, rhs.high);
const auto high2 = NewBinary(state, OpIMul, TypeU32(state), lhs.high, rhs.low);
const auto high1 = Binary(state, OpIMul, TypeU32(state), lhs.low, rhs.high);
const auto high2 = Binary(state, OpIMul, TypeU32(state), lhs.high, rhs.low);
return MakePair(state, low,
NewBinary(state, OpIAdd, TypeU32(state),
NewBinary(state, OpIAdd, TypeU32(state), high0, high1), high2));
Binary(state, OpIAdd, TypeU32(state),
Binary(state, OpIAdd, TypeU32(state), high0, high1), high2));
}
uint32_t EmitShift64(EmitterState& state, uint32_t opcode, uint32_t value, uint32_t shift) {
@@ -126,33 +106,33 @@ uint32_t EmitShift64(EmitterState& state, uint32_t opcode, uint32_t value, uint3
EmitShiftRightLogicalU64Values(state, pair.low, pair.high, shift, low, high);
} else {
const auto amount =
NewBinary(state, OpBitwiseAnd, TypeU32(state), shift, ConstantU32(state, 63));
Binary(state, OpBitwiseAnd, TypeU32(state), shift, ConstantU32(state, 63));
const auto word_shift =
NewBinary(state, OpBitwiseAnd, TypeU32(state), amount, ConstantU32(state, 31));
Binary(state, OpBitwiseAnd, TypeU32(state), amount, ConstantU32(state, 31));
const auto at_least_32 =
NewBinary(state, OpUGreaterThanEqual, TypeBool(state), amount, ConstantU32(state, 32));
Binary(state, OpUGreaterThanEqual, TypeBool(state), amount, ConstantU32(state, 32));
const auto nonzero =
NewBinary(state, OpINotEqual, TypeBool(state), amount, ConstantU32(state, 0));
Binary(state, OpINotEqual, TypeBool(state), amount, ConstantU32(state, 0));
const auto high_shifted =
NewBinary(state, OpShiftRightArithmetic, TypeU32(state), pair.high, word_shift);
Binary(state, OpShiftRightArithmetic, TypeU32(state), pair.high, word_shift);
const auto low_shifted =
NewBinary(state, OpShiftRightLogical, TypeU32(state), pair.low, word_shift);
Binary(state, OpShiftRightLogical, TypeU32(state), pair.low, word_shift);
const auto carry_count =
NewBinary(state, OpBitwiseAnd, TypeU32(state),
NewBinary(state, OpISub, TypeU32(state), ConstantU32(state, 32), word_shift),
Binary(state, OpBitwiseAnd, TypeU32(state),
Binary(state, OpISub, TypeU32(state), ConstantU32(state, 32), word_shift),
ConstantU32(state, 31));
const auto carry =
NewSelect(state, TypeU32(state), nonzero,
NewBinary(state, OpShiftLeftLogical, TypeU32(state), pair.high, carry_count),
Select(state, TypeU32(state), nonzero,
Binary(state, OpShiftLeftLogical, TypeU32(state), pair.high, carry_count),
ConstantU32(state, 0));
const auto low_below_32 = NewBinary(state, OpBitwiseOr, TypeU32(state), low_shifted, carry);
const auto low_below_32 = Binary(state, OpBitwiseOr, TypeU32(state), low_shifted, carry);
const auto negative =
NewBinary(state, OpSLessThan, TypeBool(state), pair.high, ConstantU32(state, 0));
const auto sign_fill = NewSelect(state, TypeU32(state), negative,
Binary(state, OpSLessThan, TypeBool(state), pair.high, ConstantU32(state, 0));
const auto sign_fill = Select(state, TypeU32(state), negative,
ConstantU32(state, 0xffffffffu), ConstantU32(state, 0));
return MakePair(state,
NewSelect(state, TypeU32(state), at_least_32, high_shifted, low_below_32),
NewSelect(state, TypeU32(state), at_least_32, sign_fill, high_shifted));
Select(state, TypeU32(state), at_least_32, high_shifted, low_below_32),
Select(state, TypeU32(state), at_least_32, sign_fill, high_shifted));
}
return MakePair(state, low, high);
}
@@ -165,36 +145,36 @@ uint32_t EmitConstantShift64(EmitterState& state, uint32_t opcode, uint32_t valu
const auto pair = ExtractPair(state, value);
if (opcode == OpShiftLeftLogical) {
if (shift < 32u) {
const auto low = NewBinary(state, OpShiftLeftLogical, TypeU32(state), pair.low,
const auto low = Binary(state, OpShiftLeftLogical, TypeU32(state), pair.low,
ConstantU32(state, shift));
const auto high = NewBinary(state, OpBitwiseOr, TypeU32(state),
NewBinary(state, OpShiftLeftLogical, TypeU32(state),
const auto high = Binary(state, OpBitwiseOr, TypeU32(state),
Binary(state, OpShiftLeftLogical, TypeU32(state),
pair.high, ConstantU32(state, shift)),
NewBinary(state, OpShiftRightLogical, TypeU32(state),
Binary(state, OpShiftRightLogical, TypeU32(state),
pair.low, ConstantU32(state, 32u - shift)));
return MakePair(state, low, high);
}
return MakePair(state, ConstantU32(state, 0),
shift == 32u ? pair.low
: NewBinary(state, OpShiftLeftLogical, TypeU32(state),
: Binary(state, OpShiftLeftLogical, TypeU32(state),
pair.low, ConstantU32(state, shift - 32u)));
}
if (shift < 32u) {
const auto low = NewBinary(state, OpBitwiseOr, TypeU32(state),
NewBinary(state, OpShiftRightLogical, TypeU32(state), pair.low,
const auto low = Binary(state, OpBitwiseOr, TypeU32(state),
Binary(state, OpShiftRightLogical, TypeU32(state), pair.low,
ConstantU32(state, shift)),
NewBinary(state, OpShiftLeftLogical, TypeU32(state), pair.high,
Binary(state, OpShiftLeftLogical, TypeU32(state), pair.high,
ConstantU32(state, 32u - shift)));
const auto high =
NewBinary(state, opcode, TypeU32(state), pair.high, ConstantU32(state, shift));
Binary(state, opcode, TypeU32(state), pair.high, ConstantU32(state, shift));
return MakePair(state, low, high);
}
const auto high = opcode == OpShiftRightArithmetic
? NewBinary(state, OpShiftRightArithmetic, TypeU32(state), pair.high,
? Binary(state, OpShiftRightArithmetic, TypeU32(state), pair.high,
ConstantU32(state, 31u))
: ConstantU32(state, 0);
const auto low = shift == 32u ? pair.high
: NewBinary(state, opcode, TypeU32(state), pair.high,
: Binary(state, opcode, TypeU32(state), pair.high,
ConstantU32(state, shift - 32u));
return MakePair(state, low, high);
}
@@ -207,12 +187,12 @@ uint32_t EmitFindMsb64(EmitterState& state, uint32_t value) {
{OpExtInst, TypeI32(state), high_i, GlslStd450(state), GlslFindUMsb, pair.high});
state.builder.AddFunction(
{OpExtInst, TypeI32(state), low_i, GlslStd450(state), GlslFindUMsb, pair.low});
const auto high = NewUnary(state, OpBitcast, TypeU32(state), high_i);
const auto low = NewUnary(state, OpBitcast, TypeU32(state), low_i);
const auto high = Unary(state, OpBitcast, TypeU32(state), high_i);
const auto low = Unary(state, OpBitcast, TypeU32(state), low_i);
const auto high_nonzero =
NewBinary(state, OpINotEqual, TypeBool(state), pair.high, ConstantU32(state, 0));
return NewSelect(state, TypeU32(state), high_nonzero,
NewBinary(state, OpIAdd, TypeU32(state), high, ConstantU32(state, 32)), low);
Binary(state, OpINotEqual, TypeBool(state), pair.high, ConstantU32(state, 0));
return Select(state, TypeU32(state), high_nonzero,
Binary(state, OpIAdd, TypeU32(state), high, ConstantU32(state, 32)), low);
}
uint32_t EmitMinMax3(EmitterState& state, uint32_t a, uint32_t b, uint32_t c, bool signed_value,
@@ -226,10 +206,10 @@ uint32_t EmitMinMax3(EmitterState& state, uint32_t a, uint32_t b, uint32_t c, bo
uint32_t EmitMed3(EmitterState& state, uint32_t a, uint32_t b, uint32_t c, bool signed_value) {
const auto minimum = EmitMinMax3(state, a, b, c, signed_value, false);
const auto maximum = EmitMinMax3(state, a, b, c, signed_value, true);
const auto ab = NewBinary(state, OpIAdd, TypeU32(state), a, b);
const auto abc = NewBinary(state, OpIAdd, TypeU32(state), ab, c);
return NewBinary(state, OpISub, TypeU32(state),
NewBinary(state, OpISub, TypeU32(state), abc, minimum), maximum);
const auto ab = Binary(state, OpIAdd, TypeU32(state), a, b);
const auto abc = Binary(state, OpIAdd, TypeU32(state), ab, c);
return Binary(state, OpISub, TypeU32(state),
Binary(state, OpISub, TypeU32(state), abc, minimum), maximum);
}
uint32_t EmitFMinMax3(EmitterState& state, uint32_t a, uint32_t b, uint32_t c, bool max_value) {
@@ -242,11 +222,11 @@ uint32_t EmitFMed3(EmitterState& state, uint32_t a, uint32_t b, uint32_t c) {
const auto max_ab = EmitMinMaxF32Value(state, a, b, true);
const auto high_min = EmitMinMaxF32Value(state, max_ab, c, false);
const auto median = EmitMinMaxF32Value(state, min_ab, high_min, true);
const auto nan_ab = NewBinary(state, OpLogicalOr, TypeBool(state),
const auto nan_ab = Binary(state, OpLogicalOr, TypeBool(state),
EmitClassifyF32(state, a).nan, EmitClassifyF32(state, b).nan);
const auto any_nan =
NewBinary(state, OpLogicalOr, TypeBool(state), nan_ab, EmitClassifyF32(state, c).nan);
return NewSelect(state, TypeF32(state), any_nan, min3, median);
Binary(state, OpLogicalOr, TypeBool(state), nan_ab, EmitClassifyF32(state, c).nan);
return Select(state, TypeF32(state), any_nan, min3, median);
}
uint32_t EmitExt(EmitterState& state, uint32_t type, uint32_t opcode,
@@ -270,37 +250,30 @@ uint32_t EmitF32ToU32(EmitterState& state, uint32_t src, bool signed_value) {
}
const auto nan = EmitClassifyF32(state, src).nan;
if (signed_value) {
const auto below = NewBinary(state, OpFOrdLessThanEqual, TypeBool(state), src,
const auto below = Binary(state, OpFOrdLessThanEqual, TypeBool(state), src,
ConstantF32(state, 0xcf000000u));
const auto above = NewBinary(state, OpFOrdGreaterThanEqual, TypeBool(state), src,
const auto above = Binary(state, OpFOrdGreaterThanEqual, TypeBool(state), src,
ConstantF32(state, 0x4f000000u));
const auto high =
NewSelect(state, TypeU32(state), above, ConstantU32(state, 0x7fffffffu), converted_raw);
Select(state, TypeU32(state), above, ConstantU32(state, 0x7fffffffu), converted_raw);
const auto low =
NewSelect(state, TypeU32(state), below, ConstantU32(state, 0x80000000u), high);
return NewSelect(state, TypeU32(state), nan, ConstantU32(state, 0), low);
Select(state, TypeU32(state), below, ConstantU32(state, 0x80000000u), high);
return Select(state, TypeU32(state), nan, ConstantU32(state, 0), low);
}
const auto below =
NewBinary(state, OpFOrdLessThanEqual, TypeBool(state), src, ConstantF32(state, 0));
const auto above = NewBinary(state, OpFOrdGreaterThanEqual, TypeBool(state), src,
Binary(state, OpFOrdLessThanEqual, TypeBool(state), src, ConstantF32(state, 0));
const auto above = Binary(state, OpFOrdGreaterThanEqual, TypeBool(state), src,
ConstantF32(state, 0x4f800000u));
const auto zero = NewBinary(state, OpLogicalOr, TypeBool(state), nan, below);
const auto zero = Binary(state, OpLogicalOr, TypeBool(state), nan, below);
const auto high =
NewSelect(state, TypeU32(state), above, ConstantU32(state, 0xffffffffu), converted_raw);
return NewSelect(state, TypeU32(state), zero, ConstantU32(state, 0), high);
Select(state, TypeU32(state), above, ConstantU32(state, 0xffffffffu), converted_raw);
return Select(state, TypeU32(state), zero, ConstantU32(state, 0), high);
}
uint32_t EmitPackHalf(EmitterState& state, uint32_t src) {
return EmitExt(state, TypeU32(state), GlslPackHalf2x16, {src});
}
uint32_t EmitUnpackHalf(EmitterState& state, uint32_t bits) {
const auto pair = EmitExt(state, TypeF32Vector(state, 2), GlslUnpackHalf2x16, {bits});
const auto result = state.builder.AllocateId();
state.builder.AddFunction({OpCompositeExtract, TypeF32(state), result, pair, 0});
return result;
}
} // namespace
bool EmitValueAlu(ValueEmitContext& ctx, const IR::Inst& inst) {
@@ -341,7 +314,7 @@ bool EmitValueAlu(ValueEmitContext& ctx, const IR::Inst& inst) {
return true;
}
case IR::ValueOpcode::ConvertF32F16:
ctx.Define(inst, EmitUnpackHalf(state, ctx.Arg(inst, 0)));
ctx.Define(inst, EmitF16BitsToF32(state, ctx.Arg(inst, 0)));
return true;
case IR::ValueOpcode::ConvertS32F32:
ctx.Define(inst, EmitF32ToU32(state, ctx.Arg(inst, 0), true));
@@ -350,7 +323,7 @@ bool EmitValueAlu(ValueEmitContext& ctx, const IR::Inst& inst) {
ctx.Define(inst, EmitF32ToU32(state, ctx.Arg(inst, 0), false));
return true;
case IR::ValueOpcode::ConvertF32S32: {
const auto signed_value = NewUnary(state, OpBitcast, TypeI32(state), ctx.Arg(inst, 0));
const auto signed_value = Unary(state, OpBitcast, TypeI32(state), ctx.Arg(inst, 0));
ctx.Emit(inst, OpConvertSToF, IR::Type::F32, {signed_value});
return true;
}
@@ -394,9 +367,9 @@ bool EmitValueAlu(ValueEmitContext& ctx, const IR::Inst& inst) {
case IR::ValueOpcode::PackFloat2x16Rtz: {
const auto low = EmitF32ToF16RtzBits(state, ctx.Arg(inst, 0));
const auto high =
NewBinary(state, OpShiftLeftLogical, TypeU32(state),
Binary(state, OpShiftLeftLogical, TypeU32(state),
EmitF32ToF16RtzBits(state, ctx.Arg(inst, 1)), ConstantU32(state, 16));
ctx.Define(inst, NewBinary(state, OpBitwiseOr, TypeU32(state), low, high));
ctx.Define(inst, Binary(state, OpBitwiseOr, TypeU32(state), low, high));
return true;
}
case IR::ValueOpcode::FPAbs32:
@@ -458,10 +431,10 @@ bool EmitValueAlu(ValueEmitContext& ctx, const IR::Inst& inst) {
return true;
case IR::ValueOpcode::IAbs32: {
const auto value = ctx.Arg(inst, 0);
const auto neg = NewUnary(state, OpSNegate, TypeU32(state), value);
const auto neg = Unary(state, OpSNegate, TypeU32(state), value);
const auto negative =
NewBinary(state, OpSLessThan, TypeBool(state), value, ConstantU32(state, 0));
ctx.Define(inst, NewSelect(state, TypeU32(state), negative, neg, value));
Binary(state, OpSLessThan, TypeBool(state), value, ConstantU32(state, 0));
ctx.Define(inst, Select(state, TypeU32(state), negative, neg, value));
return true;
}
case IR::ValueOpcode::ShiftLeftLogical32: return binary(OpShiftLeftLogical, IR::Type::U32);
@@ -496,25 +469,25 @@ bool EmitValueAlu(ValueEmitContext& ctx, const IR::Inst& inst) {
case IR::ValueOpcode::BitwiseXor32: return binary(OpBitwiseXor, IR::Type::U32);
case IR::ValueOpcode::BitwiseNot32: return unary(OpNot, IR::Type::U32);
case IR::ValueOpcode::BitwiseAnd64:
ctx.Define(inst, NewBinary(state, OpBitwiseAnd, TypeU64(state), ctx.Arg(inst, 0),
ctx.Define(inst, Binary(state, OpBitwiseAnd, TypeU64(state), ctx.Arg(inst, 0),
ctx.Arg(inst, 1)));
return true;
case IR::ValueOpcode::BitReverse32: return unary(OpBitReverse, IR::Type::U32);
case IR::ValueOpcode::BitCount32: return unary(OpBitCount, IR::Type::U32);
case IR::ValueOpcode::BitCount64: {
const auto pair =
ExtractPair(state, NewUnary(state, OpBitCount, TypeU64(state), ctx.Arg(inst, 0)));
ctx.Define(inst, NewBinary(state, OpIAdd, TypeU32(state), pair.low, pair.high));
ExtractPair(state, Unary(state, OpBitCount, TypeU64(state), ctx.Arg(inst, 0)));
ctx.Define(inst, Binary(state, OpIAdd, TypeU32(state), pair.low, pair.high));
return true;
}
case IR::ValueOpcode::FindILsb32: {
const auto value = EmitExt(state, TypeI32(state), GlslFindILsb, {ctx.Arg(inst, 0)});
ctx.Define(inst, NewUnary(state, OpBitcast, TypeU32(state), value));
ctx.Define(inst, Unary(state, OpBitcast, TypeU32(state), value));
return true;
}
case IR::ValueOpcode::FindUMsb32: {
const auto value = EmitExt(state, TypeI32(state), GlslFindUMsb, {ctx.Arg(inst, 0)});
ctx.Define(inst, NewUnary(state, OpBitcast, TypeU32(state), value));
ctx.Define(inst, Unary(state, OpBitcast, TypeU32(state), value));
return true;
}
case IR::ValueOpcode::FindUMsb64:
@@ -638,13 +611,13 @@ bool EmitValueAlu(ValueEmitContext& ctx, const IR::Inst& inst) {
return true;
case IR::ValueOpcode::FPRecip32: {
const auto source = EmitFlushF32DenormToSignedZero(state, ctx.Arg(inst, 0));
ctx.Define(inst, NewBinary(state, OpFDiv, TypeF32(state),
ctx.Define(inst, Binary(state, OpFDiv, TypeF32(state),
ConstantF32(state, 0x3f800000u), source));
return true;
}
case IR::ValueOpcode::FPRecipIFlag32:
// Integer-to-float inputs used by IFLAG cannot be denormal.
ctx.Define(inst, NewBinary(state, OpFDiv, TypeF32(state),
ctx.Define(inst, Binary(state, OpFDiv, TypeF32(state),
ConstantF32(state, 0x3f800000u), ctx.Arg(inst, 0)));
return true;
case IR::ValueOpcode::FPRecipSqrt32:
@@ -659,7 +632,7 @@ bool EmitValueAlu(ValueEmitContext& ctx, const IR::Inst& inst) {
case IR::ValueOpcode::FPCos: {
auto source = EmitTrigCycleF32(state, ctx.Arg(inst, 0), op == IR::ValueOpcode::FPSin);
source =
NewBinary(state, OpFMul, TypeF32(state), source, ConstantF32(state, 0x40c90fdbu));
Binary(state, OpFMul, TypeF32(state), source, ConstantF32(state, 0x40c90fdbu));
ctx.Define(inst, EmitExt(state, TypeF32(state),
op == IR::ValueOpcode::FPSin ? GlslSin : GlslCos, {source}));
return true;
@@ -673,7 +646,7 @@ bool EmitValueAlu(ValueEmitContext& ctx, const IR::Inst& inst) {
{EmitFlushF32DenormToSignedZero(state, ctx.Arg(inst, 0))}));
return true;
case IR::ValueOpcode::FPLdexp: {
const auto exponent = NewUnary(state, OpBitcast, TypeI32(state), ctx.Arg(inst, 1));
const auto exponent = Unary(state, OpBitcast, TypeI32(state), ctx.Arg(inst, 1));
ctx.Define(inst,
EmitExt(state, TypeF32(state), GlslLdexp, {ctx.Arg(inst, 0), exponent}));
return true;