shader: saturate V_CVT_PK_U16_U32 and V_CVT_PK_I16_I32

This commit is contained in:
TheCruZ
2026-10-25 00:04:35 +02:00
committed by nmzik
parent 66e21a6245
commit 9210264d47
5 changed files with 58 additions and 17 deletions
+35 -2
View File
@@ -25986,8 +25986,9 @@ TestCase Vop3CvtPkI16I32Captured() {
TestCase test;
test.name = "Vop3CvtPkI16I32Captured";
test.code = std::move(code);
// Each half saturates: 98305 -> 0x7fff, -98306 -> 0x8000.
test.initial = {0x00018001u, 0xfffe7ffeu, 0};
test.expected = {0x00018001u, 0xfffe7ffeu, 0x7ffe8001u};
test.expected = {0x00018001u, 0xfffe7ffeu, 0x80007fffu};
test.opcodes = {O::BUFFER_LOAD_DWORD, O::V_MOV_B32, O::V_CVT_PK_I16_I32,
O::BUFFER_STORE_DWORD, O::S_ENDPGM};
test.decoded_counts = {{"0x00000014: V_CVT_PK_I16_I32 v5, v7, v16\n", 1}};
@@ -25996,6 +25997,35 @@ TestCase Vop3CvtPkI16I32Captured() {
return test;
}
// V_CVT_PK_U16_U32 / V_CVT_PK_I16_I32 saturate each half: Min(src.u, 0xffff) and
// Clamp(src.s, -0x8000, 0x7fff).
TestCase Vop3CvtPk16Saturates() {
using O = ShaderOpcode;
TestCase test;
test.name = "Vop3CvtPk16Saturates";
test.initial = {0x00001234u, 0x0000ffffu, 0x00010000u, 0x80000000u,
0x00007fffu, 0xffff8000u, 0x00008000u, 0xffff7fffu,
0u, 0u, 0u, 0u};
test.expected = {0x00001234u, 0x0000ffffu, 0x00010000u, 0x80000000u,
0x00007fffu, 0xffff8000u, 0x00008000u, 0xffff7fffu,
0xffff1234u, 0xffffffffu, 0x80007fffu, 0x80007fffu};
auto &code = test.code;
for (u32 i = 0; i < 8u; i++) {
AppendVMovU32(&code, 30, i * 4u);
AppendBufferLoadDword(&code, i, 30);
}
AppendVop3(&code, 0x36a, 10, Vgpr(0), Vgpr(1)); // in range
AppendVop3(&code, 0x36a, 11, Vgpr(2), Vgpr(3)); // both clamp to 0xffff
AppendVop3(&code, 0x36b, 12, Vgpr(4), Vgpr(5)); // in range
AppendVop3(&code, 0x36b, 13, Vgpr(6), Vgpr(7)); // clamp to 0x7fff / 0x8000
for (u32 i = 0; i < 4u; i++) AppendStoreVgpr(&code, 10u + i, 8u + i);
AppendEnd(&code);
test.opcodes = {O::V_MOV_B32, O::BUFFER_LOAD_DWORD, O::V_CVT_PK_U16_U32,
O::V_CVT_PK_I16_I32, O::BUFFER_STORE_DWORD, O::S_ENDPGM};
return test;
}
TestCase Vop3MulLoU16CapturedAndSelectors() {
using O = ShaderOpcode;
@@ -27048,7 +27078,7 @@ TestCase VectorLaneAndPackedOps() {
{},
{0x12345678u, 0x12345678u, 0x12345678u, 0x12345678u, 0x40003c00u,
0x46004400u, 0x48004200u, 0x40003c00u, 0x44004200u, 0x48804400u,
0x40000000u, 0xef015678u},
0x40000000u, 0xffffffffu},
{O::V_MOV_B32, O::V_READFIRSTLANE_B32, O::V_READLANE_B32,
O::V_WRITELANE_B32, O::V_PERMLANE16_B32, O::V_CVT_PKRTZ_F16_F32,
O::V_PK_ADD_F16, O::V_PK_MUL_F16, O::V_PK_MIN_F16, O::V_PK_MAX_F16,
@@ -44044,6 +44074,7 @@ std::vector<TestCase> MakeCases() {
AddCase(Vop2SdwaLshrrevCapturedByte1Source);
AddCase(Vop2SdwaSubNcPreservesByteAndWordDestinations);
AddCase(Vop3CvtPkI16I32Captured);
AddCase(Vop3CvtPk16Saturates);
AddCase(Vop3MulLoU16CapturedAndSelectors);
AddCase(Vop3MadI16CapturedSelectorsAndSaturation);
AddCase(Vop3F32ClampFlushesNaN);
@@ -51063,6 +51094,8 @@ int main(int argc, char **argv) {
if (argc == 2 && std::strcmp(argv[1], "--cvt-pk-i16-only") == 0) {
VulkanHarness vulkan;
RunCase(&vulkan, Vop3CvtPkI16I32Captured());
RunCase(&vulkan, Vop3CvtPk16Saturates());
RunCase(&vulkan, VectorLaneAndPackedOps());
return 0;
}
if (argc == 2 && std::strcmp(argv[1], "--med3-i16-only") == 0) {