fix(agc): prepare the null pixel program at draw when its variant was not prepared
This commit is contained in:
parent
ca412953ea
commit
bbfd61430a
|
|
@ -179,6 +179,21 @@ void PublishRegisteredShader(std::shared_ptr<ShaderRegistry>& registry, const st
|
|||
transaction.Commit();
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
bool PreparedAtUse(const ShaderSnapshot& snapshot, const ShaderRecompiler::RecompileRequest& request) {
|
||||
if (snapshot.codeAddress == NullPixelProgramAddress() && request.shader.stage == ShaderRecompiler::ShaderStage::Fragment) {
|
||||
APS5_LOG_ERR("The null pixel program has no artifact for this draw (wave %u, %zu user SGPRs); preparing it at draw", request.context.waveSize, request.context.userData.size());
|
||||
return true;
|
||||
}
|
||||
if (!snapshot.header.empty()) return snapshot.prepared->deferred;
|
||||
if (snapshot.type != 0 || request.shader.stage != ShaderRecompiler::ShaderStage::Compute) throw std::runtime_error("AGC driver: unregistered program is not a compute shader");
|
||||
APS5_LOG_ERR("Compute shader 0x%llx was not registered; preparing its artifact at dispatch", static_cast<unsigned long long>(snapshot.codeAddress));
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
std::shared_ptr<const ShaderRecompiler::SourceHandle> SourceHandleFor(const ShaderSnapshot& snapshot, std::size_t codeOffset, const ShaderRecompiler::RecompileRequest& request) {
|
||||
struct PreparedKeyStorage {};
|
||||
auto& key = HostThreadLocal<std::vector<std::uint64_t>, PreparedKeyStorage>();
|
||||
|
|
@ -187,11 +202,7 @@ std::shared_ptr<const ShaderRecompiler::SourceHandle> SourceHandleFor(const Shad
|
|||
for (const auto& entry : snapshot.prepared->entries) {
|
||||
if (entry.codeOffset == codeOffset && ShaderRecompiler::MatchesPreparedShader(request, *entry.handle, key)) return entry.handle;
|
||||
}
|
||||
if (snapshot.header.empty() || snapshot.prepared->deferred) {
|
||||
if (snapshot.header.empty()) {
|
||||
if (snapshot.type != 0 || request.shader.stage != ShaderRecompiler::ShaderStage::Compute) throw std::runtime_error("AGC driver: unregistered program is not a compute shader");
|
||||
APS5_LOG_ERR("Compute shader 0x%llx was not registered; preparing its artifact at dispatch", static_cast<unsigned long long>(snapshot.codeAddress));
|
||||
}
|
||||
if (PreparedAtUse(snapshot, request)) {
|
||||
auto handle = PrepareShaderWithDiagnostics(request);
|
||||
snapshot.prepared->entries.push_back({codeOffset, handle});
|
||||
return handle;
|
||||
|
|
@ -241,11 +252,7 @@ ShaderRecompiler::PreparedShaderInvocation InvocationFor(const ShaderSnapshot& s
|
|||
invocationRequest.shader.code = ShaderRecompiler::GetPreparedCode(*entry.handle);
|
||||
if (auto invocation = ShaderRecompiler::PreparedShaderInvocation::TryCreate(invocationRequest, entry.handle, key)) return std::move(*invocation);
|
||||
}
|
||||
if (snapshot.header.empty() || snapshot.prepared->deferred) {
|
||||
if (snapshot.header.empty()) {
|
||||
if (snapshot.type != 0 || request.shader.stage != ShaderRecompiler::ShaderStage::Compute) throw std::runtime_error("AGC driver: unregistered program is not a compute shader");
|
||||
APS5_LOG_ERR("Compute shader 0x%llx was not registered; preparing its artifact at dispatch", static_cast<unsigned long long>(snapshot.codeAddress));
|
||||
}
|
||||
if (PreparedAtUse(snapshot, request)) {
|
||||
auto handle = PrepareShaderWithDiagnostics(request);
|
||||
invocationRequest = request;
|
||||
invocationRequest.shader.code = ShaderRecompiler::GetPreparedCode(*handle);
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
#include "Optimization/ResourceProgram.hpp"
|
||||
#include "ControlFlow/RequestSerializer.hpp"
|
||||
#include "prx/libSceAgcDriver/Execution/include/Driver/Shaders/ShaderRegistry.hpp"
|
||||
#include "prx/libSceAgcDriver/Graphics/include/ShaderInputState.hpp"
|
||||
#include "prx/libSceAgcDriver/Execution/include/Driver.hpp"
|
||||
#include "prx/libSceAgcDriver/Submit/include/Acb.hpp"
|
||||
#include <spirv/unified1/spirv.hpp>
|
||||
|
|
@ -63,7 +64,24 @@ void RunUnregistered(AgcDriver::VulkanDevice& device, ShaderRecompiler::Recompil
|
|||
}
|
||||
}
|
||||
|
||||
void NullPixelAtDraw(AgcDriver::VulkanDevice& device) {
|
||||
std::vector<std::uint32_t> code(64, 0);
|
||||
code.front() = 0xbf810000u;
|
||||
AgcDriver::DriverDetail::ShaderSnapshot snapshot{AgcDriver::DriverDetail::NullPixelProgramAddress(), 0, 1, code, {}};
|
||||
snapshot.header.resize(sizeof(Shader));
|
||||
std::array<std::uint32_t, 4> users{};
|
||||
const auto pixel = AgcDriver::Graphics::DecodePixelStageInfo({}, {}, true);
|
||||
const ShaderRecompiler::RecompileRequest registered{{ShaderRecompiler::ShaderStage::Fragment, snapshot.codeAddress, snapshot.code, 0, {}}, {64, 0, {}, {}, pixel, {}, {}}, device.Target(), {0, 0, 0, 128}};
|
||||
snapshot.prepared->entries.push_back({0, ShaderRecompiler::PrepareShader(registered)});
|
||||
ShaderRecompiler::RecompileRequest request{{ShaderRecompiler::ShaderStage::Fragment, snapshot.codeAddress, snapshot.code, 0, {}}, {32, 0, users, {}, pixel, {}, {}}, device.Target(), {0, 0, 20, 108}};
|
||||
static_cast<void>(AgcDriver::DriverDetail::InvocationFor(snapshot, 0, request));
|
||||
Require(snapshot.prepared->entries.size() == 2, "the null pixel program was not prepared at draw");
|
||||
static_cast<void>(AgcDriver::DriverDetail::InvocationFor(snapshot, 0, request));
|
||||
Require(AgcDriver::DriverDetail::SourceHandleFor(snapshot, 0, request) == snapshot.prepared->entries.back().handle && snapshot.prepared->entries.size() == 2, "the null pixel program was prepared again for the same draw");
|
||||
}
|
||||
|
||||
void Run(AgcDriver::VulkanDevice& device) {
|
||||
NullPixelAtDraw(device);
|
||||
alignas(256) std::array<std::uint32_t, 1> code{0xbf810000u};
|
||||
std::array<std::uint32_t, 4> users{};
|
||||
const ShaderRecompiler::ShaderComputeStageInfo compute{{1, 1, 1}, 0, {false, false, false}, false, 1, {}};
|
||||
|
|
|
|||
Loading…
Reference in New Issue