[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());
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);
}
if (!fastHandle) {
// If that didn't succeed, link a pipeline using the
// pre-compiled fragment and vertex shader libraries.
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();
baseHandle = this->createBaseInstance(key)->handle;
}
// If that didn't succeed, link a pipeline using the
// pre-compiled fragment and vertex shader libraries.
if (!fastHandle)
baseHandle = this->getBasePipeline(state);
} else {
// Create optimized variant right away, no choice
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(
const DxvkGraphicsPipelineStateInfo& state) const {
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(
const DxvkGraphicsPipelineBaseInstanceKey& key) const {
auto vk = m_device->vkd();

View File

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

View File

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