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 ad9c4f949..55c09e78c 100644 --- a/core/libs/prx/libSceAgcDriver/Execution/src/Driver/Shaders/ShaderRegistry.cpp +++ b/core/libs/prx/libSceAgcDriver/Execution/src/Driver/Shaders/ShaderRegistry.cpp @@ -19,10 +19,12 @@ #include #include #include +#include #include #include #include #include +#include #include #include #include "RdnaDecoder/RdnaInstructionDecoder.hpp" @@ -30,14 +32,25 @@ namespace AgcDriver::DriverDetail { std::shared_ptr PrepareShaderWithDiagnostics(const ShaderRecompiler::RecompileRequest& request, ShaderRecompiler::ShaderPreparationContext* preparation) { + std::exception_ptr failure; + std::string dump; try { auto handle = ShaderRecompiler::PrepareShader(request, preparation); return handle; } catch (...) { + failure = std::current_exception(); try { - if (std::getenv("APS5_DUMP_SHADERS") != nullptr) static_cast(Driver::dumpRequest(request.shader.codeAddress, request)); + if (std::getenv("APS5_DUMP_SHADERS") != nullptr) dump = Driver::dumpRequest(request.shader.codeAddress, request); } catch (...) {} - throw; + } + try { + std::rethrow_exception(failure); + } catch (const std::exception& error) { + std::ostringstream where; + where << "shader 0x" << std::hex << request.shader.codeAddress << " stage " << static_cast(request.shader.stage); + if (!dump.empty()) where << " (" << dump << ")"; + where << ": "; + throw std::runtime_error(where.str() + error.what()); } } diff --git a/core/libs/prx/libSceAgcDriver/tests/execution/PreparedShaders.cpp b/core/libs/prx/libSceAgcDriver/tests/execution/PreparedShaders.cpp index ed91e5570..e34258828 100644 --- a/core/libs/prx/libSceAgcDriver/tests/execution/PreparedShaders.cpp +++ b/core/libs/prx/libSceAgcDriver/tests/execution/PreparedShaders.cpp @@ -200,7 +200,11 @@ void FailureCapture(AgcDriver::VulkanDevice& device) { #else Require(unsetenv("APS5_DUMP_SHADERS") == 0, "cannot disable shader capture"); #endif - Require(failure([&] { static_cast(AgcDriver::DriverDetail::PrepareShaderWithDiagnostics(request)); }) == expected, "disabled shader capture changed the preparation failure"); + std::ostringstream prefix; + prefix << "shader 0x" << std::hex << request.shader.codeAddress << " stage " << static_cast(request.shader.stage) << ": "; + const auto diagnosed = failure([&] { static_cast(AgcDriver::DriverDetail::PrepareShaderWithDiagnostics(request)); }); + Require(diagnosed.rfind(prefix.str(), 0) == 0, "diagnosed failure names no shader address and stage"); + Require(diagnosed.substr(prefix.str().size()) == expected, "diagnosed failure changed the reason"); Require(!std::ifstream(path, std::ios::binary).is_open(), "disabled shader capture created a request"); #ifdef _WIN32 Require(_putenv_s("APS5_DUMP_SHADERS", "1") == 0, "cannot enable shader capture"); @@ -208,12 +212,14 @@ void FailureCapture(AgcDriver::VulkanDevice& device) { Require(setenv("APS5_DUMP_SHADERS", "1", 1) == 0, "cannot enable shader capture"); #endif const auto actual = failure([&] { static_cast(AgcDriver::DriverDetail::PrepareShaderWithDiagnostics(request)); }); + 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"); #ifdef _WIN32 Require(_putenv_s("APS5_DUMP_SHADERS", saved.c_str()) == 0, "cannot restore shader capture"); #else Require((previous != nullptr ? setenv("APS5_DUMP_SHADERS", saved.c_str(), 1) : unsetenv("APS5_DUMP_SHADERS")) == 0, "cannot restore shader capture"); #endif - Require(actual == expected, "shader capture changed the preparation failure"); std::ifstream file(path, std::ios::binary); std::ostringstream text; text << file.rdbuf();