Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions core/libs/prx/libSceAgcDriver/tests/ShaderDiskCache.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1387,6 +1387,9 @@ void verifyBindingPlanSelection() {
expected.guestDescriptor[0] += 0x10000u;
expected.guestDescriptor[6] = 128u;
require(sameBinding(expected, populated.bindings[0]) && sameBinding(full.bindings[3], populated.bindings[1]), "selected plan changed binding order or reused stale buffer data");
BindingAllocationResult reused = full;
builder.Populate(reused, compiled, selected, 0u, snapshot, {});
require(sameBindings(reused.bindings, populated.bindings) && reused.pushConstants.empty(), "a reused allocation kept bindings or metadata of its previous plan");
bool rejected = false;
try { static_cast<void>(builder.Select(plan, std::array{UINT32_MAX})); }
catch (const std::runtime_error&) { rejected = true; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -119,8 +119,8 @@ DescriptorImageShape ImageShapeForResource(const ImageResource& image) {
fail("DescriptorBindingBuilder::Populate image resource dimension has no descriptor image shape");
}

std::vector<std::uint32_t> GuestBuffersDescriptor(const std::vector<std::uint32_t>& resources, const ResourceSnapshot& snapshot) {
std::vector<std::uint32_t> result;
void GuestBuffersDescriptor(std::vector<std::uint32_t>& result, const std::vector<std::uint32_t>& resources, const ResourceSnapshot& snapshot) {
result.clear();
result.reserve(resources.size() * 4u);
for (const std::uint32_t r : resources) {
if (r >= snapshot.buffers.size()) {
Expand All @@ -134,11 +134,10 @@ std::vector<std::uint32_t> GuestBuffersDescriptor(const std::vector<std::uint32_
result.push_back(value.dwords[dword]);
}
}
return result;
}

std::vector<std::uint32_t> GuestSamplersDescriptor(const std::vector<std::uint32_t>& resources, const ResourceSnapshot& snapshot) {
std::vector<std::uint32_t> result;
void GuestSamplersDescriptor(std::vector<std::uint32_t>& result, const std::vector<std::uint32_t>& resources, const ResourceSnapshot& snapshot) {
result.clear();
result.reserve(resources.size() * 4u);
std::uint32_t dwordCount = 0;
for (std::size_t i = 0; i < resources.size(); i++) {
Expand All @@ -159,7 +158,6 @@ std::vector<std::uint32_t> GuestSamplersDescriptor(const std::vector<std::uint32
result.push_back(value.dwords[dword]);
}
}
return result;
}

constexpr std::uint32_t ForceUnnormalizedBit = 1u << 15u;
Expand Down Expand Up @@ -571,15 +569,17 @@ void DescriptorBindingBuilder::Populate(BindingAllocationResult& allocation, con
allocation.shaderDataUserWords.reserve(layout.userDataRegisters.size());
for (const auto reg : layout.userDataRegisters) allocation.shaderDataUserWords.push_back(reg - userDataBase);
}
std::vector<DescriptorBinding> bindings;
bindings.reserve(plan.bindings.size());
auto bindings = std::move(allocation.bindings);
bindings.resize(plan.bindings.size());
std::size_t writtenHere = 0;
std::size_t readOnlyHere = 0;
for (const auto& entry : plan.bindings) {
auto physical = entry.descriptor;
for (std::size_t index = 0; index < plan.bindings.size(); ++index) {
const auto& entry = plan.bindings[index];
auto& physical = bindings[index];
physical = entry.descriptor;
switch (physical.role) {
case DescriptorRole::GuestBuffers:
physical.guestDescriptor = GuestBuffersDescriptor(entry.resources, snapshot);
GuestBuffersDescriptor(physical.guestDescriptor, entry.resources, snapshot);
writtenHere += entry.writtenBuffers;
readOnlyHere += entry.readOnlyBuffers;
break;
Expand All @@ -598,7 +598,7 @@ void DescriptorBindingBuilder::Populate(BindingAllocationResult& allocation, con
}
break;
case DescriptorRole::GuestSamplers:
physical.guestDescriptor = GuestSamplersDescriptor(entry.resources, snapshot);
GuestSamplersDescriptor(physical.guestDescriptor, entry.resources, snapshot);
for (const auto element : entry.samplerFilterElements) {
auto& filter = physical.guestDescriptor.at(element * 4u + 2u);
filter = PointFilteredSamplerWord(physical.guestDescriptor.at(element * 4u), filter);
Expand Down Expand Up @@ -659,8 +659,6 @@ void DescriptorBindingBuilder::Populate(BindingAllocationResult& allocation, con
fail("DescriptorBindingBuilder::Populate guest descriptor size is not a multiple of the binding count");
}
}

bindings.push_back(std::move(physical));
}

if (bufferWrittenTraceEnabled()) {
Expand Down
15 changes: 13 additions & 2 deletions core/shader/recompiler/Recompiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1008,7 +1008,7 @@ const ResourceSnapshot& mergeTargetImage(const CompiledVariant& variant, const R
return merged;
}

RecompileResult materializeResult(const CompiledVariant& variant, const RecompileRequest& request, const ResourceSnapshot& captured, bool registrationDefaults = false) {
RecompileResult materializeResult(const CompiledVariant& variant, const RecompileRequest& request, const ResourceSnapshot& captured, bool registrationDefaults = false, std::vector<DescriptorBinding> reuse = {}) {
ResourceSnapshot merged;
const auto& snapshot = mergeTargetImage(variant, request, captured, registrationDefaults, merged);
RecompileResult result;
Expand Down Expand Up @@ -1161,6 +1161,7 @@ RecompileResult materializeResult(const CompiledVariant& variant, const Recompil
const auto resolved = ResourceMaterializer::ResolveImageTablesShared(variant.info.info, snapshot, artifact.variantId);
const auto& tables = *resolved;
BindingAllocationResult bindings;
bindings.bindings = std::move(reuse);
DescriptorBindingBuilder{}.Populate(bindings, variant.bindings, *bindingPlan, variant.info.userDataBase, snapshot, partialThreads(request), &tables);
result.workgroupMemoryDwords = WorkgroupMemoryStrideDwords(variant.info.info);
result.bindings = std::move(bindings.bindings);
Expand Down Expand Up @@ -1477,23 +1478,33 @@ std::shared_ptr<const RecompileResult> materializePreparedMemoized(SourceEntry&
const auto hash = snapshotHash(request, snapshot);
std::uint64_t index = 0;
auto& counters = resultMemoCounters();
std::shared_ptr<const RecompileResult> recycled;
{
std::lock_guard lock(source.mutex);
index = (variant->artifact.variantId * 0x9e3779b97f4a7c15ull) ^ hash;
if (auto* set = memoSet(source, index)) {
auto* victim = set;
for (std::size_t way = 0; way < ResultMemoWays; ++way) {
auto& entry = set[way];
if (entry.used < victim->used) victim = &entry;
if (entry.result == nullptr || entry.variantId != variant->artifact.variantId || entry.hash != hash) continue;
entry.used = ++source.memoClock;
counters.hits.fetch_add(1, std::memory_order_relaxed);
if (memoHit != nullptr) *memoHit = true;
reportResultMemo();
return entry.result;
}
if (victim->result != nullptr && victim->result.use_count() == 1) {
recycled = std::move(victim->result);
*victim = {};
counters.evictions.fetch_add(1, std::memory_order_relaxed);
}
}
}
std::vector<DescriptorBinding> reuse;
if (recycled != nullptr) reuse = std::move(const_cast<RecompileResult&>(*recycled).bindings);
const auto started = profile ? std::chrono::steady_clock::now() : std::chrono::steady_clock::time_point{};
auto result = std::make_shared<RecompileResult>(materializeResult(*variant, request, snapshot));
auto result = std::make_shared<RecompileResult>(materializeResult(*variant, request, snapshot, false, std::move(reuse)));
result->cacheHit = cacheHit;
if (profile) counters.populateNanoseconds.fetch_add(static_cast<std::uint64_t>(std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::steady_clock::now() - started).count()), std::memory_order_relaxed);
counters.misses.fetch_add(1, std::memory_order_relaxed);
Expand Down
Loading