1
0
mirror of https://github.com/EduApps-CDG/OpenDX synced 2024-12-30 09:45:37 +01:00

[dxvk] Made pipe manager and pipeline classes thread-safe

This commit is contained in:
Philip Rebohle 2018-05-01 16:45:28 +02:00
parent cf1358b2f4
commit d201a1f7c6
6 changed files with 108 additions and 27 deletions

View File

@ -42,19 +42,50 @@ namespace dxvk {
VkPipeline DxvkComputePipeline::getPipelineHandle( VkPipeline DxvkComputePipeline::getPipelineHandle(
const DxvkComputePipelineStateInfo& state, const DxvkComputePipelineStateInfo& state,
DxvkStatCounters& stats) { DxvkStatCounters& stats) {
for (const PipelineStruct& pair : m_pipelines) { VkPipeline pipeline = VK_NULL_HANDLE;
if (pair.stateVector == state)
return pair.pipeline; { std::lock_guard<sync::Spinlock> lock(m_mutex);
if (this->findPipeline(state, pipeline))
return pipeline;
} }
VkPipeline pipeline = this->compilePipeline(state, m_basePipeline); // If no pipeline exists with the given state vector,
m_pipelines.push_back({ state, pipeline }); // create a new one and add it to the pipeline set.
VkPipeline newPipeline = this->compilePipeline(state, m_basePipeline);
if (m_basePipeline == VK_NULL_HANDLE) { std::lock_guard<sync::Spinlock> lock(m_mutex);
m_basePipeline = pipeline;
// Discard the pipeline if another thread
// was faster compiling the same pipeline
if (this->findPipeline(state, pipeline)) {
m_vkd->vkDestroyPipeline(m_vkd->device(), newPipeline, nullptr);
return pipeline;
}
// Add new pipeline to the set
m_pipelines.push_back({ state, newPipeline });
if (m_basePipeline == VK_NULL_HANDLE)
m_basePipeline = newPipeline;
stats.addCtr(DxvkStatCounter::PipeCountCompute, 1);
return newPipeline;
}
}
bool DxvkComputePipeline::findPipeline(
const DxvkComputePipelineStateInfo& state,
VkPipeline& pipeline) const {
for (const PipelineStruct& pair : m_pipelines) {
if (pair.stateVector == state) {
pipeline = pair.pipeline;
return true;
}
}
stats.addCtr(DxvkStatCounter::PipeCountCompute, 1); return false;
return pipeline;
} }

View File

@ -1,5 +1,7 @@
#pragma once #pragma once
#include <vector>
#include "dxvk_binding.h" #include "dxvk_binding.h"
#include "dxvk_pipecache.h" #include "dxvk_pipecache.h"
#include "dxvk_pipelayout.h" #include "dxvk_pipelayout.h"
@ -76,10 +78,15 @@ namespace dxvk {
Rc<DxvkPipelineLayout> m_layout; Rc<DxvkPipelineLayout> m_layout;
Rc<DxvkShaderModule> m_cs; Rc<DxvkShaderModule> m_cs;
sync::Spinlock m_mutex;
std::vector<PipelineStruct> m_pipelines; std::vector<PipelineStruct> m_pipelines;
VkPipeline m_basePipeline = VK_NULL_HANDLE; VkPipeline m_basePipeline = VK_NULL_HANDLE;
bool findPipeline(
const DxvkComputePipelineStateInfo& state,
VkPipeline& pipeline) const;
VkPipeline compilePipeline( VkPipeline compilePipeline(
const DxvkComputePipelineStateInfo& state, const DxvkComputePipelineStateInfo& state,
VkPipeline baseHandle) const; VkPipeline baseHandle) const;

View File

@ -78,23 +78,52 @@ namespace dxvk {
VkPipeline DxvkGraphicsPipeline::getPipelineHandle( VkPipeline DxvkGraphicsPipeline::getPipelineHandle(
const DxvkGraphicsPipelineStateInfo& state, const DxvkGraphicsPipelineStateInfo& state,
DxvkStatCounters& stats) { DxvkStatCounters& stats) {
VkPipeline pipeline = VK_NULL_HANDLE;
for (const PipelineStruct& pair : m_pipelines) { { std::lock_guard<sync::Spinlock> lock(m_mutex);
if (pair.stateVector == state)
return pair.pipeline; if (this->findPipeline(state, pipeline))
return pipeline;
} }
VkPipeline pipeline = this->validatePipelineState(state) // If no pipeline exists with the given state vector,
// create a new one and add it to the pipeline set.
VkPipeline newPipeline = this->validatePipelineState(state)
? this->compilePipeline(state, m_basePipeline) ? this->compilePipeline(state, m_basePipeline)
: VK_NULL_HANDLE; : VK_NULL_HANDLE;
m_pipelines.push_back({ state, pipeline }); { std::lock_guard<sync::Spinlock> lock(m_mutex);
// Discard the pipeline if another thread
// was faster compiling the same pipeline
if (this->findPipeline(state, pipeline)) {
m_vkd->vkDestroyPipeline(m_vkd->device(), newPipeline, nullptr);
return pipeline;
}
// Add new pipeline to the set
m_pipelines.push_back({ state, newPipeline });
if (m_basePipeline == VK_NULL_HANDLE)
m_basePipeline = newPipeline;
stats.addCtr(DxvkStatCounter::PipeCountGraphics, 1);
return newPipeline;
}
}
bool DxvkGraphicsPipeline::findPipeline(
const DxvkGraphicsPipelineStateInfo& state,
VkPipeline& pipeline) const {
for (const PipelineStruct& pair : m_pipelines) {
if (pair.stateVector == state) {
pipeline = pair.pipeline;
return true;
}
}
if (m_basePipeline == VK_NULL_HANDLE) return false;
m_basePipeline = pipeline;
stats.addCtr(DxvkStatCounter::PipeCountGraphics, 1);
return pipeline;
} }

View File

@ -1,6 +1,6 @@
#pragma once #pragma once
#include <vector> #include <mutex>
#include "dxvk_binding.h" #include "dxvk_binding.h"
#include "dxvk_constant_state.h" #include "dxvk_constant_state.h"
@ -160,10 +160,15 @@ namespace dxvk {
DxvkGraphicsCommonPipelineStateInfo m_common; DxvkGraphicsCommonPipelineStateInfo m_common;
sync::Spinlock m_mutex;
std::vector<PipelineStruct> m_pipelines; std::vector<PipelineStruct> m_pipelines;
VkPipeline m_basePipeline = VK_NULL_HANDLE; VkPipeline m_basePipeline = VK_NULL_HANDLE;
bool findPipeline(
const DxvkGraphicsPipelineStateInfo& state,
VkPipeline& pipeline) const;
VkPipeline compilePipeline( VkPipeline compilePipeline(
const DxvkGraphicsPipelineStateInfo& state, const DxvkGraphicsPipelineStateInfo& state,
VkPipeline baseHandle) const; VkPipeline baseHandle) const;

View File

@ -21,17 +21,19 @@ namespace dxvk {
} }
bool DxvkPipelineKeyEq::operator () (const DxvkComputePipelineKey& a, const DxvkComputePipelineKey& b) const { bool DxvkPipelineKeyEq::operator () (
const DxvkComputePipelineKey& a,
const DxvkComputePipelineKey& b) const {
return a.cs == b.cs; return a.cs == b.cs;
} }
bool DxvkPipelineKeyEq::operator () (const DxvkGraphicsPipelineKey& a, const DxvkGraphicsPipelineKey& b) const { bool DxvkPipelineKeyEq::operator () (
return a.vs == b.vs const DxvkGraphicsPipelineKey& a,
&& a.tcs == b.tcs const DxvkGraphicsPipelineKey& b) const {
&& a.tes == b.tes return a.vs == b.vs && a.tcs == b.tcs
&& a.gs == b.gs && a.tes == b.tes && a.gs == b.gs
&& a.fs == b.fs; && a.fs == b.fs;
} }
@ -52,6 +54,8 @@ namespace dxvk {
if (cs == nullptr) if (cs == nullptr)
return nullptr; return nullptr;
std::lock_guard<std::mutex> lock(m_mutex);
DxvkComputePipelineKey key; DxvkComputePipelineKey key;
key.cs = cs; key.cs = cs;
@ -77,6 +81,8 @@ namespace dxvk {
if (vs == nullptr) if (vs == nullptr)
return nullptr; return nullptr;
std::lock_guard<std::mutex> lock(m_mutex);
DxvkGraphicsPipelineKey key; DxvkGraphicsPipelineKey key;
key.vs = vs; key.vs = vs;
key.tcs = tcs; key.tcs = tcs;

View File

@ -1,5 +1,6 @@
#pragma once #pragma once
#include <mutex>
#include <unordered_map> #include <unordered_map>
#include "dxvk_compute.h" #include "dxvk_compute.h"
@ -99,6 +100,8 @@ namespace dxvk {
const DxvkDevice* m_device; const DxvkDevice* m_device;
std::mutex m_mutex;
std::unordered_map< std::unordered_map<
DxvkComputePipelineKey, DxvkComputePipelineKey,
Rc<DxvkComputePipeline>, Rc<DxvkComputePipeline>,