shader: preserve full region addresses for LDS and GDS reads and writes
This commit is contained in:
parent
460a196fca
commit
d692d8ee08
|
|
@ -276,14 +276,8 @@ uint32_t ByteAddress(ValueEmitContext& ctx, const IR::Inst& inst, const IR::Memo
|
|||
|
||||
uint32_t DwordIndex(ValueEmitContext& ctx, const IR::Inst& inst, const IR::MemoryInfo& mem,
|
||||
uint32_t prefix = 0) {
|
||||
auto address = ByteAddress(ctx, inst, mem, prefix);
|
||||
if (mem.kind == IR::ResourceKind::Lds || mem.kind == IR::ResourceKind::Gds) {
|
||||
// RDNA2 DS region addresses retain bits [15:2] after adding the byte offset.
|
||||
address = Binary(ctx.state, spv::OpBitwiseAnd, TypeU32(ctx.state), address,
|
||||
ConstantU32(ctx.state, 0xffffu));
|
||||
}
|
||||
return Binary(ctx.state, spv::OpShiftRightLogical, TypeU32(ctx.state),
|
||||
address, ConstantU32(ctx.state, 2));
|
||||
ByteAddress(ctx, inst, mem, prefix), ConstantU32(ctx.state, 2));
|
||||
}
|
||||
|
||||
uint32_t LoadWordInBounds(ValueEmitContext& ctx, const MemoryResourceAccess& resource,
|
||||
|
|
@ -632,7 +626,12 @@ template <typename Fn>
|
|||
uint32_t EmitAtomicAccess(ValueEmitContext& ctx, const IR::Inst& inst,
|
||||
const IR::MemoryInfo& mem, Fn&& operation) {
|
||||
return EmitValueOrZeroIfCondition(ctx.state, ctx.Arg(inst, inst.NumArgs() - 1), [&]() {
|
||||
const auto index = DwordIndex(ctx, inst, mem);
|
||||
auto index = DwordIndex(ctx, inst, mem);
|
||||
if (mem.kind == IR::ResourceKind::Lds || mem.kind == IR::ResourceKind::Gds) {
|
||||
// Keep region-address truncation local to DS atomics.
|
||||
index = Binary(ctx.state, spv::OpBitwiseAnd, TypeU32(ctx.state), index,
|
||||
ConstantU32(ctx.state, 0x3fffu));
|
||||
}
|
||||
const auto resource = PrepareMemoryResourceAccess(ctx.state, mem);
|
||||
return EmitValueOrZeroIfCondition(
|
||||
ctx.state, EmitMemoryElementInBounds(ctx.state, resource, index), [&]() {
|
||||
|
|
|
|||
|
|
@ -32259,6 +32259,45 @@ TestCase DsReadWriteVariants() {
|
|||
O::BUFFER_STORE_DWORD, O::S_ENDPGM}};
|
||||
}
|
||||
|
||||
TestCase DsReadWriteFullRegionAddress(u32 wave_size, bool gds) {
|
||||
using O = ShaderOpcode;
|
||||
TestCase test;
|
||||
test.name = gds ? (wave_size == 32u ? "DsGdsFullAddress32" : "DsGdsFullAddress64")
|
||||
: (wave_size == 32u ? "DsLdsFullAddress32" : "DsLdsFullAddress64");
|
||||
auto &code = test.code;
|
||||
code.push_back(EncodeVop2(0x1a, 1, InlineU32(2), 0));
|
||||
code.push_back(EncodeVop2(0x25, 2, InlineU32(1), 0));
|
||||
code.insert(code.end(), {EncodeDs0(0x0d, 4, gds), EncodeDs1(0, 2, 1)});
|
||||
AppendVMovLiteral(&code, 3, 0x10000u);
|
||||
code.push_back(EncodeVop2(0x25, 3, Vgpr(1), 3));
|
||||
AppendVMovLiteral(&code, 4, 0xdeadbeefu);
|
||||
// A high region address must not alias the valid word in the same lane.
|
||||
code.insert(code.end(), {EncodeDs0(0x0d, 4, gds), EncodeDs1(0, 4, 3),
|
||||
EncodeDs0(0x36, 4, gds), EncodeDs1(5, 0, 1),
|
||||
EncodeDs0(0x36, 4, gds), EncodeDs1(6, 0, 3)});
|
||||
AppendStoreVgprAtLaneDwordOffset(&code, 5, 0, 0);
|
||||
AppendStoreVgprAtLaneDwordOffset(&code, 6, 0, wave_size);
|
||||
AppendEnd(&code);
|
||||
test.initial.assign(wave_size * 2u, 0xdeadbeefu);
|
||||
test.expected.resize(wave_size * 2u);
|
||||
std::iota(test.expected.begin(), test.expected.begin() + wave_size, 1u);
|
||||
test.compute_info.threads_num[0] = wave_size;
|
||||
test.compute_info.threads_num[1] = test.compute_info.threads_num[2] = 1u;
|
||||
test.compute_info.thread_ids_num = 1;
|
||||
test.compute_info.wave_size = wave_size;
|
||||
test.compute_info.lds_size_dwords = wave_size + 1u;
|
||||
test.has_compute_info = true;
|
||||
if (gds) {
|
||||
test.gds_initial.resize(wave_size + 1u);
|
||||
test.expected_gds.resize(wave_size + 1u);
|
||||
std::iota(test.expected_gds.begin(), test.expected_gds.end(), 0u);
|
||||
}
|
||||
test.opcodes = {O::V_LSHLREV_B32, O::V_ADD_NC_U32, O::V_MOV_B32, O::DS_WRITE_B32,
|
||||
O::DS_READ_B32, O::BUFFER_STORE_DWORD, O::S_ENDPGM};
|
||||
test.forbidden_spirv = {"%uint_65535"};
|
||||
return test;
|
||||
}
|
||||
|
||||
TestCase DsReadU16D16CapturedPreservesHighHalf() {
|
||||
using O = ShaderOpcode;
|
||||
|
||||
|
|
@ -38119,6 +38158,9 @@ std::vector<TestCase> MakeCases() {
|
|||
}
|
||||
}
|
||||
AddCase(DsReadWriteVariants);
|
||||
for (u32 wave_size : {32u, 64u})
|
||||
for (bool gds : {false, true})
|
||||
cases.push_back(DsReadWriteFullRegionAddress(wave_size, gds));
|
||||
AddCase(DsWriteB16D16HiCapturedUsesHighHalf);
|
||||
AddCase(DsWriteB8D16HiWritesByteTwo);
|
||||
AddCase(DsReadU16D16CapturedPreservesHighHalf);
|
||||
|
|
@ -43566,6 +43608,9 @@ int main(int argc, char **argv) {
|
|||
if (argc == 2 && std::strcmp(argv[1], "--lds-limit-only") == 0) {
|
||||
VulkanHarness vulkan;
|
||||
CheckComputeLdsLimit(vulkan);
|
||||
for (u32 wave_size : {32u, 64u})
|
||||
for (bool gds : {false, true})
|
||||
RunCase(&vulkan, DsReadWriteFullRegionAddress(wave_size, gds));
|
||||
RunCase(&vulkan, DsWideLdsPartialBounds());
|
||||
RunCase(&vulkan, DsAtomic64Bounds(false));
|
||||
RunCase(&vulkan, DsAtomic64Bounds(true));
|
||||
|
|
|
|||
Loading…
Reference in New Issue