Merge #9533's merge of main into feat/agc-msaa-d32s8-stencil-view

The conflict in core/libs/prx/libSceAgcDriver/CMakeLists.txt from #12862's split is resolved with tools/agc_test_split.py resolve, which moves this PR's test registrations into tests/cmake/.
This commit is contained in:
Yunus Shaikh committed 2026-10-31 15:06:22 -07:00
commit a63bd1432f
677 files changed
+62844 -11463

No files matched your search

+10
View File
@@ -500,6 +500,16 @@ if(BUILD_TESTING)
set_tests_properties(guest_firmware_constant_returns PROPERTIES ENVIRONMENT_MODIFICATION
"PATH=path_list_prepend:$<TARGET_FILE_DIR:libSceAvSetting>;PATH=path_list_prepend:$<TARGET_FILE_DIR:libSceComposite>;PATH=path_list_prepend:$<TARGET_FILE_DIR:libSceFsInternalForVsh>;PATH=path_list_prepend:$<TARGET_FILE_DIR:libSceHttpCache>;PATH=path_list_prepend:$<TARGET_FILE_DIR:libScePlayReady>;PATH=path_list_prepend:$<TARGET_FILE_DIR:libSceSdma>;PATH=path_list_prepend:$<TARGET_FILE_DIR:libSceSsl>;PATH=path_list_prepend:$<TARGET_FILE_DIR:libSceVisionManager>;PATH=path_list_prepend:$<TARGET_FILE_DIR:libmdbg_syscore>")
endif()
add_test_executable(guest_playready_tests tests/GuestPlayReady.cpp)
target_include_directories(guest_playready_tests PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
target_link_libraries(guest_playready_tests PRIVATE libScePlayReady libkernel libc)
configure_windows_unwind(guest_playready_tests)
add_test(NAME guest_playready COMMAND guest_playready_tests)
set_tests_properties(guest_playready PROPERTIES TIMEOUT 20)
if(WIN32)
set_tests_properties(guest_playready PROPERTIES ENVIRONMENT_MODIFICATION
"PATH=path_list_prepend:$<TARGET_FILE_DIR:libScePlayReady>")
endif()
if(Python3_Interpreter_FOUND)
add_test(NAME nid_verneed COMMAND ${Python3_EXECUTABLE}
${CMAKE_CURRENT_SOURCE_DIR}/nid/tests/test_verneed.py $<TARGET_FILE:nid_patcher>)
+206
View File
@@ -1,3 +1,5 @@
#include "prx/libSceAbstractTcs/include/LegacyExports.hpp"
#include "prx/libc/include/general/ExportMacros.hpp"
#include <cstddef>
#include <cstdint>
#include "SceTypes.hpp"
@@ -8,3 +10,207 @@ extern "C" {
APS5_DUMMY_FUN
}
extern "C" {
int APS5_VABI abstractTcsLegacyUnknown__plus_uyvmTPkPT0_nid_no_patch() {
NotImplemented_nid_no_patch(__func__);
}
APS5_EXPORT("+uyvmTPkPT0", abstractTcsLegacyUnknown__plus_uyvmTPkPT0_nid_no_patch);
int APS5_VABI abstractTcsLegacyUnknown__plus_yHj1U_minus_k1zU_nid_no_patch() {
NotImplemented_nid_no_patch(__func__);
}
APS5_EXPORT("+yHj1U-k1zU", abstractTcsLegacyUnknown__plus_yHj1U_minus_k1zU_nid_no_patch);
int APS5_VABI abstractTcsLegacyUnknown_065iwsKaKA4_nid_no_patch() {
NotImplemented_nid_no_patch(__func__);
}
APS5_EXPORT("065iwsKaKA4", abstractTcsLegacyUnknown_065iwsKaKA4_nid_no_patch);
int APS5_VABI abstractTcsLegacyUnknown_0MDv01EA_minus_Wo_nid_no_patch() {
NotImplemented_nid_no_patch(__func__);
}
APS5_EXPORT("0MDv01EA-Wo", abstractTcsLegacyUnknown_0MDv01EA_minus_Wo_nid_no_patch);
int APS5_VABI abstractTcsLegacyUnknown_1vgiZdMEU8k_nid_no_patch() {
NotImplemented_nid_no_patch(__func__);
}
APS5_EXPORT("1vgiZdMEU8k", abstractTcsLegacyUnknown_1vgiZdMEU8k_nid_no_patch);
int APS5_VABI abstractTcsLegacyUnknown_29VsAacFFxw_nid_no_patch() {
NotImplemented_nid_no_patch(__func__);
}
APS5_EXPORT("29VsAacFFxw", abstractTcsLegacyUnknown_29VsAacFFxw_nid_no_patch);
int APS5_VABI abstractTcsLegacyUnknown_4_minus_Soqq0Hrqg_nid_no_patch() {
NotImplemented_nid_no_patch(__func__);
}
APS5_EXPORT("4-Soqq0Hrqg", abstractTcsLegacyUnknown_4_minus_Soqq0Hrqg_nid_no_patch);
int APS5_VABI abstractTcsLegacyUnknown_5NEeXee1_minus_kQ_nid_no_patch() {
NotImplemented_nid_no_patch(__func__);
}
APS5_EXPORT("5NEeXee1-kQ", abstractTcsLegacyUnknown_5NEeXee1_minus_kQ_nid_no_patch);
int APS5_VABI abstractTcsLegacyUnknown_5b5Tx09Z8uE_nid_no_patch() {
NotImplemented_nid_no_patch(__func__);
}
APS5_EXPORT("5b5Tx09Z8uE", abstractTcsLegacyUnknown_5b5Tx09Z8uE_nid_no_patch);
int APS5_VABI abstractTcsLegacyUnknown_6zjNlHxuPhY_nid_no_patch() {
NotImplemented_nid_no_patch(__func__);
}
APS5_EXPORT("6zjNlHxuPhY", abstractTcsLegacyUnknown_6zjNlHxuPhY_nid_no_patch);
int APS5_VABI abstractTcsLegacyUnknown_8uRxMgcUE6c_nid_no_patch() {
NotImplemented_nid_no_patch(__func__);
}
APS5_EXPORT("8uRxMgcUE6c", abstractTcsLegacyUnknown_8uRxMgcUE6c_nid_no_patch);
int APS5_VABI abstractTcsLegacyUnknown_9KwAuQYhInc_nid_no_patch() {
NotImplemented_nid_no_patch(__func__);
}
APS5_EXPORT("9KwAuQYhInc", abstractTcsLegacyUnknown_9KwAuQYhInc_nid_no_patch);
int APS5_VABI abstractTcsLegacyUnknown_9RskWGK_plus_Kto_nid_no_patch() {
NotImplemented_nid_no_patch(__func__);
}
APS5_EXPORT("9RskWGK+Kto", abstractTcsLegacyUnknown_9RskWGK_plus_Kto_nid_no_patch);
int APS5_VABI abstractTcsLegacyUnknown_BnQJZLesghs_nid_no_patch() {
NotImplemented_nid_no_patch(__func__);
}
APS5_EXPORT("BnQJZLesghs", abstractTcsLegacyUnknown_BnQJZLesghs_nid_no_patch);
int APS5_VABI abstractTcsLegacyUnknown_CKQqO0otsv0_nid_no_patch() {
NotImplemented_nid_no_patch(__func__);
}
APS5_EXPORT("CKQqO0otsv0", abstractTcsLegacyUnknown_CKQqO0otsv0_nid_no_patch);
int APS5_VABI abstractTcsLegacyUnknown_IarxytjvEuI_nid_no_patch() {
NotImplemented_nid_no_patch(__func__);
}
APS5_EXPORT("IarxytjvEuI", abstractTcsLegacyUnknown_IarxytjvEuI_nid_no_patch);
int APS5_VABI abstractTcsLegacyUnknown_J5koYi_plus_uPnk_nid_no_patch() {
NotImplemented_nid_no_patch(__func__);
}
APS5_EXPORT("J5koYi+uPnk", abstractTcsLegacyUnknown_J5koYi_plus_uPnk_nid_no_patch);
int APS5_VABI abstractTcsLegacyUnknown_JwWSY1YarEs_nid_no_patch() {
NotImplemented_nid_no_patch(__func__);
}
APS5_EXPORT("JwWSY1YarEs", abstractTcsLegacyUnknown_JwWSY1YarEs_nid_no_patch);
int APS5_VABI abstractTcsLegacyUnknown_La1inpscek8_nid_no_patch() {
NotImplemented_nid_no_patch(__func__);
}
APS5_EXPORT("La1inpscek8", abstractTcsLegacyUnknown_La1inpscek8_nid_no_patch);
int APS5_VABI abstractTcsLegacyUnknown_RZ_plus_sajO2y8o_nid_no_patch() {
NotImplemented_nid_no_patch(__func__);
}
APS5_EXPORT("RZ+sajO2y8o", abstractTcsLegacyUnknown_RZ_plus_sajO2y8o_nid_no_patch);
int APS5_VABI abstractTcsLegacyUnknown_SoP4nFTiu2I_nid_no_patch() {
NotImplemented_nid_no_patch(__func__);
}
APS5_EXPORT("SoP4nFTiu2I", abstractTcsLegacyUnknown_SoP4nFTiu2I_nid_no_patch);
int APS5_VABI abstractTcsLegacyUnknown_V4T61w1Cqe8_nid_no_patch() {
NotImplemented_nid_no_patch(__func__);
}
APS5_EXPORT("V4T61w1Cqe8", abstractTcsLegacyUnknown_V4T61w1Cqe8_nid_no_patch);
int APS5_VABI abstractTcsLegacyUnknown_ZWtONs1OIvg_nid_no_patch() {
NotImplemented_nid_no_patch(__func__);
}
APS5_EXPORT("ZWtONs1OIvg", abstractTcsLegacyUnknown_ZWtONs1OIvg_nid_no_patch);
int APS5_VABI abstractTcsLegacyUnknown_ahZrMN_minus_Jt6Y_nid_no_patch() {
NotImplemented_nid_no_patch(__func__);
}
APS5_EXPORT("ahZrMN-Jt6Y", abstractTcsLegacyUnknown_ahZrMN_minus_Jt6Y_nid_no_patch);
int APS5_VABI abstractTcsLegacyUnknown_bVvlpS2KicM_nid_no_patch() {
NotImplemented_nid_no_patch(__func__);
}
APS5_EXPORT("bVvlpS2KicM", abstractTcsLegacyUnknown_bVvlpS2KicM_nid_no_patch);
int APS5_VABI abstractTcsLegacyUnknown_bg0nEmwlF7w_nid_no_patch() {
NotImplemented_nid_no_patch(__func__);
}
APS5_EXPORT("bg0nEmwlF7w", abstractTcsLegacyUnknown_bg0nEmwlF7w_nid_no_patch);
int APS5_VABI abstractTcsLegacyUnknown_cAWoVxe45V0_nid_no_patch() {
NotImplemented_nid_no_patch(__func__);
}
APS5_EXPORT("cAWoVxe45V0", abstractTcsLegacyUnknown_cAWoVxe45V0_nid_no_patch);
int APS5_VABI abstractTcsLegacyUnknown_cCGY_plus_evCvVc_nid_no_patch() {
NotImplemented_nid_no_patch(__func__);
}
APS5_EXPORT("cCGY+evCvVc", abstractTcsLegacyUnknown_cCGY_plus_evCvVc_nid_no_patch);
int APS5_VABI abstractTcsLegacyUnknown_clQhSM8NcKU_nid_no_patch() {
NotImplemented_nid_no_patch(__func__);
}
APS5_EXPORT("clQhSM8NcKU", abstractTcsLegacyUnknown_clQhSM8NcKU_nid_no_patch);
int APS5_VABI abstractTcsLegacyUnknown_eY11gxVQj3w_nid_no_patch() {
NotImplemented_nid_no_patch(__func__);
}
APS5_EXPORT("eY11gxVQj3w", abstractTcsLegacyUnknown_eY11gxVQj3w_nid_no_patch);
int APS5_VABI abstractTcsLegacyUnknown_fe6dqznfu0M_nid_no_patch() {
NotImplemented_nid_no_patch(__func__);
}
APS5_EXPORT("fe6dqznfu0M", abstractTcsLegacyUnknown_fe6dqznfu0M_nid_no_patch);
int APS5_VABI abstractTcsLegacyUnknown_foVwhntBh5s_nid_no_patch() {
NotImplemented_nid_no_patch(__func__);
}
APS5_EXPORT("foVwhntBh5s", abstractTcsLegacyUnknown_foVwhntBh5s_nid_no_patch);
int APS5_VABI abstractTcsLegacyUnknown_l7InnXfshQg_nid_no_patch() {
NotImplemented_nid_no_patch(__func__);
}
APS5_EXPORT("l7InnXfshQg", abstractTcsLegacyUnknown_l7InnXfshQg_nid_no_patch);
int APS5_VABI abstractTcsLegacyUnknown_mFGc4QJTRHA_nid_no_patch() {
NotImplemented_nid_no_patch(__func__);
}
APS5_EXPORT("mFGc4QJTRHA", abstractTcsLegacyUnknown_mFGc4QJTRHA_nid_no_patch);
int APS5_VABI abstractTcsLegacyUnknown_nCiacsEZ4bs_nid_no_patch() {
NotImplemented_nid_no_patch(__func__);
}
APS5_EXPORT("nCiacsEZ4bs", abstractTcsLegacyUnknown_nCiacsEZ4bs_nid_no_patch);
int APS5_VABI abstractTcsLegacyUnknown_ru8kyGpFGLM_nid_no_patch() {
NotImplemented_nid_no_patch(__func__);
}
APS5_EXPORT("ru8kyGpFGLM", abstractTcsLegacyUnknown_ru8kyGpFGLM_nid_no_patch);
int APS5_VABI abstractTcsLegacyUnknown_tp06H_minus_EvwAg_nid_no_patch() {
NotImplemented_nid_no_patch(__func__);
}
APS5_EXPORT("tp06H-EvwAg", abstractTcsLegacyUnknown_tp06H_minus_EvwAg_nid_no_patch);
int APS5_VABI abstractTcsLegacyUnknown_uTt_minus_bJVheZI_nid_no_patch() {
NotImplemented_nid_no_patch(__func__);
}
APS5_EXPORT("uTt-bJVheZI", abstractTcsLegacyUnknown_uTt_minus_bJVheZI_nid_no_patch);
int APS5_VABI abstractTcsLegacyUnknown_yCjJib_minus_VZrc_nid_no_patch() {
NotImplemented_nid_no_patch(__func__);
}
APS5_EXPORT("yCjJib-VZrc", abstractTcsLegacyUnknown_yCjJib_minus_VZrc_nid_no_patch);
int APS5_VABI abstractTcsLegacyUnknown_zz6g6ReL0Ec_nid_no_patch() {
NotImplemented_nid_no_patch(__func__);
}
APS5_EXPORT("zz6g6ReL0Ec", abstractTcsLegacyUnknown_zz6g6ReL0Ec_nid_no_patch);
}
@@ -0,0 +1,48 @@
#pragma once
#include "SceTypes.hpp"
extern "C" {
int APS5_VABI abstractTcsLegacyUnknown__plus_uyvmTPkPT0_nid_no_patch();
int APS5_VABI abstractTcsLegacyUnknown__plus_yHj1U_minus_k1zU_nid_no_patch();
int APS5_VABI abstractTcsLegacyUnknown_065iwsKaKA4_nid_no_patch();
int APS5_VABI abstractTcsLegacyUnknown_0MDv01EA_minus_Wo_nid_no_patch();
int APS5_VABI abstractTcsLegacyUnknown_1vgiZdMEU8k_nid_no_patch();
int APS5_VABI abstractTcsLegacyUnknown_29VsAacFFxw_nid_no_patch();
int APS5_VABI abstractTcsLegacyUnknown_4_minus_Soqq0Hrqg_nid_no_patch();
int APS5_VABI abstractTcsLegacyUnknown_5NEeXee1_minus_kQ_nid_no_patch();
int APS5_VABI abstractTcsLegacyUnknown_5b5Tx09Z8uE_nid_no_patch();
int APS5_VABI abstractTcsLegacyUnknown_6zjNlHxuPhY_nid_no_patch();
int APS5_VABI abstractTcsLegacyUnknown_8uRxMgcUE6c_nid_no_patch();
int APS5_VABI abstractTcsLegacyUnknown_9KwAuQYhInc_nid_no_patch();
int APS5_VABI abstractTcsLegacyUnknown_9RskWGK_plus_Kto_nid_no_patch();
int APS5_VABI abstractTcsLegacyUnknown_BnQJZLesghs_nid_no_patch();
int APS5_VABI abstractTcsLegacyUnknown_CKQqO0otsv0_nid_no_patch();
int APS5_VABI abstractTcsLegacyUnknown_IarxytjvEuI_nid_no_patch();
int APS5_VABI abstractTcsLegacyUnknown_J5koYi_plus_uPnk_nid_no_patch();
int APS5_VABI abstractTcsLegacyUnknown_JwWSY1YarEs_nid_no_patch();
int APS5_VABI abstractTcsLegacyUnknown_La1inpscek8_nid_no_patch();
int APS5_VABI abstractTcsLegacyUnknown_RZ_plus_sajO2y8o_nid_no_patch();
int APS5_VABI abstractTcsLegacyUnknown_SoP4nFTiu2I_nid_no_patch();
int APS5_VABI abstractTcsLegacyUnknown_V4T61w1Cqe8_nid_no_patch();
int APS5_VABI abstractTcsLegacyUnknown_ZWtONs1OIvg_nid_no_patch();
int APS5_VABI abstractTcsLegacyUnknown_ahZrMN_minus_Jt6Y_nid_no_patch();
int APS5_VABI abstractTcsLegacyUnknown_bVvlpS2KicM_nid_no_patch();
int APS5_VABI abstractTcsLegacyUnknown_bg0nEmwlF7w_nid_no_patch();
int APS5_VABI abstractTcsLegacyUnknown_cAWoVxe45V0_nid_no_patch();
int APS5_VABI abstractTcsLegacyUnknown_cCGY_plus_evCvVc_nid_no_patch();
int APS5_VABI abstractTcsLegacyUnknown_clQhSM8NcKU_nid_no_patch();
int APS5_VABI abstractTcsLegacyUnknown_eY11gxVQj3w_nid_no_patch();
int APS5_VABI abstractTcsLegacyUnknown_fe6dqznfu0M_nid_no_patch();
int APS5_VABI abstractTcsLegacyUnknown_foVwhntBh5s_nid_no_patch();
int APS5_VABI abstractTcsLegacyUnknown_l7InnXfshQg_nid_no_patch();
int APS5_VABI abstractTcsLegacyUnknown_mFGc4QJTRHA_nid_no_patch();
int APS5_VABI abstractTcsLegacyUnknown_nCiacsEZ4bs_nid_no_patch();
int APS5_VABI abstractTcsLegacyUnknown_ru8kyGpFGLM_nid_no_patch();
int APS5_VABI abstractTcsLegacyUnknown_tp06H_minus_EvwAg_nid_no_patch();
int APS5_VABI abstractTcsLegacyUnknown_uTt_minus_bJVheZI_nid_no_patch();
int APS5_VABI abstractTcsLegacyUnknown_yCjJib_minus_VZrc_nid_no_patch();
int APS5_VABI abstractTcsLegacyUnknown_zz6g6ReL0Ec_nid_no_patch();
}
@@ -1 +1,2 @@
#pragma once
#include "prx/libSceAbstractTcs/include/LegacyExports.hpp"
@@ -36,6 +36,25 @@ void testPacketSize() {
}
}
void testSystemSoftwareVersion() {
std::array<std::uint32_t, 3> packet{0xc0020000u, 0xbeefcafeu, 0};
std::uint32_t version = 0;
check(sceAgcDcbGetSystemSoftwareVersion(&version, packet.data()) == 0, "assigned system software version");
check(version == 0xbeefcafeu, "system software version uses the second packet word");
check(packet[0] == 0xc0020000u && packet[1] == 0xbeefcafeu, "query does not modify the packet");
std::array<std::uint32_t, 2> tooShort{0xc0000000u, 0xbeefcafeu};
expectFailure([&] { sceAgcDcbGetSystemSoftwareVersion(&version, tooShort.data()); });
expectFailure([&] { sceAgcDcbGetSystemSoftwareVersion(nullptr, packet.data()); });
expectFailure([&] { sceAgcDcbGetSystemSoftwareVersion(&version, nullptr); });
for (const auto header : {0x80000000u, 0x3fff1000u, 0x40001000u, 0x00027600u}) {
std::array<std::uint32_t, 3> invalidHeader{header, 0xbeefcafeu, 0};
expectFailure([&] { sceAgcDcbGetSystemSoftwareVersion(&version, invalidHeader.data()); });
}
}
void testRejections() {
for (const auto header : {0x80000000u, 0x3fff1000u, 0x40001000u, 0x00047600u}) {
std::uint32_t word = header;
@@ -53,6 +72,7 @@ int main() {
try {
testPacketSize();
testRejections();
testSystemSoftwareVersion();
LibcRunShutdown_nid_postfix();
std::puts("AGC packet info tests passed");
return 0;
File diff suppressed because it is too large. Load diff
@@ -44,6 +44,11 @@ struct DispatchVariant {
std::uint32_t pushOffset = 0;
std::vector<std::int8_t> runBases;
std::uint64_t relocatableWords = 0;
std::uint64_t valueWords = 0;
std::vector<std::array<std::uint32_t, 3>> valueSlots;
std::vector<std::array<std::uint32_t, 3>> descriptorPatches;
std::uint64_t calleeWords = 0;
std::vector<std::pair<std::uint32_t, std::uint32_t>> calleeReads;
std::vector<std::pair<std::uint32_t, std::uint32_t>> shaderDataPatches;
std::uint64_t userDataMask = ~std::uint64_t{0};
std::shared_ptr<const ShaderRecompiler::ShaderVertexStageInfo> vertexInfo;
@@ -135,6 +135,8 @@ struct StageCapture {
struct RelocatableUserWord {
std::uint32_t reg;
std::vector<std::pair<std::int64_t, std::uint32_t>> reads;
bool value = false;
std::uint32_t high = 0;
};
struct DrawRelocation {
@@ -103,6 +103,9 @@ public:
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 void tagUserValueWords(DispatchVariant& variant, const DrawProgram& program);
static std::uint64_t relocatedContentKey(const RelocatableUserWord& word, std::uint32_t value, bool& readable);
static void applyShaderDataPatches(DispatchVariant& variant);
static std::string dumpRequest(std::uint64_t address, const ShaderRecompiler::RecompileRequest& request, std::string_view suffix = {});
static void reportSkip(const char* kind, const std::string& what);
DrawEntryCounters DrawCacheCounters();
@@ -195,8 +198,6 @@ private:
void traceDrawKeyLookup(const std::array<std::uint64_t, 5>& components, bool cacheMiss);
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 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);
void reportDrawRelocation();
@@ -223,7 +223,9 @@ void PublishRegisteredShader(std::shared_ptr<ShaderRegistry>& registry, const st
void SubmitRegistrationPreparation(std::function<void()> task, const PreparedShaders* prepared = nullptr);
void PrioritizeRegistrationPreparation(PreparedShaders& prepared);
void AwaitRegistrationPreparation();
void SubmitLibraryPrebuild(std::function<void()> task);
void SubmitLibraryPrebuild(std::function<void()> task, std::uint64_t program = 0);
bool LibraryPrebuildsWaiting();
void PrioritizeLibraryPrebuilds(std::span<const std::uint64_t> programs);
void SubmitComputePrebuild(std::function<void()> task);
void AwaitLibraryPrebuilds();
void CloseRegistrationPreparation();
@@ -108,7 +108,7 @@ public:
// mutex through the flush hook, so a thread submitting on another queue's behalf (a WAIT_REG_MEM
// poller, a compute worker's between-packet flush) passes false: it must only submit, never wait.
void SubmitRecorded(bool reapFirst = true);
void StoreIdleResults(bool reapFirst = true);
void StoreIdleResults(bool reapFirst = true, const std::function<bool()>& stop = [] { return false; });
// Unlocked drain: SubmitAndEpoch (under the mutex) returns the serial covering every recorded
// batch (0: nothing in flight); WaitRecorded(serial) waits for it WITHOUT the mutex (the caller
// holds a shared_ptr to this device); ReapRecorded(serial) (under the mutex) runs the completions
@@ -657,7 +657,7 @@ DrawVerdict Driver::draw(QueueState& queue, std::span<const std::uint32_t> packe
throw;
}
for (std::size_t i = 0; i < matched.size(); ++i) {
if (matched[i] == nullptr || matched[i]->shaderDataPatches.empty()) continue;
if (matched[i] == nullptr || (matched[i]->shaderDataPatches.empty() && matched[i]->descriptorPatches.empty())) continue;
applyShaderDataPatches(*matched[i]);
if (stageData[i].compiled != nullptr) stageData[i].compiled = patchDataWords(*matched[i], stageData[i].words);
}
@@ -237,7 +237,9 @@ void Driver::cacheDrawStages(bool useDrawEntries, bool drawHit, const Pm4::DrawP
std::vector<ShaderRecompiler::MemoryRegion> regions(stageCapture.regions.begin(), stageCapture.regions.end());
for (const auto& read : decodeReads[i]) regions.push_back({read.address, read.Bytes()});
std::stable_sort(regions.begin(), regions.end(), [](const ShaderRecompiler::MemoryRegion& a, const ShaderRecompiler::MemoryRegion& b) { return a.guestAddress < b.guestAddress; });
tagVariantRuns(*variant, regions, stageCapture.userDataUse, decodeReads[i].empty() && (!vertexInfos[i] || vertexInfos[i]->resourcesNum == 0), programs[i].hiddenUserWords, stageCapture.supplied);
const bool relocatable = decodeReads[i].empty() && (!vertexInfos[i] || vertexInfos[i]->resourcesNum == 0);
tagVariantRuns(*variant, regions, stageCapture.userDataUse, relocatable, programs[i].hiddenUserWords, stageCapture.supplied);
if (relocatable) tagUserValueWords(*variant, programs[i]);
if (drawStageDataHits() && stageCapture.capture != nullptr && !stageCapture.capture->readTrace.leaves.empty()) recordStageDataPositions(*variant, *stageCapture.capture, decodeReads[i]);
if (traceDrawCache() && entry != nullptr && matched[i] == nullptr && i < entry->stages.size()) {
const auto& variants = entry->stages[i];
@@ -1,4 +1,6 @@
#include "prx/libSceAgcDriver/Execution/include/Driver/Driver.hpp"
#include "ControlFlow/GraphBuilder.hpp"
#include "RdnaDecoder/RdnaInstructionDecoder.hpp"
#include "prx/libSceAgcDriver/Execution/include/Driver/Diagnostics.hpp"
#include "prx/libSceAgcDriver/Execution/include/GuestMemory.hpp"
#include "prx/libSceAgcDriver/Execution/include/ProfileOutput.hpp"
@@ -9,6 +11,8 @@
#include <cstdlib>
#include <cstring>
#include <limits>
#include <optional>
#include <span>
namespace AgcDriver::DriverDetail {
@@ -34,6 +38,7 @@ std::uint64_t Driver::relocatedContentKey(const RelocatableUserWord& word, std::
hash ^= mixed;
hash *= 0x100000001b3ull;
};
if (word.value) return hash;
mix(value & 3u);
if (value == 0) {
readable = false;
@@ -45,7 +50,7 @@ std::uint64_t Driver::relocatedContentKey(const RelocatableUserWord& word, std::
mix(words);
for (std::size_t done = 0; done < words; done += MaxContentWords) {
const auto count = std::min<std::size_t>(words - done, MaxContentWords);
const auto address = AlignedWord(value) + static_cast<std::uint64_t>(offset) + done * sizeof(std::uint32_t);
const auto address = (static_cast<std::uint64_t>(word.high) << 32u) + AlignedWord(value) + static_cast<std::uint64_t>(offset) + done * sizeof(std::uint32_t);
if (GuestMemory::CopyMapped(address, std::as_writable_bytes(std::span(content).first(count))) != GuestMemory::Compare::Equal) {
readable = false;
return hash;
@@ -56,6 +61,80 @@ std::uint64_t Driver::relocatedContentKey(const RelocatableUserWord& word, std::
return hash;
}
void Driver::tagUserValueWords(DispatchVariant& variant, const DrawProgram& program) {
if (!drawRelocationEnabled() || variant.compiled == nullptr) return;
const auto& compiled = *variant.compiled;
const auto& forwarded = compiled.shaderDataUserWords;
const auto users = std::min<std::size_t>(program.userData.size(), 64);
const auto bound = [&](std::uint32_t value) {
std::size_t count = 0;
for (const auto& binding : compiled.bindings) count += static_cast<std::size_t>(std::count(binding.guestDescriptor.begin(), binding.guestDescriptor.end(), value));
return count;
};
const auto elsewhere = [&](std::uint32_t index, std::uint32_t value) {
for (std::size_t slot = 0; (slot + 1) * sizeof(std::uint32_t) <= compiled.pushConstants.size(); ++slot) {
std::uint32_t word = 0;
std::memcpy(&word, compiled.pushConstants.data() + slot * sizeof(std::uint32_t), sizeof(word));
if (word == value && (slot >= forwarded.size() || forwarded[slot] != index)) return true;
}
if (std::any_of(compiled.specialization.begin(), compiled.specialization.end(), [&](const auto& constant) { return constant.value == value; })) return true;
return std::find(variant.words.begin(), variant.words.end(), value) != variant.words.end();
};
const auto readThrough = [&](const std::uint32_t* descriptor) {
const auto base = static_cast<std::uint64_t>(descriptor[0]) | static_cast<std::uint64_t>(descriptor[1] & 0xffffu) << 32u;
const auto stride = (descriptor[1] >> 16u) & 0x3fffu;
const auto bytes = std::max<std::uint64_t>(stride != 0 ? static_cast<std::uint64_t>(stride) * descriptor[2] : descriptor[2], 16u);
return std::any_of(variant.runs.begin(), variant.runs.end(), [&](const auto& run) { return run.first < base + bytes && run.second > base; });
};
const auto taken = [&](std::uint32_t index) { return ((variant.relocatableWords | variant.valueWords | variant.calleeWords) >> index & 1u) != 0; };
if (ShaderRecompiler::GcnGuestShaders() && program.binary.stage == ShaderRecompiler::ShaderStage::Vertex) {
for (const auto instruction : program.binary.code) {
if ((instruction & 0xff80ff00u) != 0xbe802100u) continue;
const auto target = instruction & 0xffu;
if (target < program.firstUserSgpr) continue;
const auto index = program.hiddenUserWords + target - program.firstUserSgpr;
if (index + 1 >= users || taken(index) || taken(index + 1)) continue;
const auto low = program.userData[index];
const auto address = static_cast<std::uint64_t>(low) | static_cast<std::uint64_t>(program.userData[index + 1]) << 32u;
if (address == 0 || address % 4u != 0 || bound(low) != 0 || elsewhere(index, low)) continue;
std::array<std::uint32_t, 1024> code;
if (GuestMemory::CopyMapped(address, std::as_writable_bytes(std::span(code))) != GuestMemory::Compare::Equal) continue;
std::optional<std::uint32_t> length;
try {
length = ShaderRecompiler::UserDataCalleeLength(code, (instruction >> 16u) & 0x7fu);
} catch (const std::exception&) {
continue;
}
if (!length || *length == 0) continue;
variant.calleeWords |= std::uint64_t {1} << index;
variant.calleeReads.emplace_back(index, *length);
}
}
for (std::uint32_t index = program.hiddenUserWords; index + 2 < users; ++index) {
const auto base = program.userData[index];
if (base == 0 || taken(index) || bound(base) != 1 || elsewhere(index, base)) continue;
std::uint32_t binding = 0, word = 0;
for (std::size_t b = 0; b < compiled.bindings.size(); ++b) {
const auto& descriptor = compiled.bindings[b].guestDescriptor;
const auto found = std::find(descriptor.begin(), descriptor.end(), base);
if (found == descriptor.end()) continue;
binding = static_cast<std::uint32_t>(b);
word = static_cast<std::uint32_t>(found - descriptor.begin());
}
const auto& target = compiled.bindings[binding];
const auto element = word / 4u;
const bool readOnly = target.role == ShaderRecompiler::DescriptorRole::GuestBuffers && target.guestDescriptor.size() == static_cast<std::size_t>(target.count) * 4u && word % 4u == 0 && element < target.bufferWritten.size() && !target.bufferWritten[element] && (element >= target.bufferAtomic.size() || !target.bufferAtomic[element]);
if (!readOnly || target.guestDescriptor[word + 1] != program.userData[index + 1] || target.guestDescriptor[word + 2] != program.userData[index + 2] || readThrough(target.guestDescriptor.data() + word)) continue;
variant.valueWords |= std::uint64_t {1} << index;
variant.valueSlots.push_back({index, binding, word});
const auto records = program.userData[index + 2];
if (records != 0 && !taken(index + 2) && bound(records) == 1 && !elsewhere(index + 2, records)) {
variant.valueWords |= std::uint64_t {1} << (index + 2);
variant.valueSlots.push_back({index + 2, binding, word + 2});
}
}
}
void Driver::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) {
std::uint64_t relocatable = eligible && drawRelocationEnabled() ? use.asBase & ~use.asValue : 0;
if (hiddenWords != 0) relocatable &= hiddenWords >= 64 ? 0 : ~((std::uint64_t {1} << hiddenWords) - 1);
@@ -149,7 +228,9 @@ void Driver::learnPendingRelocation() {
for (std::uint32_t index = program.hiddenUserWords; index < program.userData.size() && index < 64; ++index) {
const auto reg = program.userDataBase + index - program.hiddenUserWords;
const auto held = std::find_if(shape->words.begin(), shape->words.end(), [&](const RelocatableUserWord& word) { return word.reg == reg; });
if ((variant.relocatableWords >> index & 1u) == 0) {
const bool relocatable = (variant.relocatableWords >> index & 1u) != 0;
const bool value = !relocatable && (variant.valueWords >> index & 1u) != 0;
if (!relocatable && !value && (variant.calleeWords >> index & 1u) == 0) {
if (held == shape->words.end()) continue;
shape->words.erase(held);
shape->banned.push_back(reg);
@@ -157,7 +238,12 @@ void Driver::learnPendingRelocation() {
continue;
}
if (held != shape->words.end() || std::find(shape->banned.begin(), shape->banned.end(), reg) != shape->banned.end()) continue;
RelocatableUserWord word{reg, {}};
RelocatableUserWord word{reg, {}, value};
for (const auto& [callee, length] : variant.calleeReads) {
if (callee != index) continue;
word.reads.emplace_back(0, length);
word.high = program.userData[index + 1];
}
const auto base = AlignedWord(program.userData[index]);
for (std::size_t run = 0; run < variant.runs.size() && run < variant.runBases.size(); ++run) {
if (variant.runBases[run] != static_cast<std::int8_t>(index)) continue;
@@ -215,7 +301,7 @@ void Driver::relocateDrawEntry(const QueueState& queue, std::uint64_t alias, std
}
for (const auto& variant : donor->stages[i]) {
if (variant == nullptr || variant->compiled == nullptr) continue;
const bool allowed = std::all_of(moves.begin(), moves.end(), [&](const Move& move) { return move.program != i || (move.index < 64 && (variant->relocatableWords >> move.index & 1u) != 0 && move.from != 0 && move.to != 0 && ((move.from ^ move.to) & 3u) == 0); });
const bool allowed = std::all_of(moves.begin(), moves.end(), [&](const Move& move) { return move.program != i || (move.index < 64 && move.from != 0 && move.to != 0 && ((((variant->relocatableWords | variant->calleeWords) >> move.index & 1u) != 0 && ((move.from ^ move.to) & 3u) == 0) || (variant->valueWords >> move.index & 1u) != 0)); });
if (!allowed) {
++counters.refused;
continue;
@@ -224,6 +310,10 @@ void Driver::relocateDrawEntry(const QueueState& queue, std::uint64_t alias, std
copy->runs = variant->runs;
copy->runBases = variant->runBases;
copy->relocatableWords = variant->relocatableWords;
copy->valueWords = variant->valueWords;
copy->valueSlots = variant->valueSlots;
copy->calleeWords = variant->calleeWords;
copy->calleeReads = variant->calleeReads;
copy->words = variant->words;
copy->forgetSerial = variant->forgetSerial;
copy->compiled = variant->compiled;
@@ -246,6 +336,9 @@ void Driver::relocateDrawEntry(const QueueState& queue, std::uint64_t alias, std
for (std::uint32_t slot = 0; slot < forwarded.size(); ++slot) {
if (forwarded[slot] == move.index) copy->shaderDataPatches.emplace_back(slot, move.to);
}
for (const auto& [index, binding, word] : variant->valueSlots) {
if (index == move.index) copy->descriptorPatches.push_back({binding, word, move.to});
}
}
relocated->stages[i].push_back(std::move(copy));
}
@@ -257,7 +350,7 @@ void Driver::relocateDrawEntry(const QueueState& queue, std::uint64_t alias, std
}
void Driver::applyShaderDataPatches(DispatchVariant& variant) {
if (variant.shaderDataPatches.empty()) return;
if (variant.shaderDataPatches.empty() && variant.descriptorPatches.empty()) return;
auto rebased = std::make_shared<ShaderRecompiler::RecompileResult>(*variant.compiled);
for (const auto& [slot, value] : variant.shaderDataPatches) {
const auto at = static_cast<std::size_t>(slot) * sizeof(std::uint32_t);
@@ -266,8 +359,12 @@ void Driver::applyShaderDataPatches(DispatchVariant& variant) {
if (binding.role == ShaderRecompiler::DescriptorRole::ShaderData && slot < binding.guestDescriptor.size()) binding.guestDescriptor[slot] = value;
}
}
for (const auto& [binding, word, value] : variant.descriptorPatches) {
if (binding < rebased->bindings.size() && word < rebased->bindings[binding].guestDescriptor.size()) rebased->bindings[binding].guestDescriptor[word] = value;
}
variant.compiled = std::move(rebased);
variant.shaderDataPatches.clear();
variant.descriptorPatches.clear();
}
void Driver::reportDrawRelocation() {
@@ -216,7 +216,7 @@ void Driver::run(std::uint32_t id) noexcept {
}
lock.unlock();
if (storeIdleResults) {
if (const auto localDevice = device.Load()) localDevice->StoreIdleResults();
if (const auto localDevice = device.Load()) localDevice->StoreIdleResults(true, [&] { return worker.queued.load(std::memory_order_acquire) != 0 || runningWorkers.load(std::memory_order_acquire) != 0; });
}
lock.lock();
if (ready()) break;
@@ -13,11 +13,14 @@
#include "prx/libSceAgcDriver/Eq/include/Event.hpp"
#include "ThreadOwned.hpp"
#include "prx/libc/include/HostThreadLocal.hpp"
#include <algorithm>
#include <atomic>
#include <bit>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <exception>
#include <optional>
namespace AgcDriver::DriverDetail {
@@ -320,6 +323,53 @@ void Driver::reserveOutputs(Submission& submission) {
for (const auto token : eopTokens) eopFlips.erase(token);
}
namespace {
std::vector<std::uint64_t> BoundGraphicsPrograms(const Submission& submission) {
constexpr std::array<std::uint32_t, 6> programRegisters{0x008u, 0x048u, 0x088u, 0x0c8u, 0x108u, 0x148u};
static std::array<std::atomic<std::uint32_t>, programRegisters.size()> lastHigh{};
std::array<std::optional<std::uint32_t>, programRegisters.size()> low{};
std::array<bool, programRegisters.size()> written{};
std::vector<std::uint64_t> programs;
const auto note = [&](std::uint32_t offset, std::uint32_t value) {
for (std::size_t program = 0; program < programRegisters.size(); ++program) {
if (offset == programRegisters[program] + 1u) lastHigh[program].store(value & 0xffu, std::memory_order_relaxed);
else if (offset == programRegisters[program]) low[program] = value;
else continue;
written[program] = true;
}
};
const auto flush = [&] {
for (std::size_t program = 0; program < programRegisters.size(); ++program) {
if (!written[program] || !low[program]) continue;
written[program] = false;
programs.push_back((static_cast<std::uint64_t>(*low[program]) << 8u) | (static_cast<std::uint64_t>(lastHigh[program].load(std::memory_order_relaxed)) << 40u));
}
};
const auto& commands = submission.commands;
for (std::size_t cursor = 0; cursor < commands.size();) {
const auto header = commands[cursor];
const auto count = Pm4::PacketWords(header);
if (cursor + count > commands.size()) break;
const auto packet = std::span(commands).subspan(cursor, count);
const auto opcode = (header >> 8u) & 0xffu;
if (!Pm4::FillerPacket(header) && opcode == 0x76 && count > 2 && !Pm4::IsTagMarker(packet)) {
for (std::size_t index = 2; index < count; ++index) note((packet[1] & ~0x70000000u) + static_cast<std::uint32_t>(index - 2), packet[index]);
} else if (!Pm4::FillerPacket(header) && opcode == 0x63) {
if (const auto found = submission.registerLists.find(cursor); found != submission.registerLists.end()) {
for (std::size_t index = 0; index + 1 < found->second.size(); index += 2) note(found->second[index] & ~0x70000000u, found->second[index + 1]);
}
}
flush();
cursor += count;
}
std::ranges::sort(programs);
programs.erase(std::ranges::unique(programs).begin(), programs.end());
return programs;
}
}
void Driver::executeRewindTail(const Submission& stalled) {
PerformanceTimer timing("Driver.Rewind");
static const bool ring = ReadSubmissionRingSettings();
@@ -357,6 +407,7 @@ void Driver::executeRewindTail(const Submission& stalled) {
if (APS5_ENABLE_TIMING_LOG) tail.copiedAt = std::chrono::steady_clock::now();
validate(tail, stalled.rewindTail);
readRegisterLists(tail);
if (LibraryPrebuildsWaiting()) PrioritizeLibraryPrebuilds(BoundGraphicsPrograms(tail));
if (APS5_ENABLE_TIMING_LOG) tail.validatedAt = std::chrono::steady_clock::now();
waitForFlipRoom(tail);
if (APS5_ENABLE_TIMING_LOG) tail.roomReadyAt = std::chrono::steady_clock::now();
@@ -421,6 +472,7 @@ void Driver::Submit(const Packet* packet, std::uint32_t queue, bool cpuFlip) {
waitForFlipRoom(submission);
holdFlipBehindWorker(submission);
AwaitRegistrationPreparation();
if (LibraryPrebuildsWaiting()) PrioritizeLibraryPrebuilds(BoundGraphicsPrograms(submission));
if (APS5_ENABLE_TIMING_LOG) submission.roomReadyAt = std::chrono::steady_clock::now();
static const bool trace = std::getenv("APS5_TRACE_GPU") != nullptr;
if (trace) std::fprintf(stderr, "[gpu] %.1f submit queue=0x%x dwords=%zu at %p\n", TraceMs(), queue, submission.commands.size(), static_cast<const void*>(descriptor.addr));
@@ -1221,6 +1221,7 @@ struct RegisteredPreparation {
std::optional<ShaderRecompiler::RecompileRequest> request;
std::vector<std::uint64_t> abiKey;
std::shared_ptr<VulkanDevice> prebuildDevice;
std::uint64_t program = 0;
};
bool RegistrationPrepareWithinMemoryBudget();
@@ -1267,6 +1268,7 @@ std::unique_ptr<RegisteredPreparation> PlanRegistered(const ShaderSnapshot& snap
const auto code = std::span(snapshot.code).subspan(codeOffset);
auto plan = std::make_unique<RegisteredPreparation>();
plan->codeOffset = codeOffset;
plan->program = address;
ShaderRecompiler::RdnaProgram decoded;
plan->registration = registration;
try {
@@ -1351,7 +1353,7 @@ bool LibraryPrebuildDisabled() {
return disabled;
}
void PrebuildStageLibrary(const std::shared_ptr<VulkanDevice>& device, const Graphics::ShaderStages& stages, ShaderRecompiler::ShaderStage stage, std::shared_ptr<const ShaderRecompiler::RecompileResult> result, std::uint32_t pushOffset) {
void PrebuildStageLibrary(const std::shared_ptr<VulkanDevice>& device, const Graphics::ShaderStages& stages, ShaderRecompiler::ShaderStage stage, std::shared_ptr<const ShaderRecompiler::RecompileResult> result, std::uint32_t pushOffset, std::uint64_t program) {
if (LibraryPrebuildDisabled() || result == nullptr || (stage != ShaderRecompiler::ShaderStage::Vertex && stage != ShaderRecompiler::ShaderStage::Fragment)) return;
SubmitLibraryPrebuild([device, stages, stage, result = std::move(result), pushOffset] {
const std::array<Graphics::CompiledShader, 1> shaders{{{stage, result.get(), pushOffset}}};
@@ -1360,7 +1362,7 @@ void PrebuildStageLibrary(const std::shared_ptr<VulkanDevice>& device, const Gra
} catch (const std::exception& error) {
APS5_LOG_OUT("shader library prebuild skipped: %s", error.what());
}
});
}, program);
}
std::vector<PreparedShaders::Entry> PrepareRegistered(RegisteredPreparation& plan) {
@@ -1374,7 +1376,7 @@ std::vector<PreparedShaders::Entry> PrepareRegistered(RegisteredPreparation& pla
append();
if (plan.prebuildDevice != nullptr && request.target.registrationModules && request.shader.stage == ShaderRecompiler::ShaderStage::Fragment && !LibraryPrebuildDisabled()) {
try {
PrebuildStageLibrary(plan.prebuildDevice, {Graphics::ShaderPath::Vertex, 0u, 32u, request.context.waveSize, {}, {}}, request.shader.stage, ShaderRecompiler::RegistrationResult(request, *entries.front().handle), request.layout.pushConstantOffsetBytes);
PrebuildStageLibrary(plan.prebuildDevice, {Graphics::ShaderPath::Vertex, 0u, 32u, request.context.waveSize, {}, {}}, request.shader.stage, ShaderRecompiler::RegistrationResult(request, *entries.front().handle), request.layout.pushConstantOffsetBytes, plan.program);
} catch (const std::exception& error) {
APS5_LOG_OUT("shader library prebuild skipped: %s", error.what());
}
@@ -1566,13 +1568,14 @@ private:
public:
void Submit(std::function<void()> task, const PreparedShaders* prepared = nullptr, bool budgeted = false) {
void Submit(std::function<void()> task, const PreparedShaders* prepared = nullptr, bool budgeted = false, std::uint64_t program = 0) {
{
std::unique_lock lock(mutex);
if (threads != 0 && !closed) {
const auto sequence = ++submitted;
if (prepared != nullptr && prepared->demanded.load()) tasks.push_front({std::move(task), prepared, sequence, budgeted});
else tasks.push_back({std::move(task), prepared, sequence, budgeted});
if (prepared != nullptr && prepared->demanded.load()) tasks.push_front({std::move(task), prepared, sequence, budgeted, program});
else tasks.push_back({std::move(task), prepared, sequence, budgeted, program});
if (program != 0) waitingPrograms.fetch_add(1, std::memory_order_relaxed);
unfinished.insert(sequence);
lock.unlock();
ready.notify_one();
@@ -1590,6 +1593,16 @@ public:
std::rotate(tasks.begin(), found, std::next(found));
}
void Prioritize(std::span<const std::uint64_t> programs) {
const auto bound = [&](const Task& task) { return task.program != 0 && std::ranges::binary_search(programs, task.program); };
std::lock_guard lock(mutex);
if (std::ranges::any_of(tasks, bound)) std::stable_partition(tasks.begin(), tasks.end(), bound);
}
bool ProgramsWaiting() const {
return waitingPrograms.load(std::memory_order_relaxed) != 0;
}
void AwaitSubmitted() {
std::unique_lock lock(mutex);
const auto ticket = submitted;
@@ -1604,6 +1617,7 @@ public:
closed = true;
if (dropQueued) {
dropped.swap(tasks);
waitingPrograms.store(0, std::memory_order_relaxed);
for (const auto& task : dropped) unfinished.erase(task.sequence);
idle.notify_all();
}
@@ -1688,6 +1702,7 @@ private:
}
task = std::move(*next);
pool.tasks.erase(next);
if (task.program != 0) pool.waitingPrograms.fetch_sub(1, std::memory_order_relaxed);
++pool.running;
if (task.budgeted) ++pool.budgetedRunning;
}
@@ -1717,12 +1732,14 @@ private:
const PreparedShaders* prepared = nullptr;
std::uint64_t sequence = 0;
bool budgeted = false;
std::uint64_t program = 0;
};
std::mutex mutex;
std::condition_variable ready;
std::condition_variable idle;
std::deque<Task> tasks;
std::atomic<std::size_t> waitingPrograms{0};
std::vector<Worker> workers;
unsigned threads = 0;
inline static std::atomic<unsigned> liveWorkers{0};
@@ -1807,8 +1824,17 @@ void AwaitRegistrationPreparation() {
if (auto* pool = RegistrationPreparePool::Existing()) pool->AwaitSubmitted();
}
void SubmitLibraryPrebuild(std::function<void()> task) {
RegistrationPreparePool::Prebuild().Submit(std::move(task));
void SubmitLibraryPrebuild(std::function<void()> task, std::uint64_t program) {
RegistrationPreparePool::Prebuild().Submit(std::move(task), nullptr, false, program);
}
bool LibraryPrebuildsWaiting() {
auto* pool = RegistrationPreparePool::ExistingPrebuild();
return pool != nullptr && pool->ProgramsWaiting();
}
void PrioritizeLibraryPrebuilds(std::span<const std::uint64_t> programs) {
if (auto* pool = RegistrationPreparePool::ExistingPrebuild(); pool != nullptr && !programs.empty()) pool->Prioritize(programs);
}
void SubmitComputePrebuild(std::function<void()> task) {
@@ -2013,6 +2039,11 @@ void Driver::ResolveGraphicsStagesAbi(std::span<const Shader* const> stages, std
return;
}
auto prepared = PrepareGraphicsStages(decoded, localDevice->Target(), true);
if (decoded.state.stages.path == Graphics::ShaderPath::Vertex) {
for (const auto& stage : prepared) {
if (stage.registration != nullptr) PrebuildStageLibrary(localDevice, decoded.state.stages, stage.stage, stage.registration, stage.pushOffset, stage.snapshot->codeAddress + stage.entry.codeOffset * sizeof(std::uint32_t));
}
}
for (auto& stage : prepared) {
if (stage.entry.handle == nullptr) continue;
const auto& entries = transaction.Read(*stage.snapshot).entries;
@@ -2023,11 +2054,6 @@ void Driver::ResolveGraphicsStagesAbi(std::span<const Shader* const> stages, std
if (stage.snapshot->type == 1) continue;
ResolvePreparedGraphics(*stage.snapshot, {}, primitiveType == state.userConfig.end() ? 0u : primitiveType->second, localDevice->Target(), true);
}
if (decoded.state.stages.path == Graphics::ShaderPath::Vertex) {
for (const auto& stage : prepared) {
if (stage.registration != nullptr) PrebuildStageLibrary(localDevice, decoded.state.stages, stage.stage, stage.registration, stage.pushOffset);
}
}
PreparedShaderState::GraphicsAbi abi{key, registry, {}};
for (const auto& stage : prepared) abi.stages.push_back(stage.snapshot);
auto& graphicsAbis = transaction.Edit(*owner).graphicsAbis;
@@ -1401,10 +1401,7 @@ VulkanDevice::VulkanDevice(const PresentationWindow* window, bool compileOnly) :
state->fragmentShaderBarycentric = barycentricFeatures.fragmentShaderBarycentric == VK_TRUE;
state->fragmentBarycentricBuiltins = state->fragmentShaderBarycentric;
if (state->fragmentShaderBarycentric && hasExtension(VK_KHR_DRIVER_PROPERTIES_EXTENSION_NAME)) {
VkPhysicalDeviceDriverProperties driver{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES};
VkPhysicalDeviceProperties2 driverProperties{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2, &driver};
state->InstanceFunction<PFN_vkGetPhysicalDeviceProperties2>("vkGetPhysicalDeviceProperties2")(selected, &driverProperties);
state->fragmentShaderBarycentric = FragmentShaderBarycentricUsable(driver.driverID, state->fragmentShaderBarycentric);
state->fragmentShaderBarycentric = FragmentShaderBarycentricUsable(driverId, state->fragmentShaderBarycentric);
}
}
VkPhysicalDeviceShaderTerminateInvocationFeaturesKHR terminateFeatures{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_TERMINATE_INVOCATION_FEATURES_KHR};
@@ -1428,11 +1425,8 @@ VulkanDevice::VulkanDevice(const PresentationWindow* window, bool compileOnly) :
state->shaderClock = clockFeatures.shaderSubgroupClock == VK_TRUE && clockFeatures.shaderDeviceClock == VK_TRUE;
}
if (state->shaderClock && hasExtension(VK_KHR_DRIVER_PROPERTIES_EXTENSION_NAME)) {
VkPhysicalDeviceDriverProperties driver{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES};
VkPhysicalDeviceProperties2 driverProperties{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2, &driver};
state->InstanceFunction<PFN_vkGetPhysicalDeviceProperties2>("vkGetPhysicalDeviceProperties2")(selected, &driverProperties);
state->narrowSubgroupClock = NarrowSubgroupClock(driver.driverID, state->properties.deviceID, state->properties.deviceName);
APS5_LOG_OUT("Shader clock driver=%d narrowSubgroupClock=%d", static_cast<int>(driver.driverID), state->narrowSubgroupClock ? 1 : 0);
state->narrowSubgroupClock = NarrowSubgroupClock(driverId, state->properties.deviceID, state->properties.deviceName);
APS5_LOG_OUT("Shader clock driver=%d narrowSubgroupClock=%d", static_cast<int>(driverId), state->narrowSubgroupClock ? 1 : 0);
}
VkPhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT demoteFeatures{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DEMOTE_TO_HELPER_INVOCATION_FEATURES_EXT};
if (hasExtension(VK_EXT_SHADER_DEMOTE_TO_HELPER_INVOCATION_EXTENSION_NAME)) {
@@ -1741,10 +1735,7 @@ VulkanDevice::VulkanDevice(const PresentationWindow* window, bool compileOnly) :
if (libraryDevice) deviceExtensions.insert(deviceExtensions.end(), libraryExtensions.begin(), libraryExtensions.end());
state->graphicsPipelineLibrary = libraryDevice && std::getenv("APS5_NO_GPL") == nullptr;
if (state->graphicsPipelineLibrary && hasExtension(VK_KHR_DRIVER_PROPERTIES_EXTENSION_NAME)) {
VkPhysicalDeviceDriverProperties driver{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES};
VkPhysicalDeviceProperties2 driverProperties{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2, &driver};
state->InstanceFunction<PFN_vkGetPhysicalDeviceProperties2>("vkGetPhysicalDeviceProperties2")(selected, &driverProperties);
state->pipelineLinkTimeOptimization = PipelineLinkTimeOptimizationUsable(driver.driverID);
state->pipelineLinkTimeOptimization = PipelineLinkTimeOptimizationUsable(driverId);
}
}
VkPhysicalDeviceMaintenance5FeaturesKHR maintenance5Features{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_5_FEATURES_KHR};
@@ -2493,12 +2484,12 @@ bool OpportunisticReap() {
}
void VulkanDevice::StoreIdleResults(bool reapFirst) {
void VulkanDevice::StoreIdleResults(bool reapFirst, const std::function<bool()>& stop) {
if (!Graphics::StorageTexture::AnyPending()) return;
GuestMemory::TagGpuLockSite(GuestMemory::GpuLockSite::Flush);
std::lock_guard gpuLock(GuestMemory::GpuMutex());
const auto lease = GuestAllocations::GuestAllocationsAcquire_nid_postfix();
Graphics::StorageTexture::FlushAllPending("idle");
static_cast<void>(Graphics::StorageTexture::FlushAllPendingUntil("idle", stop));
SubmitRecorded(reapFirst);
}
@@ -254,6 +254,7 @@ struct MirrorStats {
std::uint64_t sweeps = 0;
std::uint64_t heapChecks = 0;
std::uint64_t sparseBinds = 0;
std::uint64_t evictions = 0;
};
MirrorStats MirrorCounters();
std::uint64_t SnapshotMismatches();
@@ -321,6 +322,10 @@ public:
void AllowDeviceStaging() { stagingAllowed = true; }
void DisallowAddressStaging() { addressStaging = false; }
void AllowAdjustedRegions() { adjustedRegions = true; }
bool HoldsMirror(const std::shared_ptr<ImageMirror>& mirror) const;
bool EvictMirror(const std::shared_ptr<ImageMirror>& mirror);
bool WasEvicted(std::uint64_t address) const;
void RecordEvicted(std::uint64_t address);
// Records the copy-in of every staged region anew for another use of this upload (a resource
// cache hit, from ShaderResources::Revalidate, under GuestMemory::GpuMutex, once the imports
// were confirmed unchanged): the previous use's copy-back left the shadow behind, and the next
@@ -537,6 +542,7 @@ private:
std::vector<std::pair<std::uint64_t, std::uint64_t>> servedInsideBase;
std::vector<std::pair<std::uint64_t, std::vector<std::byte>>> heapReferences;
std::vector<std::pair<std::uint64_t, std::shared_ptr<Buffer>>> heapReadbacks;
std::vector<std::uint64_t> evictedRanges;
// UploadPrepare ran (regions are frozen); `uploaded` once UploadFinish ran.
bool prepared = false;
bool uploaded = false;
@@ -20,6 +20,8 @@ using GuestRuns = std::vector<std::pair<std::uint64_t, std::uint64_t>>;
GuestRuns GuestNonzeroBlocks(const GuestRuns& candidates);
bool GuestBytesZero(std::uint64_t begin, std::uint64_t end);
void SetResidentAddressSpaceLimit(std::uint64_t bytes);
void SetHeapMirrorBudget(std::uint64_t bytes);
std::shared_ptr<void> HoldHeapMirror(std::uint64_t address);
class ResidentBuffer : public std::enable_shared_from_this<ResidentBuffer> {
public:
@@ -155,6 +155,7 @@ struct ImageTableReuseCounts {
std::uint64_t writesMade = 0;
};
ImageTableReuseCounts ImageTableReuses();
std::uint64_t SampledTexturesCleared();
std::uint64_t SampledLookupKeyScans();
struct PresyncSurface {
@@ -59,7 +59,7 @@ struct OwnedImage {
class Texture {
public:
Texture(const Context& context, TextureDetiler& detiler, const GuestTextureResource& descriptor, VkComponentMapping components, std::span<const std::byte> snapshot, bool depthCompare = false);
Texture(const Context& context, TextureDetiler& detiler, const GuestTextureResource& descriptor, VkComponentMapping components, std::span<const std::byte> snapshot, bool depthCompare = false, const VkClearColorValue* clear = nullptr);
Texture(const Context& context, const std::shared_ptr<ResidentColor>& source, const GuestTextureResource& descriptor, VkComponentMapping components);
// A view of a storage image's own VkImage: the sampled texture follows the image's content, so a
// compute pass writing it and the next pass sampling it share one image and copy nothing.
@@ -218,6 +218,7 @@ public:
// overlapping pending image, as before).
static bool FlushPending(std::uint64_t address, std::size_t bytes, const StorageTexture* except = nullptr, const char* reason = "memory access", PublishScope scope = PublishScope::Whole, bool* published = nullptr, bool waited = false);
static void FlushAllPending(const char* reason);
static bool FlushAllPendingUntil(const char* reason, const std::function<bool()>& stop);
static bool WaitForFlushing(std::uint64_t address, std::size_t bytes, const StorageTexture* except = nullptr);
static void SaveBeforeUnwatch(std::uint64_t address, std::size_t bytes);
static constexpr std::uint64_t SmallStoreBytes = 64 * 1024;
@@ -42,6 +42,7 @@
#include <mutex>
#include <optional>
#include <set>
#include <unordered_set>
#include <thread>
#include <stop_token>
#include <cerrno>
@@ -87,6 +88,7 @@ struct ImageMirror {
// apart from host import serials.
std::uint64_t serial = 0;
std::atomic<std::uint64_t> watchedSerial{0};
std::uint64_t lastDispatch = 0;
};
// The address space. An address-based build maps every readable registered range; building that
@@ -136,7 +138,16 @@ struct GuestBufferMemory::AddressSpace {
mutable std::list<const std::vector<std::uint64_t>*> tableRecency;
};
std::atomic<std::uint64_t> testHeapMirrorBudget{0};
void SetHeapMirrorBudget(std::uint64_t bytes) {
testHeapMirrorBudget.store(bytes, std::memory_order_release);
}
namespace {
struct RefreshBlock;
static thread_local GuestBufferMemory* buildingBufferMemory = nullptr;
static thread_local std::vector<RefreshBlock>* buildingBlocks = nullptr;
struct RetiredImport;
@@ -2463,6 +2474,8 @@ struct ImageMirrors {
std::uint64_t pinnedVersion = 0;
std::uint64_t sweeps = 0;
std::uint64_t heapChecks = 0;
std::uint64_t evictions = 0;
std::uint64_t dispatchCounter = 0;
std::chrono::steady_clock::time_point lastReport = std::chrono::steady_clock::now();
};
@@ -2546,6 +2559,7 @@ bool mirrorsEnabled() {
}
std::uint64_t heapMirrorBudget() {
if (const auto test = testHeapMirrorBudget.load(std::memory_order_acquire); test != 0) return test;
static const std::uint64_t bytes = [] {
const char* value = std::getenv("APS5_HEAP_MIRROR_MIB");
return (value ? std::strtoull(value, nullptr, 10) : 24576ull) << 20u;
@@ -2563,7 +2577,7 @@ std::string heapMirrorError(std::uint64_t address, std::uint64_t bytes, std::uin
return std::string(prefix) + where + std::string(reason) + holding;
}
void sweepMirrors();
void sweepMirrors(std::uint64_t neededBytes = 0, std::uint64_t protectAddress = 0);
void unlistMirror(ImageMirrors& state, ImageMirror& mirror) {
if (!mirror.listed) return;
@@ -2633,7 +2647,7 @@ void reserveHeapBytes(std::uint64_t address, std::uint64_t bytes, std::uint64_t
}
if (attempt != 0) throw std::runtime_error(heapMirrorError(address, bytes, held, "past the budget"));
}
sweepMirrors();
sweepMirrors(need, address);
}
}
@@ -2655,7 +2669,7 @@ void growResident(ImageMirror& mirror, const GuestRuns& runs) {
}
if (attempt != 0) throw std::runtime_error(heapMirrorError(mirror.base, mirror.reserved, state.heapBytes, "past the budget"));
}
sweepMirrors();
sweepMirrors(need, mirror.base);
}
try {
mirror.resident->Bind(runs);
@@ -3296,14 +3310,20 @@ std::shared_ptr<ImageMirror> findMirror(const Context& context, std::uint64_t be
return mirror;
}
// Drops mirrors whose registered range is gone (a later build made a new one for the replacement).
void sweepMirrors() {
void sweepMirrors(std::uint64_t neededBytes, std::uint64_t protectAddress) {
const bool released = releaseExpiredJoinedHeaps();
const auto space = Spaces().current.load();
auto space = Spaces().current.load();
auto& state = Mirrors();
std::vector<std::shared_ptr<ImageMirror>> dropped;
std::lock_guard lock(state.mutex);
if (released) ++state.version;
if (space != nullptr && state.pinnedSpace == space->serial && state.pinnedVersion == state.version) return;
if (neededBytes == 0 && space != nullptr && state.pinnedSpace == space->serial && state.pinnedVersion == state.version) return;
if (neededBytes != 0 && state.heapBytes + neededBytes > heapMirrorBudget()) {
if (auto cached = Spaces().current.exchange(nullptr); cached != nullptr) {
space.reset();
cached.reset();
}
}
++state.sweeps;
bool pinned = space != nullptr;
std::size_t leased = 0;
@@ -3317,9 +3337,47 @@ void sweepMirrors() {
continue;
}
if (it->second->heap) unlistMirror(state, *it->second);
dropped.push_back(std::move(it->second));
it = state.entries.erase(it);
++state.version;
}
if (neededBytes != 0 && state.heapBytes + neededBytes > heapMirrorBudget()) {
std::unordered_set<const ImageMirror*> queued;
if (buildingBlocks != nullptr) {
for (const auto& block : *buildingBlocks) queued.insert(block.mirror);
}
while (state.heapBytes + neededBytes > heapMirrorBudget()) {
auto victim = state.entries.end();
for (auto it = state.entries.begin(); it != state.entries.end(); ++it) {
if (!it->second->heap || it->first == protectAddress || queued.count(it->second.get()) != 0) continue;
const bool buildingHolds = buildingBufferMemory != nullptr && buildingBufferMemory->HoldsMirror(it->second);
const auto allowedCount = (buildingHolds && !it->second->writable) ? 2 : 1;
if (it->second.use_count() == allowedCount) {
if (victim == state.entries.end()) {
victim = it;
} else if (it->second->lastDispatch != victim->second->lastDispatch) {
if (it->second->lastDispatch < victim->second->lastDispatch) victim = it;
} else if (it->second->writable != victim->second->writable) {
if (!it->second->writable && victim->second->writable) victim = it;
} else if (it->first < victim->first) {
victim = it;
}
}
}
if (victim == state.entries.end()) break;
if (buildingBufferMemory != nullptr) {
buildingBufferMemory->RecordEvicted(victim->first);
if (buildingBufferMemory->HoldsMirror(victim->second)) {
buildingBufferMemory->EvictMirror(victim->second);
}
}
unlistMirror(state, *victim->second);
dropped.push_back(std::move(victim->second));
state.entries.erase(victim);
++state.version;
++state.evictions;
}
}
state.pinnedSpace = pinned ? space->serial : 0;
state.pinnedVersion = state.version;
}
@@ -3386,7 +3444,7 @@ void reportMirrors() {
}
heapBytes = state.heapBytes;
}
AgcDriver::ProfilePrint_nid_no_patch("[buffers] image mirrors: %zu ranges (%.1f MiB, %zu writable, %zu heap %.1f MiB), %llu address-based builds served, %llu descriptor sub-ranges bound, %llu sparse heaps bound, %llu rebuilds, %llu refreshes: %llu blocks compared, %llu copied, %llu refresh syncs; heap refills %llu, unwatched heaps %llu, %llu heap mirrors released for imports (%.1f MiB)\n", count, bytes / 1048576.0, writable, heaps, heapBytes / 1048576.0, static_cast<unsigned long long>(state.builds), static_cast<unsigned long long>(state.subranges), static_cast<unsigned long long>(state.sparseBinds), static_cast<unsigned long long>(state.rebuilds), static_cast<unsigned long long>(state.refreshes), static_cast<unsigned long long>(state.blocksCompared), static_cast<unsigned long long>(state.blocksCopied), static_cast<unsigned long long>(state.syncs), static_cast<unsigned long long>(state.heapRefills), static_cast<unsigned long long>(state.heapUnwatched), static_cast<unsigned long long>(state.heapImported), state.heapImportedBytes / 1048576.0);
AgcDriver::ProfilePrint_nid_no_patch("[buffers] image mirrors: %zu ranges (%.1f MiB, %zu writable, %zu heap %.1f MiB), %llu address-based builds served, %llu descriptor sub-ranges bound, %llu sparse heaps bound, %llu rebuilds, %llu refreshes: %llu blocks compared, %llu copied, %llu refresh syncs; heap refills %llu, unwatched heaps %llu, %llu heap mirrors evicted for budget, %llu heap mirrors released for imports (%.1f MiB)\n", count, bytes / 1048576.0, writable, heaps, heapBytes / 1048576.0, static_cast<unsigned long long>(state.builds), static_cast<unsigned long long>(state.subranges), static_cast<unsigned long long>(state.sparseBinds), static_cast<unsigned long long>(state.rebuilds), static_cast<unsigned long long>(state.refreshes), static_cast<unsigned long long>(state.blocksCompared), static_cast<unsigned long long>(state.blocksCopied), static_cast<unsigned long long>(state.syncs), static_cast<unsigned long long>(state.heapRefills), static_cast<unsigned long long>(state.heapUnwatched), static_cast<unsigned long long>(state.evictions), static_cast<unsigned long long>(state.heapImported), state.heapImportedBytes / 1048576.0);
#ifdef _WIN32
auto& imports = Imports();
std::lock_guard importsLock(imports.mutex);
@@ -3673,7 +3731,7 @@ std::string AddressCopyOverflow(std::vector<AddressCopy> copies, std::uint64_t l
MirrorStats MirrorCounters() {
auto& state = Mirrors();
std::lock_guard lock(state.mutex);
MirrorStats stats{0, state.heapBytes, state.rebuilds, state.blocksCopied, state.heapRefills, state.sweeps, state.heapChecks, state.sparseBinds};
MirrorStats stats{0, state.heapBytes, state.rebuilds, state.blocksCopied, state.heapRefills, state.sweeps, state.heapChecks, state.sparseBinds, state.evictions};
for (const auto& [base, mirror] : state.entries) stats.heapMirrors += mirror->heap ? 1 : 0;
return stats;
}
@@ -3682,6 +3740,14 @@ std::uint64_t SnapshotMismatches() {
return Snapshots().mismatched.load(std::memory_order_relaxed);
}
std::shared_ptr<void> HoldHeapMirror(std::uint64_t address) {
auto& state = Mirrors();
std::lock_guard lock(state.mutex);
auto it = state.entries.find(address);
if (it != state.entries.end()) return it->second;
return nullptr;
}
HeapMirrorHold HeapMirrorsWithin(std::uint64_t begin, std::uint64_t end) {
auto& state = Mirrors();
std::lock_guard lock(state.mutex);
@@ -4359,7 +4425,50 @@ void GuestBufferMemory::CountAddressBuild(double snapshotsUs) {
totals.snapshotsUs = 0;
}
bool GuestBufferMemory::HoldsMirror(const std::shared_ptr<ImageMirror>& mirror) const {
for (const auto& region : regions) {
if (region.mirror == mirror) return true;
}
return false;
}
bool GuestBufferMemory::EvictMirror(const std::shared_ptr<ImageMirror>& mirror) {
bool found = false;
for (auto& region : regions) {
if (region.mirror == mirror) {
region.mirror.reset();
region.hostBacked = !region.writable;
auto committed = GuestMemory::DescribeCommitted(region.begin, region.end - region.begin);
if (!committed.whole) {
region.sparse = true;
region.backed = std::move(committed.ranges);
} else {
region.sparse = false;
region.backed.clear();
}
found = true;
}
}
return found;
}
bool GuestBufferMemory::WasEvicted(std::uint64_t address) const {
return std::find(evictedRanges.begin(), evictedRanges.end(), address) != evictedRanges.end();
}
void GuestBufferMemory::RecordEvicted(std::uint64_t address) {
if (!WasEvicted(address)) evictedRanges.push_back(address);
}
void GuestBufferMemory::AcquireRegistered() {
struct BuildingScope {
explicit BuildingScope(GuestBufferMemory* self) { buildingBufferMemory = self; }
~BuildingScope() {
buildingBufferMemory = nullptr;
buildingBlocks = nullptr;
}
};
const BuildingScope buildingScope(this);
Require(!uploaded && regions.empty() && lease.empty() && space == nullptr, "guest allocation lease must precede resource registration");
ensurePinWaiter();
static const bool profile = std::getenv("APS5_PROFILE_DRAW") != nullptr;
@@ -4375,6 +4484,7 @@ void GuestBufferMemory::AcquireRegistered() {
// APS5_NO_SORTED_SNAPSHOT_LOOKUP=1: AddSnapshot scans the regions as before instead of searching.
static const bool sortedLookup = std::getenv("APS5_NO_SORTED_SNAPSHOT_LOOKUP") == nullptr;
std::vector<RefreshBlock> blocks;
buildingBlocks = &blocks;
std::vector<ImageMirror*> heaps;
bool mirrored = false;
bool served = false;
@@ -4529,7 +4639,7 @@ void GuestBufferMemory::AcquireRegistered() {
if (part.mirror->sparse) {
part.sparse = true;
part.backed = part.mirror->committed;
} else heaps.push_back(part.mirror.get());
}
}
regions.push_back(std::move(part));
}
@@ -4543,7 +4653,7 @@ void GuestBufferMemory::AcquireRegistered() {
imported.emplace_back(range->address, range->address + range->bytes);
continue;
}
if (mirrorsEnabled()) {
if (mirrorsEnabled() && !WasEvicted(range->address)) {
region.mirror = acquireMirror(context, range, blocks, range->releasable);
lap(timing.mirrorsUs, at);
if (region.mirror != nullptr) {
@@ -4551,8 +4661,6 @@ void GuestBufferMemory::AcquireRegistered() {
if (region.mirror->sparse) {
region.sparse = true;
region.backed = region.mirror->committed;
} else if (region.mirror->heap) {
heaps.push_back(region.mirror.get());
}
regions.push_back(std::move(region));
continue;
@@ -4596,6 +4704,9 @@ void GuestBufferMemory::AcquireRegistered() {
copies.push_back({copied.begin, copied.end, committed, reason, reason == nullptr, overBudget});
}
releaseImportedMirrors(context, imported);
for (const auto& region : regions) {
if (region.mirror != nullptr && region.mirror->heap && !region.mirror->sparse) heaps.push_back(region.mirror.get());
}
regionsSorted = sortedLookup;
if (!copies.empty()) {
std::uint64_t copied = 0;
@@ -4670,7 +4781,7 @@ void GuestBufferMemory::AcquireRegistered() {
}
space = std::move(built);
spaces.droppedByWaiter.store(false, std::memory_order_relaxed);
spaces.current.store(space);
if (evictedRanges.empty()) spaces.current.store(space);
}
}
}
@@ -5500,6 +5611,19 @@ void GuestBufferMemory::UploadFinish(bool addressable, std::optional<std::pair<s
for (const auto& region : regions) CompletePendingCpuWrites(context, region.begin, static_cast<std::size_t>(region.end - region.begin));
if (space != nullptr) completeSpaceWrites();
uploaded = true;
{
auto& state = Mirrors();
std::lock_guard lock(state.mutex);
const auto stamp = ++state.dispatchCounter;
for (const auto& region : regions) {
if (region.mirror != nullptr) region.mirror->lastDispatch = stamp;
}
if (space != nullptr) {
for (const auto& region : space->base) {
if (region.mirror != nullptr) region.mirror->lastDispatch = stamp;
}
}
}
for (const auto& region : regions) static_cast<void>(FlushDepthPlanes(region.begin, static_cast<std::size_t>(region.end - region.begin)));
for (const auto& [begin, end] : writes) RequireNoResidentDepthRead_nid_no_patch(begin, static_cast<std::size_t>(end - begin), htileClear);
for (const auto& [begin, end] : writes) StorageTexture::FlushPending(begin, static_cast<std::size_t>(end - begin), nullptr, "written buffer range");
@@ -398,6 +398,7 @@ std::list<CachedTexture>::iterator findSampledEntry(TextureCache& cache, VkDevic
struct TextureCounters {
std::atomic<std::uint64_t> fromStorage{0};
std::atomic<std::uint64_t> snapshots{0};
std::atomic<std::uint64_t> cleared{0};
std::atomic<std::uint64_t> pendingReads{0};
std::atomic<std::uint64_t> storageFallbacks{0};
std::atomic<std::uint64_t> records{0};
@@ -435,7 +436,7 @@ void reportTextureCounters() {
auto last = counters.lastReport.load();
if (nowMs - last < 10000 || !counters.lastReport.compare_exchange_strong(last, nowMs)) return;
const auto count = [](const std::atomic<std::uint64_t>& value) { return static_cast<unsigned long long>(value.load(std::memory_order_relaxed)); };
AgcDriver::ProfilePrint_nid_no_patch("[textures] sampled created: %llu from storage images, %llu snapshots (%llu snapshot reads over recorded writes inside cachedTexture, %llu storage-path fallbacks); stage-A records %llu: %llu fast hits, %llu full lookups; storage images %llu hits, %llu created, %llu own-object refreshes; image tables %llu reused, %llu resolved; untracked snapshots %llu kept by the write-watch hint, %llu compared\n", count(counters.fromStorage), count(counters.snapshots), count(counters.pendingReads), count(counters.storageFallbacks), count(counters.records), count(counters.fastHits), count(counters.fastMisses), count(counters.storageHits), count(counters.storageCreated), count(counters.ownRefreshes), count(counters.tablesReused), count(counters.tablesResolved), count(counters.untrackedKept), count(counters.untrackedCompared));
AgcDriver::ProfilePrint_nid_no_patch("[textures] sampled created: %llu from storage images, %llu cleared on the GPU, %llu snapshots (%llu snapshot reads over recorded writes inside cachedTexture, %llu storage-path fallbacks); stage-A records %llu: %llu fast hits, %llu full lookups; storage images %llu hits, %llu created, %llu own-object refreshes; image tables %llu reused, %llu resolved; untracked snapshots %llu kept by the write-watch hint, %llu compared\n", count(counters.fromStorage), count(counters.cleared), count(counters.snapshots), count(counters.pendingReads), count(counters.storageFallbacks), count(counters.records), count(counters.fastHits), count(counters.fastMisses), count(counters.storageHits), count(counters.storageCreated), count(counters.ownRefreshes), count(counters.tablesReused), count(counters.tablesResolved), count(counters.untrackedKept), count(counters.untrackedCompared));
}
// What the sampled-texture lookups on this thread proved their returned objects current against,
@@ -532,6 +533,18 @@ bool ClearedViewEnabled() {
return !disabled;
}
std::optional<VkClearColorValue> SampledClearColor(const Context& context, const GuestTextureResource& resource, DccKeys keys, bool depthCompare) {
if (depthCompare || !IsDccClear(keys) || keys == DccKeys::ClearRegister) return std::nullopt;
if (IsBlockCompressed(resource.format) || IsRepackedTextureFormat(resource.format) || SrgbExpandsToRgba8(context, resource.format)) return std::nullopt;
const auto format = SampledTextureFormat(context, resource.format);
if (format != DccClearTextureFormat(resource.format)) return std::nullopt;
std::array<std::uint32_t, 4> pattern{};
if (!FillDccClear(format, keys, resource.dccAlphaOnMsb, std::as_writable_bytes(std::span(pattern)))) return std::nullopt;
VkClearColorValue clear{};
if (!ClearColorForTexel(format, BytesPerElement(resource.format), pattern, clear)) return std::nullopt;
return clear;
}
std::uint64_t DepthCopyMinBytes() {
static const std::uint64_t bytes = [] {
const char* text = std::getenv("APS5_DEPTH_COPY_MIN_KIB");
@@ -919,6 +932,7 @@ std::shared_ptr<Texture> cachedTexture(const Context& context, std::span<const s
return texture;
}
if (source != nullptr) return std::make_shared<Texture>(context, source, resource, components);
if (const auto clear = SampledClearColor(context, resource, *keys, depthCompare)) return std::make_shared<Texture>(context, *context.detiler, resource, components, std::span<const std::byte>{}, false, &*clear);
std::vector<std::byte> snapshot(bytes);
ReadTextureSurface(resource, *keys, snapshot);
return std::make_shared<Texture>(context, *context.detiler, resource, components, snapshot, depthCompare);
@@ -990,9 +1004,11 @@ std::shared_ptr<Texture> cachedTexture(const Context& context, std::span<const s
eraseTexture(cache, it);
++cache.counts.stale;
}
if (source != nullptr) parkSnapshot(cache, recycled);
const auto clear = source == nullptr ? SampledClearColor(context, resource, *keys, depthCompare) : std::nullopt;
const bool noSnapshot = source != nullptr || clear.has_value();
if (noSnapshot) parkSnapshot(cache, recycled);
else if (recycled.empty()) recycled = spareSnapshot(cache, bytes);
CachedTexture entry{key, address, source != nullptr ? std::vector<std::byte>{} : (recycled.empty() ? std::vector<std::byte>(bytes) : std::move(recycled)), nullptr, *keys, snapshotGeneration};
CachedTexture entry{key, address, noSnapshot ? std::vector<std::byte>{} : (recycled.empty() ? std::vector<std::byte>(bytes) : std::move(recycled)), nullptr, *keys, snapshotGeneration};
entry.committed = std::move(committed);
entry.surfaceBytes = bytes;
const auto createTexture = [&](auto&&... args) {
@@ -1019,6 +1035,10 @@ std::shared_ptr<Texture> cachedTexture(const Context& context, std::span<const s
}
entry.accounted = source->Cached() ? 0u : heldBytes(*source);
counters.fromStorage.fetch_add(1, std::memory_order_relaxed);
} else if (clear) {
entry.texture = createTexture(*context.detiler, resource, components, std::span<const std::byte>{}, false, &*clear);
entry.accounted = entry.texture->AllocationBytes();
counters.cleared.fetch_add(1, std::memory_order_relaxed);
} else {
// Snapshot before the upload so a write racing with it is caught by the next comparison.
const bool pending = *keys == DccKeys::Uncompressed && Recorder::SnapshotWriteOverlaps(address, bytes);
@@ -5437,6 +5457,10 @@ std::uint64_t SampledLookupKeyScans() {
return sampledLookupKeyScans;
}
std::uint64_t SampledTexturesCleared() {
return TextureCounts().cleared.load(std::memory_order_relaxed);
}
ImageTableReuseCounts ImageTableReuses() {
const auto& counters = TextureCounts();
return {counters.tablesReused.load(std::memory_order_relaxed) + counters.tablesReplayed.load(std::memory_order_relaxed), counters.tablesResolved.load(std::memory_order_relaxed), counters.tablesReplayed.load(std::memory_order_relaxed), counters.tableWritesKept.load(std::memory_order_relaxed), counters.tableWritesMade.load(std::memory_order_relaxed)};
@@ -337,7 +337,7 @@ std::uint64_t SampledTextureMemory() {
return SampledMemoryCounter().load(std::memory_order_relaxed);
}
Texture::Texture(const Context& context, TextureDetiler& detiler, const GuestTextureResource& descriptor, VkComponentMapping components, std::span<const std::byte> snapshot, bool depthCompare) : context(context) {
Texture::Texture(const Context& context, TextureDetiler& detiler, const GuestTextureResource& descriptor, VkComponentMapping components, std::span<const std::byte> snapshot, bool depthCompare, const VkClearColorValue* clear) : context(context) {
static const bool profile = std::getenv("APS5_PROFILE_DRAW") != nullptr;
PhaseTimer timer;
@@ -363,7 +363,8 @@ Texture::Texture(const Context& context, TextureDetiler& detiler, const GuestTex
#endif
const auto guestBytes = geometry.guestBytes;
Require(snapshot.size() == guestBytes, "texture snapshot size mismatch");
Require(clear != nullptr ? snapshot.empty() : snapshot.size() == guestBytes, "texture snapshot size mismatch");
Require(clear == nullptr || (!depthCompare && !srgbExpand && !IsRepackedTextureFormat(descriptor.format) && !IsBlockCompressed(descriptor.format)), "a cleared texture needs a plain color format");
const auto sliceLinearBytes = geometry.sliceLinearBytes;
Require(arrayLayers == 0 || sliceLinearBytes <= UINT64_MAX / arrayLayers, "detiled texture buffer size overflows");
@@ -405,7 +406,39 @@ Texture::Texture(const Context& context, TextureDetiler& detiler, const GuestTex
allocationBytes = expanded.bytes;
}
{
if (clear != nullptr) {
static const bool syncUploads = std::getenv("APS5_SYNC_TEXTURE_UPLOAD") != nullptr;
auto* recorder = syncUploads ? nullptr : Recorder::Active();
std::unique_ptr<CommandBatch> batch;
VkCommandBuffer commands = VK_NULL_HANDLE;
if (recorder != nullptr) {
commands = recorder->Commands();
recorder->Keep(owned);
} else {
batch = std::make_unique<CommandBatch>(context);
commands = batch->Handle();
}
const VkImageSubresourceRange range{aspect, 0, descriptor.mipCount, 0, geometry.imageLayers};
VkImageMemoryBarrier toTransferDst{VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER};
toTransferDst.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
toTransferDst.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
toTransferDst.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
toTransferDst.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
toTransferDst.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
toTransferDst.image = image;
toTransferDst.subresourceRange = range;
context.Function<PFN_vkCmdPipelineBarrier>("vkCmdPipelineBarrier")(commands, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, nullptr, 0, nullptr, 1, &toTransferDst);
context.Function<PFN_vkCmdClearColorImage>("vkCmdClearColorImage")(commands, image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, clear, 1, &range);
VkImageMemoryBarrier toShaderRead = toTransferDst;
toShaderRead.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
toShaderRead.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
toShaderRead.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
toShaderRead.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
context.Function<PFN_vkCmdPipelineBarrier>("vkCmdPipelineBarrier")(commands, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, 0, nullptr, 0, nullptr, 1, &toShaderRead);
if (batch) batch->SubmitAndWait();
else ++Profile().recordedUploads;
if (profile) Profile().gpu += timer.lap();
} else {
// Debug aid: APS5_DUMP_TEXTURE=<hex addresses, comma separated> saves the detiled first mip
// of those sampled textures on their first 8 uploads as texture_<address>_<n>.raw (u32
// width, height, VkFormat, then tightly packed rows).
@@ -3511,8 +3544,9 @@ std::uint64_t StorageTexture::writeBackWindows(std::span<const ImportSegment> se
const auto parts = std::span<const AddedPiece>(added).subspan(first, last - first);
const auto sliceBegin = window.tiledBegin - window.window.rangeBegin;
const auto intoSlabs = std::all_of(parts.begin(), parts.end(), [&](const AddedPiece& part) {
if (!part.slab || part.seeded) return false;
const auto& copy = slabPieces[part.pieces].copies[part.copy];
return part.slab && !part.seeded && copy.dstOffset % 4 == 0 && copy.size % 4 == 0 && (part.begin - sliceBegin) % blockBytes == 0 && (part.end - sliceBegin) % blockBytes == 0;
return copy.dstOffset % 4 == 0 && copy.size % 4 == 0 && (part.begin - sliceBegin) % blockBytes == 0 && (part.end - sliceBegin) % blockBytes == 0;
});
if (intoSlabs) slabRetiled.push_back({i, first, last});
}
@@ -4643,6 +4677,25 @@ void StorageTexture::FlushAllPending(const char* reason) {
static_cast<void>(FlushPending(0, std::numeric_limits<std::size_t>::max(), nullptr, reason));
}
bool StorageTexture::FlushAllPendingUntil(const char* reason, const std::function<bool()>& stop) {
std::optional<PublishOnCpuScope> onCpu;
if (reason != nullptr && std::strcmp(reason, "idle") == 0) onCpu.emplace();
std::vector<std::pair<std::uint64_t, std::size_t>> ranges;
{
auto& pending = Pending();
std::lock_guard lock(pending.mutex);
for (const auto* texture : pending.textures) ranges.emplace_back(texture->descriptor.baseAddress, static_cast<std::size_t>(texture->guestBytes));
}
constexpr std::size_t piece = std::size_t{4} << 20u;
for (const auto& [address, bytes] : ranges) {
for (std::size_t offset = 0; offset < bytes; offset += piece) {
if (stop()) return false;
static_cast<void>(FlushPending(address + offset, std::min(piece, bytes - offset), nullptr, reason));
}
}
return true;
}
std::size_t StorageTexture::StoreSmallPending(const char* reason) {
std::vector<std::shared_ptr<StorageTexture>> small;
{
@@ -1,4 +1,5 @@
#include "prx/libSceAgcDriver/Execution/include/AsyncLog.hpp"
#include "tests/TemporaryFile.hpp"
#include <atomic>
#include <chrono>
#include <csignal>
@@ -122,7 +123,7 @@ std::string LargeLine(std::size_t index, std::size_t bytes) {
}
void OrderPerThread() {
std::FILE* file = std::tmpfile();
std::FILE* file = TemporaryFile::Open();
Check(file != nullptr, "temporary file");
auto& log = AgcDriver::AsyncLog::Get();
std::string expected;
@@ -139,7 +140,7 @@ void OrderPerThread() {
}
void LongLine() {
std::FILE* file = std::tmpfile();
std::FILE* file = TemporaryFile::Open();
Check(file != nullptr, "temporary file");
const std::string longText(3000, 'x');
AgcDriver::AsyncLog::Get().Defer(file, "%s|%d\n", AgcDriver::LogLiteral{longText.c_str()}, 7);
@@ -158,7 +159,7 @@ void Coalescing() {
}
void FlushWaitsForHeldStream() {
std::FILE* file = std::tmpfile();
std::FILE* file = TemporaryFile::Open();
Check(file != nullptr, "temporary file");
auto& log = AgcDriver::AsyncLog::Get();
{
@@ -178,7 +179,7 @@ void FlushWaitsForHeldStream() {
}
void BoundedFlushGivesUp() {
std::FILE* file = std::tmpfile();
std::FILE* file = TemporaryFile::Open();
Check(file != nullptr, "temporary file");
auto& log = AgcDriver::AsyncLog::Get();
Check(log.FlushFor(0ms), "FlushFor waited with nothing queued");
@@ -194,7 +195,7 @@ void BoundedFlushGivesUp() {
}
void FullQueueBlocksCaller() {
std::FILE* file = std::tmpfile();
std::FILE* file = TemporaryFile::Open();
Check(file != nullptr, "temporary file");
auto& log = AgcDriver::AsyncLog::Get();
constexpr std::size_t lineBytes = 1024 * 1024;
@@ -1,4 +1,5 @@
#include "prx/libSceAgcDriver/Execution/include/FrameDumpIo.hpp"
#include "tests/TemporaryFile.hpp"
#include <array>
#include <chrono>
#include <csignal>
@@ -54,7 +55,7 @@ std::FILE* Pipe(int& reader) {
}
void SuccessfulBytes() {
auto* file = std::tmpfile();
auto* file = TemporaryFile::Open();
Check(file != nullptr, "cannot create BMP test file");
const std::array<std::byte, 16> pixels{std::byte{1}, std::byte{2}, std::byte{3}, std::byte{4}};
Check(!AgcDriver::WriteBmpStream_nid_no_patch(file, 2, 2, pixels), "valid BMP write failed");
@@ -13,6 +13,7 @@
#include "prx/libSceAgcDriver/Submit/include/Dcb.hpp"
#include "prx/libc/include/Shutdown.hpp"
#include "SceTypes.hpp"
#include "tests/TemporaryFile.hpp"
#include <algorithm>
#include <array>
#include <atomic>
@@ -130,7 +131,7 @@ std::string verdict(const WaitReport& report) {
}
std::pair<int, std::string> report(const std::filesystem::path& directory, bool full = false) {
std::FILE* output = std::tmpfile();
std::FILE* output = TemporaryFile::Open();
check(output != nullptr, "cannot create a temporary file for the report");
const auto code = AgcDriver::Pm4Analysis::Report(directory, full, output);
std::string text;
@@ -31,6 +31,7 @@
#include "prx/libc/include/GuestWriteWatch.hpp"
#include "prx/libc/include/Shutdown.hpp"
#include "prx/libc/include/general/VabiMacros.hpp"
#include "tests/TemporaryFile.hpp"
#include "ResidentPresent.hpp"
#include "ImageTableAbi.hpp"
#include "IntermediateRepresentation/include/IntermediateRepresentation/IrMetadata/BufferFormat.hpp"
@@ -1420,7 +1421,7 @@ class StderrCapture {
public:
StderrCapture() {
std::fflush(stderr);
file = std::tmpfile();
file = TemporaryFile::Open();
Require(file != nullptr, "cannot open a temporary file for stderr");
#ifdef _WIN32
saved = _dup(_fileno(stderr));
@@ -0,0 +1,20 @@
#include "execution/TargetAddressWindow.hpp"
#include <array>
#include <cstddef>
#include <cstdint>
#include <iostream>
#include <stdexcept>
int main() {
constexpr std::size_t BlockBytes = 65536u;
if (AgcDriver::Tests::TargetAddressWindowPair(0x1fffe0000ull, BlockBytes) != std::array<std::size_t, 2>{0u, 1u}) return 1;
if (AgcDriver::Tests::TargetAddressWindowPair(0x1ffff0000ull, BlockBytes) != std::array<std::size_t, 2>{1u, 2u}) return 1;
if (AgcDriver::Tests::TargetAddressWindowPair(0x300000000ull, BlockBytes) != std::array<std::size_t, 2>{0u, 1u}) return 1;
try {
AgcDriver::Tests::TargetAddressWindowPair(0x1ffff0000ull, static_cast<std::size_t>(0x100000000ull));
} catch (const std::runtime_error&) {
std::cout << "target address window test passed\n";
return 0;
}
return 1;
}
@@ -0,0 +1,11 @@
if(BUILD_TESTING)
add_test_executable(agc_adaptive_staging_tests tests/AdaptiveStaging.cpp)
target_include_directories(agc_adaptive_staging_tests PRIVATE ${LIBS_INCLUDE_DIR})
target_link_libraries(agc_adaptive_staging_tests PRIVATE libc)
add_test(NAME agc_adaptive_staging COMMAND agc_adaptive_staging_tests)
set_tests_properties(agc_adaptive_staging PROPERTIES TIMEOUT 30)
if(WIN32)
set_tests_properties(agc_adaptive_staging PROPERTIES ENVIRONMENT_MODIFICATION
"PATH=path_list_prepend:$<TARGET_FILE_DIR:libc>")
endif()
endif()
@@ -0,0 +1,13 @@
if(BUILD_TESTING)
add_test_executable(agc_async_log_tests tests/AsyncLog.cpp)
target_include_directories(agc_async_log_tests PRIVATE ${LIBS_INCLUDE_DIR})
target_link_libraries(agc_async_log_tests PRIVATE libc)
configure_windows_unwind(agc_async_log_tests)
add_test(NAME agc_async_log COMMAND agc_async_log_tests)
add_test(NAME agc_async_log_fatal COMMAND agc_async_log_tests fatal)
set_tests_properties(agc_async_log agc_async_log_fatal PROPERTIES TIMEOUT 20)
if(WIN32)
set_tests_properties(agc_async_log agc_async_log_fatal PROPERTIES ENVIRONMENT_MODIFICATION
"PATH=path_list_prepend:$<TARGET_FILE_DIR:libc>")
endif()
endif()
@@ -0,0 +1,9 @@
add_test_executable(agc_barrier_batch_tests EXCLUDE_FROM_ALL tests/BarrierBatch.cpp Graphics/src/BarrierBatch.cpp)
target_include_directories(agc_barrier_batch_tests PRIVATE ${LIBS_INCLUDE_DIR} ${ANYPS5_VULKAN_HEADERS_INCLUDE_DIR})
target_link_libraries(agc_barrier_batch_tests PRIVATE libc)
set_target_properties(agc_barrier_batch_tests PROPERTIES CXX_EXTENSIONS OFF)
configure_windows_unwind(agc_barrier_batch_tests)
if(BUILD_TESTING)
agc_add_default_test(agc_barrier_batch_tests)
endif()
@@ -0,0 +1,21 @@
add_test_executable(agc_buffer_pool_tests EXCLUDE_FROM_ALL tests/BufferPool.cpp)
target_sources(agc_buffer_pool_tests PRIVATE Graphics/src/BufferPool.cpp tests/AllocationFailure.cpp)
target_include_directories(agc_buffer_pool_tests PRIVATE ${LIBS_INCLUDE_DIR} ${CMAKE_SOURCE_DIR}/core/shader/recompiler ${ANYPS5_VULKAN_HEADERS_INCLUDE_DIR})
target_link_libraries(agc_buffer_pool_tests PRIVATE libSceAgcDriver libc)
set_target_properties(agc_buffer_pool_tests PROPERTIES CXX_EXTENSIONS OFF)
configure_windows_unwind(agc_buffer_pool_tests)
if(BUILD_TESTING)
set_target_properties(agc_buffer_pool_tests PROPERTIES EXCLUDE_FROM_ALL OFF)
add_test(NAME agc_buffer_pool COMMAND agc_buffer_pool_tests)
add_test(NAME agc_buffer_pool_small_device_shared COMMAND agc_buffer_pool_tests --small-device-retention)
set_tests_properties(agc_buffer_pool_small_device_shared PROPERTIES ENVIRONMENT
"APS5_STAGING_POOL_MIB=256;APS5_BUFFER_POOL_SHARED=1")
add_test(NAME agc_buffer_pool_small_device_no_staging COMMAND agc_buffer_pool_tests --small-device-retention)
set_tests_properties(agc_buffer_pool_small_device_no_staging PROPERTIES ENVIRONMENT
"APS5_STAGING_POOL_MIB=0")
if(WIN32)
set_tests_properties(agc_buffer_pool agc_buffer_pool_small_device_shared agc_buffer_pool_small_device_no_staging PROPERTIES ENVIRONMENT_MODIFICATION
"PATH=path_list_prepend:$<TARGET_FILE_DIR:libc>")
endif()
endif()
@@ -0,0 +1,14 @@
add_test_executable(agc_buffer_resource_vcc_tests EXCLUDE_FROM_ALL tests/BufferResourceVcc.cpp)
target_link_libraries(agc_buffer_resource_vcc_tests PRIVATE shader_recompiler_agc_driver libc)
set_target_properties(agc_buffer_resource_vcc_tests PROPERTIES CXX_EXTENSIONS OFF)
configure_windows_unwind(agc_buffer_resource_vcc_tests)
if(BUILD_TESTING)
set_target_properties(agc_buffer_resource_vcc_tests PROPERTIES EXCLUDE_FROM_ALL OFF)
add_test(NAME agc_buffer_resource_vcc COMMAND agc_buffer_resource_vcc_tests)
set_tests_properties(agc_buffer_resource_vcc PROPERTIES TIMEOUT 30)
if(WIN32)
set_tests_properties(agc_buffer_resource_vcc PROPERTIES ENVIRONMENT_MODIFICATION
"PATH=path_list_prepend:$<TARGET_FILE_DIR:libc>")
endif()
endif()
@@ -0,0 +1,37 @@
if(BUILD_TESTING)
add_test_executable(agc_capture_trace_tests tests/CaptureTrace.cpp)
target_include_directories(agc_capture_trace_tests PRIVATE ${LIBS_INCLUDE_DIR})
target_link_libraries(agc_capture_trace_tests PRIVATE libc)
configure_windows_unwind(agc_capture_trace_tests)
set(agcCaptureTraceDirectory ${CMAKE_CURRENT_BINARY_DIR}/capture_trace_tests)
file(MAKE_DIRECTORY "${agcCaptureTraceDirectory}/default")
file(MAKE_DIRECTORY "${agcCaptureTraceDirectory}/explicit")
file(MAKE_DIRECTORY "${agcCaptureTraceDirectory}/failure")
file(MAKE_DIRECTORY "${agcCaptureTraceDirectory}/best-effort")
file(MAKE_DIRECTORY "${agcCaptureTraceDirectory}/disabled")
set(agcCaptureTraceExplicitPath "${agcCaptureTraceDirectory}/explicit/trace.log")
set(agcCaptureTraceFailurePath "${agcCaptureTraceDirectory}/failure/missing-parent/trace.log")
set(agcCaptureTraceBestEffortPath "${agcCaptureTraceDirectory}/best-effort/trace.log")
add_test(NAME agc_capture_trace_path_default COMMAND agc_capture_trace_tests path-default)
add_test(NAME agc_capture_trace_path_empty COMMAND agc_capture_trace_tests path-empty)
set_tests_properties(agc_capture_trace_path_empty PROPERTIES ENVIRONMENT "APS5_CAPTURE_TRACE_PATH=")
add_test(NAME agc_capture_trace_path_explicit COMMAND agc_capture_trace_tests path-explicit)
set_tests_properties(agc_capture_trace_path_explicit PROPERTIES ENVIRONMENT "APS5_CAPTURE_TRACE_PATH=${agcCaptureTraceExplicitPath}")
add_test(NAME agc_capture_trace_explicit_writes COMMAND agc_capture_trace_tests explicit-writes)
set_tests_properties(agc_capture_trace_explicit_writes PROPERTIES ENVIRONMENT "APS5_CAPTURE_TRACE=1;APS5_CAPTURE_TRACE_PATH=${agcCaptureTraceExplicitPath}")
add_test(NAME agc_capture_trace_default_writes COMMAND agc_capture_trace_tests default-writes)
set_tests_properties(agc_capture_trace_default_writes PROPERTIES ENVIRONMENT "APS5_CAPTURE_TRACE=1" WORKING_DIRECTORY "${agcCaptureTraceDirectory}/default")
add_test(NAME agc_capture_trace_open_failure COMMAND agc_capture_trace_tests open-failure)
set_tests_properties(agc_capture_trace_open_failure PROPERTIES ENVIRONMENT "APS5_CAPTURE_TRACE=1;APS5_CAPTURE_TRACE_PATH=${agcCaptureTraceFailurePath}" WORKING_DIRECTORY "${agcCaptureTraceDirectory}/failure")
add_test(NAME agc_capture_trace_best_effort_overflow COMMAND agc_capture_trace_tests best-effort-overflow)
set_tests_properties(agc_capture_trace_best_effort_overflow PROPERTIES ENVIRONMENT "APS5_CAPTURE_TRACE=1;APS5_CAPTURE_TRACE_PATH=${agcCaptureTraceBestEffortPath}" WORKING_DIRECTORY "${agcCaptureTraceDirectory}/best-effort")
add_test(NAME agc_capture_trace_disabled COMMAND agc_capture_trace_tests disabled)
set_tests_properties(agc_capture_trace_disabled PROPERTIES WORKING_DIRECTORY "${agcCaptureTraceDirectory}/disabled")
if(WIN32)
set_tests_properties(agc_capture_trace_path_default agc_capture_trace_path_empty
agc_capture_trace_path_explicit agc_capture_trace_explicit_writes
agc_capture_trace_default_writes agc_capture_trace_open_failure agc_capture_trace_best_effort_overflow
agc_capture_trace_disabled PROPERTIES ENVIRONMENT_MODIFICATION
"PATH=path_list_prepend:$<TARGET_FILE_DIR:libc>")
endif()
endif()
@@ -0,0 +1,12 @@
if(BUILD_TESTING AND NOT WIN32)
add_test_executable(agc_collect_memo_generation_tests
tests/CollectMemoGeneration.cpp
Execution/src/GuestMemory.cpp
Execution/src/PerformanceTraceThread.cpp
)
target_include_directories(agc_collect_memo_generation_tests PRIVATE ${LIBS_INCLUDE_DIR})
target_link_libraries(agc_collect_memo_generation_tests PRIVATE shader_recompiler_agc_driver libc)
set_target_properties(agc_collect_memo_generation_tests PROPERTIES CXX_EXTENSIONS OFF)
add_test(NAME agc_collect_memo_generation COMMAND agc_collect_memo_generation_tests)
set_tests_properties(agc_collect_memo_generation PROPERTIES TIMEOUT 30)
endif()
@@ -0,0 +1,17 @@
add_test_executable(agc_command_batch_failure_tests EXCLUDE_FROM_ALL
tests/CommandBatch.cpp tests/CommandBatchFailure.cpp Graphics/src/Resources.cpp tests/AllocationFailure.cpp)
target_include_directories(agc_command_batch_failure_tests PRIVATE
${LIBS_INCLUDE_DIR} ${CMAKE_SOURCE_DIR}/core/shader/recompiler ${ANYPS5_VULKAN_HEADERS_INCLUDE_DIR})
target_link_libraries(agc_command_batch_failure_tests PRIVATE libSceAgcDriver libc)
set_target_properties(agc_command_batch_failure_tests PROPERTIES CXX_EXTENSIONS OFF)
configure_windows_unwind(agc_command_batch_failure_tests)
if(BUILD_TESTING)
set_target_properties(agc_command_batch_failure_tests PROPERTIES EXCLUDE_FROM_ALL OFF)
add_test(NAME agc_command_batch_failure COMMAND agc_command_batch_failure_tests)
set_tests_properties(agc_command_batch_failure PROPERTIES TIMEOUT 30)
if(WIN32)
set_tests_properties(agc_command_batch_failure PROPERTIES
ENVIRONMENT_MODIFICATION "PATH=path_list_prepend:$<TARGET_FILE_DIR:libc>")
endif()
endif()
@@ -0,0 +1,12 @@
if(BUILD_TESTING)
add_test_executable(agc_compile_budget_tests tests/CompileBudget.cpp)
target_include_directories(agc_compile_budget_tests PRIVATE ${LIBS_INCLUDE_DIR})
target_link_libraries(agc_compile_budget_tests PRIVATE libc)
configure_windows_unwind(agc_compile_budget_tests)
add_test(NAME agc_compile_budget COMMAND agc_compile_budget_tests)
set_tests_properties(agc_compile_budget PROPERTIES TIMEOUT 30)
if(WIN32)
set_tests_properties(agc_compile_budget PROPERTIES ENVIRONMENT_MODIFICATION
"PATH=path_list_prepend:$<TARGET_FILE_DIR:libc>")
endif()
endif()
@@ -0,0 +1,29 @@
if(BUILD_TESTING)
add_test_executable(agc_compute_pipeline_capture_tests tests/ComputePipelineCapture.cpp Execution/src/ComputePipelineCapture.cpp)
target_include_directories(agc_compute_pipeline_capture_tests PRIVATE ${LIBS_INCLUDE_DIR} ${ANYPS5_VULKAN_HEADERS_INCLUDE_DIR})
target_link_libraries(agc_compute_pipeline_capture_tests PRIVATE libc)
set_target_properties(agc_compute_pipeline_capture_tests PROPERTIES CXX_EXTENSIONS OFF)
configure_windows_unwind(agc_compute_pipeline_capture_tests)
add_test(NAME agc_compute_pipeline_capture COMMAND agc_compute_pipeline_capture_tests)
set_tests_properties(agc_compute_pipeline_capture PROPERTIES TIMEOUT 30)
foreach(mode IN ITEMS entry-cap byte-cap io invalid)
string(REPLACE "-" "_" name "${mode}")
add_test(NAME agc_compute_pipeline_capture_optional_${name} COMMAND agc_compute_pipeline_capture_tests --optional-${mode})
set_tests_properties(agc_compute_pipeline_capture_optional_${name} PROPERTIES TIMEOUT 30)
if(WIN32)
set_tests_properties(agc_compute_pipeline_capture_optional_${name} PROPERTIES ENVIRONMENT_MODIFICATION "PATH=path_list_prepend:$<TARGET_FILE_DIR:libc>")
endif()
endforeach()
if(WIN32)
set_tests_properties(agc_compute_pipeline_capture PROPERTIES ENVIRONMENT_MODIFICATION "PATH=path_list_prepend:$<TARGET_FILE_DIR:libc>")
endif()
endif()
if(BUILD_TESTING AND ANYPS5_ENABLE_SPIRV_TOOLS)
add_test(NAME agc_compute_pipeline_capture_run COMMAND ${CMAKE_COMMAND}
-DFIXTURE=$<TARGET_FILE:agc_driver_branch_past_endpgm_tests>
-DREPLAY=$<TARGET_FILE:agc_compute_pipeline_replay>
-DOUTPUT_ROOT=${CMAKE_CURRENT_BINARY_DIR}/capture-tests
-P ${CMAKE_CURRENT_SOURCE_DIR}/tests/ComputePipelineCaptureRun.cmake)
set_tests_properties(agc_compute_pipeline_capture_run PROPERTIES TIMEOUT 30 SKIP_REGULAR_EXPRESSION "compute pipeline capture run: skipped, no usable Vulkan device")
endif()
@@ -0,0 +1,15 @@
if(BUILD_TESTING AND ANYPS5_ENABLE_SPIRV_TOOLS)
add_test_executable(agc_compute_pipeline_replay_tests tests/ComputePipelineReplay.cpp)
target_include_directories(agc_compute_pipeline_replay_tests PRIVATE
${LIBS_INCLUDE_DIR}
${CMAKE_SOURCE_DIR}/core/shader/recompiler
${ANYPS5_VULKAN_HEADERS_INCLUDE_DIR}
${ANYPS5_SPIRV_HEADERS_INCLUDE_DIR}
)
target_link_libraries(agc_compute_pipeline_replay_tests PRIVATE libSceAgcDriver libc)
set_target_properties(agc_compute_pipeline_replay_tests PROPERTIES CXX_EXTENSIONS OFF)
configure_windows_unwind(agc_compute_pipeline_replay_tests)
add_test(NAME agc_compute_pipeline_replay COMMAND agc_compute_pipeline_replay_tests)
set_tests_properties(agc_compute_pipeline_replay PROPERTIES TIMEOUT 30 SKIP_RETURN_CODE 77)
add_dependencies(agc_compute_pipeline_replay_tests agc_compute_pipeline_replay agc_driver_branch_past_endpgm_tests)
endif()
@@ -0,0 +1,8 @@
add_test_executable(agc_constant_bit_test_tests EXCLUDE_FROM_ALL tests/ConstantBitTest.cpp)
target_link_libraries(agc_constant_bit_test_tests PRIVATE shader_recompiler_agc_driver libc)
set_target_properties(agc_constant_bit_test_tests PROPERTIES CXX_EXTENSIONS OFF)
configure_windows_unwind(agc_constant_bit_test_tests)
if(BUILD_TESTING)
agc_add_default_test(agc_constant_bit_test_tests)
endif()
@@ -0,0 +1,13 @@
add_test_executable(agc_constant_phi_tests EXCLUDE_FROM_ALL tests/ConstantPhi.cpp)
target_link_libraries(agc_constant_phi_tests PRIVATE shader_recompiler_agc_driver libc)
set_target_properties(agc_constant_phi_tests PROPERTIES CXX_EXTENSIONS OFF)
configure_windows_unwind(agc_constant_phi_tests)
if(BUILD_TESTING)
set_target_properties(agc_constant_phi_tests PROPERTIES EXCLUDE_FROM_ALL OFF)
add_test(NAME agc_constant_phi COMMAND agc_constant_phi_tests)
if(WIN32)
set_tests_properties(agc_constant_phi PROPERTIES ENVIRONMENT_MODIFICATION
"PATH=path_list_prepend:$<TARGET_FILE_DIR:libc>")
endif()
endif()
@@ -0,0 +1,13 @@
add_test_executable(agc_constant_select_tests EXCLUDE_FROM_ALL tests/ConstantSelect.cpp)
target_link_libraries(agc_constant_select_tests PRIVATE shader_recompiler_agc_driver libc)
set_target_properties(agc_constant_select_tests PROPERTIES CXX_EXTENSIONS OFF)
configure_windows_unwind(agc_constant_select_tests)
if(BUILD_TESTING)
set_target_properties(agc_constant_select_tests PROPERTIES EXCLUDE_FROM_ALL OFF)
add_test(NAME agc_constant_select COMMAND agc_constant_select_tests)
if(WIN32)
set_tests_properties(agc_constant_select PROPERTIES ENVIRONMENT_MODIFICATION
"PATH=path_list_prepend:$<TARGET_FILE_DIR:libc>")
endif()
endif()
@@ -0,0 +1,14 @@
add_test_executable(agc_copy_guest_bytes_tests EXCLUDE_FROM_ALL tests/CopyGuestBytes.cpp)
target_include_directories(agc_copy_guest_bytes_tests PRIVATE
${LIBS_INCLUDE_DIR}
${CMAKE_SOURCE_DIR}/core/shader/recompiler
${ANYPS5_VULKAN_HEADERS_INCLUDE_DIR}
${ANYPS5_SPIRV_HEADERS_INCLUDE_DIR}
)
target_link_libraries(agc_copy_guest_bytes_tests PRIVATE libSceAgcDriver libc)
set_target_properties(agc_copy_guest_bytes_tests PROPERTIES CXX_EXTENSIONS OFF)
configure_windows_unwind(agc_copy_guest_bytes_tests)
if(BUILD_TESTING)
agc_add_default_test(agc_copy_guest_bytes_tests)
endif()
@@ -0,0 +1,14 @@
add_test_executable(agc_dcc_key_sharing_tests EXCLUDE_FROM_ALL tests/DccKeySharing.cpp)
target_include_directories(agc_dcc_key_sharing_tests PRIVATE ${LIBS_INCLUDE_DIR} ${CMAKE_SOURCE_DIR}/core/shader/recompiler ${ANYPS5_VULKAN_HEADERS_INCLUDE_DIR})
target_link_libraries(agc_dcc_key_sharing_tests PRIVATE libc)
set_target_properties(agc_dcc_key_sharing_tests PROPERTIES CXX_EXTENSIONS OFF)
configure_windows_unwind(agc_dcc_key_sharing_tests)
if(BUILD_TESTING)
set_target_properties(agc_dcc_key_sharing_tests PROPERTIES EXCLUDE_FROM_ALL OFF)
add_test(NAME agc_dcc_key_sharing COMMAND agc_dcc_key_sharing_tests)
if(WIN32)
set_tests_properties(agc_dcc_key_sharing PROPERTIES ENVIRONMENT_MODIFICATION
"PATH=path_list_prepend:$<TARGET_FILE_DIR:libc>")
endif()
endif()
@@ -0,0 +1,14 @@
add_test_executable(agc_deferred_destruction_tests EXCLUDE_FROM_ALL tests/DeferredDestruction.cpp)
target_include_directories(agc_deferred_destruction_tests PRIVATE ${LIBS_INCLUDE_DIR} ${CMAKE_SOURCE_DIR}/core/shader/recompiler ${ANYPS5_VULKAN_HEADERS_INCLUDE_DIR})
target_link_libraries(agc_deferred_destruction_tests PRIVATE libSceAgcDriver libc)
set_target_properties(agc_deferred_destruction_tests PROPERTIES CXX_EXTENSIONS OFF)
configure_windows_unwind(agc_deferred_destruction_tests)
if(BUILD_TESTING)
set_target_properties(agc_deferred_destruction_tests PROPERTIES EXCLUDE_FROM_ALL OFF)
add_test(NAME agc_deferred_destruction COMMAND agc_deferred_destruction_tests)
if(WIN32)
set_tests_properties(agc_deferred_destruction PROPERTIES ENVIRONMENT_MODIFICATION
"PATH=path_list_prepend:$<TARGET_FILE_DIR:libc>")
endif()
endif()
@@ -0,0 +1,13 @@
add_test_executable(agc_denormal_flush_elimination_tests EXCLUDE_FROM_ALL tests/DenormalFlushElimination.cpp)
target_link_libraries(agc_denormal_flush_elimination_tests PRIVATE shader_recompiler_agc_driver libc)
set_target_properties(agc_denormal_flush_elimination_tests PROPERTIES CXX_EXTENSIONS OFF)
configure_windows_unwind(agc_denormal_flush_elimination_tests)
if(BUILD_TESTING)
set_target_properties(agc_denormal_flush_elimination_tests PROPERTIES EXCLUDE_FROM_ALL OFF)
add_test(NAME agc_denormal_flush_elimination COMMAND agc_denormal_flush_elimination_tests)
if(WIN32)
set_tests_properties(agc_denormal_flush_elimination PROPERTIES ENVIRONMENT_MODIFICATION
"PATH=path_list_prepend:$<TARGET_FILE_DIR:libc>")
endif()
endif()
@@ -0,0 +1,14 @@
add_test_executable(agc_depth_range_remap_tests EXCLUDE_FROM_ALL tests/DepthRangeRemap.cpp)
target_link_libraries(agc_depth_range_remap_tests PRIVATE shader_recompiler_agc_driver libc)
set_target_properties(agc_depth_range_remap_tests PROPERTIES CXX_EXTENSIONS OFF)
configure_windows_unwind(agc_depth_range_remap_tests)
if(BUILD_TESTING)
set_target_properties(agc_depth_range_remap_tests PROPERTIES EXCLUDE_FROM_ALL OFF)
add_test(NAME agc_depth_range_remap COMMAND agc_depth_range_remap_tests)
set_tests_properties(agc_depth_range_remap PROPERTIES ENVIRONMENT "ANYPS5_NO_SHADER_CACHE=1")
if(WIN32)
set_tests_properties(agc_depth_range_remap PROPERTIES ENVIRONMENT_MODIFICATION
"PATH=path_list_prepend:$<TARGET_FILE_DIR:libc>")
endif()
endif()
@@ -0,0 +1,15 @@
if(BUILD_TESTING)
add_test_executable(agc_descriptor_cache_failure_tests
tests/DescriptorCacheFailure.cpp
Graphics/src/ShaderResources.cpp)
target_include_directories(agc_descriptor_cache_failure_tests PRIVATE
$<TARGET_PROPERTY:libSceAgcDriver,INCLUDE_DIRECTORIES>)
target_link_libraries(agc_descriptor_cache_failure_tests PRIVATE libSceAgcDriver shader_recompiler_agc_driver libc libkernel)
configure_windows_unwind(agc_descriptor_cache_failure_tests)
add_test(NAME agc_descriptor_cache_failure COMMAND agc_descriptor_cache_failure_tests)
set_tests_properties(agc_descriptor_cache_failure PROPERTIES TIMEOUT 20)
if(WIN32)
set_tests_properties(agc_descriptor_cache_failure PROPERTIES ENVIRONMENT_MODIFICATION
"PATH=path_list_prepend:$<TARGET_FILE_DIR:libc>")
endif()
endif()
@@ -0,0 +1,14 @@
add_test_executable(agc_device_fault_tests EXCLUDE_FROM_ALL tests/DeviceFault.cpp)
target_include_directories(agc_device_fault_tests PRIVATE ${LIBS_INCLUDE_DIR} ${ANYPS5_VULKAN_HEADERS_INCLUDE_DIR})
set_target_properties(agc_device_fault_tests PROPERTIES CXX_EXTENSIONS OFF)
target_link_libraries(agc_device_fault_tests PRIVATE libc libkernel)
configure_windows_unwind(agc_device_fault_tests)
if(BUILD_TESTING)
set_target_properties(agc_device_fault_tests PROPERTIES EXCLUDE_FROM_ALL OFF)
add_test(NAME agc_device_fault COMMAND agc_device_fault_tests)
if(WIN32)
set_tests_properties(agc_device_fault PROPERTIES ENVIRONMENT_MODIFICATION
"PATH=path_list_prepend:$<TARGET_FILE_DIR:libc>")
endif()
endif()
@@ -0,0 +1,14 @@
add_test_executable(agc_device_memory_fallback_tests EXCLUDE_FROM_ALL tests/DeviceMemoryFallback.cpp)
target_include_directories(agc_device_memory_fallback_tests PRIVATE ${LIBS_INCLUDE_DIR} ${CMAKE_SOURCE_DIR}/core/shader/recompiler ${ANYPS5_VULKAN_HEADERS_INCLUDE_DIR})
target_link_libraries(agc_device_memory_fallback_tests PRIVATE libSceAgcDriver libc)
set_target_properties(agc_device_memory_fallback_tests PROPERTIES CXX_EXTENSIONS OFF)
configure_windows_unwind(agc_device_memory_fallback_tests)
if(BUILD_TESTING)
set_target_properties(agc_device_memory_fallback_tests PROPERTIES EXCLUDE_FROM_ALL OFF)
add_test(NAME agc_device_memory_fallback COMMAND agc_device_memory_fallback_tests)
if(WIN32)
set_tests_properties(agc_device_memory_fallback PROPERTIES ENVIRONMENT_MODIFICATION
"PATH=path_list_prepend:$<TARGET_FILE_DIR:libc>")
endif()
endif()
@@ -0,0 +1,14 @@
add_test_executable(agc_display_buffer_dcc_tests EXCLUDE_FROM_ALL tests/DisplayBufferDcc.cpp)
target_include_directories(agc_display_buffer_dcc_tests PRIVATE ${LIBS_INCLUDE_DIR} ${CMAKE_SOURCE_DIR}/core/shader/recompiler ${ANYPS5_VULKAN_HEADERS_INCLUDE_DIR})
target_link_libraries(agc_display_buffer_dcc_tests PRIVATE libSceAgcDriver libc)
set_target_properties(agc_display_buffer_dcc_tests PROPERTIES CXX_EXTENSIONS OFF)
configure_windows_unwind(agc_display_buffer_dcc_tests)
if(BUILD_TESTING)
set_target_properties(agc_display_buffer_dcc_tests PROPERTIES EXCLUDE_FROM_ALL OFF)
add_test(NAME agc_display_buffer_dcc COMMAND agc_display_buffer_dcc_tests)
if(WIN32)
set_tests_properties(agc_display_buffer_dcc PROPERTIES ENVIRONMENT_MODIFICATION
"PATH=path_list_prepend:$<TARGET_FILE_DIR:libc>")
endif()
endif()
@@ -0,0 +1,8 @@
add_test_executable(agc_dpp_write_tests EXCLUDE_FROM_ALL tests/DppWrite.cpp)
target_link_libraries(agc_dpp_write_tests PRIVATE shader_recompiler_agc_driver libc)
set_target_properties(agc_dpp_write_tests PROPERTIES CXX_EXTENSIONS OFF)
configure_windows_unwind(agc_dpp_write_tests)
if(BUILD_TESTING)
agc_add_default_test(agc_dpp_write_tests)
endif()
@@ -0,0 +1,9 @@
add_test_executable(agc_draw_inputs_in_place_driver_tests EXCLUDE_FROM_ALL tests/DrawInputsInPlace.cpp)
target_include_directories(agc_draw_inputs_in_place_driver_tests PRIVATE ${LIBS_INCLUDE_DIR} ${ANYPS5_VULKAN_HEADERS_INCLUDE_DIR})
set_target_properties(agc_draw_inputs_in_place_driver_tests PROPERTIES CXX_EXTENSIONS OFF)
configure_windows_unwind(agc_draw_inputs_in_place_driver_tests)
if(BUILD_TESTING)
set_target_properties(agc_draw_inputs_in_place_driver_tests PROPERTIES EXCLUDE_FROM_ALL OFF)
add_test(NAME agc_draw_inputs_in_place_driver COMMAND agc_draw_inputs_in_place_driver_tests)
endif()
@@ -0,0 +1,14 @@
if(BUILD_TESTING)
add_test(NAME agc_driver_address_passes_targets_split COMMAND agc_driver_address_passes_tests --targets)
set_tests_properties(agc_driver_address_passes_targets_split PROPERTIES ENVIRONMENT "APS5_NO_ADDRESS_READ_PASSES=1" SKIP_RETURN_CODE 77 TIMEOUT 60)
if(WIN32)
set_tests_properties(agc_driver_address_passes_targets_split PROPERTIES ENVIRONMENT_MODIFICATION
"PATH=path_list_prepend:$<TARGET_FILE_DIR:libc>")
endif()
add_test(NAME agc_driver_address_passes_draw_transitions COMMAND agc_driver_address_passes_tests --targets)
set_tests_properties(agc_driver_address_passes_draw_transitions PROPERTIES ENVIRONMENT "APS5_NO_ADDRESS_READ_PASSES=1;APS5_DRAW_TRANSITIONS=1" SKIP_RETURN_CODE 77 TIMEOUT 60)
if(WIN32)
set_tests_properties(agc_driver_address_passes_draw_transitions PROPERTIES ENVIRONMENT_MODIFICATION
"PATH=path_list_prepend:$<TARGET_FILE_DIR:libc>")
endif()
endif()
@@ -0,0 +1,20 @@
target_include_directories(agc_driver_alpha_to_coverage_tests PRIVATE $<TARGET_PROPERTY:shader_recompiler_agc_driver,INTERFACE_INCLUDE_DIRECTORIES>)
if(BUILD_TESTING)
add_test(NAME agc_driver_dithered_alpha_to_coverage COMMAND agc_driver_alpha_to_coverage_tests --dithered8)
add_test(NAME agc_driver_two_sample_dithered_alpha_to_coverage COMMAND agc_driver_alpha_to_coverage_tests --dithered2)
set(multisampledDccClearTests)
foreach(samples IN ITEMS 2 4 8)
set(testName "agc_driver_msaa_dcc_srgb_clear_${samples}")
add_test(NAME ${testName} COMMAND agc_driver_alpha_to_coverage_tests --dcc-srgb-clear ${samples})
list(APPEND multisampledDccClearTests ${testName})
set(testName "agc_driver_msaa_dcc_clear_${samples}")
add_test(NAME ${testName} COMMAND agc_driver_alpha_to_coverage_tests --dcc-fast-clear ${samples})
list(APPEND multisampledDccClearTests ${testName})
set(testName "agc_driver_msaa_dcc_compared_import_${samples}")
add_test(NAME ${testName} COMMAND agc_driver_alpha_to_coverage_tests --dcc-compared-import ${samples})
list(APPEND multisampledDccClearTests ${testName})
endforeach()
set_tests_properties(agc_driver_dithered_alpha_to_coverage agc_driver_two_sample_dithered_alpha_to_coverage PROPERTIES
ENVIRONMENT "ANYPS5_NO_SHADER_CACHE=1" SKIP_RETURN_CODE 77 TIMEOUT 30 WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}")
endif()
@@ -0,0 +1,9 @@
if(BUILD_TESTING)
add_test(NAME agc_driver_array_layer_target_cpu COMMAND agc_driver_array_layer_target_tests)
set_tests_properties(agc_driver_array_layer_target_cpu PROPERTIES
ENVIRONMENT "ANYPS5_NO_SHADER_CACHE=1;APS5_NO_HOST_IMPORT=1" TIMEOUT 30 SKIP_RETURN_CODE 77)
if(WIN32)
set_tests_properties(agc_driver_array_layer_target_cpu PROPERTIES ENVIRONMENT_MODIFICATION
"PATH=path_list_prepend:$<TARGET_FILE_DIR:libc>")
endif()
endif()
@@ -0,0 +1,38 @@
add_test_executable(agc_driver_bda_device_tests EXCLUDE_FROM_ALL
tests/BdaDevice.cpp
tests/BdaShader.cpp
tests/BdaExecution.cpp
tests/BdaContracts.cpp
tests/HostImportFailure.cpp
)
target_include_directories(agc_driver_bda_device_tests PRIVATE
${LIBS_INCLUDE_DIR}
$<TARGET_PROPERTY:shader_recompiler_agc_driver,INTERFACE_INCLUDE_DIRECTORIES>
${CMAKE_SOURCE_DIR}/core/shader/recompiler
${ANYPS5_VULKAN_HEADERS_INCLUDE_DIR}
)
target_link_libraries(agc_driver_bda_device_tests PRIVATE libSceAgcDriver SDL2-static libc)
set_target_properties(agc_driver_bda_device_tests PROPERTIES CXX_EXTENSIONS OFF)
configure_windows_unwind(agc_driver_bda_device_tests)
if(BUILD_TESTING)
add_test(NAME agc_driver_host_import_failure_handles COMMAND agc_driver_bda_device_tests --host-import-failures)
set_tests_properties(agc_driver_host_import_failure_handles PROPERTIES
ENVIRONMENT "ANYPS5_NO_SHADER_CACHE=1" SKIP_RETURN_CODE 77 TIMEOUT 30 WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}")
if(WIN32)
set_tests_properties(agc_driver_host_import_failure_handles PROPERTIES
ENVIRONMENT_MODIFICATION "PATH=path_list_prepend:$<TARGET_FILE_DIR:libc>")
endif()
endif()
if(BUILD_TESTING)
agc_add_default_test(agc_driver_bda_device_tests)
add_test(NAME agc_driver_bda_device_selection_cpu COMMAND agc_driver_bda_device_tests --device-selection-cpu)
set_tests_properties(agc_driver_bda_device_selection_cpu PROPERTIES
ENVIRONMENT "ANYPS5_NO_SHADER_CACHE=1" WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}")
if(WIN32)
set_tests_properties(agc_driver_bda_device_selection_cpu PROPERTIES ENVIRONMENT_MODIFICATION
"PATH=path_list_prepend:$<TARGET_FILE_DIR:libc>")
endif()
endif()
@@ -0,0 +1,3 @@
if(BUILD_TESTING)
agc_add_draw_pipeline_test(agc_driver_bda_span_reads)
endif()
@@ -0,0 +1 @@
target_include_directories(agc_driver_buffer_descriptor_runtime_tests PRIVATE $<TARGET_PROPERTY:shader_recompiler_agc_driver,INTERFACE_INCLUDE_DIRECTORIES>)
@@ -0,0 +1,3 @@
if(BUILD_TESTING)
agc_add_draw_pipeline_test(agc_driver_buffer_load_store)
endif()
@@ -0,0 +1,3 @@
if(BUILD_TESTING)
set_tests_properties(agc_driver_clamped_global_fill PROPERTIES ENVIRONMENT "ANYPS5_NO_SHADER_CACHE=1;APS5_NO_LABEL_READBACK_STORE=1")
endif()
@@ -0,0 +1,24 @@
add_test_executable(agc_driver_cmask_fast_clear_tests EXCLUDE_FROM_ALL
tests/CmaskFastClear.cpp
${agcCoverShaderHeaders}
)
target_include_directories(agc_driver_cmask_fast_clear_tests PRIVATE
${LIBS_INCLUDE_DIR}
${agcTestShaderGeneratedRoot}
${CMAKE_SOURCE_DIR}/core/shader/recompiler
${ANYPS5_VULKAN_HEADERS_INCLUDE_DIR}
)
target_link_libraries(agc_driver_cmask_fast_clear_tests PRIVATE
libSceAgcDriver
SDL2-static
libc
)
set_target_properties(agc_driver_cmask_fast_clear_tests PROPERTIES CXX_EXTENSIONS OFF)
configure_windows_unwind(agc_driver_cmask_fast_clear_tests)
if(BUILD_TESTING)
agc_add_default_test(agc_driver_cmask_fast_clear_tests)
endif()
@@ -0,0 +1 @@
target_include_directories(agc_driver_color1555_target_tests PRIVATE $<TARGET_PROPERTY:shader_recompiler_agc_driver,INTERFACE_INCLUDE_DIRECTORIES>)
@@ -0,0 +1 @@
target_include_directories(agc_driver_color565_target_tests PRIVATE $<TARGET_PROPERTY:shader_recompiler_agc_driver,INTERFACE_INCLUDE_DIRECTORIES>)
@@ -0,0 +1 @@
target_include_directories(agc_driver_color_logic_op_tests PRIVATE $<TARGET_PROPERTY:shader_recompiler_agc_driver,INTERFACE_INCLUDE_DIRECTORIES>)
@@ -0,0 +1,3 @@
if(BUILD_TESTING)
set_property(TEST agc_driver_compute_prebuild_share APPEND PROPERTY ENVIRONMENT "APS5_PREBUILD_THREADS=4")
endif()
@@ -0,0 +1,7 @@
if(BUILD_TESTING)
add_test(NAME agc_driver_compute_user_data_calls_registered COMMAND agc_driver_compute_user_data_calls_tests --registered)
set_tests_properties(agc_driver_compute_user_data_calls_registered PROPERTIES ENVIRONMENT "ANYPS5_NO_SHADER_CACHE=1" SKIP_RETURN_CODE 77 WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}")
if(WIN32)
set_tests_properties(agc_driver_compute_user_data_calls_registered PROPERTIES ENVIRONMENT_MODIFICATION "PATH=path_list_prepend:$<TARGET_FILE_DIR:libc>")
endif()
endif()
@@ -0,0 +1,3 @@
if(BUILD_TESTING)
agc_add_spirv_mode_tests(agc_driver_constant_store_tests)
endif()
@@ -0,0 +1,3 @@
if(BUILD_TESTING)
agc_add_draw_pipeline_test(agc_driver_copied_writer_copy)
endif()
@@ -0,0 +1,7 @@
if(BUILD_TESTING)
add_test(NAME agc_driver_copied_writer_label_order_drain COMMAND agc_driver_copied_writer_label_order_tests)
set_tests_properties(agc_driver_copied_writer_label_order_drain PROPERTIES ENVIRONMENT "ANYPS5_NO_SHADER_CACHE=1;APS5_DRAIN_COMPLETION_LABELS=1" SKIP_RETURN_CODE 77 WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}" TIMEOUT 30)
if(WIN32)
set_tests_properties(agc_driver_copied_writer_label_order_drain PROPERTIES ENVIRONMENT_MODIFICATION "PATH=path_list_prepend:$<TARGET_FILE_DIR:libc>")
endif()
endif()
@@ -0,0 +1,11 @@
if(BUILD_TESTING)
set_tests_properties(agc_driver_copy_surface_bytes PROPERTIES TIMEOUT 30 ENVIRONMENT "ANYPS5_NO_SHADER_CACHE=1;APS5_SUSPEND_DRAIN=1")
set_property(TEST agc_driver_copy_surface_bytes APPEND PROPERTY ENVIRONMENT_MODIFICATION "APS5_NO_COPY_ALIAS=unset:")
add_test(NAME agc_driver_copy_surface_bytes_no_alias COMMAND agc_driver_copy_surface_bytes_tests)
set_tests_properties(agc_driver_copy_surface_bytes_no_alias PROPERTIES TIMEOUT 30 SKIP_RETURN_CODE 77
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}" ENVIRONMENT "ANYPS5_NO_SHADER_CACHE=1;APS5_SUSPEND_DRAIN=1;APS5_NO_COPY_ALIAS=1")
if(WIN32)
set_tests_properties(agc_driver_copy_surface_bytes_no_alias PROPERTIES ENVIRONMENT_MODIFICATION
"PATH=path_list_prepend:$<TARGET_FILE_DIR:libc>")
endif()
endif()
@@ -0,0 +1 @@
target_include_directories(agc_driver_depth_bounds_emulation_draw_tests PRIVATE $<TARGET_PROPERTY:shader_recompiler_agc_driver,INTERFACE_INCLUDE_DIRECTORIES>)
@@ -0,0 +1,7 @@
if(BUILD_TESTING)
add_test(NAME agc_driver_htile_mask_lifetime COMMAND agc_driver_depth_fast_clear_submit_tests --mask-lifetime)
set_tests_properties(agc_driver_htile_mask_lifetime PROPERTIES TIMEOUT 30 ENVIRONMENT "ANYPS5_NO_SHADER_CACHE=1" SKIP_RETURN_CODE 77 WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}")
if(WIN32)
set_tests_properties(agc_driver_htile_mask_lifetime PROPERTIES ENVIRONMENT_MODIFICATION "PATH=path_list_prepend:$<TARGET_FILE_DIR:libc>")
endif()
endif()
@@ -0,0 +1,25 @@
if(BUILD_TESTING)
add_test(NAME agc_driver_depth_plane_cpu_write_after_page_unwatch COMMAND agc_driver_depth_plane_partial_store_tests --cpu-write-after-page-unwatch)
set_tests_properties(agc_driver_depth_plane_cpu_write_after_page_unwatch PROPERTIES
ENVIRONMENT "ANYPS5_NO_SHADER_CACHE=1" TIMEOUT 30 SKIP_RETURN_CODE 77 WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}")
if(WIN32)
set_tests_properties(agc_driver_depth_plane_cpu_write_after_page_unwatch PROPERTIES ENVIRONMENT_MODIFICATION
"PATH=path_list_prepend:$<TARGET_FILE_DIR:libc>")
endif()
add_test(NAME agc_driver_depth_plane_cpu_write_after_partial_unwatch COMMAND agc_driver_depth_plane_partial_store_tests --cpu-write-after-partial-unwatch)
set_tests_properties(agc_driver_depth_plane_cpu_write_after_partial_unwatch PROPERTIES
ENVIRONMENT "ANYPS5_NO_SHADER_CACHE=1" TIMEOUT 30 SKIP_RETURN_CODE 77 WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}")
if(WIN32)
set_tests_properties(agc_driver_depth_plane_cpu_write_after_partial_unwatch PROPERTIES ENVIRONMENT_MODIFICATION
"PATH=path_list_prepend:$<TARGET_FILE_DIR:libc>")
endif()
add_test(NAME agc_driver_depth_plane_cpu_write_after_memo COMMAND agc_driver_depth_plane_partial_store_tests --cpu-write-after-memo)
set_tests_properties(agc_driver_depth_plane_cpu_write_after_memo PROPERTIES
ENVIRONMENT "ANYPS5_NO_SHADER_CACHE=1" TIMEOUT 30 SKIP_RETURN_CODE 77 WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}")
if(WIN32)
set_tests_properties(agc_driver_depth_plane_cpu_write_after_memo PROPERTIES ENVIRONMENT_MODIFICATION
"PATH=path_list_prepend:$<TARGET_FILE_DIR:libc>")
endif()
add_test(NAME agc_driver_depth_plane_partial_store_unimported COMMAND agc_driver_depth_plane_partial_store_tests)
add_test(NAME agc_driver_depth_plane_partial_store_buffer_copy COMMAND agc_driver_depth_plane_partial_store_tests --buffer-copy)
endif()
@@ -0,0 +1,8 @@
if(BUILD_TESTING)
add_test(NAME agc_driver_depth_plane_sampling_evicting COMMAND agc_driver_depth_plane_sampling_tests --evicting)
set_tests_properties(agc_driver_depth_plane_sampling_evicting PROPERTIES ENVIRONMENT "APS5_DEPTH_PLANE_COPY_MIB=1" SKIP_RETURN_CODE 77 TIMEOUT 120)
if(WIN32)
set_tests_properties(agc_driver_depth_plane_sampling_evicting PROPERTIES ENVIRONMENT_MODIFICATION
"PATH=path_list_prepend:$<TARGET_FILE_DIR:libc>")
endif()
endif()
@@ -0,0 +1 @@
target_include_directories(agc_driver_depth_range_remap_draw_tests PRIVATE $<TARGET_PROPERTY:shader_recompiler_agc_driver,INTERFACE_INCLUDE_DIRECTORIES>)
@@ -0,0 +1,3 @@
if(BUILD_TESTING)
agc_add_draw_pipeline_test(agc_driver_depth_storage_reuse)
endif()
@@ -0,0 +1,16 @@
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_draw_cache_relocation_recipe_verify COMMAND agc_driver_draw_cache_relocation_tests)
set_tests_properties(agc_driver_draw_cache_relocation_recipe_verify PROPERTIES
ENVIRONMENT "ANYPS5_NO_SHADER_CACHE=1;APS5_VERIFY_DRAW_RECIPE=1;APS5_PIPELINED_DRAWS=0" SKIP_RETURN_CODE 77 TIMEOUT 60 WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}")
add_test(NAME agc_driver_draw_cache_relocation_evicted COMMAND agc_driver_draw_cache_relocation_tests --evicted)
add_test(NAME agc_driver_draw_cache_relocation_kept COMMAND agc_driver_draw_cache_relocation_tests --kept)
set_tests_properties(agc_driver_draw_cache_relocation_evicted agc_driver_draw_cache_relocation_kept PROPERTIES
ENVIRONMENT "ANYPS5_NO_SHADER_CACHE=1;APS5_DRAW_CACHE_ENTRIES=2" SKIP_RETURN_CODE 77 WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}")
if(WIN32)
set_tests_properties(agc_driver_draw_cache_relocation_recipe_verify agc_driver_draw_cache_relocation_evicted agc_driver_draw_cache_relocation_kept PROPERTIES ENVIRONMENT_MODIFICATION
"PATH=path_list_prepend:$<TARGET_FILE_DIR:libc>")
endif()
agc_add_draw_pipeline_test(agc_driver_draw_cache_relocation)
endif()
@@ -0,0 +1,28 @@
if(BUILD_TESTING)
agc_add_draw_pipeline_test(agc_driver_draw_cache_reuse)
agc_add_draw_pipeline_test(agc_driver_draw_data_hit_user_words)
add_test(NAME agc_driver_draw_cache_reuse_off COMMAND agc_driver_draw_cache_reuse_tests)
set_tests_properties(agc_driver_draw_cache_reuse_off PROPERTIES ENVIRONMENT "ANYPS5_NO_SHADER_CACHE=1;APS5_NO_GPL=1" SKIP_RETURN_CODE 77)
add_test(NAME agc_driver_draw_cache_reuse_verify COMMAND agc_driver_draw_cache_reuse_tests)
set_tests_properties(agc_driver_draw_cache_reuse_verify PROPERTIES ENVIRONMENT "ANYPS5_NO_SHADER_CACHE=1;APS5_VERIFY_DRAW_DATA_HITS=1" SKIP_RETURN_CODE 77)
add_test(NAME agc_driver_draw_cache_reuse_entry_verify COMMAND agc_driver_draw_cache_reuse_tests)
set_tests_properties(agc_driver_draw_cache_reuse_entry_verify PROPERTIES ENVIRONMENT "ANYPS5_NO_SHADER_CACHE=1;APS5_VERIFY_DRAW_ENTRIES=1" SKIP_RETURN_CODE 77 FAIL_REGULAR_EXPRESSION "FATAL:")
if(WIN32)
set_tests_properties(agc_driver_draw_cache_reuse_entry_verify PROPERTIES ENVIRONMENT_MODIFICATION
"PATH=path_list_prepend:$<TARGET_FILE_DIR:libc>")
endif()
add_test(NAME agc_driver_draw_cache_reuse_inline COMMAND agc_driver_draw_cache_reuse_tests)
set_tests_properties(agc_driver_draw_cache_reuse_inline PROPERTIES ENVIRONMENT "ANYPS5_NO_SHADER_CACHE=1;APS5_PIPELINED_DRAWS=0;APS5_VERIFY_DRAW_RECIPE=1;APS5_VERIFY_REGISTER_KEYS=1" SKIP_RETURN_CODE 77)
add_test(NAME agc_driver_draw_cache_reuse_indirect COMMAND agc_driver_draw_cache_reuse_tests)
set_tests_properties(agc_driver_draw_cache_reuse_indirect PROPERTIES ENVIRONMENT "ANYPS5_NO_SHADER_CACHE=1;APS5_DRAW_CACHE_INDIRECT=1;APS5_PROFILE_DRAW=1" SKIP_RETURN_CODE 77)
set_tests_properties(agc_driver_draw_cache_reuse agc_driver_draw_cache_reuse_off agc_driver_draw_cache_reuse_verify agc_driver_draw_cache_reuse_inline agc_driver_draw_cache_reuse_indirect PROPERTIES FAIL_REGULAR_EXPRESSION "FATAL:")
set_property(TEST agc_driver_draw_cache_reuse agc_driver_draw_cache_reuse_off APPEND PROPERTY ENVIRONMENT "APS5_VERIFY_DRAW_RECIPE=1" "APS5_VERIFY_REGISTER_KEYS=1")
add_test(NAME agc_driver_draw_data_hit_user_words_verify COMMAND agc_driver_draw_data_hit_user_words_tests)
set_tests_properties(agc_driver_draw_data_hit_user_words_verify PROPERTIES ENVIRONMENT "APS5_VERIFY_DRAW_DATA_HITS=1" SKIP_RETURN_CODE 77)
add_test(NAME agc_driver_draw_data_hit_user_words_refresh COMMAND agc_driver_draw_data_hit_user_words_tests)
set_tests_properties(agc_driver_draw_data_hit_user_words_refresh PROPERTIES ENVIRONMENT "APS5_DRAW_PIPELINE=1" SKIP_RETURN_CODE 77)
if(WIN32)
set_tests_properties(agc_driver_draw_cache_reuse_off agc_driver_draw_cache_reuse_verify agc_driver_draw_cache_reuse_inline agc_driver_draw_cache_reuse_indirect agc_driver_draw_data_hit_user_words_verify agc_driver_draw_data_hit_user_words_refresh PROPERTIES ENVIRONMENT_MODIFICATION
"PATH=path_list_prepend:$<TARGET_FILE_DIR:libc>")
endif()
endif()
@@ -0,0 +1,19 @@
if(BUILD_TESTING)
add_test_executable(agc_driver_draw_program_trace_tests
tests/DrawProgramTrace.cpp
Execution/src/Driver/Draw/DrawProgramTrace.cpp
)
target_include_directories(agc_driver_draw_program_trace_tests PRIVATE
${LIBS_INCLUDE_DIR}
${CMAKE_SOURCE_DIR}/core/shader/recompiler
)
set_target_properties(agc_driver_draw_program_trace_tests PROPERTIES CXX_EXTENSIONS OFF)
configure_windows_unwind(agc_driver_draw_program_trace_tests)
add_test(NAME agc_driver_draw_program_trace COMMAND agc_driver_draw_program_trace_tests)
set_tests_properties(agc_driver_draw_program_trace PROPERTIES TIMEOUT 20)
if(MINGW)
target_link_libraries(agc_driver_draw_program_trace_tests PRIVATE libc)
set_tests_properties(agc_driver_draw_program_trace PROPERTIES ENVIRONMENT_MODIFICATION
"PATH=path_list_prepend:$<TARGET_FILE_DIR:libc>")
endif()
endif()
@@ -0,0 +1,24 @@
if(BUILD_TESTING)
set(agcDrawShaderFailureTraceDirectory ${CMAKE_CURRENT_BINARY_DIR}/draw_shader_failure_tests)
file(MAKE_DIRECTORY "${agcDrawShaderFailureTraceDirectory}/failure")
file(MAKE_DIRECTORY "${agcDrawShaderFailureTraceDirectory}/success")
file(MAKE_DIRECTORY "${agcDrawShaderFailureTraceDirectory}/disabled")
file(MAKE_DIRECTORY "${agcDrawShaderFailureTraceDirectory}/failure_correlation_disabled")
set_tests_properties(agc_driver_draw_shader_failure PROPERTIES ENVIRONMENT "ANYPS5_NO_SHADER_CACHE=1;APS5_CAPTURE_TRACE=1;APS5_TRACE_SHADER_CORRELATION=1;APS5_CAPTURE_TRACE_PATH=${agcDrawShaderFailureTraceDirectory}/failure/trace.log" SKIP_RETURN_CODE 77 WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}")
add_test(NAME agc_driver_draw_shader_failure_successful COMMAND agc_driver_draw_shader_failure_tests successful-draw)
set_tests_properties(agc_driver_draw_shader_failure_successful PROPERTIES ENVIRONMENT "ANYPS5_NO_SHADER_CACHE=1;APS5_CAPTURE_TRACE=1;APS5_TRACE_SHADER_CORRELATION=1;APS5_CAPTURE_TRACE_PATH=${agcDrawShaderFailureTraceDirectory}/success/trace.log" SKIP_RETURN_CODE 77 WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}")
add_test(NAME agc_driver_draw_shader_failure_correlation_disabled COMMAND agc_driver_draw_shader_failure_tests disabled-correlation)
set_tests_properties(agc_driver_draw_shader_failure_correlation_disabled PROPERTIES ENVIRONMENT "ANYPS5_NO_SHADER_CACHE=1;APS5_CAPTURE_TRACE=1;APS5_CAPTURE_TRACE_PATH=${agcDrawShaderFailureTraceDirectory}/disabled/trace.log" SKIP_RETURN_CODE 77 WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}")
add_test(NAME agc_driver_draw_shader_failure_request_correlation_disabled COMMAND agc_driver_draw_shader_failure_tests request-failure-correlation-disabled)
set_tests_properties(agc_driver_draw_shader_failure_request_correlation_disabled PROPERTIES ENVIRONMENT "ANYPS5_NO_SHADER_CACHE=1;APS5_CAPTURE_TRACE=1;APS5_CAPTURE_TRACE_PATH=${agcDrawShaderFailureTraceDirectory}/failure_correlation_disabled/trace.log" SKIP_RETURN_CODE 77 WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}")
file(MAKE_DIRECTORY "${agcDrawShaderFailureTraceDirectory}/materialization")
file(MAKE_DIRECTORY "${agcDrawShaderFailureTraceDirectory}/materialization_correlation_disabled")
add_test(NAME agc_driver_draw_shader_failure_materialization COMMAND agc_driver_draw_shader_failure_tests materialization-failure)
set_tests_properties(agc_driver_draw_shader_failure_materialization PROPERTIES ENVIRONMENT "ANYPS5_NO_SHADER_CACHE=1;APS5_CAPTURE_TRACE=1;APS5_TRACE_SHADER_CORRELATION=1;APS5_CAPTURE_TRACE_PATH=${agcDrawShaderFailureTraceDirectory}/materialization/trace.log" SKIP_RETURN_CODE 77 WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}")
add_test(NAME agc_driver_draw_shader_failure_materialization_correlation_disabled COMMAND agc_driver_draw_shader_failure_tests materialization-failure-correlation-disabled)
set_tests_properties(agc_driver_draw_shader_failure_materialization_correlation_disabled PROPERTIES ENVIRONMENT "ANYPS5_NO_SHADER_CACHE=1;APS5_CAPTURE_TRACE=1;APS5_CAPTURE_TRACE_PATH=${agcDrawShaderFailureTraceDirectory}/materialization_correlation_disabled/trace.log" SKIP_RETURN_CODE 77 WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}")
if(WIN32)
set_tests_properties(agc_driver_draw_shader_failure agc_driver_draw_shader_failure_successful agc_driver_draw_shader_failure_correlation_disabled agc_driver_draw_shader_failure_request_correlation_disabled agc_driver_draw_shader_failure_materialization agc_driver_draw_shader_failure_materialization_correlation_disabled PROPERTIES ENVIRONMENT_MODIFICATION
"PATH=path_list_prepend:$<TARGET_FILE_DIR:libc>")
endif()
endif()
@@ -0,0 +1,10 @@
if(BUILD_TESTING)
add_test(NAME agc_driver_draw_unsupported_buffer_type_skip_refused COMMAND agc_driver_draw_unsupported_buffer_type_tests --skip-refused)
set_tests_properties(agc_driver_draw_unsupported_buffer_type_skip_refused PROPERTIES
ENVIRONMENT "ANYPS5_NO_SHADER_CACHE=1;APS5_SKIP_REFUSED_DRAWS=1" SKIP_RETURN_CODE 77 TIMEOUT 30 WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}")
if(WIN32)
set_tests_properties(agc_driver_draw_unsupported_buffer_type_skip_refused PROPERTIES ENVIRONMENT_MODIFICATION
"PATH=path_list_prepend:$<TARGET_FILE_DIR:libc>")
endif()
agc_add_draw_pipeline_test(agc_driver_draw_unsupported_buffer_type)
endif()
@@ -0,0 +1,3 @@
if(BUILD_TESTING)
agc_add_draw_pipeline_test(agc_driver_draw_write_ranges)
endif()
@@ -0,0 +1 @@
target_include_directories(agc_driver_dual_source_blend_tests PRIVATE $<TARGET_PROPERTY:shader_recompiler_agc_driver,INTERFACE_INCLUDE_DIRECTORIES>)
@@ -0,0 +1,8 @@
if(BUILD_TESTING)
add_test(NAME agc_driver_dword_pattern_fill_translated COMMAND agc_driver_dword_pattern_fill_tests)
set_tests_properties(agc_driver_dword_pattern_fill_translated PROPERTIES ENVIRONMENT "ANYPS5_NO_SHADER_CACHE=1;APS5_NO_FILL_HLE=1" SKIP_RETURN_CODE 77 WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}" TIMEOUT 30)
if(WIN32)
set_tests_properties(agc_driver_dword_pattern_fill_translated PROPERTIES ENVIRONMENT_MODIFICATION
"PATH=path_list_prepend:$<TARGET_FILE_DIR:libc>")
endif()
endif()
@@ -0,0 +1,11 @@
if(BUILD_TESTING)
add_test(NAME agc_driver_emulated_color_compare_srgb_decode COMMAND agc_driver_emulated_color_compare_tests)
set_tests_properties(agc_driver_emulated_color_compare_srgb_decode PROPERTIES
ENVIRONMENT "ANYPS5_NO_SHADER_CACHE=1;APS5_SRGB_SHADER_DECODE=1"
SKIP_RETURN_CODE 77 WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}")
set_tests_properties(agc_driver_emulated_color_compare agc_driver_emulated_color_compare_srgb_decode PROPERTIES TIMEOUT 30)
if(WIN32)
set_tests_properties(agc_driver_emulated_color_compare_srgb_decode PROPERTIES ENVIRONMENT_MODIFICATION
"PATH=path_list_prepend:$<TARGET_FILE_DIR:libc>")
endif()
endif()
@@ -0,0 +1,7 @@
if(BUILD_TESTING)
add_test(NAME agc_driver_f16_to_f32_unpack_spirv COMMAND agc_driver_f16_to_f32_unpack_tests --verify-spirv)
set_tests_properties(agc_driver_f16_to_f32_unpack_spirv PROPERTIES ENVIRONMENT "ANYPS5_NO_SHADER_CACHE=1" SKIP_RETURN_CODE 77 WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}")
if(WIN32)
set_tests_properties(agc_driver_f16_to_f32_unpack_spirv PROPERTIES ENVIRONMENT_MODIFICATION "PATH=path_list_prepend:$<TARGET_FILE_DIR:libc>")
endif()
endif()
@@ -0,0 +1,7 @@
if(BUILD_TESTING)
add_test(NAME agc_driver_f64_denorm_preserve_spirv COMMAND agc_driver_f64_fma_subnormals_tests --verify-spv-denorm-mode)
set_tests_properties(agc_driver_f64_denorm_preserve_spirv PROPERTIES ENVIRONMENT "ANYPS5_NO_SHADER_CACHE=1" SKIP_RETURN_CODE 77 WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}")
if(WIN32)
set_tests_properties(agc_driver_f64_denorm_preserve_spirv PROPERTIES ENVIRONMENT_MODIFICATION "PATH=path_list_prepend:$<TARGET_FILE_DIR:libc>")
endif()
endif()
@@ -0,0 +1 @@
target_include_directories(agc_driver_failed_capture_dump_tests PRIVATE $<TARGET_PROPERTY:shader_recompiler_agc_driver,INTERFACE_INCLUDE_DIRECTORIES>)
@@ -0,0 +1,3 @@
if(BUILD_TESTING)
agc_add_draw_pipeline_test(agc_driver_finisher_label_order)
endif()
@@ -0,0 +1,11 @@
if(BUILD_TESTING)
set_target_properties(agc_driver_flat_apertures_tests PROPERTIES EXCLUDE_FROM_ALL OFF)
foreach(flatAperturesPart RANGE 13)
add_test(NAME agc_driver_flat_apertures_${flatAperturesPart} COMMAND agc_driver_flat_apertures_tests --part ${flatAperturesPart}/14)
set_tests_properties(agc_driver_flat_apertures_${flatAperturesPart} PROPERTIES ENVIRONMENT "ANYPS5_NO_SHADER_CACHE=1" SKIP_RETURN_CODE 77 WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}")
if(WIN32)
set_tests_properties(agc_driver_flat_apertures_${flatAperturesPart} PROPERTIES ENVIRONMENT_MODIFICATION
"PATH=path_list_prepend:$<TARGET_FILE_DIR:libc>")
endif()
endforeach()
endif()
@@ -0,0 +1,3 @@
if(BUILD_TESTING)
set_tests_properties(agc_driver_flat_store PROPERTIES RUN_SERIAL TRUE)
endif()
@@ -0,0 +1,29 @@
add_test_executable(agc_driver_flip_tests EXCLUDE_FROM_ALL
tests/Flip.cpp
)
target_include_directories(agc_driver_flip_tests PRIVATE
${LIBS_INCLUDE_DIR}
${CMAKE_SOURCE_DIR}/3rdparty/Vulkan-Headers/include
)
target_link_libraries(agc_driver_flip_tests PRIVATE
libSceAgcDriver
libc
)
set_target_properties(agc_driver_flip_tests PROPERTIES CXX_EXTENSIONS OFF)
configure_windows_unwind(agc_driver_flip_tests)
if(BUILD_TESTING)
agc_add_default_test(agc_driver_flip_tests)
add_test(NAME agc_driver_present_mode COMMAND agc_driver_flip_tests present-mode)
add_test(NAME agc_driver_worker_failure_log COMMAND agc_driver_flip_tests failure-log)
set_tests_properties(agc_driver_worker_failure_log PROPERTIES ENVIRONMENT "ANYPS5_NO_SHADER_CACHE=1" SKIP_RETURN_CODE 77 TIMEOUT 20)
add_test(NAME agc_driver_flip_compute COMMAND agc_driver_flip_tests compute)
set_tests_properties(agc_driver_flip_compute PROPERTIES ENVIRONMENT "ANYPS5_NO_SHADER_CACHE=1" SKIP_RETURN_CODE 77)
if(WIN32)
set_tests_properties(agc_driver_flip_compute agc_driver_present_mode agc_driver_worker_failure_log PROPERTIES ENVIRONMENT_MODIFICATION
"PATH=path_list_prepend:$<TARGET_FILE_DIR:libc>")
endif()
endif()
@@ -0,0 +1,17 @@
if(BUILD_TESTING)
if(WIN32 OR CMAKE_SYSTEM_NAME STREQUAL "Linux")
add_test_executable(agc_driver_frame_capture_eop_tests tests/FrameCaptureEop.cpp Execution/src/FrameCapture.cpp)
target_include_directories(agc_driver_frame_capture_eop_tests PRIVATE ${LIBS_INCLUDE_DIR} ${CMAKE_SOURCE_DIR}/core/shader/recompiler ${ANYPS5_VULKAN_HEADERS_INCLUDE_DIR} ${ANYPS5_SPIRV_HEADERS_INCLUDE_DIR})
target_link_libraries(agc_driver_frame_capture_eop_tests PRIVATE libSceAgcDriver libkernel libc libzstd_static)
set_target_properties(agc_driver_frame_capture_eop_tests PROPERTIES CXX_EXTENSIONS OFF)
configure_windows_unwind(agc_driver_frame_capture_eop_tests)
add_test(NAME agc_driver_frame_capture_eop COMMAND agc_driver_frame_capture_eop_tests)
set_tests_properties(agc_driver_frame_capture_eop PROPERTIES
ENVIRONMENT "ANYPS5_NO_SHADER_CACHE=1;APS5_FRAME_CAPTURE=${CMAKE_CURRENT_BINARY_DIR}/frame-capture-eop;APS5_FRAME_CAPTURE_AT_FLIP=1;APS5_FRAME_CAPTURE_FRAMES=3"
TIMEOUT 120)
if(WIN32)
set_tests_properties(agc_driver_frame_capture_eop PROPERTIES ENVIRONMENT_MODIFICATION
"PATH=path_list_prepend:$<TARGET_FILE_DIR:libc>")
endif()
endif()
endif()
@@ -0,0 +1,34 @@
if(BUILD_TESTING)
add_test_executable(agc_driver_frame_replay_state_tests tests/FrameReplayState.cpp Execution/src/FrameCapture.cpp)
target_include_directories(agc_driver_frame_replay_state_tests PRIVATE ${LIBS_INCLUDE_DIR})
target_link_libraries(agc_driver_frame_replay_state_tests PRIVATE libSceAgcDriver libkernel libc libzstd_static)
set_target_properties(agc_driver_frame_replay_state_tests PROPERTIES CXX_EXTENSIONS OFF)
configure_windows_unwind(agc_driver_frame_replay_state_tests)
set(agcFrameReplayModes order tokens blocking)
if(WIN32 OR CMAKE_SYSTEM_NAME STREQUAL "Linux")
list(APPEND agcFrameReplayModes zero shader shader_host)
endif()
if(WIN32 OR CMAKE_SYSTEM_NAME STREQUAL "Linux")
list(APPEND agcFrameReplayModes unwatched)
endif()
if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
list(APPEND agcFrameReplayModes shared_page host_neighbors)
endif()
foreach(mode IN LISTS agcFrameReplayModes)
set(capture "${CMAKE_CURRENT_BINARY_DIR}/frame-replay-${mode}")
add_test(NAME agc_driver_frame_replay_${mode} COMMAND agc_driver_frame_replay_state_tests ${mode} "${capture}")
set_tests_properties(agc_driver_frame_replay_${mode} PROPERTIES TIMEOUT 30)
if(mode MATCHES "^shader")
set_tests_properties(agc_driver_frame_replay_${mode} PROPERTIES ENVIRONMENT
"APS5_FRAME_CAPTURE=${capture};APS5_FRAME_CAPTURE_AT_FLIP=1;APS5_FRAME_CAPTURE_FRAMES=1")
endif()
if(mode STREQUAL "unwatched")
set_tests_properties(agc_driver_frame_replay_${mode} PROPERTIES ENVIRONMENT
"APS5_NO_WRITE_WATCH=1;APS5_FRAME_CAPTURE=${capture};APS5_FRAME_CAPTURE_AT_FLIP=1;APS5_FRAME_CAPTURE_FRAMES=1")
endif()
if(WIN32)
set_tests_properties(agc_driver_frame_replay_${mode} PROPERTIES ENVIRONMENT_MODIFICATION
"PATH=path_list_prepend:$<TARGET_FILE_DIR:libc>")
endif()
endforeach()
endif()
@@ -0,0 +1,26 @@
if(BUILD_TESTING)
if(WIN32 OR CMAKE_SYSTEM_NAME STREQUAL "Linux")
add_test_executable(agc_driver_frame_replay_tests tests/FrameReplay.cpp Execution/src/FrameCapture.cpp)
target_include_directories(agc_driver_frame_replay_tests PRIVATE ${LIBS_INCLUDE_DIR})
target_link_libraries(agc_driver_frame_replay_tests PRIVATE libSceAgc libSceAgcDriver libkernel libc libzstd_static)
set_target_properties(agc_driver_frame_replay_tests PROPERTIES CXX_EXTENSIONS OFF)
configure_windows_unwind(agc_driver_frame_replay_tests)
add_dependencies(agc_driver_frame_replay_tests agc_frame_replay)
add_test(NAME agc_driver_frame_replay COMMAND agc_driver_frame_replay_tests $<TARGET_FILE:agc_frame_replay>)
set_tests_properties(agc_driver_frame_replay PROPERTIES
ENVIRONMENT "ANYPS5_NO_SHADER_CACHE=1;APS5_FRAME_CAPTURE=${CMAKE_CURRENT_BINARY_DIR}/frame-replay-capture;APS5_FRAME_CAPTURE_AT_FLIP=1;APS5_FRAME_CAPTURE_FRAMES=2"
TIMEOUT 120)
if(WIN32)
set_tests_properties(agc_driver_frame_replay PROPERTIES ENVIRONMENT_MODIFICATION
"PATH=path_list_prepend:$<TARGET_FILE_DIR:libc>")
endif()
add_test(NAME agc_driver_frame_replay_concurrent COMMAND agc_driver_frame_replay_tests $<TARGET_FILE:agc_frame_replay> concurrent)
set_tests_properties(agc_driver_frame_replay_concurrent PROPERTIES
ENVIRONMENT "ANYPS5_NO_SHADER_CACHE=1;APS5_FRAME_CAPTURE=${CMAKE_CURRENT_BINARY_DIR}/frame-replay-concurrent-capture;APS5_FRAME_CAPTURE_AT_FLIP=1;APS5_FRAME_CAPTURE_FRAMES=8"
TIMEOUT 120)
if(WIN32)
set_tests_properties(agc_driver_frame_replay_concurrent PROPERTIES ENVIRONMENT_MODIFICATION
"PATH=path_list_prepend:$<TARGET_FILE_DIR:libc>")
endif()
endif()
endif()
@@ -0,0 +1,11 @@
if(BUILD_TESTING)
agc_add_draw_pipeline_test(agc_driver_gated_dispatch_capture)
add_test(NAME agc_driver_gated_dispatch_capture_short_timeout COMMAND agc_driver_gated_dispatch_capture_tests)
set_tests_properties(agc_driver_gated_dispatch_capture_short_timeout PROPERTIES
ENVIRONMENT "ANYPS5_NO_SHADER_CACHE=1;APS5_GPU_WAIT_TIMEOUT_MS=1;APS5_NO_PIPELINE_LTO=1"
SKIP_RETURN_CODE 77 TIMEOUT 30 WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}")
if(WIN32)
set_tests_properties(agc_driver_gated_dispatch_capture_short_timeout PROPERTIES ENVIRONMENT_MODIFICATION
"PATH=path_list_prepend:$<TARGET_FILE_DIR:libc>")
endif()
endif()
@@ -0,0 +1 @@
target_include_directories(agc_driver_gcn_buffer_format_lookup_tests PRIVATE $<TARGET_PROPERTY:shader_recompiler_agc_driver,INTERFACE_INCLUDE_DIRECTORIES>)
Loaded 100 of 677 files, more files were not shown because too many files have changed in this diff. Show more