Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
c886c28
fix(agc): stamp the watched blocks of a partly watched store
EagleBearerYS Oct 15, 2026
a0dc9d3
test(agc): check the stamps of a store into partly watched memory
EagleBearerYS Oct 15, 2026
b02c442
perf(shader): reuse an image table column's snapshot while its memory…
EagleBearerYS Oct 15, 2026
5686705
test(agc): check the image table snapshot reuse against every write path
EagleBearerYS Oct 15, 2026
0431419
fix(agc): store pending GPU results before vouching for an unwritten …
EagleBearerYS Oct 15, 2026
17ccfc4
perf(shader): walk a changed table column from the words its compare …
EagleBearerYS Oct 15, 2026
d816062
perf(shader): share an unchanged image table column with every snapsh…
EagleBearerYS Oct 15, 2026
992222d
perf(agc): keep an unwritten table column's words by reference in the…
EagleBearerYS Oct 15, 2026
077bc20
perf(shader): reuse an unchanged image table's resolution by referenc…
EagleBearerYS Oct 15, 2026
25cfce3
perf(agc): compare two captures' shared table words by identity in th…
EagleBearerYS Oct 15, 2026
a7fb1b6
perf(agc): size a cached variant's words once before copying a captur…
EagleBearerYS Oct 15, 2026
a35de33
fix(agc): stamp a table before its pending-write query and note GPU w…
EagleBearerYS Oct 15, 2026
97590db
perf(shader): vouch for an unwritten table column once over its span,…
EagleBearerYS Oct 15, 2026
23c2017
perf(agc): validate a cached draw or dispatch by its shared table blo…
EagleBearerYS Oct 15, 2026
6643e28
perf(agc): tell the flush hook that no image is pending over a range …
EagleBearerYS Oct 15, 2026
70129f2
perf(agc): skip a vouched table's regions by range instead of one reg…
EagleBearerYS Oct 15, 2026
83c51e9
perf(agc): vouch for a cached variant's tables before the checks that…
EagleBearerYS Oct 15, 2026
dc6c346
perf(agc): supply an unwritten column's words without walking its runs
EagleBearerYS Oct 15, 2026
acd74bc
perf(agc): replay a reused image table's bound elements without check…
EagleBearerYS Oct 15, 2026
1d66d85
perf(agc): keep a freed image table's descriptor set and skip rewriti…
EagleBearerYS Oct 15, 2026
6fb584f
perf(agc): record a kept table set's descriptors when it is freed, no…
EagleBearerYS Oct 15, 2026
19ab974
fix(shader): keep the disk cache keys when the image table reuse is s…
EagleBearerYS Oct 15, 2026
d21b080
Merge upstream main into perf/shader-image-table-reuse-v3
EagleBearerYS Oct 15, 2026
4afa20d
fix(agc): keep table vouches from waiting for queued draws
EagleBearerYS Oct 15, 2026
783ff73
test(agc): keep the span query test's user data alive while it captures
EagleBearerYS Oct 15, 2026
75a337f
test(agc): end a table's epoch with a store across its heap's edge in…
EagleBearerYS Oct 15, 2026
5a31a9c
Merge branch 'perf/shader-direct-cpu-evaluable-images' into perf/shad…
EagleBearerYS Oct 15, 2026
ab82f50
Merge branch 'fix/agc-stamp-partly-watched-stores' into perf/shader-i…
EagleBearerYS Oct 15, 2026
4fc7af7
test(agc): register the image table reuse tests in one block
EagleBearerYS Oct 15, 2026
7f7d406
refactor(agc): place the image table reuse's includes and shared reso…
EagleBearerYS Oct 15, 2026
3ba5574
Merge upstream main into perf/shader-image-table-reuse-v3-pr
EagleBearerYS Oct 15, 2026
210a585
Merge upstream main into perf/shader-image-table-reuse-v3-pr
EagleBearerYS Oct 15, 2026
041af98
Merge upstream main into perf/shader-image-table-reuse-v3-pr
EagleBearerYS Oct 15, 2026
fae2221
Merge #6537's head into perf/shader-image-table-reuse-v3-pr
EagleBearerYS Oct 15, 2026
22f8c14
Merge #6243's head into perf/shader-image-table-reuse-v3-pr
EagleBearerYS Oct 16, 2026
19907d6
Merge main into perf/shader-image-table-reuse-v3-pr
EagleBearerYS Oct 16, 2026
e448df1
fix(agc): record a relocatable draw variant's shared words by run
EagleBearerYS Oct 16, 2026
51d4bab
Merge main into perf/shader-image-table-reuse-v3-pr
EagleBearerYS Oct 16, 2026
1752c4a
Merge #6537's head into perf/shader-image-table-reuse-v3-pr
EagleBearerYS Oct 16, 2026
a53d23f
Merge main into perf/shader-image-table-reuse-v3-pr
EagleBearerYS Oct 17, 2026
6884e9c
Merge #6243's head into perf/shader-image-table-reuse-v3-pr
EagleBearerYS Oct 17, 2026
4978871
Merge #6243's head into perf/shader-image-table-reuse-v3-pr
EagleBearerYS Oct 18, 2026
6720211
Merge main into perf/shader-image-table-reuse-v3-pr
EagleBearerYS Oct 18, 2026
db622e1
Merge main into perf/shader-image-table-reuse-v3-pr
EagleBearerYS Oct 18, 2026
a508aa0
Merge main into perf/shader-image-table-reuse-v3-pr
EagleBearerYS Oct 18, 2026
dad24e3
Merge main into perf/shader-image-table-reuse-v3-pr
EagleBearerYS Oct 18, 2026
209f3ce
test(shader): adapt volume rejection fixture to shared columns
Scramblrrrr Oct 16, 2026
54f2cf3
Merge main into perf/shader-image-table-reuse-v3-pr
EagleBearerYS Oct 18, 2026
790fe18
docs(environment): add the rows for the image table reuse switches
EagleBearerYS Oct 18, 2026
d032505
Merge main into perf/shader-image-table-reuse-v3-pr
EagleBearerYS Oct 18, 2026
970e814
test(agc): create the driver before the queued-draw vouch takes its s…
EagleBearerYS Oct 19, 2026
10b798f
Merge main into perf/shader-image-table-reuse-v3-pr
EagleBearerYS Oct 19, 2026
106b79e
Merge main into perf/shader-image-table-reuse-v3-pr
EagleBearerYS Oct 19, 2026
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
13 changes: 13 additions & 0 deletions core/libs/prx/libSceAgcDriver/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1686,6 +1686,10 @@ target_include_directories(agc_driver_alpha_to_coverage_tests PRIVATE $<TARGET_P

target_include_directories(agc_driver_sample_multisample_target_tests PRIVATE $<TARGET_PROPERTY:shader_recompiler_agc_driver,INTERFACE_INCLUDE_DIRECTORIES>)

target_include_directories(agc_driver_image_table_cache_bounds_tests PRIVATE $<TARGET_PROPERTY:shader_recompiler_agc_driver,INTERFACE_INCLUDE_DIRECTORIES>)

target_include_directories(agc_driver_draw_cache_relocation_tests PRIVATE $<TARGET_PROPERTY:shader_recompiler_agc_driver,INTERFACE_INCLUDE_DIRECTORIES>)

if(BUILD_TESTING)
add_test(NAME agc_driver_store_pending_identity COMMAND agc_driver_store_over_untracked_tests --pending-identity)
set_tests_properties(agc_driver_store_pending_identity PROPERTIES
Expand Down Expand Up @@ -1828,6 +1832,15 @@ if(BUILD_TESTING)
set_tests_properties(agc_shader_selected_records_image_limit agc_shader_selected_records_pair_limit agc_shader_selected_records_direct_image_limit agc_shader_selected_records_direct_pair_limit PROPERTIES ENVIRONMENT "ANYPS5_NO_SHADER_CACHE=1" WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}")
add_test(NAME agc_shader_srt_read_patching COMMAND agc_shader_memory_tests --srt-read-patching)
set_tests_properties(agc_shader_srt_read_patching PROPERTIES ENVIRONMENT "ANYPS5_NO_SHADER_CACHE=1" WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}")
add_test(NAME agc_shader_table_snapshot_reuse COMMAND agc_shader_memory_tests --table-snapshot-reuse)
set_tests_properties(agc_shader_table_snapshot_reuse PROPERTIES ENVIRONMENT "ANYPS5_NO_SHADER_CACHE=1" WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}")
add_test(NAME agc_driver_image_table_vouched_lookups COMMAND agc_driver_image_table_cache_bounds_tests --vouched-lookups)
set_tests_properties(agc_driver_image_table_vouched_lookups PROPERTIES ENVIRONMENT "ANYPS5_NO_SHADER_CACHE=1;APS5_WRITE_WATCH_IMPORTS=watch" SKIP_RETURN_CODE 77 WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}" TIMEOUT 60)
add_test(NAME agc_driver_image_table_vouch_queued_draws COMMAND agc_driver_image_table_cache_bounds_tests --queued-draws)
set_tests_properties(agc_driver_image_table_vouch_queued_draws PROPERTIES ENVIRONMENT "ANYPS5_NO_SHADER_CACHE=1" SKIP_RETURN_CODE 77 WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}" TIMEOUT 60)
if(WIN32)
set_tests_properties(agc_shader_table_snapshot_reuse agc_driver_image_table_vouched_lookups agc_driver_image_table_vouch_queued_draws PROPERTIES ENVIRONMENT_MODIFICATION "PATH=path_list_prepend:$<TARGET_FILE_DIR:libc>")
endif()
add_test(NAME agc_shader_type_zero_image_materialization COMMAND agc_shader_memory_tests --type-zero-image-materialization)
set_tests_properties(agc_shader_type_zero_image_materialization PROPERTIES ENVIRONMENT "ANYPS5_NO_SHADER_CACHE=1" WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}")
add_test(NAME agc_shader_frontend_pair COMMAND agc_shader_memory_tests --frontend-pair)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ struct DispatchVariant {

std::vector<std::pair<std::uint64_t, std::uint64_t>> runs;
std::vector<std::uint32_t> words;
std::vector<SharedWords> shared;
std::uint64_t forgetSerial = 0;
std::shared_ptr<const ShaderRecompiler::RecompileResult> compiled;
std::array<std::uint32_t, 4> meshIndexDescriptor{};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ struct StageCapture {
std::shared_ptr<const ShaderRecompiler::RecompileResult> compiled;
std::shared_ptr<const ShaderRecompiler::ResourceCapture> capture;
std::vector<ShaderRecompiler::MemoryRegion> regions;
std::vector<std::shared_ptr<const ShaderRecompiler::SrtGuestWords>> supplied;
std::uint64_t forgetSerial = 0;
std::uint32_t pushOffset = 0;
ShaderRecompiler::SrtUserDataUse userDataUse;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ class Driver {
void SettleShaderPreparations(std::span<const Shader* const> stages);
static void FoldDrawOffsets(const ShaderRecompiler::RecompileResult& result, const DrawProgram& program, Pm4::DrawParameters& parameters);
static std::optional<Graphics::IndirectDrawPath> ClassifyIndirectDraw(const ShaderRecompiler::RecompileResult& result, const Graphics::State& graphics, const DrawProgram& frontProgram, const std::shared_ptr<VulkanDevice>& localDevice, Pm4::DrawParameters& drawParameters, bool traceIndirect);
static void tagVariantRuns(DispatchVariant& variant, std::span<const ShaderRecompiler::MemoryRegion> regions, const ShaderRecompiler::SrtUserDataUse& use, bool eligible, std::uint32_t hiddenWords, std::span<const std::shared_ptr<const ShaderRecompiler::SrtGuestWords>> supplied = {});
static std::string dumpRequest(std::uint64_t address, const ShaderRecompiler::RecompileRequest& request, std::string_view suffix = {});
DrawEntryCounters DrawCacheCounters();
struct DispatchCacheFootprint {
Expand All @@ -76,6 +77,7 @@ class Driver {
};
DispatchCacheFootprint DispatchCacheSize();
static std::uint64_t DispatchCacheBytes();
static ShaderMemory::PendingWrite QueryPendingSpan(std::uint64_t address, std::size_t bytes, std::span<std::byte> known);
std::shared_ptr<const ShaderRegistry> RegisteredShaders();

private:
Expand Down Expand Up @@ -151,7 +153,6 @@ class Driver {
static std::uint64_t drawIdentityKey(const QueueState& queue, const ShaderRegistry& registry);
static bool drawRelocationEnabled();
static std::uint64_t relocatedContentKey(const RelocatableUserWord& word, std::uint32_t value, bool& readable);
static void tagVariantRuns(DispatchVariant& variant, std::span<const ShaderRecompiler::MemoryRegion> regions, const ShaderRecompiler::SrtUserDataUse& use, bool eligible, std::uint32_t hiddenWords);
static void applyShaderDataPatches(DispatchVariant& variant);
void learnPendingRelocation();
void relocateDrawEntry(const QueueState& queue, std::uint64_t alias, std::shared_ptr<DrawEntry>& entry, std::shared_ptr<const DrawDecode>& decode, std::vector<DrawUserPatch>& patches);
Expand Down Expand Up @@ -208,6 +209,7 @@ class Driver {
static std::uint64_t hookWaits();
static ShaderMemory::HookWaitCounter hookWaitCounter();
static bool validateSkipEnabled();
static bool vouchedValidation();
static bool validateLegacy();
static bool gateRetry();
static bool validateSkipVerify();
Expand Down Expand Up @@ -242,10 +244,10 @@ class Driver {
void traceCapture(const char* what, std::uint64_t program, std::uint32_t queue, std::span<const ShaderRecompiler::MemoryRegion> regions, double waitedMs);
void reportValidation(ValidateCounters& counters);
bool captureStable(std::span<const ShaderRecompiler::MemoryRegion> captured);
bool validateCaptured(std::uint64_t program, std::uint32_t queue, std::span<const ShaderRecompiler::MemoryRegion> captured, const ShaderRecompiler::RecompileResult& compiled, bool inPlace, const PendingView& view, bool* unmapped = nullptr, std::optional<SampledReadScope>* sampling = nullptr, const DataMask* data = nullptr);
bool validateCaptured(std::uint64_t program, std::uint32_t queue, std::span<const ShaderRecompiler::MemoryRegion> captured, const ShaderRecompiler::RecompileResult& compiled, bool inPlace, const PendingView& view, bool* unmapped = nullptr, std::optional<SampledReadScope>* sampling = nullptr, const DataMask* data = nullptr, std::span<const VouchedRegions> vouched = {});
static void appendEntryRegions(const DispatchVariant& variant, std::vector<ShaderRecompiler::MemoryRegion>& regions, const std::vector<std::uint32_t>* words = nullptr);
static std::shared_ptr<const ShaderRecompiler::RecompileResult> patchDataWords(const DispatchVariant& variant, const std::vector<std::uint32_t>& words);
bool syncPendingRuns(std::uint64_t program, std::uint32_t queue, const ShaderRecompiler::RecompileResult& compiled, std::span<const ShaderRecompiler::MemoryRegion> regions, std::uint64_t& synced, PendingView& pending, std::optional<SampledReadScope>& sampling);
bool syncPendingRuns(std::uint64_t program, std::uint32_t queue, const ShaderRecompiler::RecompileResult& compiled, std::span<const ShaderRecompiler::MemoryRegion> regions, std::uint64_t& synced, PendingView& pending, std::optional<SampledReadScope>& sampling, std::span<const VouchedRegions> skipped = {});
EntryOutcome validateVariant(std::uint64_t program, std::uint32_t queue, const DispatchVariant& variant, std::span<const ShaderRecompiler::MemoryRegion> regions, std::uint64_t& imagesFlushed, std::uint64_t& runsSynced, std::optional<SampledReadScope>& sampling, std::vector<std::pair<std::uint32_t, std::uint32_t>>* live = nullptr);
static int waitTimeoutMs();
static bool pollReapAll();
Expand Down
52 changes: 51 additions & 1 deletion core/libs/prx/libSceAgcDriver/Execution/include/ShaderMemory.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
namespace ShaderRecompiler {
struct SourceHandle;
class PreparedShaderInvocation;
struct SrtWriteStamp;
struct SrtGuestWords;
}

namespace AgcDriver {
Expand Down Expand Up @@ -56,7 +58,7 @@ class ShaderMemory {
// by the driver: the [capture] line charges the waits made inside a capture to it.
using WaitedMsProvider = double (*)();
static void SetWaitedMsProvider(WaitedMsProvider provider);
explicit ShaderMemory(std::span<const ShaderRecompiler::MemoryRegion> initial, PendingWriteQuery pendingWrite = nullptr, PendingWriteObserver observe = nullptr, HookWaitCounter hookWaits = nullptr);
explicit ShaderMemory(std::span<const ShaderRecompiler::MemoryRegion> initial, PendingWriteQuery pendingWrite = nullptr, PendingWriteObserver observe = nullptr, HookWaitCounter hookWaits = nullptr, PendingWriteQuery pendingSpan = nullptr);
~ShaderMemory();
ShaderMemory(const ShaderMemory&) = delete;
ShaderMemory& operator=(const ShaderMemory&) = delete;
Expand All @@ -74,6 +76,16 @@ class ShaderMemory {
[[nodiscard]] std::vector<ShaderRecompiler::MemoryRegion> TakeRecentRegions();
// The driver's source handle memo outcomes, for the [capture] line (APS5_PROFILE_DRAW).
static void CountHandleMemo(bool hit);
struct SupplyCounts {
std::uint64_t shared, copied, spilled;
};
static SupplyCounts Supplies();
[[nodiscard]] std::vector<std::shared_ptr<const ShaderRecompiler::SrtGuestWords>> SuppliedBlocks() const;
struct VouchCounts {
std::uint64_t calls, blocks, refused, words;
};
static VouchCounts Vouches();
static bool Vouched(PendingWriteQuery pending, std::uint64_t address, std::uint64_t bytes, const ShaderRecompiler::SrtWriteStamp& stamp);

private:
std::shared_ptr<const ShaderRecompiler::ResourceCapture> capture(const ShaderRecompiler::RecompileRequest& request, const ShaderRecompiler::SourceHandle* handle, const ShaderRecompiler::PreparedShaderInvocation* invocation);
Expand Down Expand Up @@ -107,22 +119,41 @@ class ShaderMemory {
bool lazy = false;
};

struct Supplied {
std::shared_ptr<const ShaderRecompiler::SrtGuestWords> words;
std::uint64_t begin = 0;
std::uint64_t end = 0;
bool recent = true;
};

static bool read(void* context, std::uint64_t address, std::uint32_t* value);
static bool readWords(void* context, std::uint64_t address, std::uint32_t* values, std::uint64_t count);
static bool accessible(void* context, std::uint64_t address, std::uint64_t bytes);
static bool pending(void* context, std::uint64_t address, std::uint64_t bytes);
static ShaderRecompiler::SrtWriteStamp stampWrites(void* context, std::uint64_t address, std::uint64_t bytes);
static bool unchangedSince(void* context, std::uint64_t address, std::uint64_t bytes, const ShaderRecompiler::SrtWriteStamp& stamp);
static bool supplyWords(void* context, const std::shared_ptr<const ShaderRecompiler::SrtGuestWords>& words);
Page& page(std::uint64_t base);
[[nodiscard]] std::size_t pageAtOrAfter(std::uint64_t base) const;
Page& addPage(std::size_t position, std::uint64_t base);
[[nodiscard]] bool overlapsInitial(std::uint64_t begin, std::uint64_t end) const;
bool place(std::uint64_t address, const std::uint32_t* values, std::uint64_t count, bool overwrite, bool recent);
void spill(std::size_t index);
void spillTouching(std::uint64_t begin, std::uint64_t end);
[[nodiscard]] std::vector<ShaderRecompiler::MemoryRegion> collect(bool recentOnly) const;

// Regions given at construction (the registered shader's code and header), referenced as given:
// the caller keeps them alive for as long as the capture is used.
std::map<std::uint64_t, std::span<const std::byte>> initial;
std::vector<std::pair<std::uint64_t, Page*>> pages;
std::uint64_t lastBase = ~std::uint64_t{0};
Page* lastPage = nullptr;
std::vector<Supplied> supplied;
std::vector<std::shared_ptr<const ShaderRecompiler::SrtGuestWords>> spilled;
PendingWriteQuery pendingWrite = nullptr;
PendingWriteObserver observe = nullptr;
HookWaitCounter hookWaits = nullptr;
PendingWriteQuery pendingSpan = nullptr;
};

// The positions, among a dispatch-cache variant's stored words, of the pure flat-SRT leaves a
Expand All @@ -140,6 +171,25 @@ struct DataWordPositionCounts {
};
DataWordPositionCounts DataWordPositions(std::span<const std::pair<std::uint64_t, std::uint64_t>> runs, std::span<const std::pair<std::uint32_t, std::uint64_t>> leaves, std::span<const std::uint64_t> otherReads, std::span<const std::uint32_t> words, std::span<const std::uint32_t> flattenedSrt, std::vector<std::uint32_t>& positions, std::vector<std::uint32_t>& slots);

struct SharedWords {
std::size_t first = 0;
std::size_t count = 0;
std::size_t offset = 0;
std::weak_ptr<const ShaderRecompiler::SrtGuestWords> block;
std::size_t region = 0;
std::size_t regions = 0;
};
void AppendSharedWords(std::vector<SharedWords>& shared, std::size_t region, std::size_t first, std::span<const std::byte> bytes, std::span<const std::shared_ptr<const ShaderRecompiler::SrtGuestWords>> blocks);
bool SameCapturedWords(std::span<const std::uint32_t> left, std::span<const SharedWords> leftShared, std::span<const std::uint32_t> right, std::span<const SharedWords> rightShared, std::size_t* compared = nullptr);
struct VouchedRegions {
std::size_t begin = 0;
std::size_t end = 0;
std::size_t words = 0;
std::uint64_t low = 0;
std::uint64_t high = 0;
};
std::size_t VouchSharedRegions(std::span<const SharedWords> shared, std::size_t regions, ShaderMemory::PendingWriteQuery pending, std::vector<VouchedRegions>& vouched);

}

#endif
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ void Driver::verifyDataHit(const ShaderSnapshot& snapshot, std::size_t codeOffse
std::fflush(stderr);
std::abort();
};
auto verifyMemory = std::make_shared<ShaderMemory>(memory, &queryPendingWrite, &observePendingWrite, hookWaitCounter());
auto verifyMemory = std::make_shared<ShaderMemory>(memory, &queryPendingWrite, &observePendingWrite, hookWaitCounter(), &QueryPendingSpan);
auto invocation = InvocationFor(snapshot, codeOffset, request);
const auto capture = CaptureInvocation(*verifyMemory, snapshot, codeOffset, request, invocation);
const auto regions = verifyMemory->Regions();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -326,7 +326,7 @@ void Driver::dispatch(QueueState& queue, std::span<const std::uint32_t> packet,
require(keepVariant != nullptr && keepVariant->shader == registeredShader, "dispatch cache belongs to another registered shader");
captureMs += phaseTiming.Elapsed();
} else if (!fromAhead) {
shaderMemory = std::make_shared<ShaderMemory>(memory, &queryPendingWrite, &observePendingWrite, hookWaitCounter());
shaderMemory = std::make_shared<ShaderMemory>(memory, &queryPendingWrite, &observePendingWrite, hookWaitCounter(), &QueryPendingSpan);
std::uint64_t forgetAtCapture = 0;

static const bool dumpShaders = std::getenv("APS5_DUMP_SHADERS") != nullptr;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ Driver::DispatchCacheFootprint Driver::DispatchCacheSize() {
}

std::uint64_t Driver::variantBytes(const DispatchVariant& variant) {
return sizeof(DispatchVariant) + variant.words.size() * sizeof(std::uint32_t) + variant.runs.size() * sizeof(std::pair<std::uint64_t, std::uint64_t>) + variant.captured.size() * sizeof(ShaderRecompiler::MemoryRegion) + (variant.vertexInfo != nullptr ? sizeof(ShaderRecompiler::ShaderVertexStageInfo) : 0);
return sizeof(DispatchVariant) + variant.words.size() * sizeof(std::uint32_t) + variant.shared.size() * sizeof(SharedWords) + variant.runs.size() * sizeof(std::pair<std::uint64_t, std::uint64_t>) + variant.captured.size() * sizeof(ShaderRecompiler::MemoryRegion) + (variant.vertexInfo != nullptr ? sizeof(ShaderRecompiler::ShaderVertexStageInfo) : 0);
}

void Driver::accountVariant(const DispatchVariant& variant, bool added) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,23 @@ void Driver::insertDispatch(std::uint64_t address, std::uint64_t key, bool noDis
fresh->forgetSerial = forgetAtCapture;

std::vector<ShaderRecompiler::MemoryRegion> srtRegions;
std::size_t capturedWords = 0;
for (const auto& region : captured) {
const bool registered = std::any_of(memory.begin(), memory.end(), [&](const auto& known) { return region.guestAddress >= known.guestAddress && region.guestAddress < known.guestAddress + known.bytes.size(); });
if (registered) continue;
srtRegions.push_back(region);
capturedWords += region.bytes.size() / sizeof(std::uint32_t);
}
const auto supplied = shaderMemory->SuppliedBlocks();
fresh->runs.reserve(srtRegions.size());
fresh->words.reserve(capturedWords);
for (const auto& region : srtRegions) {
fresh->runs.emplace_back(region.guestAddress, region.guestAddress + region.bytes.size());
const auto count = region.bytes.size() / sizeof(std::uint32_t);
const auto offset = fresh->words.size();
fresh->words.resize(offset + count);
std::memcpy(fresh->words.data() + offset, region.bytes.data(), count * sizeof(std::uint32_t));
AppendSharedWords(fresh->shared, fresh->runs.size() - 1u, offset, region.bytes, supplied);
}

DataWordPositionCounts dataCounts;
Expand Down Expand Up @@ -91,7 +99,7 @@ void Driver::insertDispatch(std::uint64_t address, std::uint64_t key, bool noDis
dispatchOrder.push_front(key);
created->order = dispatchOrder.begin();
dispatchCache.emplace(key, std::move(created));
} else if (found->second != missedEntry && !found->second->variants.empty() && found->second->variants.front()->runs == fresh->runs && found->second->variants.front()->words == fresh->words) {
} else if (found->second != missedEntry && !found->second->variants.empty() && found->second->variants.front()->runs == fresh->runs && SameCapturedWords(found->second->variants.front()->words, found->second->variants.front()->shared, fresh->words, fresh->shared)) {

attachVariant = found->second->variants.front();
} else {
Expand Down
Loading
Loading