diff --git a/src/graphics/host_gpu/renderer/pipeline/pipelineCache.cpp b/src/graphics/host_gpu/renderer/pipeline/pipelineCache.cpp index 97618059a..8b5646627 100644 --- a/src/graphics/host_gpu/renderer/pipeline/pipelineCache.cpp +++ b/src/graphics/host_gpu/renderer/pipeline/pipelineCache.cpp @@ -275,6 +275,7 @@ struct PipelineCache::ProgramCache { ShaderRecompiler::IR::ResourceSnapshot resources; ShaderRecompiler::IR::ResourceSpecialization specialization; std::vector permutations; + bool skip_dispatch = false; }; struct ProgramKeyHash { @@ -360,6 +361,7 @@ struct PipelineCache::ProgramCache { bool source_changed = false; if (entry != programs.end()) { auto& cached = entry->second; + if (cached.skip_dispatch) return {}; Permutation* permutation = nullptr; if (cached.call_source) { source_changed = cached.RefreshCallSource(runtime); @@ -419,6 +421,14 @@ struct PipelineCache::ProgramCache { DumpShaderOriginal(stage_name, options.shader_hash, params.code); ShaderRecompiler::ShaderSource source; 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(); ShaderRecompiler::TranslateResult translated; if (current != nullptr) { diff --git a/src/graphics/host_gpu/renderer/renderCompute.cpp b/src/graphics/host_gpu/renderer/renderCompute.cpp index efb2a9887..b3356abe6 100644 --- a/src/graphics/host_gpu/renderer/renderCompute.cpp +++ b/src/graphics/host_gpu/renderer/renderCompute.cpp @@ -309,6 +309,7 @@ void RenderExecutor::DispatchDirect(uint64_t submit_id, CommandBuffer& buffer, } const auto compute_program = m_context.GetPipelineCache().GetComputeProgram(cs_regs, sh_regs, input_info); + if (!compute_program) return; if (use_thread_dimensions) { input_info.dispatch_threads_num[0] = thread_group_x; 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; const auto compute_program = m_context.GetPipelineCache().GetComputeProgram( cs_regs, buffer.GetRegisters().GetShaderRegisters(), input_info); + if (!compute_program) return; buffer.EndRendering(); auto& pipeline = m_context.GetPipelineCache().GetComputePipeline(input_info, compute_program); auto& bindings = m_compute_bindings; diff --git a/src/graphics/shader/recompiler/ShaderRecompiler.cpp b/src/graphics/shader/recompiler/ShaderRecompiler.cpp index 632bc9025..2eb182c50 100644 --- a/src/graphics/shader/recompiler/ShaderRecompiler.cpp +++ b/src/graphics/shader/recompiler/ShaderRecompiler.cpp @@ -564,7 +564,12 @@ void PrepareCallTargets(ShaderSource& source, const CompileOptions& options) { call.src0.reg != call.dst.reg || call.dst.reg >= 105u); for (uint32_t i = 0; i < 2u; ++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); root.SetArg(0, value); site.target[i] = Value(&root); @@ -610,6 +615,7 @@ ShaderSource PrepareShaderSource(std::span code, const CompileOp } const Decoder::Program& RefreshShaderSource(ShaderSource& source, const IR::SrtRuntime& runtime) { + EXIT_IF(source.unsupported_call_pc != UINT32_MAX); auto& reads = source.reads; reads.clear(); IR::SrtReadCapture capture(runtime, reads); diff --git a/src/graphics/shader/recompiler/ShaderRecompiler.h b/src/graphics/shader/recompiler/ShaderRecompiler.h index e656d14e2..041ea3ca8 100644 --- a/src/graphics/shader/recompiler/ShaderRecompiler.h +++ b/src/graphics/shader/recompiler/ShaderRecompiler.h @@ -62,6 +62,7 @@ struct ShaderSource { Decoder::Program decoded; IR::ResourcePlan call_targets; std::vector calls; + uint32_t unsupported_call_pc = UINT32_MAX; std::optional linked; uint64_t revision = 0; std::vector> reads; diff --git a/tests/shaderCfgTests.cpp b/tests/shaderCfgTests.cpp index 33d189a36..5c792da2b 100644 --- a/tests/shaderCfgTests.cpp +++ b/tests/shaderCfgTests.cpp @@ -10805,6 +10805,11 @@ void TestMemoryFedScalarLeafCall() { }; IR::SrtRuntime runtime{.read_memory = read, .userdata = &memory, .read_specialization_memory = read}; 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); Check(source.calls.size() == 1 && source.decoded.has_swap_pc && source.decoded.instructions[source.calls.front().instruction].branch_target == UINT32_MAX,