mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-20 10:56:58 +02:00
shader: share indirect buffer array access after an empty root
Co-authored-by: fxpw <fxpw@outlook.com>
This commit is contained in:
@@ -400,7 +400,7 @@ uint32_t StorageBufferPackedStride(const EmitterState& state, const IR::MemoryIn
|
||||
|
||||
Prospero::BufferFormat StorageBufferFormat(const EmitterState& state, const IR::MemoryInfo& mem);
|
||||
|
||||
bool UsesSharedIndirectBufferAccess(const EmitterState& state, uint32_t resource);
|
||||
uint32_t SharedIndirectBufferResource(const EmitterState& state, uint32_t resource);
|
||||
|
||||
void EmitMemoryOffsets(EmitterState& state);
|
||||
|
||||
|
||||
@@ -309,20 +309,24 @@ auto EmitBufferAccess(ValueEmitContext& ctx, const IR::Inst& inst, IR::MemoryInf
|
||||
state.program.info.buffers[mem.resource].indirect_root != mem.resource) {
|
||||
return access(mem.resource);
|
||||
}
|
||||
const auto& buffer = state.program.info.buffers[mem.resource];
|
||||
const auto root_resource = mem.resource;
|
||||
const auto& buffer = state.program.info.buffers[root_resource];
|
||||
const auto& handle = *inst.Arg(0).ResolveInstruction();
|
||||
const auto selected = ctx.Arg(handle, 0);
|
||||
const auto shared = UsesSharedIndirectBufferAccess(state, mem.resource);
|
||||
const auto representative = SharedIndirectBufferResource(state, root_resource);
|
||||
const auto shared = representative != UINT32_MAX;
|
||||
const auto empty_root = shared && buffer.packed_stride == 0u;
|
||||
const auto selected_access = [&]() {
|
||||
if (shared) {
|
||||
const auto root_slot = buffer.descriptor_index;
|
||||
const auto child_slot = state.program.info.buffers[buffer.indirect_resources[1]].descriptor_index;
|
||||
auto slot = EmitAddU32(state, selected, ConstantU32(state, child_slot - 1u));
|
||||
if (child_slot != root_slot + 1u) {
|
||||
if (!empty_root && child_slot != root_slot + 1u) {
|
||||
slot = Select(state, TypeU32(state),
|
||||
Binary(state, spv::OpIEqual, TypeBool(state), selected, ConstantU32(state, 0u)),
|
||||
ConstantU32(state, root_slot), slot);
|
||||
}
|
||||
mem.resource = representative;
|
||||
return emit(mem, PrepareMemoryResourceAccess(state, mem, slot));
|
||||
}
|
||||
return EmitIndexSwitch(state, selected, buffer.indirect_resources.size(),
|
||||
@@ -332,12 +336,19 @@ auto EmitBufferAccess(ValueEmitContext& ctx, const IR::Inst& inst, IR::MemoryInf
|
||||
if constexpr (!has_result) {
|
||||
if (!shared) return selected_access();
|
||||
}
|
||||
const auto valid = Binary(state, spv::OpULessThan, TypeBool(state), selected,
|
||||
auto valid = Binary(state, spv::OpULessThan, TypeBool(state), selected,
|
||||
ConstantU32(state, buffer.indirect_resources.size()));
|
||||
if constexpr (has_result) {
|
||||
return EmitValueOrDefaultIfCondition(state, valid, TypeU32Composite(state, components),
|
||||
ConstantU32CompositeZero(state, components), selected_access);
|
||||
ConstantU32CompositeZero(state, components), [&]() {
|
||||
if (!empty_root) return selected_access();
|
||||
return EmitValueOrDefaultIfCondition(state,
|
||||
Binary(state, spv::OpINotEqual, TypeBool(state), selected, ConstantU32(state, 0u)),
|
||||
TypeU32Composite(state, components), access(root_resource), selected_access);
|
||||
});
|
||||
} else {
|
||||
if (empty_root) valid = AndCondition(state, valid,
|
||||
Binary(state, spv::OpINotEqual, TypeBool(state), selected, ConstantU32(state, 0u)));
|
||||
EmitIfCondition(state, valid, selected_access);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -108,24 +108,28 @@ Prospero::BufferFormat StorageBufferFormat(const EmitterState& state, const IR::
|
||||
return state.program.info.buffers[mem.resource].descriptor_format;
|
||||
}
|
||||
|
||||
bool UsesSharedIndirectBufferAccess(const EmitterState& state, uint32_t resource) {
|
||||
uint32_t SharedIndirectBufferResource(const EmitterState& state, uint32_t resource) {
|
||||
const auto& buffers = state.program.info.buffers;
|
||||
const auto& root = buffers[resource];
|
||||
if (root.indirect_root != resource || root.descriptor_index == UINT32_MAX ||
|
||||
root.packed_stride == 0u || root.indirect_resources.size() < 2u) {
|
||||
return false;
|
||||
root.indirect_resources.size() < 2u) {
|
||||
return UINT32_MAX;
|
||||
}
|
||||
const auto first = root.packed_stride == 0u ? 1u : 0u;
|
||||
const auto representative = root.indirect_resources[first];
|
||||
const auto& shared = buffers[representative];
|
||||
if (shared.packed_stride == 0u) return UINT32_MAX;
|
||||
uint32_t next_child_slot = UINT32_MAX;
|
||||
for (uint32_t ordinal = 0; ordinal < root.indirect_resources.size(); ++ordinal) {
|
||||
for (uint32_t ordinal = first; ordinal < root.indirect_resources.size(); ++ordinal) {
|
||||
const auto& candidate = buffers[root.indirect_resources[ordinal]];
|
||||
if (candidate.packed_stride != root.packed_stride ||
|
||||
candidate.descriptor_format != root.descriptor_format ||
|
||||
candidate.descriptor_swizzle != root.descriptor_swizzle ||
|
||||
if (candidate.packed_stride != shared.packed_stride ||
|
||||
candidate.descriptor_format != shared.descriptor_format ||
|
||||
candidate.descriptor_swizzle != shared.descriptor_swizzle ||
|
||||
candidate.descriptor_index == UINT32_MAX ||
|
||||
(ordinal > 1u && candidate.descriptor_index != next_child_slot)) return false;
|
||||
(ordinal > 1u && candidate.descriptor_index != next_child_slot)) return UINT32_MAX;
|
||||
if (ordinal != 0u) next_child_slot = candidate.descriptor_index + 1u;
|
||||
}
|
||||
return true;
|
||||
return representative;
|
||||
}
|
||||
|
||||
void EmitMemoryOffsets(EmitterState& state) {
|
||||
@@ -133,7 +137,7 @@ void EmitMemoryOffsets(EmitterState& state) {
|
||||
state.memory_byte_offsets.resize(count);
|
||||
std::vector<bool> dynamic_offsets(count);
|
||||
for (uint32_t resource = 0; resource < state.program.info.buffers.size(); ++resource) {
|
||||
if (!UsesSharedIndirectBufferAccess(state, resource)) continue;
|
||||
if (SharedIndirectBufferResource(state, resource) == UINT32_MAX) continue;
|
||||
for (const auto candidate: state.program.info.buffers[resource].indirect_resources) {
|
||||
dynamic_offsets[state.program.info.buffers[candidate].descriptor_index] = true;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user