mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-20 19:07:01 +02:00
graphics: separate scalar address bindings
This commit is contained in:
@@ -59,6 +59,7 @@ struct Operand {
|
||||
enum class ResourceKind {
|
||||
None,
|
||||
ScalarBuffer,
|
||||
ScalarAddress,
|
||||
Buffer,
|
||||
Flat,
|
||||
Global,
|
||||
|
||||
@@ -74,6 +74,7 @@ std::string OperandToString(const Operand& operand) {
|
||||
std::string ResourceKindToString(ResourceKind kind) {
|
||||
switch (kind) {
|
||||
case ResourceKind::ScalarBuffer: return "scalar_buffer";
|
||||
case ResourceKind::ScalarAddress: return "scalar_address";
|
||||
case ResourceKind::Buffer: return "buffer";
|
||||
case ResourceKind::Flat: return "flat";
|
||||
case ResourceKind::Global: return "global";
|
||||
|
||||
@@ -75,14 +75,16 @@ Opcode LoweredImageOpcode(Decoder::Opcode opcode) {
|
||||
}
|
||||
}
|
||||
|
||||
bool LowerScalarBufferLoadDword(const Decoder::Instruction& decoded, BasicBlock& block, Opcode op,
|
||||
bool LowerScalarMemoryLoadDword(const Decoder::Instruction& decoded, BasicBlock& block, Opcode op,
|
||||
std::string* error) {
|
||||
for (uint32_t i = 0; i < decoded.data_dwords; i++) {
|
||||
Instruction inst;
|
||||
inst.pc = decoded.pc;
|
||||
inst.op = op;
|
||||
inst.src_count = 1;
|
||||
inst.memory = OffsetMemoryInfo(decoded, ResourceKind::ScalarBuffer, i);
|
||||
const auto kind =
|
||||
op == Opcode::SLoadDword ? ResourceKind::ScalarAddress : ResourceKind::ScalarBuffer;
|
||||
inst.memory = OffsetMemoryInfo(decoded, kind, i);
|
||||
// Raw s_load uses a two-SGPR pointer base; s_buffer_load uses a four-SGPR
|
||||
// descriptor resource index.
|
||||
inst.memory.resource = op == Opcode::SLoadDword ? RawScalarLoadBase(decoded.src0)
|
||||
@@ -511,13 +513,13 @@ bool LowerMemoryInstruction(const Decoder::Instruction& decoded, BasicBlock& blo
|
||||
case Decoder::Opcode::SLoadDwordx4:
|
||||
case Decoder::Opcode::SLoadDwordx8:
|
||||
case Decoder::Opcode::SLoadDwordx16:
|
||||
return LowerScalarBufferLoadDword(decoded, block, Opcode::SLoadDword, error);
|
||||
return LowerScalarMemoryLoadDword(decoded, block, Opcode::SLoadDword, error);
|
||||
case Decoder::Opcode::SBufferLoadDword:
|
||||
case Decoder::Opcode::SBufferLoadDwordx2:
|
||||
case Decoder::Opcode::SBufferLoadDwordx4:
|
||||
case Decoder::Opcode::SBufferLoadDwordx8:
|
||||
case Decoder::Opcode::SBufferLoadDwordx16:
|
||||
return LowerScalarBufferLoadDword(decoded, block, Opcode::SBufferLoadDword, error);
|
||||
return LowerScalarMemoryLoadDword(decoded, block, Opcode::SBufferLoadDword, error);
|
||||
case Decoder::Opcode::BufferLoadUbyte:
|
||||
case Decoder::Opcode::BufferLoadSbyte:
|
||||
case Decoder::Opcode::BufferLoadUshort:
|
||||
|
||||
@@ -559,7 +559,7 @@ bool MaterializeResources(const Program& program, const SrtRuntime& runtime,
|
||||
auto base = (static_cast<uint64_t>(value.dwords[0]) |
|
||||
static_cast<uint64_t>(value.dwords[1]) << 32u) &
|
||||
AddressMask;
|
||||
if (address.kind == ResourceKind::ScalarBuffer) {
|
||||
if (address.kind == ResourceKind::ScalarAddress) {
|
||||
base &= ~uint64_t {3};
|
||||
}
|
||||
const auto before = static_cast<uint64_t>(-static_cast<int64_t>(address.min_offset));
|
||||
|
||||
@@ -724,7 +724,7 @@ private:
|
||||
uint32_t AddAddress(uint32_t source, bool unbased, const MemoryInfo& memory, ValueOpcode op,
|
||||
uint32_t pc) {
|
||||
auto immediate = static_cast<int32_t>(memory.offset);
|
||||
if (memory.kind == ResourceKind::ScalarBuffer) {
|
||||
if (memory.kind == ResourceKind::ScalarAddress) {
|
||||
immediate = static_cast<int32_t>(static_cast<uint32_t>(immediate) & ~3u);
|
||||
}
|
||||
const auto min_offset = unbased ? 0 : std::min(immediate, 0);
|
||||
|
||||
@@ -50,13 +50,17 @@ bool AddSignedAddress(uint64_t base, int64_t offset, uint64_t& result) {
|
||||
}
|
||||
|
||||
bool IsRawRead(const ValueProgram& values, const Inst& inst) {
|
||||
if (inst.GetOpcode() != ValueOpcode::LoadAddressU32 &&
|
||||
inst.GetOpcode() != ValueOpcode::ReadConstBuffer) {
|
||||
const auto op = inst.GetOpcode();
|
||||
if (op != ValueOpcode::LoadAddressU32 && op != ValueOpcode::ReadConstBuffer) {
|
||||
return false;
|
||||
}
|
||||
const auto index = inst.Flags<MemoryFlags>().index;
|
||||
return index < values.memory_info.size() &&
|
||||
values.memory_info[index].kind == ResourceKind::ScalarBuffer;
|
||||
if (index >= values.memory_info.size()) {
|
||||
return false;
|
||||
}
|
||||
const auto kind = values.memory_info[index].kind;
|
||||
return (op == ValueOpcode::LoadAddressU32 && kind == ResourceKind::ScalarAddress) ||
|
||||
(op == ValueOpcode::ReadConstBuffer && kind == ResourceKind::ScalarBuffer);
|
||||
}
|
||||
|
||||
bool IsDescriptorHandle(ValueOpcode opcode) {
|
||||
@@ -262,6 +266,22 @@ public:
|
||||
m_values.dynamic_reads.clear();
|
||||
for (auto* block: m_values.blocks) {
|
||||
for (auto& inst: *block) {
|
||||
const auto op = inst.GetOpcode();
|
||||
if (op == ValueOpcode::LoadAddressU32 || op == ValueOpcode::ReadConstBuffer) {
|
||||
const auto flags = inst.Flags<MemoryFlags>();
|
||||
if (flags.index < m_values.memory_info.size()) {
|
||||
const auto kind = m_values.memory_info[flags.index].kind;
|
||||
const bool crosswired = (op == ValueOpcode::LoadAddressU32 &&
|
||||
kind == ResourceKind::ScalarBuffer) ||
|
||||
(op == ValueOpcode::ReadConstBuffer &&
|
||||
kind == ResourceKind::ScalarAddress);
|
||||
if (crosswired) {
|
||||
return Fail(flags.pc, error,
|
||||
fmt::format("{} has incompatible scalar memory metadata",
|
||||
ValueOpcodeName(op)));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (IsDescriptorHandle(inst.GetOpcode())) {
|
||||
for (size_t index = 0; index < inst.NumArgs(); index++) {
|
||||
if (!Collect(inst.Arg(index), 0, error)) {
|
||||
|
||||
Reference in New Issue
Block a user