mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-04-02 11:01:50 -04:00
Fix another shutdown race condition in the Vulkan backend
This commit is contained in:
parent
d0faf250b5
commit
c1a7235767
3 changed files with 23 additions and 2 deletions
|
@ -411,7 +411,9 @@ struct SinglePipelineTask {
|
|||
|
||||
class CreateMultiPipelinesTask : public Task {
|
||||
public:
|
||||
CreateMultiPipelinesTask(VulkanContext *vulkan, std::vector<SinglePipelineTask> tasks) : vulkan_(vulkan), tasks_(tasks) {}
|
||||
CreateMultiPipelinesTask(VulkanContext *vulkan, std::vector<SinglePipelineTask> tasks) : vulkan_(vulkan), tasks_(tasks) {
|
||||
tasksInFlight_.fetch_add(1);
|
||||
}
|
||||
~CreateMultiPipelinesTask() {}
|
||||
|
||||
TaskType Type() const override {
|
||||
|
@ -426,12 +428,25 @@ public:
|
|||
for (auto &task : tasks_) {
|
||||
task.pipeline->Create(vulkan_, task.compatibleRenderPass, task.rpType, task.sampleCount, task.scheduleTime, task.countToCompile);
|
||||
}
|
||||
tasksInFlight_.fetch_sub(1);
|
||||
}
|
||||
|
||||
VulkanContext *vulkan_;
|
||||
std::vector<SinglePipelineTask> tasks_;
|
||||
|
||||
// Use during shutdown to make sure there aren't any leftover tasks sitting queued.
|
||||
// Could probably be done more elegantly. Like waiting for all tasks of a type, or saving pointers to them, or something...
|
||||
static void WaitForAll() {
|
||||
while (tasksInFlight_.load() > 0) {
|
||||
sleep_ms(2);
|
||||
}
|
||||
}
|
||||
|
||||
static std::atomic<int> tasksInFlight_;
|
||||
};
|
||||
|
||||
std::atomic<int> CreateMultiPipelinesTask::tasksInFlight_;
|
||||
|
||||
void VulkanRenderManager::CompileThreadFunc() {
|
||||
SetCurrentThreadName("ShaderCompile");
|
||||
while (true) {
|
||||
|
@ -465,7 +480,8 @@ void VulkanRenderManager::CompileThreadFunc() {
|
|||
for (auto &entry : toCompile) {
|
||||
switch (entry.type) {
|
||||
case CompileQueueEntry::Type::GRAPHICS:
|
||||
map[std::pair< Promise<VkShaderModule> *, Promise<VkShaderModule> *>(entry.graphics->desc->vertexShader, entry.graphics->desc->fragmentShader)].push_back(
|
||||
{
|
||||
map[std::make_pair(entry.graphics->desc->vertexShader, entry.graphics->desc->fragmentShader)].push_back(
|
||||
SinglePipelineTask{
|
||||
entry.graphics,
|
||||
entry.compatibleRenderPass,
|
||||
|
@ -477,6 +493,7 @@ void VulkanRenderManager::CompileThreadFunc() {
|
|||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (auto iter : map) {
|
||||
|
@ -500,6 +517,7 @@ void VulkanRenderManager::DrainAndBlockCompileQueue() {
|
|||
while (!compileQueue_.empty()) {
|
||||
queueRunner_.WaitForCompileNotification();
|
||||
}
|
||||
CreateMultiPipelinesTask::WaitForAll();
|
||||
}
|
||||
|
||||
void VulkanRenderManager::ReleaseCompileQueue() {
|
||||
|
|
|
@ -191,9 +191,11 @@ public:
|
|||
const std::string &GetSource() const { return source_; }
|
||||
~VKShaderModule() {
|
||||
if (module_) {
|
||||
INFO_LOG(G3D, "~VKShaderModule");
|
||||
VkShaderModule shaderModule = module_->BlockUntilReady();
|
||||
vulkan_->Delete().QueueDeleteShaderModule(shaderModule);
|
||||
vulkan_->Delete().QueueCallback([](VulkanContext *context, void *m) {
|
||||
INFO_LOG(G3D, "destroying shader module promise");
|
||||
auto module = (Promise<VkShaderModule> *)m;
|
||||
delete module;
|
||||
}, module_);
|
||||
|
|
|
@ -30,6 +30,7 @@ public:
|
|||
virtual void Cancel() {}
|
||||
virtual uint64_t id() { return 0; }
|
||||
virtual void Release() { delete this; }
|
||||
virtual const char *Kind() const { return nullptr; } // Useful for selecting task by some qualifier, like, waiting for them all.
|
||||
};
|
||||
|
||||
class Waitable {
|
||||
|
|
Loading…
Add table
Reference in a new issue