From c1f16d36bd35dd8fd57a40c46a4ce832ac5cf962 Mon Sep 17 00:00:00 2001 From: Philip Rebohle <philip.rebohle@tu-dortmund.de> Date: Sat, 13 Jan 2018 22:18:32 +0100 Subject: [PATCH] [dxvk] Implemented local pipeline cache --- src/dxvk/dxvk_compute.cpp | 9 +++++---- src/dxvk/dxvk_compute.h | 7 +++++-- src/dxvk/dxvk_device.cpp | 7 +++++-- src/dxvk/dxvk_device.h | 2 ++ src/dxvk/dxvk_graphics.cpp | 17 +++++++++-------- src/dxvk/dxvk_graphics.h | 20 +++++++++++++------- src/dxvk/dxvk_pipecache.cpp | 27 +++++++++++++++++++++++++++ src/dxvk/dxvk_pipecache.h | 35 +++++++++++++++++++++++++++++++++++ src/dxvk/dxvk_pipemanager.cpp | 22 +++++++++++++--------- src/dxvk/dxvk_pipemanager.h | 14 ++++++++------ src/dxvk/meson.build | 1 + 11 files changed, 123 insertions(+), 38 deletions(-) create mode 100644 src/dxvk/dxvk_pipecache.cpp create mode 100644 src/dxvk/dxvk_pipecache.h diff --git a/src/dxvk/dxvk_compute.cpp b/src/dxvk/dxvk_compute.cpp index f1a4e2c6..03d2703f 100644 --- a/src/dxvk/dxvk_compute.cpp +++ b/src/dxvk/dxvk_compute.cpp @@ -3,9 +3,10 @@ namespace dxvk { DxvkComputePipeline::DxvkComputePipeline( - const Rc<vk::DeviceFn>& vkd, - const Rc<DxvkShader>& cs) - : m_vkd(vkd) { + const Rc<vk::DeviceFn>& vkd, + const Rc<DxvkPipelineCache>& cache, + const Rc<DxvkShader>& cs) + : m_vkd(vkd), m_cache(cache) { DxvkDescriptorSlotMapping slotMapping; cs->defineResourceSlots(slotMapping); @@ -38,7 +39,7 @@ namespace dxvk { info.basePipelineIndex = -1; if (m_vkd->vkCreateComputePipelines(m_vkd->device(), - VK_NULL_HANDLE, 1, &info, nullptr, &m_pipeline) != VK_SUCCESS) + m_cache->handle(), 1, &info, nullptr, &m_pipeline) != VK_SUCCESS) throw DxvkError("DxvkComputePipeline::DxvkComputePipeline: Failed to compile pipeline"); } diff --git a/src/dxvk/dxvk_compute.h b/src/dxvk/dxvk_compute.h index 2140fe7f..89b1dd46 100644 --- a/src/dxvk/dxvk_compute.h +++ b/src/dxvk/dxvk_compute.h @@ -1,5 +1,6 @@ #pragma once +#include "dxvk_pipecache.h" #include "dxvk_pipelayout.h" #include "dxvk_resource.h" #include "dxvk_shader.h" @@ -19,8 +20,9 @@ namespace dxvk { public: DxvkComputePipeline( - const Rc<vk::DeviceFn>& vkd, - const Rc<DxvkShader>& cs); + const Rc<vk::DeviceFn>& vkd, + const Rc<DxvkPipelineCache>& cache, + const Rc<DxvkShader>& cs); ~DxvkComputePipeline(); /** @@ -46,6 +48,7 @@ namespace dxvk { private: Rc<vk::DeviceFn> m_vkd; + Rc<DxvkPipelineCache> m_cache; Rc<DxvkBindingLayout> m_layout; Rc<DxvkShaderModule> m_cs; diff --git a/src/dxvk/dxvk_device.cpp b/src/dxvk/dxvk_device.cpp index cafb2887..dede436d 100644 --- a/src/dxvk/dxvk_device.cpp +++ b/src/dxvk/dxvk_device.cpp @@ -12,6 +12,7 @@ namespace dxvk { m_features (features), m_memory (new DxvkMemoryAllocator(adapter, vkd)), m_renderPassPool (new DxvkRenderPassPool (vkd)), + m_pipelineCache (new DxvkPipelineCache (vkd)), m_pipelineManager (new DxvkPipelineManager(vkd)), m_submissionQueue (this) { m_vkd->vkGetDeviceQueue(m_vkd->device(), @@ -161,7 +162,8 @@ namespace dxvk { Rc<DxvkComputePipeline> DxvkDevice::createComputePipeline( const Rc<DxvkShader>& cs) { - return m_pipelineManager->createComputePipeline(cs); + return m_pipelineManager->createComputePipeline( + m_pipelineCache, cs); } @@ -171,7 +173,8 @@ namespace dxvk { const Rc<DxvkShader>& tes, const Rc<DxvkShader>& gs, const Rc<DxvkShader>& fs) { - return m_pipelineManager->createGraphicsPipeline(vs, tcs, tes, gs, fs); + return m_pipelineManager->createGraphicsPipeline( + m_pipelineCache, vs, tcs, tes, gs, fs); } diff --git a/src/dxvk/dxvk_device.h b/src/dxvk/dxvk_device.h index fc042d9f..13e6870c 100644 --- a/src/dxvk/dxvk_device.h +++ b/src/dxvk/dxvk_device.h @@ -8,6 +8,7 @@ #include "dxvk_framebuffer.h" #include "dxvk_image.h" #include "dxvk_memory.h" +#include "dxvk_pipecache.h" #include "dxvk_pipemanager.h" #include "dxvk_queue.h" #include "dxvk_recycler.h" @@ -303,6 +304,7 @@ namespace dxvk { Rc<DxvkMemoryAllocator> m_memory; Rc<DxvkRenderPassPool> m_renderPassPool; + Rc<DxvkPipelineCache> m_pipelineCache; Rc<DxvkPipelineManager> m_pipelineManager; std::mutex m_submissionLock; diff --git a/src/dxvk/dxvk_graphics.cpp b/src/dxvk/dxvk_graphics.cpp index 0f092778..321d1c5a 100644 --- a/src/dxvk/dxvk_graphics.cpp +++ b/src/dxvk/dxvk_graphics.cpp @@ -33,13 +33,14 @@ namespace dxvk { DxvkGraphicsPipeline::DxvkGraphicsPipeline( - const Rc<vk::DeviceFn>& vkd, - const Rc<DxvkShader>& vs, - const Rc<DxvkShader>& tcs, - const Rc<DxvkShader>& tes, - const Rc<DxvkShader>& gs, - const Rc<DxvkShader>& fs) - : m_vkd(vkd) { + const Rc<vk::DeviceFn>& vkd, + const Rc<DxvkPipelineCache>& cache, + const Rc<DxvkShader>& vs, + const Rc<DxvkShader>& tcs, + const Rc<DxvkShader>& tes, + const Rc<DxvkShader>& gs, + const Rc<DxvkShader>& fs) + : m_vkd(vkd), m_cache(cache) { DxvkDescriptorSlotMapping slotMapping; if (vs != nullptr) vs ->defineResourceSlots(slotMapping); if (tcs != nullptr) tcs->defineResourceSlots(slotMapping); @@ -229,7 +230,7 @@ namespace dxvk { VkPipeline pipeline = VK_NULL_HANDLE; if (m_vkd->vkCreateGraphicsPipelines(m_vkd->device(), - VK_NULL_HANDLE, 1, &info, nullptr, &pipeline) != VK_SUCCESS) + m_cache->handle(), 1, &info, nullptr, &pipeline) != VK_SUCCESS) throw DxvkError("DxvkGraphicsPipeline::DxvkGraphicsPipeline: Failed to compile pipeline"); return pipeline; } diff --git a/src/dxvk/dxvk_graphics.h b/src/dxvk/dxvk_graphics.h index d664d48c..a3247aaf 100644 --- a/src/dxvk/dxvk_graphics.h +++ b/src/dxvk/dxvk_graphics.h @@ -5,7 +5,7 @@ #include "dxvk_binding.h" #include "dxvk_constant_state.h" -#include "dxvk_hash.h" +#include "dxvk_pipecache.h" #include "dxvk_pipelayout.h" #include "dxvk_resource.h" #include "dxvk_shader.h" @@ -88,12 +88,13 @@ namespace dxvk { public: DxvkGraphicsPipeline( - const Rc<vk::DeviceFn>& vkd, - const Rc<DxvkShader>& vs, - const Rc<DxvkShader>& tcs, - const Rc<DxvkShader>& tes, - const Rc<DxvkShader>& gs, - const Rc<DxvkShader>& fs); + const Rc<vk::DeviceFn>& vkd, + const Rc<DxvkPipelineCache>& cache, + const Rc<DxvkShader>& vs, + const Rc<DxvkShader>& tcs, + const Rc<DxvkShader>& tes, + const Rc<DxvkShader>& gs, + const Rc<DxvkShader>& fs); ~DxvkGraphicsPipeline(); /** @@ -110,6 +111,10 @@ namespace dxvk { /** * \brief Pipeline handle + * + * Retrieves a pipeline handle for the given pipeline + * state. If necessary, a new pipeline will be created. + * \param [in] state Pipeline state vector * \returns Pipeline handle */ VkPipeline getPipelineHandle( @@ -123,6 +128,7 @@ namespace dxvk { }; Rc<vk::DeviceFn> m_vkd; + Rc<DxvkPipelineCache> m_cache; Rc<DxvkBindingLayout> m_layout; Rc<DxvkShaderModule> m_vs; diff --git a/src/dxvk/dxvk_pipecache.cpp b/src/dxvk/dxvk_pipecache.cpp new file mode 100644 index 00000000..4d137dbd --- /dev/null +++ b/src/dxvk/dxvk_pipecache.cpp @@ -0,0 +1,27 @@ +#include "dxvk_pipecache.h" + +namespace dxvk { + + DxvkPipelineCache::DxvkPipelineCache( + const Rc<vk::DeviceFn>& vkd) + : m_vkd(vkd) { + // TODO read pipeline cache from file + VkPipelineCacheCreateInfo info; + info.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO; + info.pNext = nullptr; + info.flags = 0; + info.initialDataSize = 0; + info.pInitialData = nullptr; + + if (m_vkd->vkCreatePipelineCache(m_vkd->device(), + &info, nullptr, &m_handle) != VK_SUCCESS) + throw DxvkError("DxvkPipelineCache: Failed to create cache"); + } + + + DxvkPipelineCache::~DxvkPipelineCache() { + m_vkd->vkDestroyPipelineCache( + m_vkd->device(), m_handle, nullptr); + } + +} \ No newline at end of file diff --git a/src/dxvk/dxvk_pipecache.h b/src/dxvk/dxvk_pipecache.h new file mode 100644 index 00000000..94dced12 --- /dev/null +++ b/src/dxvk/dxvk_pipecache.h @@ -0,0 +1,35 @@ +#pragma once + +#include "dxvk_include.h" + +namespace dxvk { + + /** + * \brief Pipeline cache + * + * Allows the Vulkan implementation to + * re-use previously compiled pipelines. + */ + class DxvkPipelineCache : public RcObject { + + public: + + DxvkPipelineCache(const Rc<vk::DeviceFn>& vkd); + ~DxvkPipelineCache(); + + /** + * \brief Pipeline cache handle + * \returns Pipeline cache handle + */ + VkPipelineCache handle() const { + return m_handle; + } + + private: + + Rc<vk::DeviceFn> m_vkd; + VkPipelineCache m_handle; + + }; + +} \ No newline at end of file diff --git a/src/dxvk/dxvk_pipemanager.cpp b/src/dxvk/dxvk_pipemanager.cpp index b4477c66..88a68d32 100644 --- a/src/dxvk/dxvk_pipemanager.cpp +++ b/src/dxvk/dxvk_pipemanager.cpp @@ -36,7 +36,9 @@ namespace dxvk { DxvkPipelineManager::DxvkPipelineManager(const Rc<vk::DeviceFn>& vkd) - : m_vkd(vkd) { } + : m_vkd(vkd) { + + } DxvkPipelineManager::~DxvkPipelineManager() { @@ -45,7 +47,8 @@ namespace dxvk { Rc<DxvkComputePipeline> DxvkPipelineManager::createComputePipeline( - const Rc<DxvkShader>& cs) { + const Rc<DxvkPipelineCache>& cache, + const Rc<DxvkShader>& cs) { if (cs == nullptr) return nullptr; @@ -59,18 +62,19 @@ namespace dxvk { return pair->second; const Rc<DxvkComputePipeline> pipeline - = new DxvkComputePipeline(m_vkd, cs); + = new DxvkComputePipeline(m_vkd, cache, cs); m_computePipelines.insert(std::make_pair(key, pipeline)); return pipeline; } Rc<DxvkGraphicsPipeline> DxvkPipelineManager::createGraphicsPipeline( - const Rc<DxvkShader>& vs, - const Rc<DxvkShader>& tcs, - const Rc<DxvkShader>& tes, - const Rc<DxvkShader>& gs, - const Rc<DxvkShader>& fs) { + const Rc<DxvkPipelineCache>& cache, + const Rc<DxvkShader>& vs, + const Rc<DxvkShader>& tcs, + const Rc<DxvkShader>& tes, + const Rc<DxvkShader>& gs, + const Rc<DxvkShader>& fs) { if (vs == nullptr) return nullptr; @@ -88,7 +92,7 @@ namespace dxvk { return pair->second; const Rc<DxvkGraphicsPipeline> pipeline - = new DxvkGraphicsPipeline(m_vkd, vs, tcs, tes, gs, fs); + = new DxvkGraphicsPipeline(m_vkd, cache, vs, tcs, tes, gs, fs); m_graphicsPipelines.insert(std::make_pair(key, pipeline)); return pipeline; } diff --git a/src/dxvk/dxvk_pipemanager.h b/src/dxvk/dxvk_pipemanager.h index 003f9a13..9d438cd7 100644 --- a/src/dxvk/dxvk_pipemanager.h +++ b/src/dxvk/dxvk_pipemanager.h @@ -73,7 +73,8 @@ namespace dxvk { * \returns Compute pipeline object */ Rc<DxvkComputePipeline> createComputePipeline( - const Rc<DxvkShader>& cs); + const Rc<DxvkPipelineCache>& cache, + const Rc<DxvkShader>& cs); /** * \brief Retrieves a graphics pipeline object @@ -89,11 +90,12 @@ namespace dxvk { * \returns Graphics pipeline object */ Rc<DxvkGraphicsPipeline> createGraphicsPipeline( - const Rc<DxvkShader>& vs, - const Rc<DxvkShader>& tcs, - const Rc<DxvkShader>& tes, - const Rc<DxvkShader>& gs, - const Rc<DxvkShader>& fs); + const Rc<DxvkPipelineCache>& cache, + const Rc<DxvkShader>& vs, + const Rc<DxvkShader>& tcs, + const Rc<DxvkShader>& tes, + const Rc<DxvkShader>& gs, + const Rc<DxvkShader>& fs); private: diff --git a/src/dxvk/meson.build b/src/dxvk/meson.build index e240736d..2694bf88 100644 --- a/src/dxvk/meson.build +++ b/src/dxvk/meson.build @@ -22,6 +22,7 @@ dxvk_src = files([ 'dxvk_lifetime.cpp', 'dxvk_main.cpp', 'dxvk_memory.cpp', + 'dxvk_pipecache.cpp', 'dxvk_pipelayout.cpp', 'dxvk_pipemanager.cpp', 'dxvk_queue.cpp',