mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-20 02:47:02 +02:00
shader: load bytes and halfwords from GPU-selected buffers
Co-authored-by: fxpw <fxpw@outlook.com>
This commit is contained in:
@@ -970,6 +970,7 @@ uint32_t IndirectBufferInBounds(EmitterState& state, const IndirectBufferAccess&
|
||||
|
||||
uint32_t LoadIndirectBuffer(ValueEmitContext& ctx, const IR::Inst& inst, uint32_t components) {
|
||||
auto& state = ctx.state;
|
||||
const auto bits = ctx.Memory(inst).data_bits;
|
||||
const auto buffer = PrepareIndirectBuffer(ctx, inst);
|
||||
const auto valid_format = Binary(state, spv::OpINotEqual, TypeBool(state), buffer.format,
|
||||
ConstantU32(state, 0));
|
||||
@@ -983,8 +984,19 @@ uint32_t LoadIndirectBuffer(ValueEmitContext& ctx, const IR::Inst& inst, uint32_
|
||||
values[component] = EmitValueOrZeroIfCondition(
|
||||
state, AndCondition(state, valid_format,
|
||||
IndirectBufferInBounds(state, buffer, component * 4u,
|
||||
ConstantU32(state, 4u), false)),
|
||||
[&]() { return LoadBdaDword(ctx, address); });
|
||||
ConstantU32(state, bits / 8u), false)),
|
||||
[&]() {
|
||||
const auto value = LoadBdaDword(ctx, address, ctx.Memory(inst).coherent);
|
||||
if (bits == 32u) return value;
|
||||
const auto byte = Binary(
|
||||
state, spv::OpBitwiseAnd, TypeU32(state),
|
||||
Unary(state, spv::OpUConvert, TypeU32(state), buffer.address),
|
||||
ConstantU32(state, bits == 8u ? 3u : 2u));
|
||||
return EmitBitFieldUExtract(
|
||||
state, value,
|
||||
Binary(state, spv::OpShiftLeftLogical, TypeU32(state), byte, ConstantU32(state, 3u)),
|
||||
ConstantU32(state, bits));
|
||||
});
|
||||
}
|
||||
return ConstructU32Composite(state, components, values);
|
||||
}
|
||||
@@ -1444,8 +1456,8 @@ void EmitLoadMemory(ValueEmitContext& ctx, const IR::Inst& inst) {
|
||||
if (mem.kind == IR::ResourceKind::FlatLocal)
|
||||
value = LoadLocalFlat(ctx, inst);
|
||||
else if (buffer_components > 1u ||
|
||||
(op == IR::ValueOpcode::LoadBufferU32 &&
|
||||
(mem.kind == IR::ResourceKind::IndirectBuffer || mem.formatted)))
|
||||
(buffer_components == 1u && mem.kind == IR::ResourceKind::IndirectBuffer) ||
|
||||
(op == IR::ValueOpcode::LoadBufferU32 && mem.formatted))
|
||||
value = LoadBuffer(ctx, inst, buffer_components);
|
||||
else if (shared_components > 1u)
|
||||
value = LoadWideShared(ctx, inst, shared_components);
|
||||
|
||||
@@ -471,7 +471,8 @@ void ValidateProgram(const Program& program, bool require_ssa) {
|
||||
}
|
||||
if (memory.kind == ResourceKind::IndirectBuffer &&
|
||||
!memory.SupportsIndirectBufferLoad(inst.GetOpcode())) {
|
||||
return Fail("indirect buffer requires a scalar, raw DWORD x1/x2/x3/x4, or formatted X load");
|
||||
return Fail("indirect buffer requires a scalar, raw 8/16-bit, raw DWORD x1/x2/x3/x4, "
|
||||
"or formatted X load");
|
||||
}
|
||||
const bool packed_formatted_load =
|
||||
BufferAccessOf(inst.GetOpcode()) == BufferAccess::Read && memory.formatted &&
|
||||
|
||||
@@ -83,7 +83,10 @@ struct MemoryInfo {
|
||||
bool planning_only = false;
|
||||
|
||||
[[nodiscard]] bool SupportsIndirectBufferLoad(ValueOpcode opcode) const {
|
||||
return !typed && data_bits == 32u &&
|
||||
if (typed) return false;
|
||||
if (data_bits == 8u) return !formatted && opcode == ValueOpcode::LoadBufferU8;
|
||||
if (data_bits == 16u) return !formatted && opcode == ValueOpcode::LoadBufferU16;
|
||||
return data_bits == 32u &&
|
||||
(formatted ? opcode == ValueOpcode::LoadBufferU32
|
||||
: opcode == ValueOpcode::ReadConstBuffer ||
|
||||
opcode == ValueOpcode::LoadBufferU32 ||
|
||||
|
||||
@@ -3372,7 +3372,7 @@ private:
|
||||
!memory.SupportsIndirectBufferLoad(op)) {
|
||||
Fail(flags.pc,
|
||||
"buffer descriptor is not a valid runtime value; GPU-selected access "
|
||||
"requires a scalar, raw DWORD x1/x2/x3/x4, or formatted X load");
|
||||
"requires a scalar, raw 8/16-bit, raw DWORD x1/x2/x3/x4, or formatted X load");
|
||||
}
|
||||
m_program.memory_info[flags.index].kind = ResourceKind::IndirectBuffer;
|
||||
m_info.uses_dma = true;
|
||||
|
||||
Reference in New Issue
Block a user