mirror of
https://github.com/doitsujin/dxvk.git
synced 2025-01-31 14:52:11 +01:00
[dxvk] Simplify graphics pipeline instance management
This commit is contained in:
parent
b6bf72aeb6
commit
c8e0c253ba
@ -35,24 +35,6 @@ namespace dxvk {
|
||||
}
|
||||
|
||||
|
||||
DxvkGraphicsPipelineInstance::DxvkGraphicsPipelineInstance(
|
||||
const Rc<vk::DeviceFn>& vkd,
|
||||
const DxvkGraphicsPipelineStateInfo& stateVector,
|
||||
VkRenderPass renderPass,
|
||||
VkPipeline pipeline)
|
||||
: m_vkd (vkd),
|
||||
m_stateVector (stateVector),
|
||||
m_renderPass (renderPass),
|
||||
m_pipeline (pipeline) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
DxvkGraphicsPipelineInstance::~DxvkGraphicsPipelineInstance() {
|
||||
m_vkd->vkDestroyPipeline(m_vkd->device(), m_pipeline, nullptr);
|
||||
}
|
||||
|
||||
|
||||
DxvkGraphicsPipeline::DxvkGraphicsPipeline(
|
||||
const DxvkDevice* device,
|
||||
const Rc<DxvkPipelineCache>& cache,
|
||||
@ -93,7 +75,8 @@ namespace dxvk {
|
||||
|
||||
|
||||
DxvkGraphicsPipeline::~DxvkGraphicsPipeline() {
|
||||
|
||||
for (const auto& instance : m_pipelines)
|
||||
this->destroyPipeline(instance.pipeline());
|
||||
}
|
||||
|
||||
|
||||
@ -105,11 +88,11 @@ namespace dxvk {
|
||||
|
||||
{ std::lock_guard<sync::Spinlock> lock(m_mutex);
|
||||
|
||||
DxvkGraphicsPipelineInstance* pipeline =
|
||||
const DxvkGraphicsPipelineInstance* instance =
|
||||
this->findInstance(state, renderPassHandle);
|
||||
|
||||
if (pipeline != nullptr)
|
||||
return pipeline->getPipeline();
|
||||
if (instance != nullptr)
|
||||
return instance->pipeline();
|
||||
}
|
||||
|
||||
// If the pipeline state vector is invalid, don't try
|
||||
@ -123,22 +106,20 @@ namespace dxvk {
|
||||
VkPipeline newPipelineHandle = this->compilePipeline(
|
||||
state, renderPassHandle, newPipelineBase);
|
||||
|
||||
Rc<DxvkGraphicsPipelineInstance> newPipeline =
|
||||
new DxvkGraphicsPipelineInstance(m_device->vkd(),
|
||||
state, renderPassHandle, newPipelineHandle);
|
||||
|
||||
{ std::lock_guard<sync::Spinlock> lock(m_mutex);
|
||||
|
||||
// Discard the pipeline if another thread
|
||||
// was faster compiling the same pipeline
|
||||
DxvkGraphicsPipelineInstance* pipeline =
|
||||
const DxvkGraphicsPipelineInstance* instance =
|
||||
this->findInstance(state, renderPassHandle);
|
||||
|
||||
if (pipeline != nullptr)
|
||||
return pipeline->getPipeline();
|
||||
if (instance != nullptr) {
|
||||
this->destroyPipeline(newPipelineHandle);
|
||||
return instance->pipeline();
|
||||
}
|
||||
|
||||
// Add new pipeline to the set
|
||||
m_pipelines.push_back(newPipeline);
|
||||
m_pipelines.emplace_back(state, renderPassHandle, newPipelineHandle);
|
||||
|
||||
stats.addCtr(DxvkStatCounter::PipeCountGraphics, 1);
|
||||
}
|
||||
@ -151,12 +132,12 @@ namespace dxvk {
|
||||
}
|
||||
|
||||
|
||||
DxvkGraphicsPipelineInstance* DxvkGraphicsPipeline::findInstance(
|
||||
const DxvkGraphicsPipelineInstance* DxvkGraphicsPipeline::findInstance(
|
||||
const DxvkGraphicsPipelineStateInfo& state,
|
||||
VkRenderPass renderPass) const {
|
||||
for (const auto& pipeline : m_pipelines) {
|
||||
if (pipeline->isCompatible(state, renderPass))
|
||||
return pipeline.ptr();
|
||||
for (const auto& instance : m_pipelines) {
|
||||
if (instance.isCompatible(state, renderPass))
|
||||
return &instance;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
@ -377,6 +358,11 @@ namespace dxvk {
|
||||
}
|
||||
|
||||
|
||||
void DxvkGraphicsPipeline::destroyPipeline(VkPipeline pipeline) const {
|
||||
m_vkd->vkDestroyPipeline(m_vkd->device(), pipeline, nullptr);
|
||||
}
|
||||
|
||||
|
||||
bool DxvkGraphicsPipeline::validatePipelineState(
|
||||
const DxvkGraphicsPipelineStateInfo& state) const {
|
||||
// Validate vertex input - each input slot consumed by the
|
||||
|
@ -90,17 +90,18 @@ namespace dxvk {
|
||||
* Stores a state vector and the
|
||||
* corresponding pipeline handle.
|
||||
*/
|
||||
class DxvkGraphicsPipelineInstance : public RcObject {
|
||||
friend class DxvkGraphicsPipeline;
|
||||
class DxvkGraphicsPipelineInstance {
|
||||
|
||||
public:
|
||||
|
||||
DxvkGraphicsPipelineInstance() { }
|
||||
DxvkGraphicsPipelineInstance(
|
||||
const Rc<vk::DeviceFn>& vkd,
|
||||
const DxvkGraphicsPipelineStateInfo& stateVector,
|
||||
VkRenderPass renderPass,
|
||||
VkPipeline pipeline);
|
||||
|
||||
~DxvkGraphicsPipelineInstance();
|
||||
const DxvkGraphicsPipelineStateInfo& state,
|
||||
VkRenderPass rp,
|
||||
VkPipeline pipe)
|
||||
: m_stateVector (state),
|
||||
m_renderPass (rp),
|
||||
m_pipeline (pipe) { }
|
||||
|
||||
/**
|
||||
* \brief Checks for matching pipeline state
|
||||
@ -110,44 +111,25 @@ namespace dxvk {
|
||||
* \returns \c true if the specialization is compatible
|
||||
*/
|
||||
bool isCompatible(
|
||||
const DxvkGraphicsPipelineStateInfo& stateVector,
|
||||
VkRenderPass renderPass) const {
|
||||
return m_renderPass == renderPass
|
||||
&& m_stateVector == stateVector;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Sets the optimized pipeline handle
|
||||
*
|
||||
* If an optimized pipeline handle has already been
|
||||
* set up, this method will fail and the new pipeline
|
||||
* handle should be destroyed.
|
||||
* \param [in] pipeline The optimized pipeline
|
||||
*/
|
||||
bool setPipeline(VkPipeline pipeline) {
|
||||
VkPipeline expected = VK_NULL_HANDLE;
|
||||
return m_pipeline.compare_exchange_strong(expected, pipeline);
|
||||
const DxvkGraphicsPipelineStateInfo& state,
|
||||
VkRenderPass rp) const {
|
||||
return m_stateVector == state
|
||||
&& m_renderPass == rp;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Retrieves pipeline
|
||||
*
|
||||
* Returns the optimized version of the pipeline if
|
||||
* if has been set, or the base pipeline if not.
|
||||
* \returns The pipeline handle
|
||||
*/
|
||||
VkPipeline getPipeline() const {
|
||||
return m_pipeline.load();
|
||||
VkPipeline pipeline() const {
|
||||
return m_pipeline;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
const Rc<vk::DeviceFn> m_vkd;
|
||||
|
||||
DxvkGraphicsPipelineStateInfo m_stateVector;
|
||||
VkRenderPass m_renderPass;
|
||||
|
||||
std::atomic<VkPipeline> m_pipeline;
|
||||
VkPipeline m_pipeline;
|
||||
|
||||
};
|
||||
|
||||
@ -227,12 +209,12 @@ namespace dxvk {
|
||||
|
||||
// List of pipeline instances, shared between threads
|
||||
alignas(CACHE_LINE_SIZE) sync::Spinlock m_mutex;
|
||||
std::vector<Rc<DxvkGraphicsPipelineInstance>> m_pipelines;
|
||||
std::vector<DxvkGraphicsPipelineInstance> m_pipelines;
|
||||
|
||||
// Pipeline handles used for derivative pipelines
|
||||
std::atomic<VkPipeline> m_basePipeline = { VK_NULL_HANDLE };
|
||||
|
||||
DxvkGraphicsPipelineInstance* findInstance(
|
||||
const DxvkGraphicsPipelineInstance* findInstance(
|
||||
const DxvkGraphicsPipelineStateInfo& state,
|
||||
VkRenderPass renderPass) const;
|
||||
|
||||
@ -241,6 +223,9 @@ namespace dxvk {
|
||||
VkRenderPass renderPass,
|
||||
VkPipeline baseHandle) const;
|
||||
|
||||
void destroyPipeline(
|
||||
VkPipeline pipeline) const;
|
||||
|
||||
bool validatePipelineState(
|
||||
const DxvkGraphicsPipelineStateInfo& state) const;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user