mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-24 21:06:55 +02:00
shader: fix scalar memory loads
This commit is contained in:
@@ -146,7 +146,12 @@ uint32_t GuestAddress(ValueEmitContext& ctx, const IR::Inst& inst, const IR::Mem
|
||||
ctx.Fail(inst, "has no address base pair");
|
||||
return ConstantDeviceAddress(state, 0);
|
||||
}
|
||||
const auto base = DeviceAddressFromWords(state, ctx.Arg(*handle, 0), ctx.Arg(*handle, 1));
|
||||
auto base_low = ctx.Arg(*handle, 0);
|
||||
if (mem.kind == IR::ResourceKind::ScalarAddress) {
|
||||
base_low = Binary(state, spv::OpBitwiseAnd, TypeU32(state), base_low,
|
||||
ConstantU32(state, ~3u));
|
||||
}
|
||||
const auto base = DeviceAddressFromWords(state, base_low, ctx.Arg(*handle, 1));
|
||||
address = Binary(state, spv::OpIAdd, TypeScalarU64(state), base,
|
||||
Unary(state, spv::OpUConvert, TypeScalarU64(state), low));
|
||||
}
|
||||
@@ -1198,6 +1203,8 @@ void EmitLoadMemory(ValueEmitContext& ctx, const IR::Inst& inst) {
|
||||
value = LoadWideBuffer(ctx, inst, buffer_components);
|
||||
else if (shared_components > 1u)
|
||||
value = LoadWideShared(ctx, inst, shared_components);
|
||||
else if (mem.kind == IR::ResourceKind::ScalarAddress)
|
||||
value = LoadBdaDword(ctx, GuestAddress(ctx, inst, mem));
|
||||
else if (address_info.access == IR::AddressAccess::Read &&
|
||||
mem.kind != IR::ResourceKind::Scratch)
|
||||
value = LoadBda(ctx, GuestAddress(ctx, inst, mem), ctx.Arg(inst, inst.NumArgs() - 1),
|
||||
|
||||
@@ -25603,6 +25603,52 @@ TestCase ScalarLoadAlignsComponentsAndMasksAddress() {
|
||||
{O::S_MOV_B32, O::S_LOAD_DWORD, O::BUFFER_STORE_DWORD, O::S_ENDPGM}};
|
||||
}
|
||||
|
||||
TestCase ScalarLoadAlignsDynamicBase() {
|
||||
using O = ShaderOpcode;
|
||||
constexpr uint64_t GuestBase = 0x10000;
|
||||
std::vector<u32> code;
|
||||
AppendSMovLiteral(&code, 8, GuestBase);
|
||||
AppendSMovLiteral(&code, 9, 0);
|
||||
code.push_back(EncodeSop2(0x00, 8, 8, 4)); // group ID supplies each base low-bit pattern
|
||||
AppendSMovLiteral(&code, 10, 7);
|
||||
code.push_back(EncodeSmem0(0x01, 12, 4));
|
||||
code.push_back(EncodeSmem1(7, 10)); // all three address components align independently
|
||||
code.push_back(EncodeVop1(0x01, 0, 12));
|
||||
code.push_back(EncodeVop1(0x01, 1, 13));
|
||||
code.push_back(EncodeVop1(0x01, 2, 4));
|
||||
code.push_back(EncodeVop2(0x1a, 3, InlineU32(3), 2));
|
||||
AppendBufferStoreDword(&code, 0, 3);
|
||||
code.push_back(EncodeVop2(0x25, 3, InlineU32(4), 3));
|
||||
AppendBufferStoreDword(&code, 1, 3);
|
||||
AppendEnd(&code);
|
||||
|
||||
TestCase test;
|
||||
test.name = "ScalarLoadAlignsDynamicBase";
|
||||
test.code = std::move(code);
|
||||
test.initial.resize(20);
|
||||
test.initial[18] = 0x12345678;
|
||||
test.initial[19] = 0x9abcdef0;
|
||||
test.expected = test.initial;
|
||||
for (u32 group = 0; group < 4; ++group) {
|
||||
test.expected[group * 2] = test.initial[18];
|
||||
test.expected[group * 2 + 1] = test.initial[19];
|
||||
}
|
||||
test.bda_mappings = {{GuestBase, 64}};
|
||||
test.required_spirv = {"get_bda_pointer"};
|
||||
test.forbidden_spirv = {"flattened_srt"};
|
||||
test.opcodes = {O::S_MOV_B32, O::S_ADD_U32, O::S_LOAD_DWORDX2, O::V_MOV_B32,
|
||||
O::V_LSHLREV_B32, O::V_ADD_NC_U32, O::BUFFER_STORE_DWORD, O::S_ENDPGM};
|
||||
test.compute_info.wave_size = 32;
|
||||
test.compute_info.threads_num[0] = 1;
|
||||
test.compute_info.threads_num[1] = 1;
|
||||
test.compute_info.threads_num[2] = 1;
|
||||
test.compute_info.group_id[0] = true;
|
||||
test.compute_info.workgroup_register = 4;
|
||||
test.has_compute_info = true;
|
||||
test.dispatch_x = 4;
|
||||
return test;
|
||||
}
|
||||
|
||||
TestCase FlatVirtualAddressRebasesGuestAllocation() {
|
||||
using O = ShaderOpcode;
|
||||
|
||||
@@ -29551,6 +29597,7 @@ std::vector<TestCase> MakeCases() {
|
||||
AddCase(ScalarMemoryLoadVariants);
|
||||
AddCase(ScalarLoadSignedImmediateOffsetAddsSoffset);
|
||||
AddCase(ScalarLoadAlignsComponentsAndMasksAddress);
|
||||
AddCase(ScalarLoadAlignsDynamicBase);
|
||||
AddCase(BufferLoadStore);
|
||||
AddCase(BufferLoadDwordOffenIdxenUsesVaddrPlusOneOffset);
|
||||
AddCase(BufferStoreDwordOffenIdxenUsesVaddrPlusOneOffset);
|
||||
|
||||
@@ -4842,11 +4842,12 @@ void TestNewShaderRecompilerScalarMemoryBindingDomains() {
|
||||
};
|
||||
|
||||
const uint32_t raw_shader[] = {
|
||||
EncodeSmem0(0x00, 12, 4),
|
||||
2u, // s_load_dword s12, s[8:9], s0 offset:2
|
||||
EncodeSmem0(0x01, 12, 4),
|
||||
2u, // s_load_dwordx2 s[12:13], s[8:9], s0 offset:2
|
||||
EncodeVop1(0x01, 0, 12),
|
||||
EncodeExp0(0x00, 0x1),
|
||||
EncodeExp1(0, 0, 0, 0),
|
||||
EncodeVop1(0x01, 1, 13),
|
||||
EncodeExp0(0x00, 0x3),
|
||||
EncodeExp1(0, 1, 0, 0),
|
||||
EncodeSopp(0x01),
|
||||
};
|
||||
std::array<uint32_t, 12> raw_user_data{};
|
||||
@@ -4879,8 +4880,10 @@ void TestNewShaderRecompilerScalarMemoryBindingDomains() {
|
||||
"raw scalar load did not use only the DMA domain");
|
||||
Check(count_live_memory_ops(
|
||||
raw.program, ShaderRecompiler::IR::ValueOpcode::LoadAddressU32,
|
||||
ShaderRecompiler::IR::ResourceKind::ScalarAddress) == 1u,
|
||||
ShaderRecompiler::IR::ResourceKind::ScalarAddress) == 2u,
|
||||
"raw scalar load did not remain a live typed address operation");
|
||||
Check(SpirvInstructionOpcodeCount(raw.spirv, 57) == 2u,
|
||||
"aligned scalar DWORDs must each use one BDA lookup");
|
||||
Check(SpirvContainsOpcode(raw.spirv, 199),
|
||||
"raw scalar SOFFSET alignment was not emitted");
|
||||
CheckSpirvBinaryValidates(raw.spirv);
|
||||
|
||||
Reference in New Issue
Block a user