mirror of
https://github.com/boykopovar/AnyPS5.git
synced 2026-11-04 13:07:32 +00:00
fix(shader): move a cached program's use lists to the heap and drop its arena
A program kept in a SourceEntry held its use-list arena until the entry was destroyed, so the buffers of values ReclaimUnusedValues dropped, and the buffers every use list outgrew, stayed allocated for as long as the program was cached. Before a program is cached, ReleaseUseArena now copies each value's use list into a heap vector and frees the arena. Values created after that draw from a new arena. Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
a661d4367f
commit
c01d0bb24f
6 files changed
+30
No files matched your search
@@ -96,6 +96,23 @@ int main() {
|
||||
keptReader.AddArgument(&kept);
|
||||
replaced = std::move(replacement);
|
||||
if (kept.UseCount() != 1u || kept.OperandUses().front().user != &keptReader) throw std::runtime_error("move assignment invalidated the assigned program's use lists");
|
||||
IrProgram cached;
|
||||
auto& source = cached.CreateValue(IrOpcode::IAdd32, IrType::U32);
|
||||
std::vector<IrValue*> users;
|
||||
for (std::uint32_t number = 0; number < 40u; ++number) {
|
||||
auto& user = cached.CreateValue(IrOpcode::IAdd32, IrType::U32);
|
||||
user.AddArgument(&source);
|
||||
users.push_back(&user);
|
||||
}
|
||||
cached.ReleaseUseArena();
|
||||
if (source.OperandUses().get_allocator().Arena() != nullptr || users.front()->OperandUses().get_allocator().Arena() != nullptr) throw std::runtime_error("releasing the use arena left a use list in it");
|
||||
if (source.UseCount() != users.size()) throw std::runtime_error("releasing the use arena lost a use");
|
||||
for (std::size_t index = 0; index < users.size(); ++index) {
|
||||
if (source.OperandUses()[index].user != users[index] || users[index]->Argument(0) != &source) throw std::runtime_error("releasing the use arena reordered a use list");
|
||||
}
|
||||
auto& late = cached.CreateValue(IrOpcode::IAdd32, IrType::U32);
|
||||
late.AddArgument(&source);
|
||||
if (late.OperandUses().get_allocator().Arena() == nullptr || source.UseCount() != users.size() + 1u || source.OperandUses().back().user != &late) throw std::runtime_error("a value created after releasing the use arena did not get a new one");
|
||||
IrProgram moved = std::move(program);
|
||||
if (value.Id() != id || value.ImmediateU32() != 42u || moved.ReclaimUnusedValues() != 1u) throw std::runtime_error("moving a program invalidated its allocation owner");
|
||||
IrProgram assigned;
|
||||
|
||||
+1
@@ -32,6 +32,7 @@ public:
|
||||
IrValue& CreateValue(IrOpcode opcode, IrType type, std::uint64_t flags);
|
||||
void SetEntryBlock(IrBlock& block);
|
||||
std::size_t ReclaimUnusedValues();
|
||||
void ReleaseUseArena();
|
||||
[[nodiscard]] std::vector<IrBlock*>& BlockOrder();
|
||||
[[nodiscard]] const std::vector<IrBlock*>& BlockOrder() const;
|
||||
|
||||
|
||||
+1
@@ -184,6 +184,7 @@ public:
|
||||
[[nodiscard]] IrValue* Argument(std::size_t index) const;
|
||||
[[nodiscard]] IrBlock* PhiBlock(std::size_t index) const;
|
||||
[[nodiscard]] const IrUseList& OperandUses() const;
|
||||
void MoveUsesToHeap();
|
||||
[[nodiscard]] std::uint64_t ImmediateU64() const;
|
||||
[[nodiscard]] std::uint16_t ImmediateF16Bits() const;
|
||||
[[nodiscard]] float ImmediateF32() const;
|
||||
|
||||
@@ -274,6 +274,11 @@ std::size_t IrProgram::ReclaimUnusedValues() {
|
||||
return removed;
|
||||
}
|
||||
|
||||
void IrProgram::ReleaseUseArena() {
|
||||
for (const auto& value : values) value->MoveUsesToHeap();
|
||||
useArena = IrUseArena{};
|
||||
}
|
||||
|
||||
std::vector<std::unique_ptr<IrBlock>>& IrProgram::Blocks() {
|
||||
return blocks;
|
||||
}
|
||||
|
||||
@@ -125,6 +125,11 @@ const IrUseList& IrValue::OperandUses() const {
|
||||
return operandUses;
|
||||
}
|
||||
|
||||
void IrValue::MoveUsesToHeap() {
|
||||
if (operandUses.get_allocator().Arena() == nullptr) return;
|
||||
operandUses = IrUseList(operandUses.begin(), operandUses.end(), IrUseAllocator<IrUse>{});
|
||||
}
|
||||
|
||||
std::uint64_t IrValue::ImmediateU64() const {
|
||||
return immediateBits;
|
||||
}
|
||||
|
||||
@@ -536,6 +536,7 @@ std::shared_ptr<SourceEntry> getSource(const RecompileRequest& request, ShaderPr
|
||||
ResourceProgram resource(request, preparation, reclaim);
|
||||
source->plan = std::move(resource.plan);
|
||||
if (!hasPreparedArtifact && std::ranges::none_of(source->variants, [&](const auto& variant) { return sameLayout(variant->layout, request.layout); })) {
|
||||
resource.program->ReleaseUseArena();
|
||||
source->program = std::move(resource.program);
|
||||
}
|
||||
} catch (...) {
|
||||
|
||||
Reference in new issue
Block a user