1
0
mirror of https://github.com/doitsujin/dxvk.git synced 2025-01-18 20:52:10 +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(
const DxvkComputePipelineStateInfo& state,
DxvkStatCounters& stats) {
for (const PipelineStruct& pair : m_pipelines) {
if (pair.stateVector == state)
return pair.pipeline;
VkPipeline pipeline = VK_NULL_HANDLE;
{ std::lock_guard<sync::Spinlock> lock(m_mutex);
if (this->findPipeline(state, pipeline))
return pipeline;
}
VkPipeline pipeline = this->compilePipeline(state, m_basePipeline);
m_pipelines.push_back({ state, pipeline });
// If no pipeline exists with the given state vector,
// create a new one and add it to the pipeline set.
VkPipeline newPipeline = this->compilePipeline(state, m_basePipeline);
if (m_basePipeline == VK_NULL_HANDLE)
m_basePipeline = 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::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 pipeline;
return false;
}

View File

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

View File

@ -78,23 +78,52 @@ namespace dxvk {
VkPipeline DxvkGraphicsPipeline::getPipelineHandle(
const DxvkGraphicsPipelineStateInfo& state,
DxvkStatCounters& stats) {
VkPipeline pipeline = VK_NULL_HANDLE;
for (const PipelineStruct& pair : m_pipelines) {
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->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)
: 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)
m_basePipeline = pipeline;
stats.addCtr(DxvkStatCounter::PipeCountGraphics, 1);
return pipeline;
return false;
}

View File

@ -1,6 +1,6 @@
#pragma once
#include <vector>
#include <mutex>
#include "dxvk_binding.h"
#include "dxvk_constant_state.h"
@ -160,10 +160,15 @@ namespace dxvk {
DxvkGraphicsCommonPipelineStateInfo m_common;
sync::Spinlock m_mutex;
std::vector<PipelineStruct> m_pipelines;
VkPipeline m_basePipeline = VK_NULL_HANDLE;
bool findPipeline(
const DxvkGraphicsPipelineStateInfo& state,
VkPipeline& pipeline) const;
VkPipeline compilePipeline(
const DxvkGraphicsPipelineStateInfo& state,
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;
}
bool DxvkPipelineKeyEq::operator () (const DxvkGraphicsPipelineKey& a, const DxvkGraphicsPipelineKey& b) const {
return a.vs == b.vs
&& a.tcs == b.tcs
&& a.tes == b.tes
&& a.gs == b.gs
&& a.fs == b.fs;
bool DxvkPipelineKeyEq::operator () (
const DxvkGraphicsPipelineKey& a,
const DxvkGraphicsPipelineKey& b) const {
return a.vs == b.vs && a.tcs == b.tcs
&& a.tes == b.tes && a.gs == b.gs
&& a.fs == b.fs;
}
@ -52,6 +54,8 @@ namespace dxvk {
if (cs == nullptr)
return nullptr;
std::lock_guard<std::mutex> lock(m_mutex);
DxvkComputePipelineKey key;
key.cs = cs;
@ -77,6 +81,8 @@ namespace dxvk {
if (vs == nullptr)
return nullptr;
std::lock_guard<std::mutex> lock(m_mutex);
DxvkGraphicsPipelineKey key;
key.vs = vs;
key.tcs = tcs;

View File

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