mirror of
https://github.com/boykopovar/AnyPS5.git
synced 2026-10-27 00:28:14 +00:00
Merge pull request #8886 from thuanquang/fix/dot2-f32-f16-accumulator-modifiers
fix(shader): apply v_dot2_f32_f16's accumulator modifiers as RDNA 2 does
This commit is contained in:
2 files changed
+60
-20
No files matched your search
@@ -31,6 +31,12 @@ alignas(256) constexpr std::array<std::uint32_t, 37> Code{
|
||||
0xe0781020, 0x80011203, 0xe0781030, 0x80011603, 0xbf810000,
|
||||
};
|
||||
|
||||
alignas(256) constexpr std::array<std::uint32_t, 20> AccumulatorCode{
|
||||
0x34020084, 0x34060086, 0xe0381000, 0x80000401, 0xbf8c3f70, 0xcc13600a, 0x1c1a0b04, 0xcc13000b,
|
||||
0x1c1a0b04, 0xcc13440c, 0x1c1a0b04, 0xcc13400d, 0x9c1a0b04, 0xcc13440e, 0x9c1a0b04, 0xe0781000,
|
||||
0x80010a03, 0xe0701010, 0x80010e03, 0xbf810000,
|
||||
};
|
||||
|
||||
constexpr std::uint32_t Rows[32][4] = {
|
||||
{0x0001bc00u, 0x81bfacbau, 0xc541aa2fu, 0x00000000u},
|
||||
{0x01f61a79u, 0x3c000381u, 0xc1729fffu, 0x00000000u},
|
||||
@@ -101,6 +107,43 @@ constexpr std::uint32_t Expected[32][10] = {
|
||||
{0xbaf43c38u, 0xbaf43c38u, 0x3af43c38u, 0x3af43c38u, 0x3abe63ecu, 0xbaf43c38u, 0xc021e000u, 0x3fb50000u, 0xba90cd60u, 0x3abe63ecu}
|
||||
};
|
||||
|
||||
constexpr std::uint32_t AccumulatorExpected[32][5] = {
|
||||
{0xc541a901u, 0xc541a901u, 0x4541ab5du, 0x4541ab5du, 0xc541a901u},
|
||||
{0xc1729fdfu, 0xc1729fdfu, 0x4172a01fu, 0x4172a01fu, 0xc1729fdfu},
|
||||
{0x4187e315u, 0x4187e315u, 0x4187e315u, 0xc1882737u, 0xc1882737u},
|
||||
{0x3f7fdb0fu, 0x3f7fdb0fu, 0x3f7fdb0fu, 0xbf801279u, 0xbf801279u},
|
||||
{0xbe511687u, 0xbe511687u, 0xbe511687u, 0xbe5166f4u, 0xbe5166f4u},
|
||||
{0xc1e56f13u, 0xc1e56f13u, 0x41e55ba5u, 0x41e55ba5u, 0xc1e56f13u},
|
||||
{0x439a1228u, 0x439a1228u, 0x439a1228u, 0xc3a5d2acu, 0xc3a5d2acu},
|
||||
{0x37f5fb14u, 0x37f5fb14u, 0x37f5fc0cu, 0x37f5fc0cu, 0x37f5fb14u},
|
||||
{0x7fd0a000u, 0x7fd0a000u, 0x7fd0a000u, 0x7fd0a000u, 0x7fd0a000u},
|
||||
{0xffc8ab86u, 0xffc8ab86u, 0x7fc8ab86u, 0x7fc8ab86u, 0xffc8ab86u},
|
||||
{0x7fe00000u, 0x7fe00000u, 0x7fe00000u, 0x7fe00000u, 0x7fe00000u},
|
||||
{0xffc00000u, 0xffc00000u, 0xffc00000u, 0xffc00000u, 0xffc00000u},
|
||||
{0xb974e480u, 0xb974e480u, 0xb974e480u, 0xb974e480u, 0xb974e480u},
|
||||
{0x7f800000u, 0x7f800000u, 0x7f800000u, 0xff800000u, 0xff800000u},
|
||||
{0xff800000u, 0xff800000u, 0xff800000u, 0xff800000u, 0xff800000u},
|
||||
{0x00000000u, 0x00000000u, 0x00000000u, 0x80000000u, 0x80000000u},
|
||||
{0x7fe00000u, 0x7fe00000u, 0x7fe00000u, 0x7fe00000u, 0x7fe00000u},
|
||||
{0x7fc42000u, 0x7fc42000u, 0x7fc42000u, 0x7fc42000u, 0x7fc42000u},
|
||||
{0xbf052ae0u, 0xbf052ae0u, 0xbf052ae0u, 0xbf052ae0u, 0xbf052ae0u},
|
||||
{0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u},
|
||||
{0x5f834da7u, 0x5f834da7u, 0x5f834da7u, 0xdf834da7u, 0xdf834da7u},
|
||||
{0x7f7fffffu, 0x7f7fffffu, 0x7f7fffffu, 0xff7fffffu, 0xff7fffffu},
|
||||
{0x42750eeeu, 0x42750eeeu, 0x42750eeeu, 0xc2750eeeu, 0xc2750eeeu},
|
||||
{0x43380748u, 0x43380748u, 0x43380748u, 0xc3380746u, 0xc3380746u},
|
||||
{0xffc00000u, 0xffc00000u, 0xffc00000u, 0xffc00000u, 0xffc00000u},
|
||||
{0xf540cddbu, 0xf540cddbu, 0x7540cddbu, 0x7540cddbu, 0xf540cddbu},
|
||||
{0x7fc00000u, 0x7fc00000u, 0x7fc00000u, 0x7fc00000u, 0x7fc00000u},
|
||||
{0x7fe00000u, 0x7fe00000u, 0x7fe00000u, 0xffe00000u, 0xffe00000u},
|
||||
{0x3cb7c720u, 0x3cb7c720u, 0x3cb7c720u, 0x3cb7c720u, 0x3cb7c720u},
|
||||
{0xbf9bd158u, 0xbf9bd158u, 0xbf9bd158u, 0xbf9bd158u, 0xbf9bd158u},
|
||||
{0x565f49ebu, 0x565f49ebu, 0x565f49ebu, 0xd65f49ebu, 0xd65f49ebu},
|
||||
{0xbaf43c38u, 0xbaf43c38u, 0xbaf43c38u, 0xbaf43c38u, 0xbaf43c38u}
|
||||
};
|
||||
|
||||
constexpr const char* AccumulatorNames[5] = {"v_dot2 op_sel src2", "v_dot2 op_sel_hi src2 cleared", "v_dot2 neg_hi src2", "v_dot2 neg_lo src2", "v_dot2 neg_lo and neg_hi src2"};
|
||||
|
||||
constexpr const char* Names[10] = {"v_dot2c", "v_dot2", "v_dot2 neg_lo src0/src2 neg_hi src1", "v_dot2 neg_lo src1 neg_hi src0", "v_dot2 op_sel src0", "v_dot2 clamp", "v_dot2c inline 1.0", "v_dot2c literal", "v_dot2c dpp quad_perm", "v_dot2 op_sel src1"};
|
||||
|
||||
void Fill(std::uint32_t tid, std::uint32_t* words) {
|
||||
@@ -140,21 +183,9 @@ auto Compile(AgcDriver::VulkanDevice& device, std::span<const std::uint32_t> cod
|
||||
return ShaderRecompiler::Recompile(request);
|
||||
}
|
||||
|
||||
void CheckRefused(AgcDriver::VulkanDevice& device, std::uint32_t word0, const std::string& what) {
|
||||
alignas(256) const std::array<std::uint32_t, 3> code{word0, 0x1c1a0b04u, 0xbf810000u};
|
||||
std::string refusal;
|
||||
try {
|
||||
static_cast<void>(Compile(device, code));
|
||||
} catch (const std::exception& error) {
|
||||
refusal = error.what();
|
||||
}
|
||||
Require(refusal.find("v_dot2_f32_f16 accumulator op_sel, op_sel_hi and neg_hi are not implemented") != std::string::npos, what + " was not refused");
|
||||
}
|
||||
|
||||
void Run(AgcDriver::VulkanDevice& device) {
|
||||
void Run(AgcDriver::VulkanDevice& device, std::span<const std::uint32_t> code) {
|
||||
for (std::uint32_t tid = 0; tid < Threads; ++tid) Fill(tid, &Input[tid * Inputs]);
|
||||
Output.fill(0xdeadbeefu);
|
||||
const std::span<const std::uint32_t> code(Code);
|
||||
const auto result = Compile(device, code);
|
||||
device.Dispatch(result, 1, 1, 1, {}, reinterpret_cast<std::uintptr_t>(code.data()));
|
||||
device.WaitIdle();
|
||||
@@ -167,6 +198,13 @@ void Check() {
|
||||
}
|
||||
}
|
||||
|
||||
void CheckAccumulator() {
|
||||
for (std::uint32_t tid = 0; tid < Threads; ++tid) {
|
||||
const std::uint32_t* out = &Output[tid * Results];
|
||||
for (std::uint32_t i = 0; i < 5; ++i) Expect(tid, out[i], AccumulatorExpected[tid][i], AccumulatorNames[i]);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int main() {
|
||||
@@ -177,11 +215,10 @@ int main() {
|
||||
std::puts("skipped, v_dot2_f32_f16 is computed in f64 and the device has no shaderFloat64");
|
||||
return VulkanTestSkipped;
|
||||
}
|
||||
Run(*device);
|
||||
Run(*device, Code);
|
||||
Check();
|
||||
CheckRefused(*device, 0xcc13600au, "op_sel on the accumulator");
|
||||
CheckRefused(*device, 0xcc13440au, "neg_hi on the accumulator");
|
||||
CheckRefused(*device, 0xcc13000au, "op_sel_hi cleared on the accumulator");
|
||||
Run(*device, AccumulatorCode);
|
||||
CheckAccumulator();
|
||||
std::puts("v_dot2_f32_f16 tests passed");
|
||||
return 0;
|
||||
} catch (const std::exception& error) {
|
||||
|
||||
@@ -2480,9 +2480,6 @@ RdnaInstruction DecodeRdnaVop3p(std::uint32_t programCounter, std::span<const st
|
||||
if (instruction.sourceCount > 2u) {
|
||||
instruction.source2 = DecodeRdnaScalarSource(src2, programCounter);
|
||||
}
|
||||
if (instruction.op == RdnaOpcode::VDot2F32F16 && ((((opSel | negHi) >> 2u) & 1u) != 0u || ((opSelHi >> 2u) & 1u) == 0u)) {
|
||||
throw std::invalid_argument("VOP3P v_dot2_f32_f16 accumulator op_sel, op_sel_hi and neg_hi are not implemented");
|
||||
}
|
||||
if (instruction.op == RdnaOpcode::VFmaF32 || instruction.op == RdnaOpcode::VDot2F32F16 || isMadMixF16(instruction.op) || isPackedVop3p(instruction.op) || isVop3pIntegerSaturate(instruction.op)) {
|
||||
instruction.destination.clamp = clamp != 0u;
|
||||
} else if (clamp != 0u && instruction.op != RdnaOpcode::VPkMulLoU16) {
|
||||
@@ -2493,6 +2490,12 @@ RdnaInstruction DecodeRdnaVop3p(std::uint32_t programCounter, std::span<const st
|
||||
} else {
|
||||
applyVop3pSourceModifiers(instruction, opSel, opSelHi, neg, negHi);
|
||||
}
|
||||
if (instruction.op == RdnaOpcode::VDot2F32F16) {
|
||||
instruction.source2.opSel = false;
|
||||
instruction.source2.opSelHi = true;
|
||||
instruction.source2.absolute = instruction.source2.negateHi;
|
||||
instruction.source2.negateHi = false;
|
||||
}
|
||||
if (instruction.op == RdnaOpcode::VMadMixloF16) {
|
||||
applyVop3pMixAbsModifiers(instruction);
|
||||
instruction.destination.sdwaSel = 4;
|
||||
|
||||
Reference in new issue
Block a user