mirror of
https://github.com/ayozetr/bloodborne_linux.git
synced 2026-11-08 01:08:25 -10:00
GPU: skip the draws of a pipeline the driver cannot create
"Failed to create graphics pipeline: ErrorUnknown" (some AMD and older drivers) stopped the game with code 23. The pipeline now stays empty and is logged; its draws and dispatches are skipped, on the GPU thread and when a background compile finishes, and it is not saved to the cache, so the next start tries it again. A cached one the driver rejects already rebuilt the cache. After Supermedo/bloodborne_pc 188c1f6, adapted to the background compiles.
This commit is contained in:
1 parent
25cdef7482
commit
49a37b4459
4 files changed
+38
-4
No files matched your search
@@ -1,6 +1,7 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include <cstdio>
|
||||
#include <boost/container/small_vector.hpp>
|
||||
|
||||
#include "common/serdes.h"
|
||||
@@ -115,8 +116,13 @@ ComputePipeline::ComputePipeline(const Instance& instance, Scheduler& scheduler,
|
||||
throw Serialization::CorruptData{"cached compute pipeline rejected by the driver: " +
|
||||
vk::to_string(pipeline_result)};
|
||||
}
|
||||
ASSERT_MSG(pipeline_result == vk::Result::eSuccess, "Failed to create compute pipeline: {}",
|
||||
vk::to_string(pipeline_result));
|
||||
// bbport: as for graphics pipelines, one the driver cannot build skips its dispatches.
|
||||
if (pipeline_result != vk::Result::eSuccess) {
|
||||
std::printf("GPU: the driver could not create compute pipeline %s (%s): its dispatches "
|
||||
"are skipped\n",
|
||||
debug_str.c_str(), vk::to_string(pipeline_result).c_str());
|
||||
return;
|
||||
}
|
||||
pipeline = std::move(pipe);
|
||||
SetObjectName(device, *pipeline, "Compute Pipeline {}", debug_str);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include <cstdio>
|
||||
#include <algorithm>
|
||||
#include <utility>
|
||||
#include <boost/container/small_vector.hpp>
|
||||
@@ -429,8 +430,15 @@ GraphicsPipeline::GraphicsPipeline(
|
||||
throw Serialization::CorruptData{"cached graphics pipeline rejected by the driver: " +
|
||||
vk::to_string(pipeline_result)};
|
||||
}
|
||||
ASSERT_MSG(pipeline_result == vk::Result::eSuccess, "Failed to create graphics pipeline: {}",
|
||||
vk::to_string(pipeline_result));
|
||||
// bbport: a driver that cannot build one pipeline ("ErrorUnknown" on some AMD and older
|
||||
// drivers) stopped the game here (code 23). The pipeline stays empty instead, and the draws
|
||||
// that use it are skipped (PipelineCache): a missing effect rather than a closed game.
|
||||
if (pipeline_result != vk::Result::eSuccess) {
|
||||
std::printf("GPU: the driver could not create graphics pipeline %s (%s): its draws are "
|
||||
"skipped\n",
|
||||
debug_str.c_str(), vk::to_string(pipeline_result).c_str());
|
||||
return;
|
||||
}
|
||||
pipeline = std::move(pipe);
|
||||
SetObjectName(device, *pipeline, "Graphics Pipeline {}", debug_str);
|
||||
}
|
||||
|
||||
@@ -674,6 +674,13 @@ const GraphicsPipeline* PipelineCache::GetGraphicsPipeline(const DrawIndirectPar
|
||||
it.value() = std::make_unique<GraphicsPipeline>(
|
||||
instance, scheduler, desc_heap, profile, sel.graphics_key, *pipeline_cache, sel.infos,
|
||||
sel.runtime_infos, sel.fetch_shader, sel.modules, sdata, false);
|
||||
// bbport: the driver could not create it. The empty entry keeps the key from compiling
|
||||
// again on every draw (they are skipped); it is not saved, so the next start tries anew.
|
||||
if (!it.value()->IsValid()) {
|
||||
it.value().reset();
|
||||
sel.fetch_shader.reset();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RegisterPipelineData(sel.graphics_key, pipeline_hash, sdata);
|
||||
++num_new_pipelines;
|
||||
@@ -693,6 +700,10 @@ const GraphicsPipeline* PipelineCache::GetGraphicsPipeline(const DrawIndirectPar
|
||||
|
||||
const GraphicsPipeline* PipelineCache::FinishPipeline(const GraphicsPipelineKey& key,
|
||||
PendingPipeline& job) {
|
||||
if (!job.pipeline || !job.pipeline->IsValid()) {
|
||||
graphics_pipelines[key].reset(); // bbport: as GetGraphicsPipeline, skipped and not saved
|
||||
return nullptr;
|
||||
}
|
||||
const auto pipeline_hash = std::hash<GraphicsPipelineKey>{}(key);
|
||||
RegisterPipelineData(key, pipeline_hash, job.sdata);
|
||||
++num_new_pipelines;
|
||||
@@ -774,6 +785,10 @@ const ComputePipeline* PipelineCache::GetComputePipeline() {
|
||||
it.value() = std::make_unique<ComputePipeline>(instance, scheduler, desc_heap, profile,
|
||||
*pipeline_cache, compute_key, *sel.infos[0],
|
||||
sel.modules[0], sdata, false);
|
||||
if (!it.value()->IsValid()) { // bbport: as for graphics pipelines
|
||||
it.value().reset();
|
||||
return nullptr;
|
||||
}
|
||||
RegisterPipelineData(compute_key, sdata);
|
||||
++num_new_pipelines;
|
||||
|
||||
|
||||
@@ -36,6 +36,11 @@ public:
|
||||
return *pipeline;
|
||||
}
|
||||
|
||||
/// bbport: false when the driver could not create the pipeline (its draws are skipped).
|
||||
bool IsValid() const noexcept {
|
||||
return static_cast<bool>(pipeline);
|
||||
}
|
||||
|
||||
vk::PipelineLayout GetLayout() const noexcept {
|
||||
return *pipeline_layout;
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user