mirror of
https://github.com/doitsujin/dxvk.git
synced 2025-01-19 05:52:11 +01:00
[dxvk] Implement DxvkGraphicsPipelineInstance
This should come in handy when compiling an optimized version of a pipeline asynchronously. This can be extended to hold multiple pipeline handles, i.e. one optimized one and one without opts. Collateral damage: We're not using derivative pipelines anymore, needs to be re-added at a later point.
This commit is contained in:
parent
c7d2957d8f
commit
010fc6ad49
@ -34,6 +34,22 @@ namespace dxvk {
|
||||
}
|
||||
|
||||
|
||||
DxvkGraphicsPipelineInstance::DxvkGraphicsPipelineInstance(
|
||||
const Rc<vk::DeviceFn>& vkd,
|
||||
const DxvkGraphicsPipelineStateInfo& stateVector,
|
||||
VkRenderPass renderPass)
|
||||
: m_vkd (vkd),
|
||||
m_stateVector (stateVector),
|
||||
m_renderPass (renderPass) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
DxvkGraphicsPipelineInstance::~DxvkGraphicsPipelineInstance() {
|
||||
m_vkd->vkDestroyPipeline(m_vkd->device(), m_pipeline, nullptr);
|
||||
}
|
||||
|
||||
|
||||
DxvkGraphicsPipeline::DxvkGraphicsPipeline(
|
||||
const DxvkDevice* device,
|
||||
const Rc<DxvkPipelineCache>& cache,
|
||||
@ -71,7 +87,7 @@ namespace dxvk {
|
||||
|
||||
|
||||
DxvkGraphicsPipeline::~DxvkGraphicsPipeline() {
|
||||
this->destroyPipelines();
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -79,55 +95,58 @@ namespace dxvk {
|
||||
const DxvkGraphicsPipelineStateInfo& state,
|
||||
const DxvkRenderPass& renderPass,
|
||||
DxvkStatCounters& stats) {
|
||||
VkPipeline pipeline = VK_NULL_HANDLE;
|
||||
VkRenderPass renderPassHandle = renderPass.getDefaultHandle();
|
||||
|
||||
{ std::lock_guard<sync::Spinlock> lock(m_mutex);
|
||||
|
||||
if (this->findPipeline(state, renderPassHandle, pipeline))
|
||||
return pipeline;
|
||||
DxvkGraphicsPipelineInstance* pipeline =
|
||||
this->findInstance(state, renderPassHandle);
|
||||
|
||||
if (pipeline != nullptr)
|
||||
return pipeline->getPipeline();
|
||||
}
|
||||
|
||||
// If no pipeline exists with the given state vector,
|
||||
// create a new one and add it to the pipeline set.
|
||||
VkPipeline newPipeline = this->validatePipelineState(state)
|
||||
? this->compilePipeline(state, renderPassHandle, m_basePipeline)
|
||||
: VK_NULL_HANDLE;
|
||||
// If the pipeline state vector is invalid, don't try
|
||||
// to create a new pipeline, it won't work anyway.
|
||||
if (!this->validatePipelineState(state))
|
||||
return VK_NULL_HANDLE;
|
||||
|
||||
// If no pipeline instance exists with the given state
|
||||
// vector, create a new one and add it to the list.
|
||||
Rc<DxvkGraphicsPipelineInstance> newPipeline =
|
||||
new DxvkGraphicsPipelineInstance(m_device->vkd(), state, renderPassHandle);
|
||||
|
||||
newPipeline->setPipeline(this->compilePipeline(
|
||||
state, renderPassHandle, VK_NULL_HANDLE));
|
||||
|
||||
{ std::lock_guard<sync::Spinlock> lock(m_mutex);
|
||||
|
||||
// Discard the pipeline if another thread
|
||||
// was faster compiling the same pipeline
|
||||
if (this->findPipeline(state, renderPassHandle, pipeline)) {
|
||||
m_vkd->vkDestroyPipeline(m_vkd->device(), newPipeline, nullptr);
|
||||
return pipeline;
|
||||
}
|
||||
DxvkGraphicsPipelineInstance* pipeline =
|
||||
this->findInstance(state, renderPassHandle);
|
||||
|
||||
if (pipeline != nullptr)
|
||||
return pipeline->getPipeline();
|
||||
|
||||
// Add new pipeline to the set
|
||||
m_pipelines.push_back({ state, renderPassHandle, newPipeline });
|
||||
|
||||
if (m_basePipeline == VK_NULL_HANDLE)
|
||||
m_basePipeline = newPipeline;
|
||||
m_pipelines.push_back(newPipeline);
|
||||
|
||||
stats.addCtr(DxvkStatCounter::PipeCountGraphics, 1);
|
||||
return newPipeline;
|
||||
return newPipeline->getPipeline();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool DxvkGraphicsPipeline::findPipeline(
|
||||
DxvkGraphicsPipelineInstance* DxvkGraphicsPipeline::findInstance(
|
||||
const DxvkGraphicsPipelineStateInfo& state,
|
||||
VkRenderPass renderPass,
|
||||
VkPipeline& pipeline) const {
|
||||
for (const PipelineStruct& pair : m_pipelines) {
|
||||
if (pair.stateVector == state
|
||||
&& pair.renderPass == renderPass) {
|
||||
pipeline = pair.pipeline;
|
||||
return true;
|
||||
}
|
||||
VkRenderPass renderPass) const {
|
||||
for (const auto& pipeline : m_pipelines) {
|
||||
if (pipeline->isCompatible(state, renderPass))
|
||||
return pipeline.ptr();
|
||||
}
|
||||
|
||||
return false;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
@ -328,12 +347,6 @@ namespace dxvk {
|
||||
}
|
||||
|
||||
|
||||
void DxvkGraphicsPipeline::destroyPipelines() {
|
||||
for (const PipelineStruct& pair : m_pipelines)
|
||||
m_vkd->vkDestroyPipeline(m_vkd->device(), pair.pipeline, nullptr);
|
||||
}
|
||||
|
||||
|
||||
bool DxvkGraphicsPipeline::validatePipelineState(
|
||||
const DxvkGraphicsPipelineStateInfo& state) const {
|
||||
// Validate vertex input - each input slot consumed by the
|
||||
|
@ -90,6 +90,65 @@ namespace dxvk {
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* \brief Graphics pipeline instance
|
||||
*
|
||||
* Stores a state vector and the corresponding
|
||||
* pipeline handles.
|
||||
*/
|
||||
class DxvkGraphicsPipelineInstance : public RcObject {
|
||||
|
||||
public:
|
||||
|
||||
DxvkGraphicsPipelineInstance(
|
||||
const Rc<vk::DeviceFn>& vkd,
|
||||
const DxvkGraphicsPipelineStateInfo& stateVector,
|
||||
VkRenderPass renderPass);
|
||||
|
||||
~DxvkGraphicsPipelineInstance();
|
||||
|
||||
/**
|
||||
* \brief Checks for matching pipeline state
|
||||
*
|
||||
* \param [in] stateVector Graphics pipeline state
|
||||
* \param [in] renderPass Render pass handle
|
||||
* \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 pipeline handle
|
||||
* \param [in] pipeline The pipeline
|
||||
*/
|
||||
void setPipeline(VkPipeline pipeline) {
|
||||
m_pipeline = pipeline;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Retrieves pipeline
|
||||
* \returns The pipeline
|
||||
*/
|
||||
VkPipeline getPipeline() const {
|
||||
return m_pipeline;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
const Rc<vk::DeviceFn> m_vkd;
|
||||
|
||||
DxvkGraphicsPipelineStateInfo m_stateVector;
|
||||
VkRenderPass m_renderPass;
|
||||
|
||||
VkPipeline m_pipeline = VK_NULL_HANDLE;
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* \brief Graphics pipeline
|
||||
*
|
||||
@ -163,23 +222,18 @@ namespace dxvk {
|
||||
|
||||
DxvkGraphicsCommonPipelineStateInfo m_common;
|
||||
|
||||
sync::Spinlock m_mutex;
|
||||
std::vector<PipelineStruct> m_pipelines;
|
||||
sync::Spinlock m_mutex;
|
||||
std::vector<Rc<DxvkGraphicsPipelineInstance>> m_pipelines;
|
||||
|
||||
VkPipeline m_basePipeline = VK_NULL_HANDLE;
|
||||
|
||||
bool findPipeline(
|
||||
DxvkGraphicsPipelineInstance* findInstance(
|
||||
const DxvkGraphicsPipelineStateInfo& state,
|
||||
VkRenderPass renderPass,
|
||||
VkPipeline& pipeline) const;
|
||||
VkRenderPass renderPass) const;
|
||||
|
||||
VkPipeline compilePipeline(
|
||||
const DxvkGraphicsPipelineStateInfo& state,
|
||||
VkRenderPass renderPass,
|
||||
VkPipeline baseHandle) const;
|
||||
|
||||
void destroyPipelines();
|
||||
|
||||
bool validatePipelineState(
|
||||
const DxvkGraphicsPipelineStateInfo& state) const;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user