shader: fix packed integer negation

Co-authored-by: shadowbeat070 <70843316+shadowbeat070@users.noreply.github.com>
This commit is contained in:
nmzik
2026-09-18 02:30:46 +04:00
parent bfc8cd0e0b
commit 95d3d9d3ad
4 changed files with 43 additions and 8 deletions
@@ -166,9 +166,9 @@ void Translator::V_CVT_PK_U8_F32(const Decoder::Instruction& inst) {
}
void Translator::V_PACK_B32_F16(const Decoder::Instruction& inst) {
const auto low = ReadF16LaneBits(inst.src0, false);
const auto low = Read16LaneBits(inst.src0, false);
const auto high =
ir.ShiftLeftLogical(ReadF16LaneBits(inst.src1, false), IR::U32(IR::Value(16u)));
ir.ShiftLeftLogical(Read16LaneBits(inst.src1, false), IR::U32(IR::Value(16u)));
WriteOperand(DestinationOperand(inst), ir.BitwiseOr(low, high));
}
@@ -541,10 +541,7 @@ IR::U32 Translator::ReadU16LaneRaw(const Decoder::Operand& operand, bool high_la
IR::U32 Translator::ReadU16LaneAsU32(const Decoder::Operand& operand, bool high_lane,
bool sign_extend) {
auto value = ReadU16LaneRaw(operand, high_lane);
if (high_lane ? operand.negate_hi : operand.negate) {
value = ir.BitwiseAnd(ir.ISub(IR::U32(IR::Value(0u)), value), IR::U32(IR::Value(0xffffu)));
}
auto value = Read16LaneBits(operand, high_lane);
if (sign_extend || operand.sdwa_sext) {
value = IR::U32(
ir.Emit(IR::ValueOpcode::BitFieldSExtract, {value, IR::Value(0u), IR::Value(16u)}));
@@ -556,12 +553,13 @@ IR::U32 Translator::ReadU16AsU32(const Decoder::Operand& operand, bool sign_exte
return ReadU16LaneAsU32(operand, false, sign_extend);
}
IR::U32 Translator::ReadF16LaneBits(const Decoder::Operand& operand, bool high_lane) {
IR::U32 Translator::Read16LaneBits(const Decoder::Operand& operand, bool high_lane) {
auto value = ReadU16LaneRaw(operand, high_lane);
if (operand.absolute) {
value = ir.BitwiseAnd(value, IR::U32(IR::Value(0x7fffu)));
}
if (high_lane ? operand.negate_hi : operand.negate) {
// RDNA2 source NEG flips the sign bit, including packed integer operands.
value = ir.BitwiseXor(value, IR::U32(IR::Value(0x8000u)));
}
return value;
@@ -44,7 +44,7 @@ private:
IR::U32 ReadU16LaneRaw(const Decoder::Operand& operand, bool high_lane);
IR::U32 ReadU16LaneAsU32(const Decoder::Operand& operand, bool high_lane, bool sign_extend);
IR::U32 ReadU16AsU32(const Decoder::Operand& operand, bool sign_extend);
IR::U32 ReadF16LaneBits(const Decoder::Operand& operand, bool high_lane);
IR::U32 Read16LaneBits(const Decoder::Operand& operand, bool high_lane);
std::array<IR::U32, 2> ExtractU64(IR::U64 value);
void WriteU32Pair(const Decoder::Operand& operand, const std::array<IR::U32, 2>& value);
IR::U32 ConditionBit(const Decoder::Operand& operand);
+37
View File
@@ -19000,6 +19000,37 @@ TestCase Vop3pOpselHiUsesArchitecturalSourceBits() {
{O::V_MOV_B32, O::V_PK_FMA_F16, O::BUFFER_STORE_DWORD, O::S_ENDPGM}};
}
TestCase Vop3pIntegerNegationCapturedAndSelectedHalves() {
using O = ShaderOpcode;
std::vector<u32> code;
AppendVMovLiteral(&code, 6, 0xfed4ff38u); // (-200, -300)
AppendVMovLiteral(&code, 3, 0x012c00c8u); // (200, 300)
// Captured temporal shader: NEG_LO/HI turns 0x7fff into 0xffff (-1).
// Adding that clamped offset must select (199,299), not collapse to (0,0).
code.insert(code.end(), {0xcc074107u, 0x30020cffu, 0x00007fffu});
code.insert(code.end(), {0xcc0a4010u, 0x18020f03u});
AppendStoreVgpr(&code, 7, 0);
AppendStoreVgpr(&code, 16, 1);
AppendVMovLiteral(&code, 0, 0x80011234u);
AppendVMovLiteral(&code, 1, 0xbeef5678u);
// Independently negate src0 low and src1 high, then reverse both the
// modified sources and src1 half selection. NEG flips the selected sign bit.
AppendVop3p(&code, 0x0a, 10, Vgpr(0), Vgpr(1), 0, 0x3, 0, 0x2, 0x1);
AppendVop3p(&code, 0x0a, 11, Vgpr(0), Vgpr(1), 0, 0x1, 0x2, 0x1, 0x2);
AppendStoreVgpr(&code, 10, 2);
AppendStoreVgpr(&code, 11, 3);
AppendEnd(&code);
return {"Vop3pIntegerNegationCapturedAndSelectedHalves",
code,
{},
{0xffffffffu, 0x012b00c7u, 0xbef0e8acu, 0x56795123u},
{O::V_MOV_B32, O::V_PK_MAX_I16, O::V_PK_ADD_U16,
O::BUFFER_STORE_DWORD, O::S_ENDPGM}};
}
TestCase CvtPkU8F32PacksSelectedByte() {
using O = ShaderOpcode;
@@ -26908,6 +26939,7 @@ std::vector<TestCase> MakeCases() {
AddCase(Vop2PkFmacF16AccumulatesPackedHalvesIndependently);
AddCase(Vop2PkFmacF16DppNegatesBothPackedHalves);
AddCase(Vop3pOpselHiUsesArchitecturalSourceBits);
AddCase(Vop3pIntegerNegationCapturedAndSelectedHalves);
AddCase(CvtPkU8F32PacksSelectedByte);
AddCase(CvtPkrtzF16F32SubnormalRoundsTowardZero);
AddCase(CvtPkrtzF16F32SdwaAndOutputModifiers);
@@ -31628,6 +31660,11 @@ int main(int argc, char **argv) {
std::setvbuf(stdout, nullptr, _IONBF, 0);
EnsureConfigInitialized();
CheckLeastRecentlyUsedCacheOrdering();
if (argc == 2 && std::strcmp(argv[1], "--packed-integer-neg-only") == 0) {
VulkanHarness vulkan;
RunCase(&vulkan, Vop3pIntegerNegationCapturedAndSelectedHalves());
return 0;
}
if (argc == 2 && std::strcmp(argv[1], "--dpp-only") == 0) {
VulkanHarness vulkan;
RunCase(&vulkan, VectorDpp8Captured(false));