diff --git a/3rdparty/SPIRV-Headers b/3rdparty/SPIRV-Headers index b824a462d4..01e0577914 160000 --- a/3rdparty/SPIRV-Headers +++ b/3rdparty/SPIRV-Headers @@ -1 +1 @@ -Subproject commit b824a462d4256d720bebb40e78b9eb8f78bbb305 +Subproject commit 01e0577914a75a2569c846778c2f93aa8e6feddd diff --git a/3rdparty/SPIRV-Tools b/3rdparty/SPIRV-Tools index 262bdab481..7f2d9ee926 160000 --- a/3rdparty/SPIRV-Tools +++ b/3rdparty/SPIRV-Tools @@ -1 +1 @@ -Subproject commit 262bdab48146c937467f826699a40da0fdfc0f1a +Subproject commit 7f2d9ee926f98fc77a3ed1e1e0f113b8c9c49458 diff --git a/core/libs/prx/libSceAgcDriver/Execution/include/Driver/Driver.hpp b/core/libs/prx/libSceAgcDriver/Execution/include/Driver/Driver.hpp index 4c458de865..75c47c8e6d 100644 --- a/core/libs/prx/libSceAgcDriver/Execution/include/Driver/Driver.hpp +++ b/core/libs/prx/libSceAgcDriver/Execution/include/Driver/Driver.hpp @@ -35,6 +35,7 @@ #include #include #include +#include #include #include #include @@ -67,7 +68,7 @@ public: void SettleShaderPreparations(std::span stages); static void FoldDrawOffsets(const ShaderRecompiler::RecompileResult& result, const DrawProgram& program, Pm4::DrawParameters& parameters); static std::optional ClassifyIndirectDraw(const ShaderRecompiler::RecompileResult& result, const Graphics::State& graphics, const DrawProgram& frontProgram, const std::shared_ptr& localDevice, Pm4::DrawParameters& drawParameters, bool traceIndirect); - static std::string dumpRequest(std::uint64_t address, const ShaderRecompiler::RecompileRequest& request); + static std::string dumpRequest(std::uint64_t address, const ShaderRecompiler::RecompileRequest& request, std::string_view suffix = {}); DrawEntryCounters DrawCacheCounters(); struct DispatchCacheFootprint { std::size_t entries = 0; diff --git a/core/libs/prx/libSceAgcDriver/Execution/src/Driver/Shaders/ShaderDiagnostics.cpp b/core/libs/prx/libSceAgcDriver/Execution/src/Driver/Shaders/ShaderDiagnostics.cpp index 5fac827511..52f65cc2d0 100644 --- a/core/libs/prx/libSceAgcDriver/Execution/src/Driver/Shaders/ShaderDiagnostics.cpp +++ b/core/libs/prx/libSceAgcDriver/Execution/src/Driver/Shaders/ShaderDiagnostics.cpp @@ -49,16 +49,17 @@ void Driver::reportSkip(const char* kind, const std::string& what) { if (!line.empty()) std::fwrite(line.data(), 1, line.size(), stderr); } -std::string Driver::dumpRequest(std::uint64_t address, const ShaderRecompiler::RecompileRequest& request) { +std::string Driver::dumpRequest(std::uint64_t address, const ShaderRecompiler::RecompileRequest& request, std::string_view suffix) { static std::mutex dumpMutex; - static std::set dumped; - char name[64]; - std::snprintf(name, sizeof(name), "shader_%llx.req", static_cast(address)); + static std::set dumped; + char hex[32]; + std::snprintf(hex, sizeof(hex), "%llx", static_cast(address)); + const std::string name = "shader_" + std::string(hex) + std::string(suffix) + ".req"; std::lock_guard lock(dumpMutex); - if (!dumped.insert(address).second) return name; + if (!dumped.insert(name).second) return name; try { const auto text = ShaderRecompiler::RequestSerializer{}.Serialize(request); - if (std::FILE* file = std::fopen(name, "wb")) { + if (std::FILE* file = std::fopen(name.c_str(), "wb")) { std::fwrite(text.data(), 1, text.size(), file); std::fclose(file); } diff --git a/core/libs/prx/libSceAgcDriver/Execution/src/Driver/Shaders/ShaderRegistry.cpp b/core/libs/prx/libSceAgcDriver/Execution/src/Driver/Shaders/ShaderRegistry.cpp index abfd695545..1f109fa409 100644 --- a/core/libs/prx/libSceAgcDriver/Execution/src/Driver/Shaders/ShaderRegistry.cpp +++ b/core/libs/prx/libSceAgcDriver/Execution/src/Driver/Shaders/ShaderRegistry.cpp @@ -53,7 +53,7 @@ std::shared_ptr PrepareShaderWithDiagnosti } catch (...) { failure = std::current_exception(); try { - if (std::getenv("APS5_DUMP_SHADERS") != nullptr) dump = Driver::dumpRequest(request.shader.codeAddress, request); + if (std::getenv("APS5_DUMP_SHADERS") != nullptr) dump = Driver::dumpRequest(request.shader.codeAddress, request, ".prepare"); } catch (...) {} } try { diff --git a/core/libs/prx/libSceAgcDriver/tests/execution/PreparedShaders.cpp b/core/libs/prx/libSceAgcDriver/tests/execution/PreparedShaders.cpp index e242f0a0b9..544b856619 100644 --- a/core/libs/prx/libSceAgcDriver/tests/execution/PreparedShaders.cpp +++ b/core/libs/prx/libSceAgcDriver/tests/execution/PreparedShaders.cpp @@ -1,6 +1,7 @@ #include "VulkanTestDevice.hpp" #include "Optimization/ResourceProgram.hpp" #include "ControlFlow/RequestSerializer.hpp" +#include "prx/libSceAgcDriver/Execution/include/Driver/Driver.hpp" #include "prx/libSceAgcDriver/Execution/include/Driver/Shaders/ShaderRegistry.hpp" #include "prx/libSceAgcDriver/Graphics/include/ShaderInputState.hpp" #include "prx/libSceAgcDriver/Execution/include/Driver.hpp" @@ -202,8 +203,10 @@ void FailureCapture(AgcDriver::VulkanDevice& device) { const auto expected = failure([&] { static_cast(PrepareShader(request)); }); const char* previous = std::getenv("APS5_DUMP_SHADERS"); const std::string saved = previous != nullptr ? previous : ""; - const std::string path = "shader_12345cafe.req"; + const std::string path = "shader_12345cafe.prepare.req"; + const std::string capturePath = "shader_12345cafe.req"; std::remove(path.c_str()); + std::remove(capturePath.c_str()); #ifdef _WIN32 Require(_putenv_s("APS5_DUMP_SHADERS", "") == 0, "cannot disable shader capture"); #else @@ -224,6 +227,14 @@ void FailureCapture(AgcDriver::VulkanDevice& device) { std::ostringstream dumpedPrefix; dumpedPrefix << "shader 0x" << std::hex << request.shader.codeAddress << " stage " << static_cast(request.shader.stage) << " (" << path << "): "; Require(actual == dumpedPrefix.str() + expected, "enabled shader capture changed the diagnosed failure"); + Require(!std::ifstream(capturePath, std::ios::binary).is_open(), "a preparation failure was dumped as a dispatch request"); + Require(AgcDriver::DriverDetail::Driver::dumpRequest(request.shader.codeAddress, request) == capturePath, "a dispatch request dump has the wrong name"); + std::ifstream capture(capturePath, std::ios::binary); + std::ostringstream captureText; + captureText << capture.rdbuf(); + capture.close(); + std::remove(capturePath.c_str()); + Require(captureText.str() == RequestSerializer{}.Serialize(request), "an earlier preparation failure dump suppressed the dispatch request dump"); #ifdef _WIN32 Require(_putenv_s("APS5_DUMP_SHADERS", saved.c_str()) == 0, "cannot restore shader capture"); #else diff --git a/core/libs/prx/libSceAgcDriver/tools/ShaderReplay.cpp b/core/libs/prx/libSceAgcDriver/tools/ShaderReplay.cpp index 2e7d97c327..37c6491ec4 100644 --- a/core/libs/prx/libSceAgcDriver/tools/ShaderReplay.cpp +++ b/core/libs/prx/libSceAgcDriver/tools/ShaderReplay.cpp @@ -184,7 +184,7 @@ bool Replay(const char* path) { int main(int argc, char** argv) { if (argc < 2) { - std::fprintf(stderr, "usage: agc_shader_replay [--dis] [--asm] [--cfg] [--mem] [--spv] [--prepare] [--materialize] [--code] [--maintenance8] [--robust2] ...\n the driver writes shader_
.req files when APS5_DUMP_SHADERS is set\n"); + std::fprintf(stderr, "usage: agc_shader_replay [--dis] [--asm] [--cfg] [--mem] [--spv] [--prepare] [--materialize] [--code] [--maintenance8] [--robust2] ...\n the driver writes shader_
.req files when APS5_DUMP_SHADERS is set; shader_
.prepare.req holds a request whose preparation failed before any resource capture, so replay it with --prepare\n"); return 2; } int failures = 0;