1
0
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:
Philip Rebohle 2018-09-16 10:07:45 +02:00
parent b6bf72aeb6
commit c8e0c253ba
No known key found for this signature in database
GPG Key ID: C8CC613427A31C99
2 changed files with 48 additions and 77 deletions

View File

@ -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

View File

@ -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;