mirror of
https://github.com/doitsujin/dxvk.git
synced 2024-12-03 13:24:20 +01:00
[dxvk] Forward link flags when using shader identifiers
Fixes a long-standing bug that now causes validation errors.
This commit is contained in:
parent
29253da356
commit
65373792d2
@ -49,7 +49,7 @@ namespace dxvk {
|
|||||||
// may wait for an ongoing compile job to finish, or
|
// may wait for an ongoing compile job to finish, or
|
||||||
// compile the pipeline immediately on the calling thread.
|
// compile the pipeline immediately on the calling thread.
|
||||||
m_libraryHandle = m_library->acquirePipelineHandle(
|
m_libraryHandle = m_library->acquirePipelineHandle(
|
||||||
DxvkShaderPipelineLibraryCompileArgs());
|
DxvkShaderPipelineLibraryCompileArgs()).handle;
|
||||||
|
|
||||||
return m_libraryHandle;
|
return m_libraryHandle;
|
||||||
} else {
|
} else {
|
||||||
|
@ -1111,7 +1111,8 @@ namespace dxvk {
|
|||||||
|
|
||||||
if (doCreateBasePipeline)
|
if (doCreateBasePipeline)
|
||||||
baseHandle = this->getBasePipeline(state);
|
baseHandle = this->getBasePipeline(state);
|
||||||
else
|
|
||||||
|
if (!baseHandle)
|
||||||
fastHandle = this->getOptimizedPipeline(state);
|
fastHandle = this->getOptimizedPipeline(state);
|
||||||
|
|
||||||
// Log pipeline state if requested, or on failure
|
// Log pipeline state if requested, or on failure
|
||||||
@ -1236,10 +1237,11 @@ namespace dxvk {
|
|||||||
const DxvkGraphicsPipelineBaseInstanceKey& key) const {
|
const DxvkGraphicsPipelineBaseInstanceKey& key) const {
|
||||||
auto vk = m_device->vkd();
|
auto vk = m_device->vkd();
|
||||||
|
|
||||||
|
DxvkShaderPipelineLibraryHandle vs = m_vsLibrary->acquirePipelineHandle(key.args);
|
||||||
|
DxvkShaderPipelineLibraryHandle fs = m_fsLibrary->acquirePipelineHandle(key.args);
|
||||||
|
|
||||||
std::array<VkPipeline, 4> libraries = {{
|
std::array<VkPipeline, 4> libraries = {{
|
||||||
key.viLibrary->getHandle(),
|
key.viLibrary->getHandle(), vs.handle, fs.handle,
|
||||||
m_vsLibrary->acquirePipelineHandle(key.args),
|
|
||||||
m_fsLibrary->acquirePipelineHandle(key.args),
|
|
||||||
key.foLibrary->getHandle(),
|
key.foLibrary->getHandle(),
|
||||||
}};
|
}};
|
||||||
|
|
||||||
@ -1248,13 +1250,14 @@ namespace dxvk {
|
|||||||
libInfo.pLibraries = libraries.data();
|
libInfo.pLibraries = libraries.data();
|
||||||
|
|
||||||
VkGraphicsPipelineCreateInfo info = { VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, &libInfo };
|
VkGraphicsPipelineCreateInfo info = { VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, &libInfo };
|
||||||
|
info.flags = vs.linkFlags | fs.linkFlags;
|
||||||
info.layout = m_bindings->getPipelineLayout(true);
|
info.layout = m_bindings->getPipelineLayout(true);
|
||||||
info.basePipelineIndex = -1;
|
info.basePipelineIndex = -1;
|
||||||
|
|
||||||
VkPipeline pipeline = VK_NULL_HANDLE;
|
VkPipeline pipeline = VK_NULL_HANDLE;
|
||||||
VkResult vr = vk->vkCreateGraphicsPipelines(vk->device(), VK_NULL_HANDLE, 1, &info, nullptr, &pipeline);
|
VkResult vr = vk->vkCreateGraphicsPipelines(vk->device(), VK_NULL_HANDLE, 1, &info, nullptr, &pipeline);
|
||||||
|
|
||||||
if (vr != VK_SUCCESS)
|
if (vr && vr != VK_PIPELINE_COMPILE_REQUIRED_EXT)
|
||||||
Logger::err(str::format("DxvkGraphicsPipeline: Failed to create base pipeline: ", vr));
|
Logger::err(str::format("DxvkGraphicsPipeline: Failed to create base pipeline: ", vr));
|
||||||
|
|
||||||
return pipeline;
|
return pipeline;
|
||||||
|
@ -1042,18 +1042,18 @@ namespace dxvk {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
VkPipeline DxvkShaderPipelineLibrary::acquirePipelineHandle(
|
DxvkShaderPipelineLibraryHandle DxvkShaderPipelineLibrary::acquirePipelineHandle(
|
||||||
const DxvkShaderPipelineLibraryCompileArgs& args) {
|
const DxvkShaderPipelineLibraryCompileArgs& args) {
|
||||||
std::lock_guard lock(m_mutex);
|
std::lock_guard lock(m_mutex);
|
||||||
|
|
||||||
if (m_device->mustTrackPipelineLifetime())
|
if (m_device->mustTrackPipelineLifetime())
|
||||||
m_useCount += 1;
|
m_useCount += 1;
|
||||||
|
|
||||||
VkPipeline& pipeline = (m_shaders.vs && !args.depthClipEnable)
|
DxvkShaderPipelineLibraryHandle& pipeline = (m_shaders.vs && !args.depthClipEnable)
|
||||||
? m_pipelineNoDepthClip
|
? m_pipelineNoDepthClip
|
||||||
: m_pipeline;
|
: m_pipeline;
|
||||||
|
|
||||||
if (pipeline)
|
if (pipeline.handle)
|
||||||
return pipeline;
|
return pipeline;
|
||||||
|
|
||||||
pipeline = compileShaderPipelineLocked(args);
|
pipeline = compileShaderPipelineLocked(args);
|
||||||
@ -1079,7 +1079,7 @@ namespace dxvk {
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
// Compile the pipeline with default args
|
// Compile the pipeline with default args
|
||||||
VkPipeline pipeline = compileShaderPipelineLocked(
|
DxvkShaderPipelineLibraryHandle pipeline = compileShaderPipelineLocked(
|
||||||
DxvkShaderPipelineLibraryCompileArgs());
|
DxvkShaderPipelineLibraryCompileArgs());
|
||||||
|
|
||||||
// On 32-bit, destroy the pipeline immediately in order to
|
// On 32-bit, destroy the pipeline immediately in order to
|
||||||
@ -1087,9 +1087,9 @@ namespace dxvk {
|
|||||||
// we need to recreate the pipeline.
|
// we need to recreate the pipeline.
|
||||||
if (m_device->mustTrackPipelineLifetime()) {
|
if (m_device->mustTrackPipelineLifetime()) {
|
||||||
auto vk = m_device->vkd();
|
auto vk = m_device->vkd();
|
||||||
vk->vkDestroyPipeline(vk->device(), pipeline, nullptr);
|
vk->vkDestroyPipeline(vk->device(), pipeline.handle, nullptr);
|
||||||
|
|
||||||
pipeline = VK_NULL_HANDLE;
|
pipeline.handle = VK_NULL_HANDLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write back pipeline handle for future use
|
// Write back pipeline handle for future use
|
||||||
@ -1100,34 +1100,34 @@ namespace dxvk {
|
|||||||
void DxvkShaderPipelineLibrary::destroyShaderPipelinesLocked() {
|
void DxvkShaderPipelineLibrary::destroyShaderPipelinesLocked() {
|
||||||
auto vk = m_device->vkd();
|
auto vk = m_device->vkd();
|
||||||
|
|
||||||
vk->vkDestroyPipeline(vk->device(), m_pipeline, nullptr);
|
vk->vkDestroyPipeline(vk->device(), m_pipeline.handle, nullptr);
|
||||||
vk->vkDestroyPipeline(vk->device(), m_pipelineNoDepthClip, nullptr);
|
vk->vkDestroyPipeline(vk->device(), m_pipelineNoDepthClip.handle, nullptr);
|
||||||
|
|
||||||
m_pipeline = VK_NULL_HANDLE;
|
m_pipeline.handle = VK_NULL_HANDLE;
|
||||||
m_pipelineNoDepthClip = VK_NULL_HANDLE;
|
m_pipelineNoDepthClip.handle = VK_NULL_HANDLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
VkPipeline DxvkShaderPipelineLibrary::compileShaderPipelineLocked(
|
DxvkShaderPipelineLibraryHandle DxvkShaderPipelineLibrary::compileShaderPipelineLocked(
|
||||||
const DxvkShaderPipelineLibraryCompileArgs& args) {
|
const DxvkShaderPipelineLibraryCompileArgs& args) {
|
||||||
this->notifyLibraryCompile();
|
this->notifyLibraryCompile();
|
||||||
|
|
||||||
// If this is not the first time we're compiling the pipeline,
|
// If this is not the first time we're compiling the pipeline,
|
||||||
// try to get a cache hit using the shader module identifier
|
// try to get a cache hit using the shader module identifier
|
||||||
// so that we don't have to decompress our SPIR-V shader again.
|
// so that we don't have to decompress our SPIR-V shader again.
|
||||||
VkPipeline pipeline = VK_NULL_HANDLE;
|
DxvkShaderPipelineLibraryHandle pipeline = { VK_NULL_HANDLE, 0 };
|
||||||
|
|
||||||
if (m_compiledOnce && canUsePipelineCacheControl()) {
|
if (m_compiledOnce && canUsePipelineCacheControl()) {
|
||||||
pipeline = this->compileShaderPipeline(args,
|
pipeline = this->compileShaderPipeline(args,
|
||||||
VK_PIPELINE_CREATE_FAIL_ON_PIPELINE_COMPILE_REQUIRED_BIT);
|
VK_PIPELINE_CREATE_FAIL_ON_PIPELINE_COMPILE_REQUIRED_BIT);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!pipeline)
|
if (!pipeline.handle)
|
||||||
pipeline = this->compileShaderPipeline(args, 0);
|
pipeline = this->compileShaderPipeline(args, 0);
|
||||||
|
|
||||||
// Well that didn't work
|
// Well that didn't work
|
||||||
if (!pipeline)
|
if (!pipeline.handle)
|
||||||
return VK_NULL_HANDLE;
|
return { VK_NULL_HANDLE, 0 };
|
||||||
|
|
||||||
// Increment stat counter the first time this
|
// Increment stat counter the first time this
|
||||||
// shader pipeline gets compiled successfully
|
// shader pipeline gets compiled successfully
|
||||||
@ -1144,7 +1144,7 @@ namespace dxvk {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
VkPipeline DxvkShaderPipelineLibrary::compileShaderPipeline(
|
DxvkShaderPipelineLibraryHandle DxvkShaderPipelineLibrary::compileShaderPipeline(
|
||||||
const DxvkShaderPipelineLibraryCompileArgs& args,
|
const DxvkShaderPipelineLibraryCompileArgs& args,
|
||||||
VkPipelineCreateFlags flags) {
|
VkPipelineCreateFlags flags) {
|
||||||
DxvkShaderStageInfo stageInfo(m_device);
|
DxvkShaderStageInfo stageInfo(m_device);
|
||||||
@ -1161,7 +1161,7 @@ namespace dxvk {
|
|||||||
// Fail if we have no idenfitier for whatever reason, caller
|
// Fail if we have no idenfitier for whatever reason, caller
|
||||||
// should fall back to the slow path if this happens
|
// should fall back to the slow path if this happens
|
||||||
if (!identifier->identifierSize)
|
if (!identifier->identifierSize)
|
||||||
return VK_NULL_HANDLE;
|
return { VK_NULL_HANDLE, 0 };
|
||||||
|
|
||||||
stageInfo.addStage(stage, *identifier, nullptr);
|
stageInfo.addStage(stage, *identifier, nullptr);
|
||||||
} else {
|
} else {
|
||||||
@ -1178,17 +1178,17 @@ namespace dxvk {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VkPipeline pipeline = VK_NULL_HANDLE;
|
||||||
|
|
||||||
if (stageMask & VK_SHADER_STAGE_VERTEX_BIT)
|
if (stageMask & VK_SHADER_STAGE_VERTEX_BIT)
|
||||||
return compileVertexShaderPipeline(args, stageInfo, flags);
|
pipeline = compileVertexShaderPipeline(args, stageInfo, flags);
|
||||||
|
else if (stageMask & VK_SHADER_STAGE_FRAGMENT_BIT)
|
||||||
if (stageMask & VK_SHADER_STAGE_FRAGMENT_BIT)
|
pipeline = compileFragmentShaderPipeline(stageInfo, flags);
|
||||||
return compileFragmentShaderPipeline(stageInfo, flags);
|
else if (stageMask & VK_SHADER_STAGE_COMPUTE_BIT)
|
||||||
|
pipeline = compileComputeShaderPipeline(stageInfo, flags);
|
||||||
if (stageMask & VK_SHADER_STAGE_COMPUTE_BIT)
|
|
||||||
return compileComputeShaderPipeline(stageInfo, flags);
|
|
||||||
|
|
||||||
// Should be unreachable
|
// Should be unreachable
|
||||||
return VK_NULL_HANDLE;
|
return { pipeline, flags };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1266,7 +1266,7 @@ namespace dxvk {
|
|||||||
VkPipeline pipeline = VK_NULL_HANDLE;
|
VkPipeline pipeline = VK_NULL_HANDLE;
|
||||||
VkResult vr = vk->vkCreateGraphicsPipelines(vk->device(), VK_NULL_HANDLE, 1, &info, nullptr, &pipeline);
|
VkResult vr = vk->vkCreateGraphicsPipelines(vk->device(), VK_NULL_HANDLE, 1, &info, nullptr, &pipeline);
|
||||||
|
|
||||||
if (vr && !(flags & VK_PIPELINE_CREATE_FAIL_ON_PIPELINE_COMPILE_REQUIRED_BIT))
|
if (vr && vr != VK_PIPELINE_COMPILE_REQUIRED_EXT)
|
||||||
Logger::err(str::format("DxvkShaderPipelineLibrary: Failed to create vertex shader pipeline: ", vr));
|
Logger::err(str::format("DxvkShaderPipelineLibrary: Failed to create vertex shader pipeline: ", vr));
|
||||||
|
|
||||||
return vr ? VK_NULL_HANDLE : pipeline;
|
return vr ? VK_NULL_HANDLE : pipeline;
|
||||||
@ -1377,7 +1377,7 @@ namespace dxvk {
|
|||||||
VkPipeline pipeline = VK_NULL_HANDLE;
|
VkPipeline pipeline = VK_NULL_HANDLE;
|
||||||
VkResult vr = vk->vkCreateComputePipelines(vk->device(), VK_NULL_HANDLE, 1, &info, nullptr, &pipeline);
|
VkResult vr = vk->vkCreateComputePipelines(vk->device(), VK_NULL_HANDLE, 1, &info, nullptr, &pipeline);
|
||||||
|
|
||||||
if (vr && !(flags & VK_PIPELINE_CREATE_FAIL_ON_PIPELINE_COMPILE_REQUIRED_BIT))
|
if (vr && vr != VK_PIPELINE_COMPILE_REQUIRED_EXT)
|
||||||
Logger::err(str::format("DxvkShaderPipelineLibrary: Failed to create compute shader pipeline: ", vr));
|
Logger::err(str::format("DxvkShaderPipelineLibrary: Failed to create compute shader pipeline: ", vr));
|
||||||
|
|
||||||
return vr ? VK_NULL_HANDLE : pipeline;
|
return vr ? VK_NULL_HANDLE : pipeline;
|
||||||
|
@ -482,6 +482,17 @@ namespace dxvk {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Pipeline library handle
|
||||||
|
*
|
||||||
|
* Stores a pipeline library handle and the necessary link flags.
|
||||||
|
*/
|
||||||
|
struct DxvkShaderPipelineLibraryHandle {
|
||||||
|
VkPipeline handle;
|
||||||
|
VkPipelineCreateFlags linkFlags;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Shader pipeline library
|
* \brief Shader pipeline library
|
||||||
*
|
*
|
||||||
@ -524,7 +535,7 @@ namespace dxvk {
|
|||||||
* \param [in] args Compile arguments
|
* \param [in] args Compile arguments
|
||||||
* \returns Vulkan pipeline handle
|
* \returns Vulkan pipeline handle
|
||||||
*/
|
*/
|
||||||
VkPipeline acquirePipelineHandle(
|
DxvkShaderPipelineLibraryHandle acquirePipelineHandle(
|
||||||
const DxvkShaderPipelineLibraryCompileArgs& args);
|
const DxvkShaderPipelineLibraryCompileArgs& args);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -552,21 +563,21 @@ namespace dxvk {
|
|||||||
DxvkShaderSet m_shaders;
|
DxvkShaderSet m_shaders;
|
||||||
const DxvkBindingLayoutObjects* m_layout;
|
const DxvkBindingLayoutObjects* m_layout;
|
||||||
|
|
||||||
dxvk::mutex m_mutex;
|
dxvk::mutex m_mutex;
|
||||||
VkPipeline m_pipeline = VK_NULL_HANDLE;
|
DxvkShaderPipelineLibraryHandle m_pipeline = { VK_NULL_HANDLE, 0 };
|
||||||
VkPipeline m_pipelineNoDepthClip = VK_NULL_HANDLE;
|
DxvkShaderPipelineLibraryHandle m_pipelineNoDepthClip = { VK_NULL_HANDLE, 0 };
|
||||||
uint32_t m_useCount = 0u;
|
uint32_t m_useCount = 0u;
|
||||||
bool m_compiledOnce = false;
|
bool m_compiledOnce = false;
|
||||||
|
|
||||||
dxvk::mutex m_identifierMutex;
|
dxvk::mutex m_identifierMutex;
|
||||||
DxvkShaderIdentifierSet m_identifiers;
|
DxvkShaderIdentifierSet m_identifiers;
|
||||||
|
|
||||||
void destroyShaderPipelinesLocked();
|
void destroyShaderPipelinesLocked();
|
||||||
|
|
||||||
VkPipeline compileShaderPipelineLocked(
|
DxvkShaderPipelineLibraryHandle compileShaderPipelineLocked(
|
||||||
const DxvkShaderPipelineLibraryCompileArgs& args);
|
const DxvkShaderPipelineLibraryCompileArgs& args);
|
||||||
|
|
||||||
VkPipeline compileShaderPipeline(
|
DxvkShaderPipelineLibraryHandle compileShaderPipeline(
|
||||||
const DxvkShaderPipelineLibraryCompileArgs& args,
|
const DxvkShaderPipelineLibraryCompileArgs& args,
|
||||||
VkPipelineCreateFlags flags);
|
VkPipelineCreateFlags flags);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user