shader: FLAT opcode=0x24
This commit is contained in:
parent
af3011cd69
commit
2b1b7ed0e4
|
|
@ -84,6 +84,7 @@ constexpr MemoryOpcodeInfo FLAT_OPCODE_LIST[] = {
|
|||
{0x18u, Opcode::FLAT_STORE_BYTE, 1, 8}, {0x1au, Opcode::FLAT_STORE_SHORT, 1, 16},
|
||||
{0x1cu, Opcode::FLAT_STORE_DWORD, 1, 32}, {0x1du, Opcode::FLAT_STORE_DWORDX2, 2, 32},
|
||||
{0x1eu, Opcode::FLAT_STORE_DWORDX4, 4, 32}, {0x1fu, Opcode::FLAT_STORE_DWORDX3, 3, 32},
|
||||
{0x24u, Opcode::FLAT_LOAD_SHORT_D16, 1, 16},
|
||||
};
|
||||
|
||||
constexpr MemoryOpcodeInfo DS_OPCODE_LIST[] = {
|
||||
|
|
@ -373,6 +374,10 @@ void DecodeFlat(uint32_t pc, std::span<const uint32_t> code, uint32_t word_index
|
|||
}
|
||||
|
||||
DecodeVectorGpr(IsFlatStoreOpcode(inst.opcode) ? data : vdst, inst.dst);
|
||||
if (inst.opcode == Opcode::FLAT_LOAD_SHORT_D16) {
|
||||
// D16 loads reuse partial destinations to preserve the untouched high half.
|
||||
inst.dst.sdwa_sel = 4u;
|
||||
}
|
||||
DecodeVectorGpr(addr, inst.src0);
|
||||
inst.src_count = 1;
|
||||
if (seg == 0u || saddr == 0x7du || saddr == 0x7fu) {
|
||||
|
|
|
|||
|
|
@ -663,6 +663,7 @@ std::string InstructionToString(const Instruction& inst) {
|
|||
case Opcode::FLAT_LOAD_SBYTE:
|
||||
case Opcode::FLAT_LOAD_USHORT:
|
||||
case Opcode::FLAT_LOAD_SSHORT:
|
||||
case Opcode::FLAT_LOAD_SHORT_D16:
|
||||
case Opcode::FLAT_LOAD_DWORD:
|
||||
case Opcode::FLAT_LOAD_DWORDX2:
|
||||
case Opcode::FLAT_LOAD_DWORDX3:
|
||||
|
|
|
|||
|
|
@ -532,6 +532,7 @@ enum class Opcode {
|
|||
FLAT_LOAD_SBYTE,
|
||||
FLAT_LOAD_USHORT,
|
||||
FLAT_LOAD_SSHORT,
|
||||
FLAT_LOAD_SHORT_D16,
|
||||
FLAT_LOAD_DWORD,
|
||||
FLAT_LOAD_DWORDX2,
|
||||
FLAT_LOAD_DWORDX3,
|
||||
|
|
|
|||
|
|
@ -1077,6 +1077,7 @@ void Translator::EmitMemory(const Decoder::Instruction& inst) {
|
|||
case Decoder::Opcode::FLAT_LOAD_SBYTE:
|
||||
case Decoder::Opcode::FLAT_LOAD_USHORT:
|
||||
case Decoder::Opcode::FLAT_LOAD_SSHORT:
|
||||
case Decoder::Opcode::FLAT_LOAD_SHORT_D16:
|
||||
case Decoder::Opcode::FLAT_LOAD_DWORD:
|
||||
case Decoder::Opcode::FLAT_LOAD_DWORDX2:
|
||||
case Decoder::Opcode::FLAT_LOAD_DWORDX3:
|
||||
|
|
|
|||
|
|
@ -18672,6 +18672,7 @@ CoverageClass ClassifyOpcode(ShaderOpcode opcode,
|
|||
case Opcode::FLAT_LOAD_SBYTE:
|
||||
case Opcode::FLAT_LOAD_USHORT:
|
||||
case Opcode::FLAT_LOAD_SSHORT:
|
||||
case Opcode::FLAT_LOAD_SHORT_D16:
|
||||
case Opcode::FLAT_LOAD_DWORD:
|
||||
case Opcode::FLAT_LOAD_DWORDX2:
|
||||
case Opcode::FLAT_LOAD_DWORDX3:
|
||||
|
|
@ -29171,6 +29172,89 @@ TestCase FlatSubdwordLoadsApplyByteOffset() {
|
|||
return test;
|
||||
}
|
||||
|
||||
TestCase GlobalLoadShortD16Captured(u32 wave_size) {
|
||||
using O = ShaderOpcode;
|
||||
constexpr uint64_t GuestBase = 0x0000000110000000ull;
|
||||
constexpr u32 Marker = 0xa5a50000u;
|
||||
constexpr uint64_t ScalarBase = GuestBase - Marker - 0x70u;
|
||||
constexpr uint64_t ExecMask = 0xaaaaaaaa55555555ull;
|
||||
constexpr u32 Values[] = {0u, 0x7fffu, 0x8000u, 0xffffu};
|
||||
TestCase test;
|
||||
test.name = wave_size == 32u ? "GlobalLoadShortD16CapturedWave32"
|
||||
: "GlobalLoadShortD16CapturedWave64";
|
||||
test.initial.resize(2u * wave_size + wave_size / 2u);
|
||||
test.expected.resize(2u * wave_size);
|
||||
for (u32 lane = 0; lane < wave_size; ++lane) {
|
||||
const u32 value = Values[lane % std::size(Values)];
|
||||
test.initial[2u * wave_size + lane / 2u] |= value << (16u * (lane % 2u));
|
||||
test.expected[lane] = Marker | value;
|
||||
test.expected[wave_size + lane] = Marker |
|
||||
((ExecMask & (uint64_t{1} << lane)) != 0u ? value : lane * 2u);
|
||||
}
|
||||
auto &code = test.code;
|
||||
AppendSMovLiteral(&code, 2, static_cast<u32>(ScalarBase));
|
||||
AppendSMovLiteral(&code, 3, static_cast<u32>(ScalarBase >> 32u));
|
||||
code.push_back(EncodeVop2(0x1a, 6, InlineU32(1), 0));
|
||||
AppendVMovLiteral(&code, 5, Marker);
|
||||
code.push_back(EncodeVop2(0x25, 6, Vgpr(5), 6));
|
||||
for (bool masked : {false, true}) {
|
||||
code.push_back(EncodeVop1(0x01, 5, Vgpr(6)));
|
||||
if (masked) {
|
||||
code.push_back(EncodeSop1(0x04, 8, 126));
|
||||
AppendSMovLiteral(&code, 126, static_cast<u32>(ExecMask));
|
||||
AppendSMovLiteral(&code, 127, static_cast<u32>(ExecMask >> 32u));
|
||||
}
|
||||
// Captured GLOBAL_LOAD_SHORT_D16: v5 supplies the byte offset and destination.
|
||||
code.insert(code.end(), {0xdc908070u, 0x05020005u});
|
||||
if (masked) code.push_back(EncodeSop1(0x04, 126, 8));
|
||||
AppendStoreVgprAtLaneDwordOffset(&code, 5, 0, masked ? wave_size : 0u);
|
||||
}
|
||||
AppendEnd(&code);
|
||||
test.bda_mappings = {{GuestBase, 8u * wave_size}};
|
||||
test.compute_info.threads_num[0] = wave_size;
|
||||
test.compute_info.threads_num[1] = 1;
|
||||
test.compute_info.threads_num[2] = 1;
|
||||
test.compute_info.thread_ids_num = 1;
|
||||
test.compute_info.wave_size = wave_size;
|
||||
test.has_compute_info = true;
|
||||
test.opcodes = {O::S_MOV_B32, O::S_MOV_B64, O::V_MOV_B32, O::V_LSHLREV_B32,
|
||||
O::V_ADD_NC_U32, O::FLAT_LOAD_SHORT_D16,
|
||||
O::BUFFER_STORE_DWORD, O::S_ENDPGM};
|
||||
test.decoded_counts = {{"FLAT_LOAD_SHORT_D16", 2}};
|
||||
return test;
|
||||
}
|
||||
|
||||
TestCase FlatLoadShortD16AddressSegments() {
|
||||
using O = ShaderOpcode;
|
||||
constexpr uint64_t GuestBase = 0x0000000110000000ull;
|
||||
std::vector<u32> code;
|
||||
AppendVMovLiteral(&code, 20, static_cast<u32>(GuestBase) + 2u);
|
||||
AppendVMovLiteral(&code, 21, static_cast<u32>(GuestBase >> 32u));
|
||||
for (u32 segment : {0u, 2u}) {
|
||||
AppendVMovLiteral(&code, 3, 0x12345678u);
|
||||
code.push_back(EncodeFlat0(0x24, segment, segment == 0u ? 0u : 0xffeu));
|
||||
code.push_back(EncodeFlat1(3, 0x7d, 0, 20));
|
||||
AppendStoreVgpr(&code, 3, segment == 0u ? 0u : 1u);
|
||||
}
|
||||
AppendVMovU32(&code, 20, 0u);
|
||||
AppendVMovLiteral(&code, 3, 0xbeef5678u);
|
||||
code.push_back(EncodeFlat0(0x1c, 1, 0));
|
||||
code.push_back(EncodeFlat1(0, 0x7d, 3, 20));
|
||||
AppendVMovLiteral(&code, 3, 0x98761234u);
|
||||
code.push_back(EncodeFlat0(0x24, 1, 2));
|
||||
code.push_back(EncodeFlat1(3, 0x7d, 0, 20));
|
||||
AppendStoreVgpr(&code, 3, 2);
|
||||
AppendEnd(&code);
|
||||
TestCase test{"FlatLoadShortD16AddressSegments", code,
|
||||
{0, 0, 0, 0, 0x80017fffu},
|
||||
{0x12348001u, 0x12347fffu, 0x9876beefu},
|
||||
{O::V_MOV_B32, O::FLAT_LOAD_SHORT_D16, O::FLAT_STORE_DWORD,
|
||||
O::BUFFER_STORE_DWORD, O::S_ENDPGM}};
|
||||
test.bda_mappings = {{GuestBase, 16}};
|
||||
test.compute_info.scratch_size_dwords = 1;
|
||||
return test;
|
||||
}
|
||||
|
||||
TestCase BranchVccnzUsesCarryProducedWaveMask() {
|
||||
using O = ShaderOpcode;
|
||||
|
||||
|
|
@ -34720,6 +34804,9 @@ std::vector<TestCase> MakeCases() {
|
|||
AddCase(TBufferStoreVariants);
|
||||
AddCase(FlatLoadVariants);
|
||||
AddCase(FlatSubdwordLoadsApplyByteOffset);
|
||||
cases.push_back(GlobalLoadShortD16Captured(32));
|
||||
cases.push_back(GlobalLoadShortD16Captured(64));
|
||||
AddCase(FlatLoadShortD16AddressSegments);
|
||||
AddCase(FlatVirtualAddressRebasesGuestAllocation);
|
||||
AddCase(GlobalSignedImmediateRebasesBeforeSaddr);
|
||||
AddCase(FlatSegmentIgnoresSaddrAndMasksOffsetMsb);
|
||||
|
|
@ -40007,6 +40094,18 @@ int main(int argc, char **argv) {
|
|||
}
|
||||
return 0;
|
||||
}
|
||||
if (argc == 2 && std::strcmp(argv[1], "--flat-d16-only") == 0) {
|
||||
VulkanHarness vulkan;
|
||||
RunCase(&vulkan, GlobalLoadShortD16Captured(32));
|
||||
RunCase(&vulkan, GlobalLoadShortD16Captured(64));
|
||||
RunCase(&vulkan, FlatLoadShortD16AddressSegments());
|
||||
RunCase(&vulkan, FlatSubdwordLoadsApplyByteOffset());
|
||||
RunCase(&vulkan, FlatVirtualAddressRebasesGuestAllocation());
|
||||
RunCase(&vulkan, GlobalSignedImmediateRebasesBeforeSaddr());
|
||||
RunCase(&vulkan, FlatSegmentIgnoresSaddrAndMasksOffsetMsb());
|
||||
RunCase(&vulkan, ScratchIsPrivatePerInvocation());
|
||||
return 0;
|
||||
}
|
||||
if (argc == 2 && std::strcmp(argv[1], "--indirect-buffer-only") == 0) {
|
||||
VulkanHarness vulkan;
|
||||
RunCase(&vulkan, ScalarBufferFromLoopReadlane(32));
|
||||
|
|
|
|||
Loading…
Reference in New Issue