mirror of
https://github.com/EduApps-CDG/OpenDX
synced 2024-12-30 09:45:37 +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(
|
DxvkGraphicsPipeline::DxvkGraphicsPipeline(
|
||||||
const DxvkDevice* device,
|
const DxvkDevice* device,
|
||||||
const Rc<DxvkPipelineCache>& cache,
|
const Rc<DxvkPipelineCache>& cache,
|
||||||
@ -93,7 +75,8 @@ namespace dxvk {
|
|||||||
|
|
||||||
|
|
||||||
DxvkGraphicsPipeline::~DxvkGraphicsPipeline() {
|
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);
|
{ std::lock_guard<sync::Spinlock> lock(m_mutex);
|
||||||
|
|
||||||
DxvkGraphicsPipelineInstance* pipeline =
|
const DxvkGraphicsPipelineInstance* instance =
|
||||||
this->findInstance(state, renderPassHandle);
|
this->findInstance(state, renderPassHandle);
|
||||||
|
|
||||||
if (pipeline != nullptr)
|
if (instance != nullptr)
|
||||||
return pipeline->getPipeline();
|
return instance->pipeline();
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the pipeline state vector is invalid, don't try
|
// If the pipeline state vector is invalid, don't try
|
||||||
@ -123,22 +106,20 @@ namespace dxvk {
|
|||||||
VkPipeline newPipelineHandle = this->compilePipeline(
|
VkPipeline newPipelineHandle = this->compilePipeline(
|
||||||
state, renderPassHandle, newPipelineBase);
|
state, renderPassHandle, newPipelineBase);
|
||||||
|
|
||||||
Rc<DxvkGraphicsPipelineInstance> newPipeline =
|
|
||||||
new DxvkGraphicsPipelineInstance(m_device->vkd(),
|
|
||||||
state, renderPassHandle, newPipelineHandle);
|
|
||||||
|
|
||||||
{ std::lock_guard<sync::Spinlock> lock(m_mutex);
|
{ std::lock_guard<sync::Spinlock> lock(m_mutex);
|
||||||
|
|
||||||
// Discard the pipeline if another thread
|
// Discard the pipeline if another thread
|
||||||
// was faster compiling the same pipeline
|
// was faster compiling the same pipeline
|
||||||
DxvkGraphicsPipelineInstance* pipeline =
|
const DxvkGraphicsPipelineInstance* instance =
|
||||||
this->findInstance(state, renderPassHandle);
|
this->findInstance(state, renderPassHandle);
|
||||||
|
|
||||||
if (pipeline != nullptr)
|
if (instance != nullptr) {
|
||||||
return pipeline->getPipeline();
|
this->destroyPipeline(newPipelineHandle);
|
||||||
|
return instance->pipeline();
|
||||||
|
}
|
||||||
|
|
||||||
// Add new pipeline to the set
|
// Add new pipeline to the set
|
||||||
m_pipelines.push_back(newPipeline);
|
m_pipelines.emplace_back(state, renderPassHandle, newPipelineHandle);
|
||||||
|
|
||||||
stats.addCtr(DxvkStatCounter::PipeCountGraphics, 1);
|
stats.addCtr(DxvkStatCounter::PipeCountGraphics, 1);
|
||||||
}
|
}
|
||||||
@ -151,12 +132,12 @@ namespace dxvk {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
DxvkGraphicsPipelineInstance* DxvkGraphicsPipeline::findInstance(
|
const DxvkGraphicsPipelineInstance* DxvkGraphicsPipeline::findInstance(
|
||||||
const DxvkGraphicsPipelineStateInfo& state,
|
const DxvkGraphicsPipelineStateInfo& state,
|
||||||
VkRenderPass renderPass) const {
|
VkRenderPass renderPass) const {
|
||||||
for (const auto& pipeline : m_pipelines) {
|
for (const auto& instance : m_pipelines) {
|
||||||
if (pipeline->isCompatible(state, renderPass))
|
if (instance.isCompatible(state, renderPass))
|
||||||
return pipeline.ptr();
|
return &instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
return nullptr;
|
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(
|
bool DxvkGraphicsPipeline::validatePipelineState(
|
||||||
const DxvkGraphicsPipelineStateInfo& state) const {
|
const DxvkGraphicsPipelineStateInfo& state) const {
|
||||||
// Validate vertex input - each input slot consumed by the
|
// Validate vertex input - each input slot consumed by the
|
||||||
|
@ -90,18 +90,19 @@ namespace dxvk {
|
|||||||
* Stores a state vector and the
|
* Stores a state vector and the
|
||||||
* corresponding pipeline handle.
|
* corresponding pipeline handle.
|
||||||
*/
|
*/
|
||||||
class DxvkGraphicsPipelineInstance : public RcObject {
|
class DxvkGraphicsPipelineInstance {
|
||||||
friend class DxvkGraphicsPipeline;
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
DxvkGraphicsPipelineInstance() { }
|
||||||
DxvkGraphicsPipelineInstance(
|
DxvkGraphicsPipelineInstance(
|
||||||
const Rc<vk::DeviceFn>& vkd,
|
const DxvkGraphicsPipelineStateInfo& state,
|
||||||
const DxvkGraphicsPipelineStateInfo& stateVector,
|
VkRenderPass rp,
|
||||||
VkRenderPass renderPass,
|
VkPipeline pipe)
|
||||||
VkPipeline pipeline);
|
: m_stateVector (state),
|
||||||
|
m_renderPass (rp),
|
||||||
~DxvkGraphicsPipelineInstance();
|
m_pipeline (pipe) { }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Checks for matching pipeline state
|
* \brief Checks for matching pipeline state
|
||||||
*
|
*
|
||||||
@ -110,47 +111,28 @@ namespace dxvk {
|
|||||||
* \returns \c true if the specialization is compatible
|
* \returns \c true if the specialization is compatible
|
||||||
*/
|
*/
|
||||||
bool isCompatible(
|
bool isCompatible(
|
||||||
const DxvkGraphicsPipelineStateInfo& stateVector,
|
const DxvkGraphicsPipelineStateInfo& state,
|
||||||
VkRenderPass renderPass) const {
|
VkRenderPass rp) const {
|
||||||
return m_renderPass == renderPass
|
return m_stateVector == state
|
||||||
&& m_stateVector == stateVector;
|
&& m_renderPass == rp;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* \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);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Retrieves pipeline
|
* \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
|
* \returns The pipeline handle
|
||||||
*/
|
*/
|
||||||
VkPipeline getPipeline() const {
|
VkPipeline pipeline() const {
|
||||||
return m_pipeline.load();
|
return m_pipeline;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
const Rc<vk::DeviceFn> m_vkd;
|
|
||||||
|
|
||||||
DxvkGraphicsPipelineStateInfo m_stateVector;
|
DxvkGraphicsPipelineStateInfo m_stateVector;
|
||||||
VkRenderPass m_renderPass;
|
VkRenderPass m_renderPass;
|
||||||
|
VkPipeline m_pipeline;
|
||||||
|
|
||||||
std::atomic<VkPipeline> m_pipeline;
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Graphics pipeline
|
* \brief Graphics pipeline
|
||||||
@ -226,13 +208,13 @@ namespace dxvk {
|
|||||||
DxvkGraphicsCommonPipelineStateInfo m_common;
|
DxvkGraphicsCommonPipelineStateInfo m_common;
|
||||||
|
|
||||||
// List of pipeline instances, shared between threads
|
// List of pipeline instances, shared between threads
|
||||||
alignas(CACHE_LINE_SIZE) sync::Spinlock m_mutex;
|
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
|
// Pipeline handles used for derivative pipelines
|
||||||
std::atomic<VkPipeline> m_basePipeline = { VK_NULL_HANDLE };
|
std::atomic<VkPipeline> m_basePipeline = { VK_NULL_HANDLE };
|
||||||
|
|
||||||
DxvkGraphicsPipelineInstance* findInstance(
|
const DxvkGraphicsPipelineInstance* findInstance(
|
||||||
const DxvkGraphicsPipelineStateInfo& state,
|
const DxvkGraphicsPipelineStateInfo& state,
|
||||||
VkRenderPass renderPass) const;
|
VkRenderPass renderPass) const;
|
||||||
|
|
||||||
@ -241,6 +223,9 @@ namespace dxvk {
|
|||||||
VkRenderPass renderPass,
|
VkRenderPass renderPass,
|
||||||
VkPipeline baseHandle) const;
|
VkPipeline baseHandle) const;
|
||||||
|
|
||||||
|
void destroyPipeline(
|
||||||
|
VkPipeline pipeline) const;
|
||||||
|
|
||||||
bool validatePipelineState(
|
bool validatePipelineState(
|
||||||
const DxvkGraphicsPipelineStateInfo& state) const;
|
const DxvkGraphicsPipelineStateInfo& state) const;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user