mirror of
https://github.com/doitsujin/dxvk.git
synced 2025-03-11 04:29:15 +01:00
[dxvk] Implement proper compute pipeline lookup
Fixes correctness issues and potential GPU lockups in case a compute shader resource is not bound at dispatch time.
This commit is contained in:
parent
05da53a570
commit
c931b4ba87
@ -29,25 +29,35 @@ namespace dxvk {
|
||||
slotMapping.bindingInfos());
|
||||
|
||||
m_cs = cs->createShaderModule(m_vkd, slotMapping);
|
||||
|
||||
this->compilePipeline();
|
||||
}
|
||||
|
||||
|
||||
DxvkComputePipeline::~DxvkComputePipeline() {
|
||||
if (m_pipeline != VK_NULL_HANDLE)
|
||||
m_vkd->vkDestroyPipeline(m_vkd->device(), m_pipeline, nullptr);
|
||||
this->destroyPipelines();
|
||||
}
|
||||
|
||||
|
||||
VkPipeline DxvkComputePipeline::getPipelineHandle(
|
||||
const DxvkComputePipelineStateInfo& state) const {
|
||||
// TODO take pipeine state into account
|
||||
return m_pipeline;
|
||||
const DxvkComputePipelineStateInfo& state) {
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
|
||||
for (const PipelineStruct& pair : m_pipelines) {
|
||||
if (pair.stateVector == state)
|
||||
return pair.pipeline;
|
||||
}
|
||||
|
||||
VkPipeline pipeline = this->compilePipeline(state, m_basePipeline);
|
||||
m_pipelines.push_back({ state, pipeline });
|
||||
|
||||
if (m_basePipeline == VK_NULL_HANDLE)
|
||||
m_basePipeline = pipeline;
|
||||
return pipeline;
|
||||
}
|
||||
|
||||
|
||||
void DxvkComputePipeline::compilePipeline() {
|
||||
VkPipeline DxvkComputePipeline::compilePipeline(
|
||||
const DxvkComputePipelineStateInfo& state,
|
||||
VkPipeline baseHandle) const {
|
||||
std::vector<VkDescriptorSetLayoutBinding> bindings;
|
||||
|
||||
if (Logger::logLevel() <= LogLevel::Debug) {
|
||||
@ -55,18 +65,45 @@ namespace dxvk {
|
||||
Logger::debug(str::format(" cs : ", m_cs ->debugName()));
|
||||
}
|
||||
|
||||
std::array<VkBool32, MaxNumActiveBindings> specData;
|
||||
std::array<VkSpecializationMapEntry, MaxNumActiveBindings> specMap;
|
||||
|
||||
for (uint32_t i = 0; i < MaxNumActiveBindings; i++) {
|
||||
specData[i] = state.bsBindingState.isBound(i) ? VK_TRUE : VK_FALSE;
|
||||
specMap [i] = { i, static_cast<uint32_t>(sizeof(VkBool32)) * i, sizeof(VkBool32) };
|
||||
}
|
||||
|
||||
VkSpecializationInfo specInfo;
|
||||
specInfo.mapEntryCount = specMap.size();
|
||||
specInfo.pMapEntries = specMap.data();
|
||||
specInfo.dataSize = specData.size() * sizeof(VkBool32);
|
||||
specInfo.pData = specData.data();
|
||||
|
||||
VkComputePipelineCreateInfo info;
|
||||
info.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO;
|
||||
info.pNext = nullptr;
|
||||
info.flags = 0;
|
||||
info.stage = m_cs->stageInfo(nullptr);
|
||||
info.flags = baseHandle == VK_NULL_HANDLE
|
||||
? VK_PIPELINE_CREATE_ALLOW_DERIVATIVES_BIT
|
||||
: VK_PIPELINE_CREATE_DERIVATIVE_BIT;
|
||||
info.stage = m_cs->stageInfo(&specInfo);
|
||||
info.layout = m_layout->pipelineLayout();
|
||||
info.basePipelineHandle = VK_NULL_HANDLE;
|
||||
info.basePipelineHandle = baseHandle;
|
||||
info.basePipelineIndex = -1;
|
||||
|
||||
VkPipeline pipeline = VK_NULL_HANDLE;
|
||||
if (m_vkd->vkCreateComputePipelines(m_vkd->device(),
|
||||
m_cache->handle(), 1, &info, nullptr, &m_pipeline) != VK_SUCCESS)
|
||||
m_cache->handle(), 1, &info, nullptr, &pipeline) != VK_SUCCESS) {
|
||||
Logger::err("DxvkComputePipeline: Failed to compile pipeline");
|
||||
return VK_NULL_HANDLE;
|
||||
}
|
||||
|
||||
return pipeline;
|
||||
}
|
||||
|
||||
|
||||
void DxvkComputePipeline::destroyPipelines() {
|
||||
for (const PipelineStruct& pair : m_pipelines)
|
||||
m_vkd->vkDestroyPipeline(m_vkd->device(), pair.pipeline, nullptr);
|
||||
}
|
||||
|
||||
}
|
@ -58,10 +58,15 @@ namespace dxvk {
|
||||
* \returns Pipeline handle
|
||||
*/
|
||||
VkPipeline getPipelineHandle(
|
||||
const DxvkComputePipelineStateInfo& state) const;
|
||||
const DxvkComputePipelineStateInfo& state);
|
||||
|
||||
private:
|
||||
|
||||
struct PipelineStruct {
|
||||
DxvkComputePipelineStateInfo stateVector;
|
||||
VkPipeline pipeline;
|
||||
};
|
||||
|
||||
const DxvkDevice* const m_device;
|
||||
const Rc<vk::DeviceFn> m_vkd;
|
||||
|
||||
@ -69,9 +74,16 @@ namespace dxvk {
|
||||
Rc<DxvkPipelineLayout> m_layout;
|
||||
Rc<DxvkShaderModule> m_cs;
|
||||
|
||||
VkPipeline m_pipeline = VK_NULL_HANDLE;
|
||||
std::mutex m_mutex;
|
||||
std::vector<PipelineStruct> m_pipelines;
|
||||
|
||||
void compilePipeline();
|
||||
VkPipeline m_basePipeline = VK_NULL_HANDLE;
|
||||
|
||||
VkPipeline compilePipeline(
|
||||
const DxvkComputePipelineStateInfo& state,
|
||||
VkPipeline baseHandle) const;
|
||||
|
||||
void destroyPipelines();
|
||||
|
||||
};
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user