mirror of
https://github.com/doitsujin/dxvk.git
synced 2025-03-14 22:29:15 +01:00
[dxvk] Ignore spec constants that are not used by the current pipeline
May reduce the number of pipeline permutations.
This commit is contained in:
parent
47794b661e
commit
94ca65d587
@ -90,6 +90,17 @@ namespace dxvk {
|
|||||||
DxvkBindingLayoutObjects* getBindings() const {
|
DxvkBindingLayoutObjects* getBindings() const {
|
||||||
return m_bindings;
|
return m_bindings;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Queries spec constant mask
|
||||||
|
*
|
||||||
|
* This only includes user spec constants.
|
||||||
|
* \returns Bit mask of used spec constants
|
||||||
|
*/
|
||||||
|
uint32_t getSpecConstantMask() const {
|
||||||
|
constexpr uint32_t globalMask = (1u << MaxNumSpecConstants) - 1;
|
||||||
|
return m_shaders.cs->getSpecConstantMask() & globalMask;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Retrieves pipeline handle
|
* \brief Retrieves pipeline handle
|
||||||
|
@ -2524,24 +2524,6 @@ namespace dxvk {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void DxvkContext::setSpecConstant(
|
|
||||||
VkPipelineBindPoint pipeline,
|
|
||||||
uint32_t index,
|
|
||||||
uint32_t value) {
|
|
||||||
auto& specConst = pipeline == VK_PIPELINE_BIND_POINT_GRAPHICS
|
|
||||||
? m_state.gp.state.sc.specConstants[index]
|
|
||||||
: m_state.cp.state.sc.specConstants[index];
|
|
||||||
|
|
||||||
if (specConst != value) {
|
|
||||||
specConst = value;
|
|
||||||
|
|
||||||
m_flags.set(pipeline == VK_PIPELINE_BIND_POINT_GRAPHICS
|
|
||||||
? DxvkContextFlag::GpDirtyPipelineState
|
|
||||||
: DxvkContextFlag::CpDirtyPipelineState);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void DxvkContext::setBarrierControl(DxvkBarrierControlFlags control) {
|
void DxvkContext::setBarrierControl(DxvkBarrierControlFlags control) {
|
||||||
m_barrierControl = control;
|
m_barrierControl = control;
|
||||||
}
|
}
|
||||||
@ -4493,6 +4475,12 @@ namespace dxvk {
|
|||||||
if (unlikely(!newPipeline))
|
if (unlikely(!newPipeline))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
if (unlikely(newPipeline->getSpecConstantMask() != m_state.cp.constants.mask))
|
||||||
|
this->resetSpecConstants<VK_PIPELINE_BIND_POINT_COMPUTE>(newPipeline->getSpecConstantMask());
|
||||||
|
|
||||||
|
if (m_flags.test(DxvkContextFlag::CpDirtySpecConstants))
|
||||||
|
this->updateSpecConstants<VK_PIPELINE_BIND_POINT_COMPUTE>();
|
||||||
|
|
||||||
// Look up Vulkan pipeline handle for the given compute state
|
// Look up Vulkan pipeline handle for the given compute state
|
||||||
auto pipelineHandle = newPipeline->getPipelineHandle(m_state.cp.state);
|
auto pipelineHandle = newPipeline->getPipelineHandle(m_state.cp.state);
|
||||||
|
|
||||||
@ -4545,6 +4533,9 @@ namespace dxvk {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (unlikely(newPipeline->getSpecConstantMask() != m_state.gp.constants.mask))
|
||||||
|
this->resetSpecConstants<VK_PIPELINE_BIND_POINT_GRAPHICS>(newPipeline->getSpecConstantMask());
|
||||||
|
|
||||||
if (m_state.gp.flags != newPipeline->flags()) {
|
if (m_state.gp.flags != newPipeline->flags()) {
|
||||||
m_state.gp.flags = newPipeline->flags();
|
m_state.gp.flags = newPipeline->flags();
|
||||||
|
|
||||||
@ -4656,6 +4647,49 @@ namespace dxvk {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<VkPipelineBindPoint BindPoint>
|
||||||
|
void DxvkContext::resetSpecConstants(
|
||||||
|
uint32_t newMask) {
|
||||||
|
auto& scInfo = BindPoint == VK_PIPELINE_BIND_POINT_GRAPHICS ? m_state.gp.state.sc : m_state.cp.state.sc;
|
||||||
|
auto& scState = BindPoint == VK_PIPELINE_BIND_POINT_GRAPHICS ? m_state.gp.constants : m_state.cp.constants;
|
||||||
|
|
||||||
|
// Set all constants to 0 that were used by the previous pipeline
|
||||||
|
// but are not used by the old one. Any stale data could otherwise
|
||||||
|
// lead to unnecessary pipeline variants being created.
|
||||||
|
for (auto i : bit::BitMask(scState.mask & ~newMask))
|
||||||
|
scInfo.specConstants[i] = 0;
|
||||||
|
|
||||||
|
scState.mask = newMask;
|
||||||
|
|
||||||
|
auto flag = BindPoint == VK_PIPELINE_BIND_POINT_GRAPHICS
|
||||||
|
? DxvkContextFlag::GpDirtySpecConstants
|
||||||
|
: DxvkContextFlag::CpDirtySpecConstants;
|
||||||
|
|
||||||
|
if (newMask)
|
||||||
|
m_flags.set(flag);
|
||||||
|
else
|
||||||
|
m_flags.clr(flag);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<VkPipelineBindPoint BindPoint>
|
||||||
|
void DxvkContext::updateSpecConstants() {
|
||||||
|
auto& scInfo = BindPoint == VK_PIPELINE_BIND_POINT_GRAPHICS ? m_state.gp.state.sc : m_state.cp.state.sc;
|
||||||
|
auto& scState = BindPoint == VK_PIPELINE_BIND_POINT_GRAPHICS ? m_state.gp.constants : m_state.cp.constants;
|
||||||
|
|
||||||
|
for (auto i : bit::BitMask(scState.mask))
|
||||||
|
scInfo.specConstants[i] = scState.data[i];
|
||||||
|
|
||||||
|
if (BindPoint == VK_PIPELINE_BIND_POINT_GRAPHICS) {
|
||||||
|
m_flags.clr(DxvkContextFlag::GpDirtySpecConstants);
|
||||||
|
m_flags.set(DxvkContextFlag::GpDirtyPipelineState);
|
||||||
|
} else {
|
||||||
|
m_flags.clr(DxvkContextFlag::CpDirtySpecConstants);
|
||||||
|
m_flags.set(DxvkContextFlag::CpDirtyPipelineState);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void DxvkContext::invalidateState() {
|
void DxvkContext::invalidateState() {
|
||||||
this->unbindComputePipeline();
|
this->unbindComputePipeline();
|
||||||
this->unbindGraphicsPipeline();
|
this->unbindGraphicsPipeline();
|
||||||
@ -5348,7 +5382,9 @@ namespace dxvk {
|
|||||||
bool DxvkContext::commitComputeState() {
|
bool DxvkContext::commitComputeState() {
|
||||||
this->spillRenderPass(false);
|
this->spillRenderPass(false);
|
||||||
|
|
||||||
if (m_flags.test(DxvkContextFlag::CpDirtyPipelineState)) {
|
if (m_flags.any(
|
||||||
|
DxvkContextFlag::CpDirtyPipelineState,
|
||||||
|
DxvkContextFlag::CpDirtySpecConstants)) {
|
||||||
if (unlikely(!this->updateComputePipelineState()))
|
if (unlikely(!this->updateComputePipelineState()))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -5397,6 +5433,9 @@ namespace dxvk {
|
|||||||
if (m_flags.test(DxvkContextFlag::GpDirtyVertexBuffers))
|
if (m_flags.test(DxvkContextFlag::GpDirtyVertexBuffers))
|
||||||
this->updateVertexBufferBindings();
|
this->updateVertexBufferBindings();
|
||||||
|
|
||||||
|
if (m_flags.test(DxvkContextFlag::GpDirtySpecConstants))
|
||||||
|
this->updateSpecConstants<VK_PIPELINE_BIND_POINT_GRAPHICS>();
|
||||||
|
|
||||||
if (m_flags.test(DxvkContextFlag::GpDirtyPipelineState)) {
|
if (m_flags.test(DxvkContextFlag::GpDirtyPipelineState)) {
|
||||||
DxvkGlobalPipelineBarrier barrier = { };
|
DxvkGlobalPipelineBarrier barrier = { };
|
||||||
|
|
||||||
|
@ -1033,7 +1033,20 @@ namespace dxvk {
|
|||||||
void setSpecConstant(
|
void setSpecConstant(
|
||||||
VkPipelineBindPoint pipeline,
|
VkPipelineBindPoint pipeline,
|
||||||
uint32_t index,
|
uint32_t index,
|
||||||
uint32_t value);
|
uint32_t value) {
|
||||||
|
auto& scState = pipeline == VK_PIPELINE_BIND_POINT_GRAPHICS
|
||||||
|
? m_state.gp.constants : m_state.cp.constants;
|
||||||
|
|
||||||
|
if (scState.data[index] != value) {
|
||||||
|
scState.data[index] = value;
|
||||||
|
|
||||||
|
if (scState.mask & (1u << index)) {
|
||||||
|
m_flags.set(pipeline == VK_PIPELINE_BIND_POINT_GRAPHICS
|
||||||
|
? DxvkContextFlag::GpDirtySpecConstants
|
||||||
|
: DxvkContextFlag::CpDirtySpecConstants);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Sets barrier control flags
|
* \brief Sets barrier control flags
|
||||||
@ -1347,7 +1360,14 @@ namespace dxvk {
|
|||||||
void unbindGraphicsPipeline();
|
void unbindGraphicsPipeline();
|
||||||
bool updateGraphicsPipeline();
|
bool updateGraphicsPipeline();
|
||||||
bool updateGraphicsPipelineState(DxvkGlobalPipelineBarrier srcBarrier);
|
bool updateGraphicsPipelineState(DxvkGlobalPipelineBarrier srcBarrier);
|
||||||
|
|
||||||
|
template<VkPipelineBindPoint BindPoint>
|
||||||
|
void resetSpecConstants(
|
||||||
|
uint32_t newMask);
|
||||||
|
|
||||||
|
template<VkPipelineBindPoint BindPoint>
|
||||||
|
void updateSpecConstants();
|
||||||
|
|
||||||
void invalidateState();
|
void invalidateState();
|
||||||
|
|
||||||
template<VkPipelineBindPoint BindPoint>
|
template<VkPipelineBindPoint BindPoint>
|
||||||
|
@ -37,6 +37,7 @@ namespace dxvk {
|
|||||||
GpDirtyStencilRef, ///< Stencil reference has changed
|
GpDirtyStencilRef, ///< Stencil reference has changed
|
||||||
GpDirtyRasterizerState, ///< Cull mode and front face have changed
|
GpDirtyRasterizerState, ///< Cull mode and front face have changed
|
||||||
GpDirtyViewport, ///< Viewport state has changed
|
GpDirtyViewport, ///< Viewport state has changed
|
||||||
|
GpDirtySpecConstants, ///< Graphics spec constants are out of date
|
||||||
GpDynamicBlendConstants, ///< Blend constants are dynamic
|
GpDynamicBlendConstants, ///< Blend constants are dynamic
|
||||||
GpDynamicDepthStencilState, ///< Depth-stencil state is dynamic
|
GpDynamicDepthStencilState, ///< Depth-stencil state is dynamic
|
||||||
GpDynamicDepthBias, ///< Depth bias is dynamic
|
GpDynamicDepthBias, ///< Depth bias is dynamic
|
||||||
@ -47,6 +48,7 @@ namespace dxvk {
|
|||||||
GpIndependentSets, ///< Graphics pipeline layout was created with independent sets
|
GpIndependentSets, ///< Graphics pipeline layout was created with independent sets
|
||||||
|
|
||||||
CpDirtyPipelineState, ///< Compute pipeline is out of date
|
CpDirtyPipelineState, ///< Compute pipeline is out of date
|
||||||
|
CpDirtySpecConstants, ///< Compute spec constants are out of date
|
||||||
|
|
||||||
DirtyDrawBuffer, ///< Indirect argument buffer is dirty
|
DirtyDrawBuffer, ///< Indirect argument buffer is dirty
|
||||||
DirtyPushConstants, ///< Push constant data has changed
|
DirtyPushConstants, ///< Push constant data has changed
|
||||||
@ -120,11 +122,18 @@ namespace dxvk {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct DxvkSpecConstantState {
|
||||||
|
uint32_t mask = 0;
|
||||||
|
std::array<uint32_t, MaxNumSpecConstants> data = { };
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
struct DxvkGraphicsPipelineState {
|
struct DxvkGraphicsPipelineState {
|
||||||
DxvkGraphicsPipelineShaders shaders;
|
DxvkGraphicsPipelineShaders shaders;
|
||||||
DxvkGraphicsPipelineStateInfo state;
|
DxvkGraphicsPipelineStateInfo state;
|
||||||
DxvkGraphicsPipelineFlags flags;
|
DxvkGraphicsPipelineFlags flags;
|
||||||
DxvkGraphicsPipeline* pipeline = nullptr;
|
DxvkGraphicsPipeline* pipeline = nullptr;
|
||||||
|
DxvkSpecConstantState constants;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -132,6 +141,7 @@ namespace dxvk {
|
|||||||
DxvkComputePipelineShaders shaders;
|
DxvkComputePipelineShaders shaders;
|
||||||
DxvkComputePipelineStateInfo state;
|
DxvkComputePipelineStateInfo state;
|
||||||
DxvkComputePipeline* pipeline = nullptr;
|
DxvkComputePipeline* pipeline = nullptr;
|
||||||
|
DxvkSpecConstantState constants;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -343,6 +343,17 @@ namespace dxvk {
|
|||||||
return m_bindings;
|
return m_bindings;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Queries spec constant mask
|
||||||
|
*
|
||||||
|
* This only includes user spec constants.
|
||||||
|
* \returns Bit mask of used spec constants
|
||||||
|
*/
|
||||||
|
uint32_t getSpecConstantMask() const {
|
||||||
|
constexpr uint32_t globalMask = (1u << MaxNumSpecConstants) - 1;
|
||||||
|
return m_specConstantMask & globalMask;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Queries global resource barrier
|
* \brief Queries global resource barrier
|
||||||
*
|
*
|
||||||
|
Loading…
x
Reference in New Issue
Block a user