mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-29 22:36:52 +01:00
shader: fix packed integer negation
Co-authored-by: shadowbeat070 <70843316+shadowbeat070@users.noreply.github.com>
This commit is contained in:
@@ -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) {
|
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 =
|
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));
|
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,
|
IR::U32 Translator::ReadU16LaneAsU32(const Decoder::Operand& operand, bool high_lane,
|
||||||
bool sign_extend) {
|
bool sign_extend) {
|
||||||
auto value = ReadU16LaneRaw(operand, high_lane);
|
auto value = Read16LaneBits(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)));
|
|
||||||
}
|
|
||||||
if (sign_extend || operand.sdwa_sext) {
|
if (sign_extend || operand.sdwa_sext) {
|
||||||
value = IR::U32(
|
value = IR::U32(
|
||||||
ir.Emit(IR::ValueOpcode::BitFieldSExtract, {value, IR::Value(0u), IR::Value(16u)}));
|
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);
|
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);
|
auto value = ReadU16LaneRaw(operand, high_lane);
|
||||||
if (operand.absolute) {
|
if (operand.absolute) {
|
||||||
value = ir.BitwiseAnd(value, IR::U32(IR::Value(0x7fffu)));
|
value = ir.BitwiseAnd(value, IR::U32(IR::Value(0x7fffu)));
|
||||||
}
|
}
|
||||||
if (high_lane ? operand.negate_hi : operand.negate) {
|
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)));
|
value = ir.BitwiseXor(value, IR::U32(IR::Value(0x8000u)));
|
||||||
}
|
}
|
||||||
return value;
|
return value;
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ private:
|
|||||||
IR::U32 ReadU16LaneRaw(const Decoder::Operand& operand, bool high_lane);
|
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 ReadU16LaneAsU32(const Decoder::Operand& operand, bool high_lane, bool sign_extend);
|
||||||
IR::U32 ReadU16AsU32(const Decoder::Operand& operand, 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);
|
std::array<IR::U32, 2> ExtractU64(IR::U64 value);
|
||||||
void WriteU32Pair(const Decoder::Operand& operand, const std::array<IR::U32, 2>& value);
|
void WriteU32Pair(const Decoder::Operand& operand, const std::array<IR::U32, 2>& value);
|
||||||
IR::U32 ConditionBit(const Decoder::Operand& operand);
|
IR::U32 ConditionBit(const Decoder::Operand& operand);
|
||||||
|
|||||||
@@ -19000,6 +19000,37 @@ TestCase Vop3pOpselHiUsesArchitecturalSourceBits() {
|
|||||||
{O::V_MOV_B32, O::V_PK_FMA_F16, O::BUFFER_STORE_DWORD, O::S_ENDPGM}};
|
{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() {
|
TestCase CvtPkU8F32PacksSelectedByte() {
|
||||||
using O = ShaderOpcode;
|
using O = ShaderOpcode;
|
||||||
|
|
||||||
@@ -26908,6 +26939,7 @@ std::vector<TestCase> MakeCases() {
|
|||||||
AddCase(Vop2PkFmacF16AccumulatesPackedHalvesIndependently);
|
AddCase(Vop2PkFmacF16AccumulatesPackedHalvesIndependently);
|
||||||
AddCase(Vop2PkFmacF16DppNegatesBothPackedHalves);
|
AddCase(Vop2PkFmacF16DppNegatesBothPackedHalves);
|
||||||
AddCase(Vop3pOpselHiUsesArchitecturalSourceBits);
|
AddCase(Vop3pOpselHiUsesArchitecturalSourceBits);
|
||||||
|
AddCase(Vop3pIntegerNegationCapturedAndSelectedHalves);
|
||||||
AddCase(CvtPkU8F32PacksSelectedByte);
|
AddCase(CvtPkU8F32PacksSelectedByte);
|
||||||
AddCase(CvtPkrtzF16F32SubnormalRoundsTowardZero);
|
AddCase(CvtPkrtzF16F32SubnormalRoundsTowardZero);
|
||||||
AddCase(CvtPkrtzF16F32SdwaAndOutputModifiers);
|
AddCase(CvtPkrtzF16F32SdwaAndOutputModifiers);
|
||||||
@@ -31628,6 +31660,11 @@ int main(int argc, char **argv) {
|
|||||||
std::setvbuf(stdout, nullptr, _IONBF, 0);
|
std::setvbuf(stdout, nullptr, _IONBF, 0);
|
||||||
EnsureConfigInitialized();
|
EnsureConfigInitialized();
|
||||||
CheckLeastRecentlyUsedCacheOrdering();
|
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) {
|
if (argc == 2 && std::strcmp(argv[1], "--dpp-only") == 0) {
|
||||||
VulkanHarness vulkan;
|
VulkanHarness vulkan;
|
||||||
RunCase(&vulkan, VectorDpp8Captured(false));
|
RunCase(&vulkan, VectorDpp8Captured(false));
|
||||||
|
|||||||
Reference in New Issue
Block a user