mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-24 21:06:55 +02:00
shader: detect and loudly skip unsupported GPU-buffer callables
This commit is contained in:
@@ -275,6 +275,7 @@ struct PipelineCache::ProgramCache {
|
|||||||
ShaderRecompiler::IR::ResourceSnapshot resources;
|
ShaderRecompiler::IR::ResourceSnapshot resources;
|
||||||
ShaderRecompiler::IR::ResourceSpecialization specialization;
|
ShaderRecompiler::IR::ResourceSpecialization specialization;
|
||||||
std::vector<Permutation> permutations;
|
std::vector<Permutation> permutations;
|
||||||
|
bool skip_dispatch = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ProgramKeyHash {
|
struct ProgramKeyHash {
|
||||||
@@ -360,6 +361,7 @@ struct PipelineCache::ProgramCache {
|
|||||||
bool source_changed = false;
|
bool source_changed = false;
|
||||||
if (entry != programs.end()) {
|
if (entry != programs.end()) {
|
||||||
auto& cached = entry->second;
|
auto& cached = entry->second;
|
||||||
|
if (cached.skip_dispatch) return {};
|
||||||
Permutation* permutation = nullptr;
|
Permutation* permutation = nullptr;
|
||||||
if (cached.call_source) {
|
if (cached.call_source) {
|
||||||
source_changed = cached.RefreshCallSource(runtime);
|
source_changed = cached.RefreshCallSource(runtime);
|
||||||
@@ -419,6 +421,14 @@ struct PipelineCache::ProgramCache {
|
|||||||
DumpShaderOriginal(stage_name, options.shader_hash, params.code);
|
DumpShaderOriginal(stage_name, options.shader_hash, params.code);
|
||||||
ShaderRecompiler::ShaderSource source;
|
ShaderRecompiler::ShaderSource source;
|
||||||
if (entry == programs.end()) source = ShaderRecompiler::PrepareShaderSource(params.code, options);
|
if (entry == programs.end()) source = ShaderRecompiler::PrepareShaderSource(params.code, options);
|
||||||
|
if (source.unsupported_call_pc != UINT32_MAX) {
|
||||||
|
PipelineCacheLog("!!! TEMPORARY COMPUTE DISPATCH SKIP !!! shader=0x{:016x} pc=0x{:08x} "
|
||||||
|
"reason=unsupported GPU-selected callable target; rendering is incomplete",
|
||||||
|
params.hash, source.unsupported_call_pc);
|
||||||
|
programs.try_emplace(lookup_key, ShaderRecompiler::IR::ResourcePlan{}, nullptr)
|
||||||
|
.first->second.skip_dispatch = true;
|
||||||
|
return {};
|
||||||
|
}
|
||||||
auto* current = entry == programs.end() ? &source : entry->second.call_source.get();
|
auto* current = entry == programs.end() ? &source : entry->second.call_source.get();
|
||||||
ShaderRecompiler::TranslateResult translated;
|
ShaderRecompiler::TranslateResult translated;
|
||||||
if (current != nullptr) {
|
if (current != nullptr) {
|
||||||
|
|||||||
@@ -309,6 +309,7 @@ void RenderExecutor::DispatchDirect(uint64_t submit_id, CommandBuffer& buffer,
|
|||||||
}
|
}
|
||||||
const auto compute_program =
|
const auto compute_program =
|
||||||
m_context.GetPipelineCache().GetComputeProgram(cs_regs, sh_regs, input_info);
|
m_context.GetPipelineCache().GetComputeProgram(cs_regs, sh_regs, input_info);
|
||||||
|
if (!compute_program) return;
|
||||||
if (use_thread_dimensions) {
|
if (use_thread_dimensions) {
|
||||||
input_info.dispatch_threads_num[0] = thread_group_x;
|
input_info.dispatch_threads_num[0] = thread_group_x;
|
||||||
input_info.dispatch_threads_num[1] = thread_group_y;
|
input_info.dispatch_threads_num[1] = thread_group_y;
|
||||||
@@ -476,6 +477,7 @@ void RenderExecutor::DispatchIndirect(uint64_t submit_id, CommandBuffer& buffer,
|
|||||||
input_info.indirect_args_address = args_addr;
|
input_info.indirect_args_address = args_addr;
|
||||||
const auto compute_program = m_context.GetPipelineCache().GetComputeProgram(
|
const auto compute_program = m_context.GetPipelineCache().GetComputeProgram(
|
||||||
cs_regs, buffer.GetRegisters().GetShaderRegisters(), input_info);
|
cs_regs, buffer.GetRegisters().GetShaderRegisters(), input_info);
|
||||||
|
if (!compute_program) return;
|
||||||
buffer.EndRendering();
|
buffer.EndRendering();
|
||||||
auto& pipeline = m_context.GetPipelineCache().GetComputePipeline(input_info, compute_program);
|
auto& pipeline = m_context.GetPipelineCache().GetComputePipeline(input_info, compute_program);
|
||||||
auto& bindings = m_compute_bindings;
|
auto& bindings = m_compute_bindings;
|
||||||
|
|||||||
@@ -564,7 +564,12 @@ void PrepareCallTargets(ShaderSource& source, const CompileOptions& options) {
|
|||||||
call.src0.reg != call.dst.reg || call.dst.reg >= 105u);
|
call.src0.reg != call.dst.reg || call.dst.reg >= 105u);
|
||||||
for (uint32_t i = 0; i < 2u; ++i) {
|
for (uint32_t i = 0; i < 2u; ++i) {
|
||||||
const auto value = Register(site.instruction, call.src0.reg + i);
|
const auto value = Register(site.instruction, call.src0.reg + i);
|
||||||
EXIT_IF(!ValidateRuntimeValue(query, value, RuntimeValueType::Integer));
|
if (!ValidateRuntimeValue(query, value, RuntimeValueType::Integer)) {
|
||||||
|
EXIT_IF(value.Instruction()->GetOpcode() != ValueOpcode::ReadConstBuffer);
|
||||||
|
source.unsupported_call_pc = call.pc;
|
||||||
|
source.calls.clear();
|
||||||
|
return;
|
||||||
|
}
|
||||||
auto& root = query.value_storage.emplace_back(ValueOpcode::ReferenceU32);
|
auto& root = query.value_storage.emplace_back(ValueOpcode::ReferenceU32);
|
||||||
root.SetArg(0, value);
|
root.SetArg(0, value);
|
||||||
site.target[i] = Value(&root);
|
site.target[i] = Value(&root);
|
||||||
@@ -610,6 +615,7 @@ ShaderSource PrepareShaderSource(std::span<const uint32_t> code, const CompileOp
|
|||||||
}
|
}
|
||||||
|
|
||||||
const Decoder::Program& RefreshShaderSource(ShaderSource& source, const IR::SrtRuntime& runtime) {
|
const Decoder::Program& RefreshShaderSource(ShaderSource& source, const IR::SrtRuntime& runtime) {
|
||||||
|
EXIT_IF(source.unsupported_call_pc != UINT32_MAX);
|
||||||
auto& reads = source.reads;
|
auto& reads = source.reads;
|
||||||
reads.clear();
|
reads.clear();
|
||||||
IR::SrtReadCapture capture(runtime, reads);
|
IR::SrtReadCapture capture(runtime, reads);
|
||||||
|
|||||||
@@ -62,6 +62,7 @@ struct ShaderSource {
|
|||||||
Decoder::Program decoded;
|
Decoder::Program decoded;
|
||||||
IR::ResourcePlan call_targets;
|
IR::ResourcePlan call_targets;
|
||||||
std::vector<Call> calls;
|
std::vector<Call> calls;
|
||||||
|
uint32_t unsupported_call_pc = UINT32_MAX;
|
||||||
std::optional<Linked> linked;
|
std::optional<Linked> linked;
|
||||||
uint64_t revision = 0;
|
uint64_t revision = 0;
|
||||||
std::vector<std::pair<uint64_t, uint64_t>> reads;
|
std::vector<std::pair<uint64_t, uint64_t>> reads;
|
||||||
|
|||||||
@@ -10805,6 +10805,11 @@ void TestMemoryFedScalarLeafCall() {
|
|||||||
};
|
};
|
||||||
IR::SrtRuntime runtime{.read_memory = read, .userdata = &memory, .read_specialization_memory = read};
|
IR::SrtRuntime runtime{.read_memory = read, .userdata = &memory, .read_specialization_memory = read};
|
||||||
const auto options = MakeCompileOptions(ShaderType::Compute);
|
const auto options = MakeCompileOptions(ShaderType::Compute);
|
||||||
|
const uint32_t gpu_callable[] = {EncodeVop1(0x02, 4, 256),
|
||||||
|
EncodeSmem0(0x09, 14, 0), 4u << 25u, EncodeSop1(0x21, 14, 14), EncodeSopp(0x01)};
|
||||||
|
const auto skipped = PrepareShaderSource(gpu_callable, options);
|
||||||
|
Check(skipped.unsupported_call_pc == 12u && skipped.calls.empty(),
|
||||||
|
"GPU-buffer callable did not report its unsupported call site");
|
||||||
auto source = PrepareShaderSource(shader, options);
|
auto source = PrepareShaderSource(shader, options);
|
||||||
Check(source.calls.size() == 1 && source.decoded.has_swap_pc &&
|
Check(source.calls.size() == 1 && source.decoded.has_swap_pc &&
|
||||||
source.decoded.instructions[source.calls.front().instruction].branch_target == UINT32_MAX,
|
source.decoded.instructions[source.calls.front().instruction].branch_target == UINT32_MAX,
|
||||||
|
|||||||
Reference in New Issue
Block a user