mirror of
https://github.com/doitsujin/dxvk.git
synced 2024-12-13 07:08:50 +01:00
[dxvk] Create full pipeline layout with INDEPENDENT_SETS_BIT
And use it to link pipelines as well as descriptor binding. Should fix issues related to descriptors.
This commit is contained in:
parent
b51d7a3cc0
commit
5e1569593a
@ -119,7 +119,7 @@ namespace dxvk {
|
||||
|
||||
VkComputePipelineCreateInfo info = { VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO };
|
||||
info.stage = *stageInfo.getStageInfos();
|
||||
info.layout = m_bindings->getPipelineLayout();
|
||||
info.layout = m_bindings->getPipelineLayout(false);
|
||||
info.basePipelineIndex = -1;
|
||||
|
||||
// Time pipeline compilation for debugging purposes
|
||||
|
@ -84,7 +84,8 @@ namespace dxvk {
|
||||
// before any draw or dispatch command is recorded.
|
||||
m_flags.clr(
|
||||
DxvkContextFlag::GpRenderPassBound,
|
||||
DxvkContextFlag::GpXfbActive);
|
||||
DxvkContextFlag::GpXfbActive,
|
||||
DxvkContextFlag::GpIndependentSets);
|
||||
|
||||
m_flags.set(
|
||||
DxvkContextFlag::GpDirtyFramebuffer,
|
||||
@ -3995,6 +3996,7 @@ namespace dxvk {
|
||||
|
||||
m_flags.set(
|
||||
DxvkContextFlag::GpRenderPassBound,
|
||||
DxvkContextFlag::GpDirtyPipeline,
|
||||
DxvkContextFlag::GpDirtyPipelineState,
|
||||
DxvkContextFlag::GpDirtyVertexBuffers,
|
||||
DxvkContextFlag::GpDirtyIndexBuffer,
|
||||
@ -4006,7 +4008,9 @@ namespace dxvk {
|
||||
DxvkContextFlag::GpDirtyDepthBounds,
|
||||
DxvkContextFlag::DirtyPushConstants);
|
||||
|
||||
m_flags.clr(DxvkContextFlag::GpRenderPassSuspended);
|
||||
m_flags.clr(
|
||||
DxvkContextFlag::GpRenderPassSuspended,
|
||||
DxvkContextFlag::GpIndependentSets);
|
||||
|
||||
this->renderPassBindFramebuffer(
|
||||
m_state.om.framebufferInfo,
|
||||
@ -4470,6 +4474,8 @@ namespace dxvk {
|
||||
|
||||
|
||||
bool DxvkContext::updateGraphicsPipelineState(DxvkGlobalPipelineBarrier srcBarrier) {
|
||||
bool oldIndependentSets = m_flags.test(DxvkContextFlag::GpIndependentSets);
|
||||
|
||||
// Set up vertex buffer strides for active bindings
|
||||
for (uint32_t i = 0; i < m_state.gp.state.il.bindingCount(); i++) {
|
||||
const uint32_t binding = m_state.gp.state.ilBindings[i].binding();
|
||||
@ -4481,7 +4487,8 @@ namespace dxvk {
|
||||
m_flags.clr(DxvkContextFlag::GpDynamicBlendConstants,
|
||||
DxvkContextFlag::GpDynamicDepthBias,
|
||||
DxvkContextFlag::GpDynamicDepthBounds,
|
||||
DxvkContextFlag::GpDynamicStencilRef);
|
||||
DxvkContextFlag::GpDynamicStencilRef,
|
||||
DxvkContextFlag::GpIndependentSets);
|
||||
|
||||
m_flags.set(m_state.gp.state.useDynamicBlendConstants()
|
||||
? DxvkContextFlag::GpDynamicBlendConstants
|
||||
@ -4533,8 +4540,16 @@ namespace dxvk {
|
||||
|
||||
if (!m_state.gp.state.rs.depthBiasEnable())
|
||||
m_cmd->cmdSetDepthBias(0.0f, 0.0f, 0.0f);
|
||||
|
||||
m_flags.set(DxvkContextFlag::GpIndependentSets);
|
||||
}
|
||||
|
||||
// If necessary, dirty descriptor sets due to layout incompatibilities
|
||||
bool newIndependentSets = m_flags.test(DxvkContextFlag::GpIndependentSets);
|
||||
|
||||
if (newIndependentSets != oldIndependentSets)
|
||||
m_descriptorState.dirtyStages(VK_SHADER_STAGE_ALL_GRAPHICS);
|
||||
|
||||
// Emit barrier based on pipeline properties, in order to avoid
|
||||
// accidental write-after-read hazards after the render pass.
|
||||
DxvkGlobalPipelineBarrier pipelineBarrier = m_state.gp.pipeline->getGlobalBarrier(m_state.gp.state);
|
||||
@ -4570,6 +4585,9 @@ namespace dxvk {
|
||||
// For 64-bit applications, using templates is slower on some drivers.
|
||||
constexpr bool useDescriptorTemplates = env::is32BitHostPlatform();
|
||||
|
||||
bool independentSets = BindPoint == VK_PIPELINE_BIND_POINT_GRAPHICS
|
||||
&& m_flags.test(DxvkContextFlag::GpIndependentSets);
|
||||
|
||||
uint32_t layoutSetMask = layout->getSetMask();
|
||||
uint32_t dirtySetMask = BindPoint == VK_PIPELINE_BIND_POINT_GRAPHICS
|
||||
? m_descriptorState.getDirtyGraphicsSets()
|
||||
@ -4752,7 +4770,7 @@ namespace dxvk {
|
||||
uint32_t firstSet = setIndex + 1 - bindCount;
|
||||
|
||||
m_cmd->cmdBindDescriptorSets(BindPoint,
|
||||
layout->getPipelineLayout(),
|
||||
layout->getPipelineLayout(independentSets),
|
||||
firstSet, bindCount, &sets[firstSet],
|
||||
0, nullptr);
|
||||
|
||||
@ -5148,8 +5166,10 @@ namespace dxvk {
|
||||
if (!pushConstRange.size)
|
||||
return;
|
||||
|
||||
// Push constants should be compatible between complete and
|
||||
// independent layouts, so always ask for the complete one
|
||||
m_cmd->cmdPushConstants(
|
||||
bindings->getPipelineLayout(),
|
||||
bindings->getPipelineLayout(false),
|
||||
pushConstRange.stageFlags,
|
||||
pushConstRange.offset,
|
||||
pushConstRange.size,
|
||||
|
@ -39,6 +39,7 @@ namespace dxvk {
|
||||
GpDynamicDepthBias, ///< Depth bias is dynamic
|
||||
GpDynamicDepthBounds, ///< Depth bounds are dynamic
|
||||
GpDynamicStencilRef, ///< Stencil reference is dynamic
|
||||
GpIndependentSets, ///< Graphics pipeline layout was created with independent sets
|
||||
|
||||
CpDirtyPipeline, ///< Compute pipeline binding are out of date
|
||||
CpDirtyPipelineState, ///< Compute pipeline needs to be recompiled
|
||||
|
@ -164,14 +164,14 @@ namespace dxvk {
|
||||
|
||||
DxvkDescriptorSetMap* DxvkDescriptorPool::getSetMap(
|
||||
const DxvkBindingLayoutObjects* layout) {
|
||||
auto pair = m_setMaps.find(layout->getPipelineLayout());
|
||||
auto pair = m_setMaps.find(layout->getPipelineLayout(false));
|
||||
if (likely(pair != m_setMaps.end())) {
|
||||
return &pair->second;
|
||||
}
|
||||
|
||||
auto iter = m_setMaps.emplace(
|
||||
std::piecewise_construct,
|
||||
std::tuple(layout->getPipelineLayout()),
|
||||
std::tuple(layout->getPipelineLayout(false)),
|
||||
std::tuple());
|
||||
|
||||
for (uint32_t i = 0; i < DxvkDescriptorSets::SetCount; i++) {
|
||||
|
@ -702,6 +702,8 @@ namespace dxvk {
|
||||
libInfo.pLibraries = libraries.data();
|
||||
|
||||
VkGraphicsPipelineCreateInfo info = { VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, &libInfo };
|
||||
info.layout = m_bindings->getPipelineLayout(true);
|
||||
info.basePipelineIndex = -1;
|
||||
|
||||
VkPipeline pipeline = VK_NULL_HANDLE;
|
||||
|
||||
@ -790,7 +792,7 @@ namespace dxvk {
|
||||
info.pDepthStencilState = &fsState.dsInfo;
|
||||
info.pColorBlendState = &foState.cbInfo;
|
||||
info.pDynamicState = &dyInfo;
|
||||
info.layout = m_bindings->getPipelineLayout();
|
||||
info.layout = m_bindings->getPipelineLayout(false);
|
||||
info.basePipelineIndex = -1;
|
||||
|
||||
if (!prState.tsInfo.patchControlPoints)
|
||||
|
@ -323,29 +323,40 @@ namespace dxvk {
|
||||
}
|
||||
}
|
||||
|
||||
// Create pipeline layout objects
|
||||
VkPushConstantRange pushConst = m_layout.getPushConstantRange();
|
||||
|
||||
VkPipelineLayoutCreateInfo pipelineLayoutInfo = { VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO };
|
||||
pipelineLayoutInfo.setLayoutCount = setLayouts.size();
|
||||
pipelineLayoutInfo.pSetLayouts = setLayouts.data();
|
||||
|
||||
if (m_layout.getSetMask() != (1u << DxvkDescriptorSets::SetCount) - 1)
|
||||
pipelineLayoutInfo.flags = VK_PIPELINE_LAYOUT_CREATE_INDEPENDENT_SETS_BIT_EXT;
|
||||
|
||||
if (pushConst.stageFlags && pushConst.size) {
|
||||
pipelineLayoutInfo.pushConstantRangeCount = 1;
|
||||
pipelineLayoutInfo.pPushConstantRanges = &pushConst;
|
||||
}
|
||||
|
||||
if (vk->vkCreatePipelineLayout(vk->device(), &pipelineLayoutInfo, nullptr, &m_pipelineLayout))
|
||||
// If the full set is defined, create a layout without INDEPENDENT_SET_BITS
|
||||
if (m_layout.getSetMask() == (1u << DxvkDescriptorSets::SetCount) - 1) {
|
||||
if (vk->vkCreatePipelineLayout(vk->device(), &pipelineLayoutInfo, nullptr, &m_completeLayout))
|
||||
throw DxvkError("DxvkBindingLayoutObjects: Failed to create pipeline layout");
|
||||
}
|
||||
|
||||
// If graphics pipeline libraries are supported, also create a variand with the
|
||||
// bit. It will be used to create shader-based libraries and link pipelines.
|
||||
if (m_device->canUseGraphicsPipelineLibrary() && (m_layout.getStages() & VK_SHADER_STAGE_ALL_GRAPHICS)) {
|
||||
pipelineLayoutInfo.flags = VK_PIPELINE_LAYOUT_CREATE_INDEPENDENT_SETS_BIT_EXT;
|
||||
|
||||
if (vk->vkCreatePipelineLayout(vk->device(), &pipelineLayoutInfo, nullptr, &m_independentLayout))
|
||||
throw DxvkError("DxvkBindingLayoutObjects: Failed to create pipeline layout");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
DxvkBindingLayoutObjects::~DxvkBindingLayoutObjects() {
|
||||
auto vk = m_device->vkd();
|
||||
|
||||
vk->vkDestroyPipelineLayout(vk->device(), m_pipelineLayout, nullptr);
|
||||
vk->vkDestroyPipelineLayout(vk->device(), m_completeLayout, nullptr);
|
||||
vk->vkDestroyPipelineLayout(vk->device(), m_independentLayout, nullptr);
|
||||
}
|
||||
|
||||
|
||||
|
@ -304,6 +304,14 @@ namespace dxvk {
|
||||
return m_pushConst;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Queries shader stages
|
||||
* \returns Shader stages
|
||||
*/
|
||||
VkShaderStageFlags getStages() const {
|
||||
return m_stages;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Queries defined descriptor set layouts
|
||||
*
|
||||
@ -433,10 +441,14 @@ namespace dxvk {
|
||||
|
||||
/**
|
||||
* \brief Retrieves pipeline layout
|
||||
* \returns Pipeline layout
|
||||
*
|
||||
* \param [in] independent Request INDEPENDENT_SETS_BIT
|
||||
* \returns Pipeline layout handle
|
||||
*/
|
||||
VkPipelineLayout getPipelineLayout() const {
|
||||
return m_pipelineLayout;
|
||||
VkPipelineLayout getPipelineLayout(bool independent) const {
|
||||
return independent
|
||||
? m_independentLayout
|
||||
: m_completeLayout;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -468,7 +480,8 @@ namespace dxvk {
|
||||
|
||||
DxvkDevice* m_device;
|
||||
DxvkBindingLayout m_layout;
|
||||
VkPipelineLayout m_pipelineLayout = VK_NULL_HANDLE;
|
||||
VkPipelineLayout m_completeLayout = VK_NULL_HANDLE;
|
||||
VkPipelineLayout m_independentLayout = VK_NULL_HANDLE;
|
||||
|
||||
uint32_t m_setMask = 0;
|
||||
|
||||
|
@ -547,7 +547,7 @@ namespace dxvk {
|
||||
info.pViewportState = &vpInfo;
|
||||
info.pRasterizationState = &rsInfo;
|
||||
info.pDynamicState = &dyInfo;
|
||||
info.layout = m_layout->getPipelineLayout();
|
||||
info.layout = m_layout->getPipelineLayout(true);
|
||||
info.basePipelineIndex = -1;
|
||||
|
||||
VkPipeline pipeline = VK_NULL_HANDLE;
|
||||
@ -625,7 +625,7 @@ namespace dxvk {
|
||||
info.pStages = stageInfo.getStageInfos();
|
||||
info.pDepthStencilState = &dsInfo;
|
||||
info.pDynamicState = &dyInfo;
|
||||
info.layout = m_layout->getPipelineLayout();
|
||||
info.layout = m_layout->getPipelineLayout(true);
|
||||
info.basePipelineIndex = -1;
|
||||
|
||||
if (m_shader && m_shader->flags().test(DxvkShaderFlag::HasSampleRateShading))
|
||||
@ -650,7 +650,7 @@ namespace dxvk {
|
||||
// Compile the compute pipeline as normal
|
||||
VkComputePipelineCreateInfo info = { VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO };
|
||||
info.stage = *stageInfo.getStageInfos();
|
||||
info.layout = m_layout->getPipelineLayout();
|
||||
info.layout = m_layout->getPipelineLayout(false);
|
||||
info.basePipelineIndex = -1;
|
||||
|
||||
VkPipeline pipeline = VK_NULL_HANDLE;
|
||||
|
Loading…
Reference in New Issue
Block a user