diff --git a/src/dxvk/dxvk_compute.cpp b/src/dxvk/dxvk_compute.cpp index 2a12806f39d..04972b0c0b4 100644 --- a/src/dxvk/dxvk_compute.cpp +++ b/src/dxvk/dxvk_compute.cpp @@ -48,9 +48,7 @@ namespace dxvk { // Retrieve actual pipeline handle on first use. This // may wait for an ongoing compile job to finish, or // compile the pipeline immediately on the calling thread. - m_libraryHandle = m_library->acquirePipelineHandle( - DxvkShaderPipelineLibraryCompileArgs()).handle; - + m_libraryHandle = m_library->acquirePipelineHandle().handle; return m_libraryHandle; } else { // Slow path for compute shaders that do use spec constants diff --git a/src/dxvk/dxvk_graphics.cpp b/src/dxvk/dxvk_graphics.cpp index 65ef519772c..3092f350e6f 100644 --- a/src/dxvk/dxvk_graphics.cpp +++ b/src/dxvk/dxvk_graphics.cpp @@ -1112,6 +1112,7 @@ namespace dxvk { if (doCreateBasePipeline) baseHandle = this->getBasePipeline(state); + // Fast-linking may fail in some situations if (!baseHandle) fastHandle = this->getOptimizedPipeline(state); @@ -1149,6 +1150,13 @@ namespace dxvk { || (state.rs.lineMode() != VK_LINE_RASTERIZATION_MODE_DEFAULT_EXT && isLineRendering)) return false; + // Depth clip is assumed to be enabled. If the driver does not + // support dynamic depth clip, we'd have to late-compile anyway + // unless the pipeline is used multiple times. + if (!m_device->features().extExtendedDynamicState3.extendedDynamicState3DepthClipEnable + && !state.rs.depthClipEnable()) + return false; + if (m_shaders.tcs != nullptr) { // If tessellation shaders are present, the input patch // vertex count must match the shader's definition. @@ -1220,9 +1228,6 @@ namespace dxvk { key.viLibrary = m_manager->createVertexInputLibrary(viState); key.foLibrary = m_manager->createFragmentOutputLibrary(foState); - if (!m_device->features().extExtendedDynamicState3.extendedDynamicState3DepthClipEnable) - key.args.depthClipEnable = state.rs.depthClipEnable(); - auto entry = m_basePipelines.find(key); if (entry != m_basePipelines.end()) return entry->second; @@ -1237,8 +1242,8 @@ namespace dxvk { const DxvkGraphicsPipelineBaseInstanceKey& key) const { auto vk = m_device->vkd(); - DxvkShaderPipelineLibraryHandle vs = m_vsLibrary->acquirePipelineHandle(key.args); - DxvkShaderPipelineLibraryHandle fs = m_fsLibrary->acquirePipelineHandle(key.args); + DxvkShaderPipelineLibraryHandle vs = m_vsLibrary->acquirePipelineHandle(); + DxvkShaderPipelineLibraryHandle fs = m_fsLibrary->acquirePipelineHandle(); std::array libraries = {{ key.viLibrary->getHandle(), vs.handle, fs.handle, diff --git a/src/dxvk/dxvk_graphics.h b/src/dxvk/dxvk_graphics.h index 435677a85a4..4f618f783cc 100644 --- a/src/dxvk/dxvk_graphics.h +++ b/src/dxvk/dxvk_graphics.h @@ -381,19 +381,16 @@ namespace dxvk { struct DxvkGraphicsPipelineBaseInstanceKey { const DxvkGraphicsPipelineVertexInputLibrary* viLibrary = nullptr; const DxvkGraphicsPipelineFragmentOutputLibrary* foLibrary = nullptr; - DxvkShaderPipelineLibraryCompileArgs args; bool eq(const DxvkGraphicsPipelineBaseInstanceKey& other) const { return viLibrary == other.viLibrary - && foLibrary == other.foLibrary - && args == other.args; + && foLibrary == other.foLibrary; } size_t hash() const { DxvkHashState hash; hash.add(size_t(viLibrary)); hash.add(size_t(foLibrary)); - hash.add(args.hash()); return hash; } }; diff --git a/src/dxvk/dxvk_shader.cpp b/src/dxvk/dxvk_shader.cpp index aa378cb823f..bdd375604c4 100644 --- a/src/dxvk/dxvk_shader.cpp +++ b/src/dxvk/dxvk_shader.cpp @@ -1022,7 +1022,7 @@ namespace dxvk { DxvkShaderPipelineLibrary::~DxvkShaderPipelineLibrary() { - this->destroyShaderPipelinesLocked(); + this->destroyShaderPipelineLocked(); } @@ -1042,22 +1042,17 @@ namespace dxvk { } - DxvkShaderPipelineLibraryHandle DxvkShaderPipelineLibrary::acquirePipelineHandle( - const DxvkShaderPipelineLibraryCompileArgs& args) { + DxvkShaderPipelineLibraryHandle DxvkShaderPipelineLibrary::acquirePipelineHandle() { std::lock_guard lock(m_mutex); if (m_device->mustTrackPipelineLifetime()) m_useCount += 1; - DxvkShaderPipelineLibraryHandle& pipeline = (m_shaders.vs && !args.depthClipEnable) - ? m_pipelineNoDepthClip - : m_pipeline; + if (m_pipeline.handle) + return m_pipeline; - if (pipeline.handle) - return pipeline; - - pipeline = compileShaderPipelineLocked(args); - return pipeline; + m_pipeline = compileShaderPipelineLocked(); + return m_pipeline; } @@ -1066,7 +1061,7 @@ namespace dxvk { std::lock_guard lock(m_mutex); if (!(--m_useCount)) - this->destroyShaderPipelinesLocked(); + this->destroyShaderPipelineLocked(); } } @@ -1079,8 +1074,7 @@ namespace dxvk { return; // Compile the pipeline with default args - DxvkShaderPipelineLibraryHandle pipeline = compileShaderPipelineLocked( - DxvkShaderPipelineLibraryCompileArgs()); + DxvkShaderPipelineLibraryHandle pipeline = compileShaderPipelineLocked(); // On 32-bit, destroy the pipeline immediately in order to // save memory. We should hit the driver's disk cache once @@ -1097,19 +1091,16 @@ namespace dxvk { } - void DxvkShaderPipelineLibrary::destroyShaderPipelinesLocked() { + void DxvkShaderPipelineLibrary::destroyShaderPipelineLocked() { auto vk = m_device->vkd(); vk->vkDestroyPipeline(vk->device(), m_pipeline.handle, nullptr); - vk->vkDestroyPipeline(vk->device(), m_pipelineNoDepthClip.handle, nullptr); m_pipeline.handle = VK_NULL_HANDLE; - m_pipelineNoDepthClip.handle = VK_NULL_HANDLE; } - DxvkShaderPipelineLibraryHandle DxvkShaderPipelineLibrary::compileShaderPipelineLocked( - const DxvkShaderPipelineLibraryCompileArgs& args) { + DxvkShaderPipelineLibraryHandle DxvkShaderPipelineLibrary::compileShaderPipelineLocked() { this->notifyLibraryCompile(); // If this is not the first time we're compiling the pipeline, @@ -1117,13 +1108,11 @@ namespace dxvk { // so that we don't have to decompress our SPIR-V shader again. DxvkShaderPipelineLibraryHandle pipeline = { VK_NULL_HANDLE, 0 }; - if (m_compiledOnce && canUsePipelineCacheControl()) { - pipeline = this->compileShaderPipeline(args, - VK_PIPELINE_CREATE_FAIL_ON_PIPELINE_COMPILE_REQUIRED_BIT); - } + if (m_compiledOnce && canUsePipelineCacheControl()) + pipeline = this->compileShaderPipeline(VK_PIPELINE_CREATE_FAIL_ON_PIPELINE_COMPILE_REQUIRED_BIT); if (!pipeline.handle) - pipeline = this->compileShaderPipeline(args, 0); + pipeline = this->compileShaderPipeline(0); // Well that didn't work if (!pipeline.handle) @@ -1145,7 +1134,6 @@ namespace dxvk { DxvkShaderPipelineLibraryHandle DxvkShaderPipelineLibrary::compileShaderPipeline( - const DxvkShaderPipelineLibraryCompileArgs& args, VkPipelineCreateFlags flags) { DxvkShaderStageInfo stageInfo(m_device); VkShaderStageFlags stageMask = getShaderStages(); @@ -1181,7 +1169,7 @@ namespace dxvk { VkPipeline pipeline = VK_NULL_HANDLE; if (stageMask & VK_SHADER_STAGE_VERTEX_BIT) - pipeline = compileVertexShaderPipeline(args, stageInfo, flags); + pipeline = compileVertexShaderPipeline(stageInfo, flags); else if (stageMask & VK_SHADER_STAGE_FRAGMENT_BIT) pipeline = compileFragmentShaderPipeline(stageInfo, flags); else if (stageMask & VK_SHADER_STAGE_COMPUTE_BIT) @@ -1193,7 +1181,6 @@ namespace dxvk { VkPipeline DxvkShaderPipelineLibrary::compileVertexShaderPipeline( - const DxvkShaderPipelineLibraryCompileArgs& args, const DxvkShaderStageInfo& stageInfo, VkPipelineCreateFlags flags) { auto vk = m_device->vkd(); @@ -1240,10 +1227,10 @@ namespace dxvk { // Only use the fixed depth clip state if we can't make it dynamic if (!m_device->features().extExtendedDynamicState3.extendedDynamicState3DepthClipEnable) { rsDepthClipInfo.pNext = std::exchange(rsInfo.pNext, &rsDepthClipInfo); - rsDepthClipInfo.depthClipEnable = args.depthClipEnable; + rsDepthClipInfo.depthClipEnable = VK_TRUE; } } else { - rsInfo.depthClampEnable = !args.depthClipEnable; + rsInfo.depthClampEnable = VK_FALSE; } // Only the view mask is used as input, and since we do not use MultiView, it is always 0 diff --git a/src/dxvk/dxvk_shader.h b/src/dxvk/dxvk_shader.h index 8e21197c174..3d4ad871317 100644 --- a/src/dxvk/dxvk_shader.h +++ b/src/dxvk/dxvk_shader.h @@ -368,26 +368,6 @@ namespace dxvk { }; - /** - * \brief Shader pipeline library compile args - */ - struct DxvkShaderPipelineLibraryCompileArgs { - VkBool32 depthClipEnable = VK_TRUE; - - bool operator == (const DxvkShaderPipelineLibraryCompileArgs& other) const { - return depthClipEnable == other.depthClipEnable; - } - - bool operator != (const DxvkShaderPipelineLibraryCompileArgs& other) const { - return !this->operator == (other); - } - - size_t hash() const { - return size_t(depthClipEnable); - } - }; - - /** * \brief Shader set * @@ -532,11 +512,9 @@ namespace dxvk { * Either returns an already compiled pipeline library object, or * performs the compilation step if that has not happened yet. * Increments the use count by one. - * \param [in] args Compile arguments * \returns Vulkan pipeline handle */ - DxvkShaderPipelineLibraryHandle acquirePipelineHandle( - const DxvkShaderPipelineLibraryCompileArgs& args); + DxvkShaderPipelineLibraryHandle acquirePipelineHandle(); /** * \brief Releases pipeline @@ -564,25 +542,21 @@ namespace dxvk { const DxvkBindingLayoutObjects* m_layout; dxvk::mutex m_mutex; - DxvkShaderPipelineLibraryHandle m_pipeline = { VK_NULL_HANDLE, 0 }; - DxvkShaderPipelineLibraryHandle m_pipelineNoDepthClip = { VK_NULL_HANDLE, 0 }; - uint32_t m_useCount = 0u; - bool m_compiledOnce = false; + DxvkShaderPipelineLibraryHandle m_pipeline = { VK_NULL_HANDLE, 0 }; + uint32_t m_useCount = 0u; + bool m_compiledOnce = false; dxvk::mutex m_identifierMutex; DxvkShaderIdentifierSet m_identifiers; - void destroyShaderPipelinesLocked(); + void destroyShaderPipelineLocked(); - DxvkShaderPipelineLibraryHandle compileShaderPipelineLocked( - const DxvkShaderPipelineLibraryCompileArgs& args); + DxvkShaderPipelineLibraryHandle compileShaderPipelineLocked(); DxvkShaderPipelineLibraryHandle compileShaderPipeline( - const DxvkShaderPipelineLibraryCompileArgs& args, VkPipelineCreateFlags flags); VkPipeline compileVertexShaderPipeline( - const DxvkShaderPipelineLibraryCompileArgs& args, const DxvkShaderStageInfo& stageInfo, VkPipelineCreateFlags flags);