mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-20 10:56:58 +02:00
shader: reuse aligned indirect buffer loads for scalar DWORD reads
Co-authored-by: TheCruZ <thecruzwtf@gmail.com> Co-authored-by: tototomate123 <rushwars201966@gmail.com>
This commit is contained in:
@@ -664,6 +664,7 @@ uint32_t LoadFormattedInBounds(ValueEmitContext& ctx, const IR::MemoryInfo& mem,
|
||||
|
||||
uint32_t ConstructU32Composite(EmitterState& state, uint32_t components,
|
||||
const std::array<uint32_t, 4>& values) {
|
||||
if (components == 1u) return values[0];
|
||||
const auto result = state.builder.AllocateId();
|
||||
std::vector<uint32_t> words {spv::OpCompositeConstruct, TypeU32Composite(state, components),
|
||||
result};
|
||||
@@ -679,7 +680,7 @@ uint32_t FormattedOutOfBoundsValue(ValueEmitContext& ctx, const IR::MemoryInfo&
|
||||
const auto source = ResolveFormattedSource(ctx, mem, plan.info, component);
|
||||
values[component] = FormattedConstant(ctx, plan.info, source.kind);
|
||||
}
|
||||
return components == 1u ? values[0] : ConstructU32Composite(ctx.state, components, values);
|
||||
return ConstructU32Composite(ctx.state, components, values);
|
||||
}
|
||||
|
||||
uint32_t FormattedLoad(ValueEmitContext& ctx, const IR::Inst& inst, const IR::MemoryInfo& mem) {
|
||||
@@ -902,15 +903,17 @@ uint32_t LoadIndirectBuffer(ValueEmitContext& ctx, const IR::Inst& inst, uint32_
|
||||
const auto buffer = PrepareIndirectBuffer(ctx, inst);
|
||||
const auto valid_format = Binary(state, spv::OpINotEqual, TypeBool(state), buffer.format,
|
||||
ConstantU32(state, 0));
|
||||
const auto base = Binary(state, spv::OpBitwiseAnd, TypeScalarU64(state), buffer.address,
|
||||
ConstantDeviceAddress(state, ~uint64_t {3}));
|
||||
std::array<uint32_t, 4> values {};
|
||||
for (uint32_t component = 0; component < components; ++component) {
|
||||
const auto address = component == 0u ? buffer.address : Binary(
|
||||
state, spv::OpIAdd, TypeScalarU64(state), buffer.address,
|
||||
const auto address = component == 0u ? base : Binary(
|
||||
state, spv::OpIAdd, TypeScalarU64(state), base,
|
||||
ConstantDeviceAddress(state, component * 4u));
|
||||
values[component] = LoadBda(
|
||||
ctx, address, AndCondition(state, valid_format,
|
||||
IndirectBufferInBounds(state, buffer, component * 4u, 4u, false)),
|
||||
32u);
|
||||
values[component] = EmitValueOrZeroIfCondition(
|
||||
state, AndCondition(state, valid_format,
|
||||
IndirectBufferInBounds(state, buffer, component * 4u, 4u, false)),
|
||||
[&]() { return LoadBdaDword(ctx, address); });
|
||||
}
|
||||
return ConstructU32Composite(state, components, values);
|
||||
}
|
||||
@@ -960,7 +963,7 @@ uint32_t LoadIndirectFormattedX(ValueEmitContext& ctx, const IR::Inst& inst) {
|
||||
});
|
||||
}
|
||||
|
||||
uint32_t LoadWideBuffer(ValueEmitContext& ctx, const IR::Inst& inst, uint32_t components) {
|
||||
uint32_t LoadBuffer(ValueEmitContext& ctx, const IR::Inst& inst, uint32_t components) {
|
||||
auto& state = ctx.state;
|
||||
return EmitValueOrDefaultIfCondition(
|
||||
state, ctx.Arg(inst, inst.NumArgs() - 1), TypeU32Composite(state, components),
|
||||
@@ -1358,8 +1361,9 @@ void EmitLoadMemory(ValueEmitContext& ctx, const IR::Inst& inst) {
|
||||
uint32_t value;
|
||||
if (mem.kind == IR::ResourceKind::FlatLocal)
|
||||
value = LoadLocalFlat(ctx, inst);
|
||||
else if (buffer_components > 1u)
|
||||
value = LoadWideBuffer(ctx, inst, buffer_components);
|
||||
else if (buffer_components > 1u ||
|
||||
(buffer_components == 1u && mem.kind == IR::ResourceKind::IndirectBuffer && !mem.formatted))
|
||||
value = LoadBuffer(ctx, inst, buffer_components);
|
||||
else if (shared_components > 1u)
|
||||
value = LoadWideShared(ctx, inst, shared_components);
|
||||
else if (mem.kind == IR::ResourceKind::ScalarAddress)
|
||||
|
||||
@@ -91,7 +91,8 @@ uint32_t TypeU32Vector(EmitterState& state, uint32_t components) {
|
||||
}
|
||||
|
||||
uint32_t TypeU32Composite(EmitterState& state, uint32_t components) {
|
||||
EXIT_IF(components < 2u || components > 4u);
|
||||
EXIT_IF(components < 1u || components > 4u);
|
||||
if (components == 1u) return TypeU32(state);
|
||||
return components == 2u ? TypeU32Pair(state) : TypeU32Vector(state, components);
|
||||
}
|
||||
|
||||
@@ -333,8 +334,9 @@ uint32_t ConstantU64(EmitterState& state, uint64_t value) {
|
||||
}
|
||||
|
||||
uint32_t ConstantU32CompositeZero(EmitterState& state, uint32_t components) {
|
||||
EXIT_IF(components < 2u || components > 4u);
|
||||
EXIT_IF(components < 1u || components > 4u);
|
||||
const auto zero = ConstantU32(state, 0);
|
||||
if (components == 1u) return zero;
|
||||
std::vector<uint32_t> values(components, zero);
|
||||
return state.builder.Constant(spv::OpConstantComposite, TypeU32Composite(state, components),
|
||||
values);
|
||||
|
||||
@@ -458,7 +458,7 @@ 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 x2/x3/x4, or formatted X load");
|
||||
return Fail("indirect buffer requires a scalar, raw DWORD x1/x2/x3/x4, or formatted X load");
|
||||
}
|
||||
if (buffer_components > 1u &&
|
||||
(!vector_buffer || memory.data_bits != 32u ||
|
||||
|
||||
@@ -76,6 +76,7 @@ struct MemoryInfo {
|
||||
return !typed && data_bits == 32u &&
|
||||
(formatted ? opcode == ValueOpcode::LoadBufferU32
|
||||
: opcode == ValueOpcode::ReadConstBuffer ||
|
||||
opcode == ValueOpcode::LoadBufferU32 ||
|
||||
opcode == ValueOpcode::LoadBufferU32x2 ||
|
||||
opcode == ValueOpcode::LoadBufferU32x3 ||
|
||||
opcode == ValueOpcode::LoadBufferU32x4);
|
||||
|
||||
@@ -2113,7 +2113,7 @@ private:
|
||||
!memory.SupportsIndirectBufferLoad(op)) {
|
||||
Fail(flags.pc,
|
||||
"buffer descriptor is not a valid runtime value; GPU-selected access "
|
||||
"requires a scalar, raw DWORD x2/x3/x4, or formatted X load");
|
||||
"requires a scalar, 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