mirror of
https://github.com/doitsujin/dxvk.git
synced 2024-12-02 19:24:12 +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
|
||||
// compile the pipeline immediately on the calling thread.
|
||||
m_libraryHandle = m_library->acquirePipelineHandle(
|
||||
DxvkShaderPipelineLibraryCompileArgs());
|
||||
DxvkShaderPipelineLibraryCompileArgs()).handle;
|
||||
|
||||
return m_libraryHandle;
|
||||
} else {
|
||||
|
@ -1111,7 +1111,8 @@ namespace dxvk {
|
||||
|
||||
if (doCreateBasePipeline)
|
||||
baseHandle = this->getBasePipeline(state);
|
||||
else
|
||||
|
||||
if (!baseHandle)
|
||||
fastHandle = this->getOptimizedPipeline(state);
|
||||
|
||||
// Log pipeline state if requested, or on failure
|
||||
@ -1236,10 +1237,11 @@ 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);
|
||||
|
||||
std::array<VkPipeline, 4> libraries = {{
|
||||
key.viLibrary->getHandle(),
|
||||
m_vsLibrary->acquirePipelineHandle(key.args),
|
||||
m_fsLibrary->acquirePipelineHandle(key.args),
|
||||
key.viLibrary->getHandle(), vs.handle, fs.handle,
|
||||
key.foLibrary->getHandle(),
|
||||
}};
|
||||
|
||||
@ -1248,13 +1250,14 @@ namespace dxvk {
|
||||
libInfo.pLibraries = libraries.data();
|
||||
|
||||
VkGraphicsPipelineCreateInfo info = { VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, &libInfo };
|
||||
info.flags = vs.linkFlags | fs.linkFlags;
|
||||
info.layout = m_bindings->getPipelineLayout(true);
|
||||
info.basePipelineIndex = -1;
|
||||
|
||||
VkPipeline pipeline = VK_NULL_HANDLE;
|
||||
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));
|
||||
|
||||
return pipeline;
|
||||
|
@ -1042,18 +1042,18 @@ namespace dxvk {
|
||||
}
|
||||
|
||||
|
||||
VkPipeline DxvkShaderPipelineLibrary::acquirePipelineHandle(
|
||||
DxvkShaderPipelineLibraryHandle DxvkShaderPipelineLibrary::acquirePipelineHandle(
|
||||
const DxvkShaderPipelineLibraryCompileArgs& args) {
|
||||
std::lock_guard lock(m_mutex);
|
||||
|
||||
if (m_device->mustTrackPipelineLifetime())
|
||||
m_useCount += 1;
|
||||
|
||||
VkPipeline& pipeline = (m_shaders.vs && !args.depthClipEnable)
|
||||
DxvkShaderPipelineLibraryHandle& pipeline = (m_shaders.vs && !args.depthClipEnable)
|
||||
? m_pipelineNoDepthClip
|
||||
: m_pipeline;
|
||||
|
||||
if (pipeline)
|
||||
if (pipeline.handle)
|
||||
return pipeline;
|
||||
|
||||
pipeline = compileShaderPipelineLocked(args);
|
||||
@ -1079,7 +1079,7 @@ namespace dxvk {
|
||||
return;
|
||||
|
||||
// Compile the pipeline with default args
|
||||
VkPipeline pipeline = compileShaderPipelineLocked(
|
||||
DxvkShaderPipelineLibraryHandle pipeline = compileShaderPipelineLocked(
|
||||
DxvkShaderPipelineLibraryCompileArgs());
|
||||
|
||||
// On 32-bit, destroy the pipeline immediately in order to
|
||||
@ -1087,9 +1087,9 @@ namespace dxvk {
|
||||
// we need to recreate the pipeline.
|
||||
if (m_device->mustTrackPipelineLifetime()) {
|
||||
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
|
||||
@ -1100,34 +1100,34 @@ namespace dxvk {
|
||||
void DxvkShaderPipelineLibrary::destroyShaderPipelinesLocked() {
|
||||
auto vk = m_device->vkd();
|
||||
|
||||
vk->vkDestroyPipeline(vk->device(), m_pipeline, nullptr);
|
||||
vk->vkDestroyPipeline(vk->device(), m_pipelineNoDepthClip, nullptr);
|
||||
vk->vkDestroyPipeline(vk->device(), m_pipeline.handle, nullptr);
|
||||
vk->vkDestroyPipeline(vk->device(), m_pipelineNoDepthClip.handle, nullptr);
|
||||
|
||||
m_pipeline = VK_NULL_HANDLE;
|
||||
m_pipelineNoDepthClip = VK_NULL_HANDLE;
|
||||
m_pipeline.handle = VK_NULL_HANDLE;
|
||||
m_pipelineNoDepthClip.handle = VK_NULL_HANDLE;
|
||||
}
|
||||
|
||||
|
||||
VkPipeline DxvkShaderPipelineLibrary::compileShaderPipelineLocked(
|
||||
DxvkShaderPipelineLibraryHandle DxvkShaderPipelineLibrary::compileShaderPipelineLocked(
|
||||
const DxvkShaderPipelineLibraryCompileArgs& args) {
|
||||
this->notifyLibraryCompile();
|
||||
|
||||
// If this is not the first time we're compiling the pipeline,
|
||||
// try to get a cache hit using the shader module identifier
|
||||
// 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()) {
|
||||
pipeline = this->compileShaderPipeline(args,
|
||||
VK_PIPELINE_CREATE_FAIL_ON_PIPELINE_COMPILE_REQUIRED_BIT);
|
||||
}
|
||||
|
||||
if (!pipeline)
|
||||
if (!pipeline.handle)
|
||||
pipeline = this->compileShaderPipeline(args, 0);
|
||||
|
||||
// Well that didn't work
|
||||
if (!pipeline)
|
||||
return VK_NULL_HANDLE;
|
||||
if (!pipeline.handle)
|
||||
return { VK_NULL_HANDLE, 0 };
|
||||
|
||||
// Increment stat counter the first time this
|
||||
// shader pipeline gets compiled successfully
|
||||
@ -1144,7 +1144,7 @@ namespace dxvk {
|
||||
}
|
||||
|
||||
|
||||
VkPipeline DxvkShaderPipelineLibrary::compileShaderPipeline(
|
||||
DxvkShaderPipelineLibraryHandle DxvkShaderPipelineLibrary::compileShaderPipeline(
|
||||
const DxvkShaderPipelineLibraryCompileArgs& args,
|
||||
VkPipelineCreateFlags flags) {
|
||||
DxvkShaderStageInfo stageInfo(m_device);
|
||||
@ -1161,7 +1161,7 @@ namespace dxvk {
|
||||
// Fail if we have no idenfitier for whatever reason, caller
|
||||
// should fall back to the slow path if this happens
|
||||
if (!identifier->identifierSize)
|
||||
return VK_NULL_HANDLE;
|
||||
return { VK_NULL_HANDLE, 0 };
|
||||
|
||||
stageInfo.addStage(stage, *identifier, nullptr);
|
||||
} else {
|
||||
@ -1178,17 +1178,17 @@ namespace dxvk {
|
||||
}
|
||||
}
|
||||
|
||||
VkPipeline pipeline = VK_NULL_HANDLE;
|
||||
|
||||
if (stageMask & VK_SHADER_STAGE_VERTEX_BIT)
|
||||
return compileVertexShaderPipeline(args, stageInfo, flags);
|
||||
|
||||
if (stageMask & VK_SHADER_STAGE_FRAGMENT_BIT)
|
||||
return compileFragmentShaderPipeline(stageInfo, flags);
|
||||
|
||||
if (stageMask & VK_SHADER_STAGE_COMPUTE_BIT)
|
||||
return compileComputeShaderPipeline(stageInfo, flags);
|
||||
pipeline = compileVertexShaderPipeline(args, stageInfo, flags);
|
||||
else if (stageMask & VK_SHADER_STAGE_FRAGMENT_BIT)
|
||||
pipeline = compileFragmentShaderPipeline(stageInfo, flags);
|
||||
else if (stageMask & VK_SHADER_STAGE_COMPUTE_BIT)
|
||||
pipeline = compileComputeShaderPipeline(stageInfo, flags);
|
||||
|
||||
// Should be unreachable
|
||||
return VK_NULL_HANDLE;
|
||||
return { pipeline, flags };
|
||||
}
|
||||
|
||||
|
||||
@ -1266,7 +1266,7 @@ namespace dxvk {
|
||||
VkPipeline pipeline = VK_NULL_HANDLE;
|
||||
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));
|
||||
|
||||
return vr ? VK_NULL_HANDLE : pipeline;
|
||||
@ -1377,7 +1377,7 @@ namespace dxvk {
|
||||
VkPipeline pipeline = VK_NULL_HANDLE;
|
||||
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));
|
||||
|
||||
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
|
||||
*
|
||||
@ -524,7 +535,7 @@ namespace dxvk {
|
||||
* \param [in] args Compile arguments
|
||||
* \returns Vulkan pipeline handle
|
||||
*/
|
||||
VkPipeline acquirePipelineHandle(
|
||||
DxvkShaderPipelineLibraryHandle acquirePipelineHandle(
|
||||
const DxvkShaderPipelineLibraryCompileArgs& args);
|
||||
|
||||
/**
|
||||
@ -553,8 +564,8 @@ namespace dxvk {
|
||||
const DxvkBindingLayoutObjects* m_layout;
|
||||
|
||||
dxvk::mutex m_mutex;
|
||||
VkPipeline m_pipeline = VK_NULL_HANDLE;
|
||||
VkPipeline m_pipelineNoDepthClip = VK_NULL_HANDLE;
|
||||
DxvkShaderPipelineLibraryHandle m_pipeline = { VK_NULL_HANDLE, 0 };
|
||||
DxvkShaderPipelineLibraryHandle m_pipelineNoDepthClip = { VK_NULL_HANDLE, 0 };
|
||||
uint32_t m_useCount = 0u;
|
||||
bool m_compiledOnce = false;
|
||||
|
||||
@ -563,10 +574,10 @@ namespace dxvk {
|
||||
|
||||
void destroyShaderPipelinesLocked();
|
||||
|
||||
VkPipeline compileShaderPipelineLocked(
|
||||
DxvkShaderPipelineLibraryHandle compileShaderPipelineLocked(
|
||||
const DxvkShaderPipelineLibraryCompileArgs& args);
|
||||
|
||||
VkPipeline compileShaderPipeline(
|
||||
DxvkShaderPipelineLibraryHandle compileShaderPipeline(
|
||||
const DxvkShaderPipelineLibraryCompileArgs& args,
|
||||
VkPipelineCreateFlags flags);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user