diff options
author | Philip Rebohle <philip.rebohle@tu-dortmund.de> | 2022-07-08 19:00:08 +0300 |
---|---|---|
committer | Philip Rebohle <philip.rebohle@tu-dortmund.de> | 2022-07-08 20:56:39 +0300 |
commit | b8e3b4165dd041f9283ff8a6a81cf7a61a83ae06 (patch) | |
tree | 4c0b82c890bfe4ca34e1eff0e443843fbc8f6efd | |
parent | 0819ffb8ca46d7a6d8fe782812267f65f618890c (diff) |
[dxvk] Try to create cached optimized pipeline whenever possiblepipeline-cache-control
-rw-r--r-- | src/dxvk/dxvk_device.cpp | 9 | ||||
-rw-r--r-- | src/dxvk/dxvk_device.h | 6 | ||||
-rw-r--r-- | src/dxvk/dxvk_graphics.cpp | 66 | ||||
-rw-r--r-- | src/dxvk/dxvk_graphics.h | 3 |
4 files changed, 63 insertions, 21 deletions
diff --git a/src/dxvk/dxvk_device.cpp b/src/dxvk/dxvk_device.cpp index 76fed23e..5e76a8a4 100644 --- a/src/dxvk/dxvk_device.cpp +++ b/src/dxvk/dxvk_device.cpp @@ -51,6 +51,15 @@ namespace dxvk { } + bool DxvkDevice::canUsePipelineCacheControl() const { + // Don't bother with this unless the device also supports shader module + // identifiers, since decoding and hashing the shaders is slow otherwise + // and likely provides no benefit over linking pipeline libraries. + return m_features.extPipelineCreationCacheControl.pipelineCreationCacheControl + && m_features.extShaderModuleIdentifier.shaderModuleIdentifier; + } + + DxvkFramebufferSize DxvkDevice::getDefaultFramebufferSize() const { return DxvkFramebufferSize { m_properties.core.properties.limits.maxFramebufferWidth, diff --git a/src/dxvk/dxvk_device.h b/src/dxvk/dxvk_device.h index 29c7a1f2..3cf743a6 100644 --- a/src/dxvk/dxvk_device.h +++ b/src/dxvk/dxvk_device.h @@ -203,6 +203,12 @@ namespace dxvk { bool canUseGraphicsPipelineLibrary() const; /** + * \brief Checks whether pipeline creation cache control can be used + * \returns \c true if all required features are supported. + */ + bool canUsePipelineCacheControl() const; + + /** * \brief Queries default framebuffer size * \returns Default framebuffer size */ diff --git a/src/dxvk/dxvk_graphics.cpp b/src/dxvk/dxvk_graphics.cpp index 3393abe5..50fbe83c 100644 --- a/src/dxvk/dxvk_graphics.cpp +++ b/src/dxvk/dxvk_graphics.cpp @@ -589,7 +589,7 @@ namespace dxvk { || instance->isCompiling.exchange(VK_TRUE, std::memory_order_acquire)) return; - VkPipeline pipeline = this->createOptimizedPipeline(state); + VkPipeline pipeline = this->createOptimizedPipeline(state, 0); instance->fastHandle.store(pipeline, std::memory_order_release); } @@ -600,18 +600,29 @@ namespace dxvk { VkPipeline fastHandle = VK_NULL_HANDLE; if (this->canCreateBasePipeline(state)) { - DxvkGraphicsPipelineVertexInputState viState(m_device, state); - DxvkGraphicsPipelineFragmentOutputState foState(m_device, state, m_shaders.fs.ptr()); + // Try to create an optimized pipeline from the cache + // first, since this is expected to be the fastest path. + if (m_device->canUsePipelineCacheControl()) { + fastHandle = this->createOptimizedPipeline(state, + VK_PIPELINE_CREATE_FAIL_ON_PIPELINE_COMPILE_REQUIRED_BIT_EXT); + } + + if (!fastHandle) { + // If that didn't succeed, link a pipeline using the + // pre-compiled fragment and vertex shader libraries. + DxvkGraphicsPipelineVertexInputState viState(m_device, 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(); + 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; + baseHandle = this->createBaseInstance(key)->handle; + } } else { // Create optimized variant right away, no choice - fastHandle = this->createOptimizedPipeline(state); + fastHandle = this->createOptimizedPipeline(state, 0); } m_stats->numGraphicsPipelines += 1; @@ -718,7 +729,8 @@ namespace dxvk { VkPipeline DxvkGraphicsPipeline::createOptimizedPipeline( - const DxvkGraphicsPipelineStateInfo& state) const { + const DxvkGraphicsPipelineStateInfo& state, + VkPipelineCreateFlags flags) const { auto vk = m_device->vkd(); if (Logger::logLevel() <= LogLevel::Debug) { @@ -763,16 +775,24 @@ namespace dxvk { // Build stage infos for all provided shaders DxvkShaderStageInfo stageInfo(m_device); - stageInfo.addStage(VK_SHADER_STAGE_VERTEX_BIT, getShaderCode(m_shaders.vs, state), &specInfo); - if (m_shaders.tcs != nullptr) - stageInfo.addStage(VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, getShaderCode(m_shaders.tcs, state), &specInfo); - if (m_shaders.tes != nullptr) - stageInfo.addStage(VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, getShaderCode(m_shaders.tes, state), &specInfo); - if (m_shaders.gs != nullptr) - stageInfo.addStage(VK_SHADER_STAGE_GEOMETRY_BIT, getShaderCode(m_shaders.gs, state), &specInfo); - if (m_shaders.fs != nullptr) - stageInfo.addStage(VK_SHADER_STAGE_FRAGMENT_BIT, getShaderCode(m_shaders.fs, state), &specInfo); + if (flags & VK_PIPELINE_CREATE_FAIL_ON_PIPELINE_COMPILE_REQUIRED_BIT_EXT) { + stageInfo.addStage(VK_SHADER_STAGE_VERTEX_BIT, m_vsLibrary->getModuleIdentifier(), &specInfo); + + if (m_shaders.fs != nullptr) + stageInfo.addStage(VK_SHADER_STAGE_FRAGMENT_BIT, m_fsLibrary->getModuleIdentifier(), &specInfo); + } else { + stageInfo.addStage(VK_SHADER_STAGE_VERTEX_BIT, getShaderCode(m_shaders.vs, state), &specInfo); + + if (m_shaders.tcs != nullptr) + stageInfo.addStage(VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, getShaderCode(m_shaders.tcs, state), &specInfo); + if (m_shaders.tes != nullptr) + stageInfo.addStage(VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, getShaderCode(m_shaders.tes, state), &specInfo); + if (m_shaders.gs != nullptr) + stageInfo.addStage(VK_SHADER_STAGE_GEOMETRY_BIT, getShaderCode(m_shaders.gs, state), &specInfo); + if (m_shaders.fs != nullptr) + stageInfo.addStage(VK_SHADER_STAGE_FRAGMENT_BIT, getShaderCode(m_shaders.fs, state), &specInfo); + } DxvkGraphicsPipelineVertexInputState viState(m_device, state); DxvkGraphicsPipelinePreRasterizationState prState(m_device, state, m_shaders.gs.ptr()); @@ -784,6 +804,7 @@ namespace dxvk { dyInfo.pDynamicStates = dynamicStates.data(); VkGraphicsPipelineCreateInfo info = { VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, &foState.rtInfo }; + info.flags = flags; info.stageCount = stageInfo.getStageCount(); info.pStages = stageInfo.getStageInfos(); info.pVertexInputState = &viState.viInfo; @@ -802,7 +823,12 @@ namespace dxvk { info.pTessellationState = nullptr; VkPipeline pipeline = VK_NULL_HANDLE; - if (vk->vkCreateGraphicsPipelines(vk->device(), VK_NULL_HANDLE, 1, &info, nullptr, &pipeline) != VK_SUCCESS) { + VkResult vr = vk->vkCreateGraphicsPipelines(vk->device(), VK_NULL_HANDLE, 1, &info, nullptr, &pipeline); + + if (vr == VK_PIPELINE_COMPILE_REQUIRED_EXT) + return VK_NULL_HANDLE; + + if (vr != VK_SUCCESS) { Logger::err("DxvkGraphicsPipeline: Failed to compile pipeline"); this->logPipelineState(LogLevel::Error, state); return VK_NULL_HANDLE; diff --git a/src/dxvk/dxvk_graphics.h b/src/dxvk/dxvk_graphics.h index d0abc060..29e316d6 100644 --- a/src/dxvk/dxvk_graphics.h +++ b/src/dxvk/dxvk_graphics.h @@ -425,7 +425,8 @@ namespace dxvk { const DxvkGraphicsPipelineBaseInstanceKey& key) const; VkPipeline createOptimizedPipeline( - const DxvkGraphicsPipelineStateInfo& state) const; + const DxvkGraphicsPipelineStateInfo& state, + VkPipelineCreateFlags flags) const; void destroyPipeline( VkPipeline pipeline) const; |