Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/doitsujin/dxvk.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhilip Rebohle <philip.rebohle@tu-dortmund.de>2022-07-08 19:00:08 +0300
committerPhilip Rebohle <philip.rebohle@tu-dortmund.de>2022-07-08 20:56:39 +0300
commitb8e3b4165dd041f9283ff8a6a81cf7a61a83ae06 (patch)
tree4c0b82c890bfe4ca34e1eff0e443843fbc8f6efd
parent0819ffb8ca46d7a6d8fe782812267f65f618890c (diff)
[dxvk] Try to create cached optimized pipeline whenever possiblepipeline-cache-control
-rw-r--r--src/dxvk/dxvk_device.cpp9
-rw-r--r--src/dxvk/dxvk_device.h6
-rw-r--r--src/dxvk/dxvk_graphics.cpp66
-rw-r--r--src/dxvk/dxvk_graphics.h3
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;