Merge pull request #3420 from gookie-dev/perf/agc-lazy-constant-ram
perf(agc): allocate a queue's constant RAM on its first write
This commit is contained in:
commit
8fcd352f04
|
|
@ -11,6 +11,7 @@
|
|||
#include <map>
|
||||
#include <array>
|
||||
#include <optional>
|
||||
#include <span>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
|
|
@ -192,11 +193,12 @@ struct Predication {
|
|||
};
|
||||
|
||||
struct QueueState {
|
||||
static constexpr std::size_t ConstantRamWords = 0x3000;
|
||||
Registers shader;
|
||||
Registers context = InitialContextRegisters();
|
||||
Registers userConfig{{0x24a, 0}, {0x24b, 0}};
|
||||
std::optional<Registers> savedContext;
|
||||
std::array<std::uint32_t, 0x3000> constantRam{};
|
||||
std::vector<std::uint32_t> constantRam;
|
||||
std::uint64_t indexBase = 0;
|
||||
std::uint64_t drawIndirectBase = 0;
|
||||
std::uint64_t dispatchIndirectBase = 0;
|
||||
|
|
@ -209,6 +211,17 @@ struct QueueState {
|
|||
void ClearContext() {
|
||||
context = InitialContextRegisters();
|
||||
}
|
||||
|
||||
std::span<const std::uint32_t> ConstantRam() const {
|
||||
static const std::array<std::uint32_t, ConstantRamWords> unwritten{};
|
||||
if (constantRam.empty()) return unwritten;
|
||||
return constantRam;
|
||||
}
|
||||
|
||||
std::span<std::uint32_t> WritableConstantRam() {
|
||||
if (constantRam.empty()) constantRam.resize(ConstantRamWords);
|
||||
return constantRam;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -610,8 +610,8 @@ std::optional<StoreWrite> ResolveStore(std::span<const std::uint32_t> packet, co
|
|||
return StoreWrite{destination, {}, dmaSourceBytes(packet)};
|
||||
}
|
||||
case 0x83: {
|
||||
if (packet.size() < 5 || packet[1] / 4 > queue.constantRam.size() || packet[2] > queue.constantRam.size() - packet[1] / 4) return std::nullopt;
|
||||
const auto words = std::span<const std::uint32_t>(queue.constantRam).subspan(packet[1] / 4, packet[2]);
|
||||
if (packet.size() < 5 || packet[1] / 4 > QueueState::ConstantRamWords || packet[2] > QueueState::ConstantRamWords - packet[1] / 4) return std::nullopt;
|
||||
const auto words = queue.ConstantRam().subspan(packet[1] / 4, packet[2]);
|
||||
if (words.size_bytes() > limit) return std::nullopt;
|
||||
// A view of the queue's constant RAM: valid until the next CONST_RAM write on this queue,
|
||||
// which is a later packet of the same worker.
|
||||
|
|
@ -913,10 +913,10 @@ void Execute(std::span<const std::uint32_t> packet, QueueState& queue) {
|
|||
return;
|
||||
}
|
||||
case 0x81:
|
||||
std::copy(packet.begin() + 2, packet.end(), queue.constantRam.begin() + packet[1] / 4);
|
||||
std::copy(packet.begin() + 2, packet.end(), queue.WritableConstantRam().begin() + packet[1] / 4);
|
||||
return;
|
||||
case 0x83:
|
||||
GuestMemory::Write(address(packet[3], packet[4]), std::as_bytes(std::span(queue.constantRam).subspan(packet[1] / 4, packet[2])), 4);
|
||||
GuestMemory::Write(address(packet[3], packet[4]), std::as_bytes(queue.ConstantRam().subspan(packet[1] / 4, packet[2])), 4);
|
||||
return;
|
||||
case 0x45: {
|
||||
std::uint32_t value = 0;
|
||||
|
|
|
|||
|
|
@ -364,9 +364,14 @@ void testMemory() {
|
|||
check(data[0] == 81 && data[1] == 82, "WRITE_DATA to memory from the graphics queue failed");
|
||||
expectFailure([&] { AgcDriver::Pm4::Validate(makePacket(0x37, {0x08000100, low(data.data()), high(data.data()), 71}), 0); }, "reserved");
|
||||
expectFailure([&] { AgcDriver::Pm4::Validate(makePacket(0x37, {0x80000100, low(data.data()), high(data.data()), 51}), 0); }, "engine");
|
||||
execute(state, makePacket(0x83, {0xbff8, 2, low(data.data()), high(data.data())}));
|
||||
check(data[0] == 0 && data[1] == 0, "unwritten constant RAM is not zero");
|
||||
execute(state, makePacket(0x81, {4, 31, 32}));
|
||||
execute(state, makePacket(0x83, {4, 2, low(data.data()), high(data.data())}));
|
||||
check(data[0] == 31 && data[1] == 32, "constant RAM round trip failed");
|
||||
auto copied = state;
|
||||
execute(copied, makePacket(0x83, {0, 3, low(data.data()), high(data.data())}));
|
||||
check(data[0] == 0 && data[1] == 31 && data[2] == 32, "a copied queue state lost its constant RAM");
|
||||
expectFailure([&] { execute(state, makePacket(0x81, {0xbffc, 1, 2})); }, "overflow");
|
||||
expectFailure([&] { execute(state, makePacket(0x40, {0x10105, 0, 0, low(data.data()), high(data.data())})); }, "64-bit immediate");
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue