1
0
mirror of https://github.com/EduApps-CDG/OpenDX synced 2024-12-30 09:45:37 +01:00

[dxvk] Repurpose asynchronous pipeline compiler

Removes support for DISABLE_OPTIMIZATION_BIT. Instead, pipelines
will not be made available until compiled by one of the worker
threads.
This commit is contained in:
Philip Rebohle 2018-09-10 16:32:17 +02:00
parent 012a5c2f74
commit c3b542878c
No known key found for this signature in database
GPG Key ID: C8CC613427A31C99
2 changed files with 29 additions and 36 deletions

View File

@ -39,19 +39,17 @@ namespace dxvk {
const Rc<vk::DeviceFn>& vkd, const Rc<vk::DeviceFn>& vkd,
const DxvkGraphicsPipelineStateInfo& stateVector, const DxvkGraphicsPipelineStateInfo& stateVector,
VkRenderPass renderPass, VkRenderPass renderPass,
VkPipeline basePipeline) VkPipeline pipeline)
: m_vkd (vkd), : m_vkd (vkd),
m_stateVector (stateVector), m_stateVector (stateVector),
m_renderPass (renderPass), m_renderPass (renderPass),
m_basePipeline(basePipeline), m_pipeline (pipeline) {
m_fastPipeline(VK_NULL_HANDLE) {
} }
DxvkGraphicsPipelineInstance::~DxvkGraphicsPipelineInstance() { DxvkGraphicsPipelineInstance::~DxvkGraphicsPipelineInstance() {
m_vkd->vkDestroyPipeline(m_vkd->device(), m_basePipeline, nullptr); m_vkd->vkDestroyPipeline(m_vkd->device(), m_pipeline, nullptr);
m_vkd->vkDestroyPipeline(m_vkd->device(), m_fastPipeline, nullptr);
} }
@ -123,14 +121,17 @@ namespace dxvk {
// If no pipeline instance exists with the given state // If no pipeline instance exists with the given state
// vector, create a new one and add it to the list. // vector, create a new one and add it to the list.
VkPipeline newPipelineBase = m_basePipelineBase.load(); VkPipeline newPipelineBase = m_basePipeline.load();
VkPipeline newPipelineHandle = this->compilePipeline(state, renderPassHandle, VkPipeline newPipelineHandle = VK_NULL_HANDLE;
m_compiler != nullptr ? VK_PIPELINE_CREATE_DISABLE_OPTIMIZATION_BIT : 0,
newPipelineBase); if (m_compiler == nullptr) {
newPipelineHandle = this->compilePipeline(
state, renderPassHandle, newPipelineBase);
}
Rc<DxvkGraphicsPipelineInstance> newPipeline = Rc<DxvkGraphicsPipelineInstance> newPipeline =
new DxvkGraphicsPipelineInstance(m_device->vkd(), state, new DxvkGraphicsPipelineInstance(m_device->vkd(),
renderPassHandle, newPipelineHandle); state, renderPassHandle, newPipelineHandle);
{ std::lock_guard<sync::Spinlock> lock(m_mutex); { std::lock_guard<sync::Spinlock> lock(m_mutex);
@ -144,15 +145,15 @@ namespace dxvk {
// Add new pipeline to the set // Add new pipeline to the set
m_pipelines.push_back(newPipeline); m_pipelines.push_back(newPipeline);
stats.addCtr(DxvkStatCounter::PipeCountGraphics, 1); stats.addCtr(DxvkStatCounter::PipeCountGraphics, 1);
} }
// Use the new pipeline as the base pipeline for derivative pipelines // Use the new pipeline as the base pipeline for derivative pipelines
if (newPipelineBase == VK_NULL_HANDLE && newPipelineHandle != VK_NULL_HANDLE) if (newPipelineBase == VK_NULL_HANDLE && newPipelineHandle != VK_NULL_HANDLE)
m_basePipelineBase.compare_exchange_strong(newPipelineBase, newPipelineHandle); m_basePipeline.compare_exchange_strong(newPipelineBase, newPipelineHandle);
// Compile optimized pipeline asynchronously // Compile pipeline asynchronously if requested
if (m_compiler != nullptr) if (m_compiler != nullptr)
m_compiler->queueCompilation(this, newPipeline); m_compiler->queueCompilation(this, newPipeline);
@ -163,18 +164,18 @@ namespace dxvk {
void DxvkGraphicsPipeline::compileInstance( void DxvkGraphicsPipeline::compileInstance(
const Rc<DxvkGraphicsPipelineInstance>& instance) { const Rc<DxvkGraphicsPipelineInstance>& instance) {
// Compile an optimized version of the pipeline // Compile an optimized version of the pipeline
VkPipeline newPipelineBase = m_fastPipelineBase.load(); VkPipeline newPipelineBase = m_basePipeline.load();
VkPipeline newPipelineHandle = this->compilePipeline( VkPipeline newPipelineHandle = this->compilePipeline(
instance->m_stateVector, instance->m_renderPass, instance->m_stateVector, instance->m_renderPass,
0, m_fastPipelineBase); newPipelineBase);
if (!instance->setFastPipeline(newPipelineHandle)) { if (!instance->setPipeline(newPipelineHandle)) {
// If another thread finished compiling an optimized version of this // If another thread finished compiling an optimized version of this
// pipeline before this one finished, discard the new pipeline object. // pipeline before this one finished, discard the new pipeline object.
m_vkd->vkDestroyPipeline(m_vkd->device(), newPipelineHandle, nullptr); m_vkd->vkDestroyPipeline(m_vkd->device(), newPipelineHandle, nullptr);
} else if (newPipelineBase == VK_NULL_HANDLE && newPipelineHandle != VK_NULL_HANDLE) { } else if (newPipelineBase == VK_NULL_HANDLE && newPipelineHandle != VK_NULL_HANDLE) {
// Use the new pipeline as the base pipeline for derivative pipelines. // Use the new pipeline as the base pipeline for derivative pipelines.
m_fastPipelineBase.compare_exchange_strong(newPipelineBase, newPipelineHandle); m_basePipeline.compare_exchange_strong(newPipelineBase, newPipelineHandle);
} }
} }
@ -194,7 +195,6 @@ namespace dxvk {
VkPipeline DxvkGraphicsPipeline::compilePipeline( VkPipeline DxvkGraphicsPipeline::compilePipeline(
const DxvkGraphicsPipelineStateInfo& state, const DxvkGraphicsPipelineStateInfo& state,
VkRenderPass renderPass, VkRenderPass renderPass,
VkPipelineCreateFlags createFlags,
VkPipeline baseHandle) const { VkPipeline baseHandle) const {
if (Logger::logLevel() <= LogLevel::Debug) { if (Logger::logLevel() <= LogLevel::Debug) {
Logger::debug("Compiling graphics pipeline..."); Logger::debug("Compiling graphics pipeline...");
@ -363,7 +363,7 @@ namespace dxvk {
VkGraphicsPipelineCreateInfo info; VkGraphicsPipelineCreateInfo info;
info.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; info.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
info.pNext = nullptr; info.pNext = nullptr;
info.flags = createFlags; info.flags = 0;
info.stageCount = stages.size(); info.stageCount = stages.size();
info.pStages = stages.data(); info.pStages = stages.data();
info.pVertexInputState = &viInfo; info.pVertexInputState = &viInfo;

View File

@ -88,8 +88,8 @@ namespace dxvk {
/** /**
* \brief Graphics pipeline instance * \brief Graphics pipeline instance
* *
* Stores a state vector and the corresponding * Stores a state vector and the
* unoptimized and optimized pipeline handles. * corresponding pipeline handle.
*/ */
class DxvkGraphicsPipelineInstance : public RcObject { class DxvkGraphicsPipelineInstance : public RcObject {
friend class DxvkGraphicsPipeline; friend class DxvkGraphicsPipeline;
@ -99,7 +99,7 @@ namespace dxvk {
const Rc<vk::DeviceFn>& vkd, const Rc<vk::DeviceFn>& vkd,
const DxvkGraphicsPipelineStateInfo& stateVector, const DxvkGraphicsPipelineStateInfo& stateVector,
VkRenderPass renderPass, VkRenderPass renderPass,
VkPipeline basePipeline); VkPipeline pipeline);
~DxvkGraphicsPipelineInstance(); ~DxvkGraphicsPipelineInstance();
@ -125,9 +125,9 @@ namespace dxvk {
* handle should be destroyed. * handle should be destroyed.
* \param [in] pipeline The optimized pipeline * \param [in] pipeline The optimized pipeline
*/ */
bool setFastPipeline(VkPipeline pipeline) { bool setPipeline(VkPipeline pipeline) {
VkPipeline expected = VK_NULL_HANDLE; VkPipeline expected = VK_NULL_HANDLE;
return m_fastPipeline.compare_exchange_strong(expected, pipeline); return m_pipeline.compare_exchange_strong(expected, pipeline);
} }
/** /**
@ -138,11 +138,7 @@ namespace dxvk {
* \returns The pipeline handle * \returns The pipeline handle
*/ */
VkPipeline getPipeline() const { VkPipeline getPipeline() const {
VkPipeline basePipeline = m_basePipeline.load(); return m_pipeline.load();
VkPipeline fastPipeline = m_fastPipeline.load();
return fastPipeline != VK_NULL_HANDLE
? fastPipeline : basePipeline;
} }
private: private:
@ -151,9 +147,8 @@ namespace dxvk {
DxvkGraphicsPipelineStateInfo m_stateVector; DxvkGraphicsPipelineStateInfo m_stateVector;
VkRenderPass m_renderPass; VkRenderPass m_renderPass;
std::atomic<VkPipeline> m_basePipeline; std::atomic<VkPipeline> m_pipeline;
std::atomic<VkPipeline> m_fastPipeline;
}; };
@ -248,8 +243,7 @@ namespace dxvk {
std::vector<Rc<DxvkGraphicsPipelineInstance>> m_pipelines; std::vector<Rc<DxvkGraphicsPipelineInstance>> m_pipelines;
// Pipeline handles used for derivative pipelines // Pipeline handles used for derivative pipelines
std::atomic<VkPipeline> m_basePipelineBase = { VK_NULL_HANDLE }; std::atomic<VkPipeline> m_basePipeline = { VK_NULL_HANDLE };
std::atomic<VkPipeline> m_fastPipelineBase = { VK_NULL_HANDLE };
DxvkGraphicsPipelineInstance* findInstance( DxvkGraphicsPipelineInstance* findInstance(
const DxvkGraphicsPipelineStateInfo& state, const DxvkGraphicsPipelineStateInfo& state,
@ -258,7 +252,6 @@ namespace dxvk {
VkPipeline compilePipeline( VkPipeline compilePipeline(
const DxvkGraphicsPipelineStateInfo& state, const DxvkGraphicsPipelineStateInfo& state,
VkRenderPass renderPass, VkRenderPass renderPass,
VkPipelineCreateFlags createFlags,
VkPipeline baseHandle) const; VkPipeline baseHandle) const;
bool validatePipelineState( bool validatePipelineState(