1
0
mirror of https://github.com/doitsujin/dxvk.git synced 2024-12-14 00:48:44 +01:00

[dxvk] Use unordered map to look up base pipelines

No reason to use a linear list here. The object is always locked
when we access this list, so we don't need the lock-free one here.
This commit is contained in:
Philip Rebohle 2022-07-30 22:50:10 +02:00
parent 0eaad2eb5b
commit 0a15146746
No known key found for this signature in database
GPG Key ID: C8CC613427A31C99
3 changed files with 50 additions and 49 deletions

View File

@ -541,7 +541,7 @@ namespace dxvk {
this->destroyPipeline(instance.fastHandle.load()); this->destroyPipeline(instance.fastHandle.load());
for (const auto& instance : m_basePipelines) for (const auto& instance : m_basePipelines)
this->destroyPipeline(instance.handle); this->destroyPipeline(instance.second);
} }
@ -654,19 +654,10 @@ namespace dxvk {
VK_PIPELINE_CREATE_FAIL_ON_PIPELINE_COMPILE_REQUIRED_BIT); VK_PIPELINE_CREATE_FAIL_ON_PIPELINE_COMPILE_REQUIRED_BIT);
} }
if (!fastHandle) { // If that didn't succeed, link a pipeline using the
// If that didn't succeed, link a pipeline using the // pre-compiled fragment and vertex shader libraries.
// pre-compiled fragment and vertex shader libraries. if (!fastHandle)
DxvkGraphicsPipelineVertexInputState viState(m_device, state, m_shaders.vs.ptr()); baseHandle = this->getBasePipeline(state);
DxvkGraphicsPipelineFragmentOutputState foState(m_device, state, m_shaders.fs.ptr());
DxvkGraphicsPipelineBaseInstanceKey key;
key.viLibrary = m_manager->createVertexInputLibrary(viState);
key.foLibrary = m_manager->createFragmentOutputLibrary(foState);
key.args.depthClipEnable = state.rs.depthClipEnable();
baseHandle = this->createBaseInstance(key)->handle;
}
} else { } else {
// Create optimized variant right away, no choice // Create optimized variant right away, no choice
fastHandle = this->createOptimizedPipeline(state, 0); fastHandle = this->createOptimizedPipeline(state, 0);
@ -692,20 +683,6 @@ namespace dxvk {
} }
DxvkGraphicsPipelineBaseInstance* DxvkGraphicsPipeline::createBaseInstance(
const DxvkGraphicsPipelineBaseInstanceKey& key) {
for (auto& instance : m_basePipelines) {
if (instance.key.viLibrary == key.viLibrary
&& instance.key.foLibrary == key.foLibrary
&& instance.key.args == key.args)
return &instance;
}
VkPipeline handle = createBasePipeline(key);
return &(*m_basePipelines.emplace(key, handle));
}
bool DxvkGraphicsPipeline::canCreateBasePipeline( bool DxvkGraphicsPipeline::canCreateBasePipeline(
const DxvkGraphicsPipelineStateInfo& state) const { const DxvkGraphicsPipelineStateInfo& state) const {
if (!m_vsLibrary || !m_fsLibrary) if (!m_vsLibrary || !m_fsLibrary)
@ -751,6 +728,26 @@ namespace dxvk {
} }
VkPipeline DxvkGraphicsPipeline::getBasePipeline(
const DxvkGraphicsPipelineStateInfo& state) {
DxvkGraphicsPipelineVertexInputState viState(m_device, state, m_shaders.vs.ptr());
DxvkGraphicsPipelineFragmentOutputState foState(m_device, state, m_shaders.fs.ptr());
DxvkGraphicsPipelineBaseInstanceKey key;
key.viLibrary = m_manager->createVertexInputLibrary(viState);
key.foLibrary = m_manager->createFragmentOutputLibrary(foState);
key.args.depthClipEnable = state.rs.depthClipEnable();
auto entry = m_basePipelines.find(key);
if (entry != m_basePipelines.end())
return entry->second;
VkPipeline handle = createBasePipeline(key);
m_basePipelines.insert({ key, handle });
return handle;
}
VkPipeline DxvkGraphicsPipeline::createBasePipeline( VkPipeline DxvkGraphicsPipeline::createBasePipeline(
const DxvkGraphicsPipelineBaseInstanceKey& key) const { const DxvkGraphicsPipelineBaseInstanceKey& key) const {
auto vk = m_device->vkd(); auto vk = m_device->vkd();

View File

@ -274,23 +274,20 @@ namespace dxvk {
const DxvkGraphicsPipelineVertexInputLibrary* viLibrary = nullptr; const DxvkGraphicsPipelineVertexInputLibrary* viLibrary = nullptr;
const DxvkGraphicsPipelineFragmentOutputLibrary* foLibrary = nullptr; const DxvkGraphicsPipelineFragmentOutputLibrary* foLibrary = nullptr;
DxvkShaderPipelineLibraryCompileArgs args; DxvkShaderPipelineLibraryCompileArgs args;
};
bool eq(const DxvkGraphicsPipelineBaseInstanceKey& other) const {
return viLibrary == other.viLibrary
&& foLibrary == other.foLibrary
&& args == other.args;
}
/** size_t hash() const {
* \brief Base pipeline instance DxvkHashState hash;
* hash.add(size_t(viLibrary));
* Stores the key and handle of a base pipeline. hash.add(size_t(foLibrary));
*/ hash.add(args.hash());
struct DxvkGraphicsPipelineBaseInstance { return hash;
DxvkGraphicsPipelineBaseInstance() { } }
DxvkGraphicsPipelineBaseInstance(
const DxvkGraphicsPipelineBaseInstanceKey& key_,
VkPipeline handle_)
: key(key_), handle(handle_) { }
DxvkGraphicsPipelineBaseInstanceKey key;
VkPipeline handle = VK_NULL_HANDLE;
}; };
@ -413,7 +410,10 @@ namespace dxvk {
alignas(CACHE_LINE_SIZE) alignas(CACHE_LINE_SIZE)
dxvk::mutex m_mutex; dxvk::mutex m_mutex;
sync::List<DxvkGraphicsPipelineInstance> m_pipelines; sync::List<DxvkGraphicsPipelineInstance> m_pipelines;
sync::List<DxvkGraphicsPipelineBaseInstance> m_basePipelines;
std::unordered_map<
DxvkGraphicsPipelineBaseInstanceKey,
VkPipeline, DxvkHash, DxvkEq> m_basePipelines;
DxvkGraphicsPipelineInstance* createInstance( DxvkGraphicsPipelineInstance* createInstance(
const DxvkGraphicsPipelineStateInfo& state, const DxvkGraphicsPipelineStateInfo& state,
@ -422,12 +422,12 @@ namespace dxvk {
DxvkGraphicsPipelineInstance* findInstance( DxvkGraphicsPipelineInstance* findInstance(
const DxvkGraphicsPipelineStateInfo& state); const DxvkGraphicsPipelineStateInfo& state);
DxvkGraphicsPipelineBaseInstance* createBaseInstance(
const DxvkGraphicsPipelineBaseInstanceKey& key);
bool canCreateBasePipeline( bool canCreateBasePipeline(
const DxvkGraphicsPipelineStateInfo& state) const; const DxvkGraphicsPipelineStateInfo& state) const;
VkPipeline getBasePipeline(
const DxvkGraphicsPipelineStateInfo& state);
VkPipeline createBasePipeline( VkPipeline createBasePipeline(
const DxvkGraphicsPipelineBaseInstanceKey& key) const; const DxvkGraphicsPipelineBaseInstanceKey& key) const;

View File

@ -329,6 +329,10 @@ namespace dxvk {
bool operator != (const DxvkShaderPipelineLibraryCompileArgs& other) const { bool operator != (const DxvkShaderPipelineLibraryCompileArgs& other) const {
return !this->operator == (other); return !this->operator == (other);
} }
size_t hash() const {
return size_t(depthClipEnable);
}
}; };