Fix another shutdown race condition in the Vulkan backend

This commit is contained in:
Henrik Rydgård 2024-01-15 17:06:00 +01:00
parent d0faf250b5
commit c1a7235767
3 changed files with 23 additions and 2 deletions

View file

@ -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() {

View file

@ -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_);

View file

@ -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 {