1
0
mirror of https://github.com/doitsujin/dxvk.git synced 2024-12-12 13:08:50 +01:00

[dxvk] Remove path to look up optimized pipeline in cache

For some reason this sometimes takes several milliseconds, which
leads to noticeable stutter. Linking a pipeline is more consistent.
This commit is contained in:
Philip Rebohle 2023-01-13 11:40:01 +01:00
parent a22d70e184
commit 070a340115
2 changed files with 27 additions and 63 deletions

View File

@ -990,7 +990,7 @@ namespace dxvk {
|| instance->isCompiling.exchange(VK_TRUE, std::memory_order_acquire))
return;
VkPipeline pipeline = this->getOptimizedPipeline(state, 0);
VkPipeline pipeline = this->getOptimizedPipeline(state);
instance->fastHandle.store(pipeline, std::memory_order_release);
// Log pipeline state on error
@ -1044,22 +1044,10 @@ namespace dxvk {
VkPipeline baseHandle = VK_NULL_HANDLE;
VkPipeline fastHandle = VK_NULL_HANDLE;
if (doCreateBasePipeline) {
// 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->getOptimizedPipeline(state,
VK_PIPELINE_CREATE_FAIL_ON_PIPELINE_COMPILE_REQUIRED_BIT);
}
// 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->getOptimizedPipeline(state, 0);
}
if (doCreateBasePipeline)
baseHandle = this->getBasePipeline(state);
else
fastHandle = this->getOptimizedPipeline(state);
// Log pipeline state if requested, or on failure
if (!fastHandle && !baseHandle)
@ -1206,8 +1194,7 @@ namespace dxvk {
VkPipeline DxvkGraphicsPipeline::getOptimizedPipeline(
const DxvkGraphicsPipelineStateInfo& state,
VkPipelineCreateFlags flags) {
const DxvkGraphicsPipelineStateInfo& state) {
DxvkGraphicsPipelineFastInstanceKey key(m_device,
m_shaders, state, m_flags, m_specConstantMask);
@ -1220,7 +1207,7 @@ namespace dxvk {
// Keep pipeline locked to prevent multiple threads from compiling
// identical Vulkan pipelines. This should be rare, but has been
// buggy on some drivers in the past, so just don't allow it.
VkPipeline handle = createOptimizedPipeline(key, flags);
VkPipeline handle = createOptimizedPipeline(key);
if (handle)
m_fastPipelines.insert({ key, handle });
@ -1230,45 +1217,22 @@ namespace dxvk {
VkPipeline DxvkGraphicsPipeline::createOptimizedPipeline(
const DxvkGraphicsPipelineFastInstanceKey& key,
VkPipelineCreateFlags flags) const {
const DxvkGraphicsPipelineFastInstanceKey& key) const {
auto vk = m_device->vkd();
// Build stage infos for all provided shaders
DxvkShaderStageInfo stageInfo(m_device);
stageInfo.addStage(VK_SHADER_STAGE_VERTEX_BIT, getShaderCode(m_shaders.vs, key.shState.vsInfo), &key.scState.scInfo);
if (flags & VK_PIPELINE_CREATE_FAIL_ON_PIPELINE_COMPILE_REQUIRED_BIT) {
stageInfo.addStage(VK_SHADER_STAGE_VERTEX_BIT, m_vsLibrary->getModuleIdentifier(VK_SHADER_STAGE_VERTEX_BIT), &key.scState.scInfo);
if (m_shaders.tcs != nullptr)
stageInfo.addStage(VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, m_vsLibrary->getModuleIdentifier(VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT), &key.scState.scInfo);
if (m_shaders.tes != nullptr)
stageInfo.addStage(VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, m_vsLibrary->getModuleIdentifier(VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT), &key.scState.scInfo);
if (m_shaders.gs != nullptr)
stageInfo.addStage(VK_SHADER_STAGE_GEOMETRY_BIT, m_vsLibrary->getModuleIdentifier(VK_SHADER_STAGE_GEOMETRY_BIT), &key.scState.scInfo);
if (m_shaders.fs != nullptr)
stageInfo.addStage(VK_SHADER_STAGE_FRAGMENT_BIT, m_fsLibrary->getModuleIdentifier(VK_SHADER_STAGE_FRAGMENT_BIT), &key.scState.scInfo);
} else {
stageInfo.addStage(VK_SHADER_STAGE_VERTEX_BIT, getShaderCode(m_shaders.vs, key.shState.vsInfo), &key.scState.scInfo);
if (m_shaders.tcs != nullptr)
stageInfo.addStage(VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, getShaderCode(m_shaders.tcs, key.shState.tcsInfo), &key.scState.scInfo);
if (m_shaders.tes != nullptr)
stageInfo.addStage(VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, getShaderCode(m_shaders.tes, key.shState.tesInfo), &key.scState.scInfo);
if (m_shaders.gs != nullptr)
stageInfo.addStage(VK_SHADER_STAGE_GEOMETRY_BIT, getShaderCode(m_shaders.gs, key.shState.gsInfo), &key.scState.scInfo);
if (m_shaders.fs != nullptr)
stageInfo.addStage(VK_SHADER_STAGE_FRAGMENT_BIT, getShaderCode(m_shaders.fs, key.shState.fsInfo), &key.scState.scInfo);
}
if (key.foState.feedbackLoop & VK_IMAGE_ASPECT_COLOR_BIT)
flags |= VK_PIPELINE_CREATE_COLOR_ATTACHMENT_FEEDBACK_LOOP_BIT_EXT;
if (key.foState.feedbackLoop & VK_IMAGE_ASPECT_DEPTH_BIT)
flags |= VK_PIPELINE_CREATE_DEPTH_STENCIL_ATTACHMENT_FEEDBACK_LOOP_BIT_EXT;
if (m_shaders.tcs != nullptr)
stageInfo.addStage(VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, getShaderCode(m_shaders.tcs, key.shState.tcsInfo), &key.scState.scInfo);
if (m_shaders.tes != nullptr)
stageInfo.addStage(VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, getShaderCode(m_shaders.tes, key.shState.tesInfo), &key.scState.scInfo);
if (m_shaders.gs != nullptr)
stageInfo.addStage(VK_SHADER_STAGE_GEOMETRY_BIT, getShaderCode(m_shaders.gs, key.shState.gsInfo), &key.scState.scInfo);
if (m_shaders.fs != nullptr)
stageInfo.addStage(VK_SHADER_STAGE_FRAGMENT_BIT, getShaderCode(m_shaders.fs, key.shState.fsInfo), &key.scState.scInfo);
VkGraphicsPipelineCreateInfo info = { VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, &key.foState.rtInfo };
info.flags = flags;
info.stageCount = stageInfo.getStageCount();
info.pStages = stageInfo.getStageInfos();
info.pVertexInputState = &key.viState.viInfo;
@ -1286,18 +1250,20 @@ namespace dxvk {
if (!key.prState.tsInfo.patchControlPoints)
info.pTessellationState = nullptr;
if (key.foState.feedbackLoop & VK_IMAGE_ASPECT_COLOR_BIT)
info.flags |= VK_PIPELINE_CREATE_COLOR_ATTACHMENT_FEEDBACK_LOOP_BIT_EXT;
if (key.foState.feedbackLoop & VK_IMAGE_ASPECT_DEPTH_BIT)
info.flags |= VK_PIPELINE_CREATE_DEPTH_STENCIL_ATTACHMENT_FEEDBACK_LOOP_BIT_EXT;
VkPipeline pipeline = VK_NULL_HANDLE;
VkResult vr = vk->vkCreateGraphicsPipelines(vk->device(), VK_NULL_HANDLE, 1, &info, nullptr, &pipeline);
if (vr != VK_SUCCESS) {
// Ignore any error if we're trying to create a cached pipeline. If linking or
// compiling an optimized pipeline fail later, we'll still be printing errors.
if (!(flags & VK_PIPELINE_CREATE_FAIL_ON_PIPELINE_COMPILE_REQUIRED_BIT))
Logger::err(str::format("DxvkGraphicsPipeline: Failed to compile pipeline: ", vr));
Logger::err(str::format("DxvkGraphicsPipeline: Failed to compile pipeline: ", vr));
return VK_NULL_HANDLE;
}
return pipeline;
}

View File

@ -606,12 +606,10 @@ namespace dxvk {
const DxvkGraphicsPipelineBaseInstanceKey& key) const;
VkPipeline getOptimizedPipeline(
const DxvkGraphicsPipelineStateInfo& state,
VkPipelineCreateFlags flags);
const DxvkGraphicsPipelineStateInfo& state);
VkPipeline createOptimizedPipeline(
const DxvkGraphicsPipelineFastInstanceKey& key,
VkPipelineCreateFlags flags) const;
const DxvkGraphicsPipelineFastInstanceKey& key) const;
void destroyBasePipelines();