1
0
mirror of https://github.com/doitsujin/dxvk.git synced 2025-01-19 05:52:11 +01:00

[dxvk] Enable state cache for compute pipelines

Also cleans up some code to get the design more in line
with how graphics pipelines are handled.
This commit is contained in:
Philip Rebohle 2018-09-23 08:32:56 +02:00
parent 6c8ac9e5f4
commit b49876528a
No known key found for this signature in database
GPG Key ID: C8CC613427A31C99
2 changed files with 49 additions and 16 deletions

View File

@ -5,6 +5,7 @@
#include "dxvk_device.h" #include "dxvk_device.h"
#include "dxvk_pipemanager.h" #include "dxvk_pipemanager.h"
#include "dxvk_spec_const.h" #include "dxvk_spec_const.h"
#include "dxvk_state_cache.h"
namespace dxvk { namespace dxvk {
@ -40,7 +41,8 @@ namespace dxvk {
DxvkComputePipeline::~DxvkComputePipeline() { DxvkComputePipeline::~DxvkComputePipeline() {
this->destroyPipelines(); for (const auto& instance : m_pipelines)
this->destroyPipeline(instance.pipeline);
} }
@ -54,28 +56,41 @@ namespace dxvk {
return pipeline; return pipeline;
} }
// If no pipeline exists with the given state vector, // If no pipeline instance exists with the given state
// create a new one and add it to the pipeline set. // vector, create a new one and add it to the list.
VkPipeline newPipeline = this->compilePipeline(state, m_basePipeline); VkPipeline newPipelineBase = m_basePipeline.load();
VkPipeline newPipelineHandle = VK_NULL_HANDLE;
// FIXME for some reason, compiling the exact
// same pipeline crashes inside driver code
{ std::lock_guard<sync::Spinlock> lock(m_mutex);
newPipelineHandle = this->compilePipeline(
state, newPipelineBase);
}
{ std::lock_guard<sync::Spinlock> lock(m_mutex); { std::lock_guard<sync::Spinlock> lock(m_mutex);
// Discard the pipeline if another thread // Discard the pipeline if another thread
// was faster compiling the same pipeline // was faster compiling the same pipeline
if (this->findPipeline(state, pipeline)) { if (this->findPipeline(state, pipeline)) {
m_vkd->vkDestroyPipeline(m_vkd->device(), newPipeline, nullptr); this->destroyPipeline(newPipelineHandle);
m_vkd->vkDestroyPipeline(m_vkd->device(), newPipelineHandle, nullptr);
return pipeline; return pipeline;
} }
// Add new pipeline to the set // Add new pipeline to the set
m_pipelines.push_back({ state, newPipeline }); m_pipelines.push_back({ state, newPipelineHandle });
m_pipeMgr->m_numComputePipelines += 1; m_pipeMgr->m_numComputePipelines += 1;
if (m_basePipeline == VK_NULL_HANDLE)
m_basePipeline = newPipeline;
return newPipeline;
} }
// Use the new pipeline as the base pipeline for derivative pipelines
if (newPipelineBase == VK_NULL_HANDLE && newPipelineHandle != VK_NULL_HANDLE)
m_basePipeline.compare_exchange_strong(newPipelineBase, newPipelineHandle);
if (newPipelineHandle != VK_NULL_HANDLE)
this->writePipelineStateToCache(state);
return newPipelineHandle;
} }
@ -141,11 +156,24 @@ namespace dxvk {
Logger::debug(str::format("DxvkComputePipeline: Finished in ", td.count(), " ms")); Logger::debug(str::format("DxvkComputePipeline: Finished in ", td.count(), " ms"));
return pipeline; return pipeline;
} }
void DxvkComputePipeline::destroyPipeline(VkPipeline pipeline) {
m_vkd->vkDestroyPipeline(m_vkd->device(), pipeline, nullptr);
}
void DxvkComputePipeline::destroyPipelines() { void DxvkComputePipeline::writePipelineStateToCache(
for (const PipelineStruct& pair : m_pipelines) const DxvkComputePipelineStateInfo& state) const {
m_vkd->vkDestroyPipeline(m_vkd->device(), pair.pipeline, nullptr); if (m_pipeMgr->m_stateCache == nullptr)
return;
DxvkStateCacheKey key;
if (m_cs != nullptr)
key.cs = m_cs->getShaderKey();
m_pipeMgr->m_stateCache->addComputePipeline(key, state);
} }
} }

View File

@ -1,5 +1,6 @@
#pragma once #pragma once
#include <atomic>
#include <vector> #include <vector>
#include "dxvk_bind_mask.h" #include "dxvk_bind_mask.h"
@ -79,7 +80,7 @@ namespace dxvk {
sync::Spinlock m_mutex; sync::Spinlock m_mutex;
std::vector<PipelineStruct> m_pipelines; std::vector<PipelineStruct> m_pipelines;
VkPipeline m_basePipeline = VK_NULL_HANDLE; std::atomic<VkPipeline> m_basePipeline = { VK_NULL_HANDLE };
bool findPipeline( bool findPipeline(
const DxvkComputePipelineStateInfo& state, const DxvkComputePipelineStateInfo& state,
@ -89,7 +90,11 @@ namespace dxvk {
const DxvkComputePipelineStateInfo& state, const DxvkComputePipelineStateInfo& state,
VkPipeline baseHandle) const; VkPipeline baseHandle) const;
void destroyPipelines(); void destroyPipeline(
VkPipeline pipeline);
void writePipelineStateToCache(
const DxvkComputePipelineStateInfo& state) const;
}; };