mirror of
https://github.com/boykopovar/AnyPS5.git
synced 2026-10-27 00:28:14 +00:00
fix(shader): give the frontend's call analysis the dispatch's wave size
AcquireFrontend built the frontend's SwappcInfo with a wave size of 0, while the driver's LinkUserDataCallees passes the dispatch's wave size. A wave64 v_cmp_e64 that reuses a call's link pair after the return, followed by a v_cndmask_b32_e64 that reads it, was refused as escaping the call/return model. The frontend now receives the dispatch's wave size, and a frontend built for one wave size is not reused for another.
This commit is contained in:
1 parent
11bb53a347
commit
9863f8b641
2 files changed
+27
-4
No files matched your search
@@ -168,7 +168,6 @@ void verifyFrontendIdentity() {
|
||||
require((preparation.AcquireFrontend(partial) == first) == reuse, "frontend pair: partial-thread state changed the frontend identity");
|
||||
auto target = request;
|
||||
target.target.subgroupSize = 64u;
|
||||
target.context.waveSize = 32u;
|
||||
target.context.compute->numThreads = {32u, 2u, 1u};
|
||||
require((preparation.AcquireFrontend(target) == first) == reuse, "frontend pair: translation-only state changed the frontend identity");
|
||||
const std::array<std::uint32_t, 2> changedUserData{1u, 2u};
|
||||
@@ -197,6 +196,10 @@ void verifyFrontendIdentity() {
|
||||
changed.context.userDataBaseRegister = 4u;
|
||||
verifyMiss(changed, "frontend pair: changed user-data base reused the frontend");
|
||||
changed = request;
|
||||
changed.context.waveSize = 32u;
|
||||
changed.context.compute->numThreads = {32u, 2u, 1u};
|
||||
verifyMiss(changed, "frontend pair: a different wave size reused the frontend");
|
||||
changed = request;
|
||||
changed.context.userData = std::span<const std::uint32_t>(userData).first(1u);
|
||||
verifyMiss(changed, "frontend pair: changed user-data count reused the frontend");
|
||||
changed = request;
|
||||
@@ -222,6 +225,25 @@ void verifyFrontendIdentity() {
|
||||
require((preparation.AcquireFrontend(request) == first) == reuse, "frontend pair: a failed miss replaced the prior frontend");
|
||||
}
|
||||
|
||||
void verifyFrontendWaveSizeCalls() {
|
||||
using namespace ShaderRecompiler;
|
||||
const std::vector<std::uint32_t> code{
|
||||
0xbb0e0005u,
|
||||
0xd4c2000eu, 0x00020300u,
|
||||
0xd5010002u, 0x003a0300u,
|
||||
0xbf820001u,
|
||||
0xbe80200eu,
|
||||
0xbf810000u};
|
||||
const std::array<std::uint32_t, 2> userData{};
|
||||
for (const std::uint32_t waveSize : {32u, 64u}) {
|
||||
auto request = FrontendRequest(code, userData);
|
||||
request.context.waveSize = waveSize;
|
||||
request.context.compute->numThreads = {waveSize, 1u, 1u};
|
||||
ShaderPreparationContext preparation;
|
||||
require(preparation.AcquireFrontend(request) != nullptr, "frontend wave size: a mask write that reuses the link pair and its v_cndmask read were refused");
|
||||
}
|
||||
}
|
||||
|
||||
void verifyFrontendProgram(const ShaderRecompiler::IrProgram& reused, const ShaderRecompiler::IrProgram& fresh) {
|
||||
using namespace ShaderRecompiler;
|
||||
require(ProgramToString(reused) == ProgramToString(fresh), "frontend pair: reused frontend changed the IR");
|
||||
@@ -256,6 +278,7 @@ void verifyFrontendProgram(const ShaderRecompiler::IrProgram& reused, const Shad
|
||||
void verifyFrontendPair() {
|
||||
using namespace ShaderRecompiler;
|
||||
verifyFrontendIdentity();
|
||||
verifyFrontendWaveSizeCalls();
|
||||
const bool reuse = std::getenv("APS5_NO_PERF_FRONTEND_PAIR") == nullptr;
|
||||
const std::vector<std::uint32_t> code{0xe0700000u, 0x80000000u, 0xbf810000u};
|
||||
const std::array<std::uint32_t, 4> buffer{0x10000000u, 0u, 0x40u, 0x00027facu};
|
||||
@@ -318,7 +341,7 @@ void verifyFrontendPair() {
|
||||
const auto freshChanged = PrepareResourceProgram(translated);
|
||||
verifyFrontendProgram(changed, freshChanged);
|
||||
require(changed.WaveSize() != freshFull.WaveSize(), "frontend pair: changed translation inputs were ignored");
|
||||
require((preparation.AcquireFrontend(request) == retained) == reuse, "frontend pair: translating a variant replaced the frontend");
|
||||
require(preparation.AcquireFrontend(request) != retained, "frontend pair: a variant with another wave size reused the frontend");
|
||||
}
|
||||
|
||||
for (const bool partialFirst : {false, true}) {
|
||||
|
||||
@@ -169,7 +169,7 @@ struct PreparedControlFlow {
|
||||
|
||||
bool Matches(const RecompileRequest& request, const SwappcInfo& swappcInfo) const {
|
||||
return stage == request.shader.stage && mergedHull == MergedHullStage(request) && swappc.fetchCallAllowed == swappcInfo.fetchCallAllowed &&
|
||||
swappc.userDataBaseRegister == swappcInfo.userDataBaseRegister && swappc.userDataCount == swappcInfo.userDataCount &&
|
||||
swappc.userDataBaseRegister == swappcInfo.userDataBaseRegister && swappc.userDataCount == swappcInfo.userDataCount && swappc.waveSize == swappcInfo.waveSize &&
|
||||
std::ranges::equal(fallbacks, swappcInfo.linkedCallFallbacks) && std::ranges::equal(code, request.shader.code);
|
||||
}
|
||||
|
||||
@@ -189,7 +189,7 @@ struct PreparedControlFlow {
|
||||
|
||||
std::shared_ptr<const PreparedControlFlow> ShaderPreparationContext::AcquireFrontend(const RecompileRequest& request) {
|
||||
const auto inputInfo = RequestInputInfo(request);
|
||||
const SwappcInfo swappc{inputInfo.vertex != nullptr, request.context.userDataBaseRegister, static_cast<std::uint32_t>(request.context.userData.size()), 0u, request.context.linkedCallFallbacks};
|
||||
const SwappcInfo swappc{inputInfo.vertex != nullptr, request.context.userDataBaseRegister, static_cast<std::uint32_t>(request.context.userData.size()), request.context.waveSize, request.context.linkedCallFallbacks};
|
||||
static const bool reuse = std::getenv("APS5_NO_PERF_FRONTEND_PAIR") == nullptr;
|
||||
if (reuse && frontend != nullptr && frontend->Matches(request, swappc)) {
|
||||
return frontend;
|
||||
|
||||
Reference in new issue
Block a user