shader: preserve untouched half in VOP1 B16 writes (#370)

shader: preserve native 16-bit destinations

Co-authored-by: nmzik <Nmzik@mail.ru>
This commit is contained in:
GodsWill Dev
2026-08-30 11:33:26 -04:00
committed by GitHub
parent 18af08460f
commit 9992ab18fc
8 changed files with 244 additions and 90 deletions
+149
View File
@@ -553,6 +553,12 @@ constexpr u32 EncodeVop1Sdwa(u32 src0, u32 dst_sel = 6, u32 dst_u = 0,
((s0 & 0x1u) << 23u);
}
constexpr u32 EncodeVop1Dpp(u32 src0, u32 dpp_ctrl = 0, u32 row_mask = 0xf,
u32 bank_mask = 0xf) {
return (src0 & 0xffu) | ((dpp_ctrl & 0x1ffu) << 8u) |
((bank_mask & 0xfu) << 24u) | ((row_mask & 0xfu) << 28u);
}
constexpr u32 EncodeVop2(u32 opcode, u32 dst, u32 src0, u32 src1) {
return ((opcode & 0x3fu) << 25u) | ((dst & 0xffu) << 17u) |
((src1 & 0xffu) << 9u) | (src0 & 0x1ffu);
@@ -14368,6 +14374,54 @@ TestCase CvtPkrtzF16F32SubnormalRoundsTowardZero() {
O::S_ENDPGM}};
}
TestCase CvtPkrtzF16F32SdwaAndOutputModifiers() {
using O = ShaderOpcode;
std::vector<u32> code;
AppendVMovLiteral(&code, 0, 0x3f000000u); // 0.5f
AppendVMovLiteral(&code, 1, 0x40000000u); // 2.0f
AppendVMovLiteral(&code, 2, 0x3f802000u); // exactly 0x3c01h
AppendVMovLiteral(&code, 3, 0x00000000u);
AppendVMovLiteral(&code, 4, 0xbf000000u); // -0.5f
for (u32 dst = 10; dst <= 18; dst++) {
AppendVMovLiteral(&code, dst, 0xa1b2c3d4u);
}
code.push_back(EncodeVop2(0x2f, 10, 249, 1));
code.push_back(EncodeVop2Sdwa(0, 6, 2, 6, 6, 0, 0, 0, 0, 0, 0, 0, 0,
1));
code.push_back(EncodeVop2(0x2f, 11, 249, 3));
code.push_back(EncodeVop2Sdwa(2, 0, 0));
code.push_back(EncodeVop2(0x2f, 12, 249, 1));
code.push_back(EncodeVop2Sdwa(0, 6, 0, 3, 5));
code.push_back(EncodeVop2(0x2f, 13, 249, 1));
code.push_back(EncodeVop2Sdwa(4, 6, 0, 6, 6, 0, 0, 0, 1, 1));
code.push_back(EncodeVop2(0x2f, 14, 250, 1));
code.push_back(EncodeVop2Dpp(0, 0, 0xf, 0xf, 1));
AppendVop3(&code, 0x12f, 15, Vgpr(0), Vgpr(1), 0, 0, 0, true);
code.push_back(EncodeVop2(0x2f, 16, 249, 1));
code.push_back(EncodeVop2Sdwa(0, 4, 2));
code.push_back(EncodeVop2(0x2f, 17, 249, 1));
code.push_back(EncodeVop2Sdwa(0, 6, 2, 6, 6, 0, 0, 0, 0, 0, 0, 0, 0,
0, 1));
AppendVop3(&code, 0x12f, 18, Vgpr(0), Vgpr(1), 0, 0, 0, false, 1);
for (u32 dst = 10; dst <= 18; dst++) {
AppendStoreVgpr(&code, dst, dst - 10);
}
AppendEnd(&code);
return {"CvtPkrtzF16F32SdwaAndOutputModifiers",
code,
{},
{0x3c003800u, 0x00000001u, 0x00000000u, 0xc0003800u,
0x4000b800u, 0x3c003800u, 0xa1b23800u, 0x44003c00u,
0x44003c00u},
{O::V_MOV_B32, O::V_CVT_PKRTZ_F16_F32, O::BUFFER_STORE_DWORD,
O::S_ENDPGM}};
}
TestCase PackedMinMaxF16NanAndSignedZeroEdges() {
using O = ShaderOpcode;
@@ -14475,6 +14529,99 @@ TestCase VectorCvtU16F16Sdwa() {
{O::V_MOV_B32, O::V_CVT_U16_F16, O::BUFFER_STORE_DWORD, O::S_ENDPGM}};
}
TestCase NativeAndSdwa16BitDestinationWrites() {
using O = ShaderOpcode;
std::vector<u32> code;
AppendVMovLiteral(&code, 0, 0x3fc00000u); // 1.5f -> 0x3e00h
AppendVMovLiteral(&code, 1, 0x00004200u); // low=3.0h
AppendVMovLiteral(&code, 2, 0x0000c000u); // low=-2.0h
AppendVMovLiteral(&code, 3, 0x00003c00u); // low=1.0h
AppendVMovLiteral(&code, 4, 0x00004000u); // low=2.0h
const u32 sentinels[] = {
0x3c001234u, 0xbbbb2345u, 0xcccc3456u, 0xdddd4567u, 0xeeee5678u,
0xffff6789u, 0xf00d789au, 0x11118888u, 0x22229999u, 0x3333aaaau,
0xaaaa0000u, 0xbbbb0000u, 0xcccc0000u, 0xabcd1234u, 0xbcde2345u,
0xcdef3456u, 0xdef01234u, 0xef012345u, 0xf0123456u, 0x01234567u,
0xaaaa1234u, 0xbbbb5678u, 0x24681234u, 0x13572468u, 0x89abcdefu,
0xfedcba98u, 0x0bad1234u,
};
// AppendStoreVgpr uses v31 as its address scratch register.
const auto output_vgpr = [](u32 index) { return 10u + index + (index >= 21u ? 1u : 0u); };
for (u32 i = 0; i < static_cast<u32>(std::size(sentinels)); i++) {
AppendVMovLiteral(&code, output_vgpr(i), sentinels[i]);
}
code.push_back(EncodeVop1(0x0a, 10, Vgpr(0)));
code.push_back(EncodeVop1(0x0a, 11, 250));
code.push_back(EncodeVop1Dpp(0));
AppendVop3(&code, 0x18a, 12, Vgpr(0), 0);
code.push_back(EncodeVop1(0x52, 13, Vgpr(1)));
code.push_back(EncodeVop1(0x53, 14, Vgpr(2)));
code.push_back(EncodeVop1(0x0a, 15, 249));
code.push_back(EncodeVop1Sdwa(0));
code.push_back(EncodeVop1(0x54, 16, 249));
code.push_back(EncodeVop1Sdwa(10, 4, 2, 5));
code.push_back(EncodeVop1(0x52, 17, 249));
code.push_back(EncodeVop1Sdwa(1, 6, 0, 4));
code.push_back(EncodeVop1(0x52, 18, 249));
code.push_back(EncodeVop1Sdwa(1, 4, 0, 4));
code.push_back(EncodeVop1(0x53, 19, 249));
code.push_back(EncodeVop1Sdwa(2, 4, 1, 4));
code.push_back(EncodeVop2(0x32, 20, 250, 4));
code.push_back(EncodeVop2Dpp(3));
AppendVop3(&code, 0x132, 21, Vgpr(3), Vgpr(4));
code.push_back(EncodeVop2(0x32, 22, 249, 4));
code.push_back(EncodeVop2Sdwa(3, 4, 0, 4, 4));
code.push_back(EncodeVop1(0x0a, 23, 249));
code.push_back(EncodeVop1Sdwa(0, 4, 2, 3));
code.push_back(EncodeVop1(0x0a, 24, 249));
code.push_back(EncodeVop1Sdwa(0, 4, 2, 5));
code.push_back(EncodeVop1(0x0a, 25, 249));
code.push_back(EncodeVop1Sdwa(0, 4, 2, 6, 0, 1, 1));
code.push_back(EncodeVop1(0x0a, 26, 249));
code.push_back(EncodeVop1Sdwa(0, 4, 2, 6, 0, 0, 0, 0, 0, 1));
code.push_back(EncodeVop1(0x0a, 27, 249));
code.push_back(EncodeVop1Sdwa(0, 4, 2, 6, 0, 0, 0, 0, 1));
AppendVop3(&code, 0x18a, 28, Vgpr(0), 0, 0, 0, 0, false, 1);
AppendVop3(&code, 0x18a, 29, Vgpr(0), 0, 0, 0, 0, true);
AppendVop3(&code, 0x34b, 30, Vgpr(3), Vgpr(4), Vgpr(3));
AppendVop3(&code, 0x34b, 32, Vgpr(3), Vgpr(4), Vgpr(3), 0, 0x8);
code.push_back(EncodeVop1(0x52, 33, 249));
code.push_back(EncodeVop1Sdwa(1, 4, 2, 4, 0, 1, 1, 0, 1));
AppendVop3(&code, 0x1d3, 34, Vgpr(1), 0, 0, 1, 0, true, 0, 1);
code.push_back(EncodeVop1(0x07, 35, 249));
code.push_back(EncodeVop1Sdwa(0, 6, 0, 6, 0, 1, 1, 0, 1));
AppendVop3(&code, 0x188, 36, Vgpr(0), 0, 0, 1, 0, true, 0, 1);
code.push_back(EncodeVop1(0x54, 37, 249));
code.push_back(EncodeVop1Sdwa(4, 4, 2, 4, 0, 1, 1));
for (u32 i = 0; i < static_cast<u32>(std::size(sentinels)); i++) {
AppendStoreVgpr(&code, output_vgpr(i), i);
}
AppendEnd(&code);
return {"NativeAndSdwa16BitDestinationWrites",
code,
{},
{0x3c003e00u, 0xbbbb3e00u, 0xcccc3e00u, 0xdddd0003u,
0xeeeefffeu, 0x00003e00u, 0xf00d3c00u, 0x00000003u,
0x00000003u, 0xfffffffeu, 0xaaaa4200u, 0xbbbb4200u,
0x00004200u, 0xabcd0000u, 0xbcde0000u, 0xcdefbe00u,
0xdef04200u, 0xef013c00u, 0xf0124200u, 0x01233c00u,
0xaaaa4200u, 0x42005678u, 0x24680000u, 0x1357fffdu,
0x00000000u, 0xffffffffu, 0x0badb800u},
{O::V_MOV_B32, O::V_CVT_F16_F32, O::V_CVT_U32_F32,
O::V_CVT_I32_F32, O::V_CVT_U16_F16, O::V_CVT_I16_F16,
O::V_RCP_F16, O::V_ADD_F16, O::V_FMA_F16, O::BUFFER_STORE_DWORD,
O::S_ENDPGM}};
}
TestCase VectorMinMaxMed3F16Ops() {
using O = ShaderOpcode;
@@ -20852,9 +20999,11 @@ std::vector<TestCase> MakeCases() {
AddCase(Vop3pOpselHiUsesArchitecturalSourceBits);
AddCase(CvtPkU8F32PacksSelectedByte);
AddCase(CvtPkrtzF16F32SubnormalRoundsTowardZero);
AddCase(CvtPkrtzF16F32SdwaAndOutputModifiers);
AddCase(PackedMinMaxF16NanAndSignedZeroEdges);
AddCase(VectorMinMaxF16Ops);
AddCase(VectorCvtU16F16Sdwa);
AddCase(NativeAndSdwa16BitDestinationWrites);
AddCase(VectorMinMaxMed3F16Ops);
AddCase(VectorSpecialF16Ops);
AddCase(VectorCosF16CapturedSdwaAndEdges);