[dxvk] Move render pass out of pipeline state vector

This commit is contained in:
Philip Rebohle 2018-05-03 19:33:41 +02:00
parent 59d4f1a1fb
commit 3a3b1eda59
6 changed files with 55 additions and 27 deletions

View File

@ -1712,8 +1712,9 @@ namespace dxvk {
for (uint32_t i = m_state.gp.state.ilBindingCount; i < MaxNumVertexBindings; i++)
m_state.gp.state.ilBindings[i].stride = 0;
m_gpActivePipeline = m_state.gp.pipeline != nullptr
? m_state.gp.pipeline->getPipelineHandle(m_state.gp.state, m_cmd->statCounters())
m_gpActivePipeline = m_state.gp.pipeline != nullptr && m_state.om.framebuffer != nullptr
? m_state.gp.pipeline->getPipelineHandle(m_state.gp.state,
m_state.om.framebuffer->getRenderPass(), m_cmd->statCounters())
: VK_NULL_HANDLE;
if (m_gpActivePipeline != VK_NULL_HANDLE) {
@ -1911,7 +1912,6 @@ namespace dxvk {
auto fb = m_device->createFramebuffer(m_state.om.renderTargets);
m_state.gp.state.msSampleCount = fb->getSampleCount();
m_state.gp.state.omRenderPass = fb->getDefaultRenderPassHandle();
m_state.om.framebuffer = fb;
m_flags.set(DxvkContextFlag::GpDirtyPipelineState);

View File

@ -110,6 +110,14 @@ namespace dxvk {
return m_renderPass->getHandle(ops);
}
/**
* \brief Retrieves render pass
* \returns Render pass reference
*/
const DxvkRenderPass& getRenderPass() const {
return *m_renderPass;
}
/**
* \brief Depth-stencil target
* \returns Depth-stencil target

View File

@ -77,32 +77,34 @@ namespace dxvk {
VkPipeline DxvkGraphicsPipeline::getPipelineHandle(
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, pipeline))
if (this->findPipeline(state, renderPassHandle, pipeline))
return pipeline;
}
// 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, m_basePipeline)
? this->compilePipeline(state, renderPassHandle, m_basePipeline)
: 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, pipeline)) {
if (this->findPipeline(state, renderPassHandle, pipeline)) {
m_vkd->vkDestroyPipeline(m_vkd->device(), newPipeline, nullptr);
return pipeline;
}
// Add new pipeline to the set
m_pipelines.push_back({ state, newPipeline });
m_pipelines.push_back({ state, renderPassHandle, newPipeline });
if (m_basePipeline == VK_NULL_HANDLE)
m_basePipeline = newPipeline;
@ -115,9 +117,11 @@ namespace dxvk {
bool DxvkGraphicsPipeline::findPipeline(
const DxvkGraphicsPipelineStateInfo& state,
VkRenderPass renderPass,
VkPipeline& pipeline) const {
for (const PipelineStruct& pair : m_pipelines) {
if (pair.stateVector == state) {
if (pair.stateVector == state
&& pair.renderPass == renderPass) {
pipeline = pair.pipeline;
return true;
}
@ -129,6 +133,7 @@ namespace dxvk {
VkPipeline DxvkGraphicsPipeline::compilePipeline(
const DxvkGraphicsPipelineStateInfo& state,
VkRenderPass renderPass,
VkPipeline baseHandle) const {
if (Logger::logLevel() <= LogLevel::Debug) {
Logger::debug("Compiling graphics pipeline...");
@ -297,7 +302,7 @@ namespace dxvk {
info.pColorBlendState = &cbInfo;
info.pDynamicState = &dyInfo;
info.layout = m_layout->pipelineLayout();
info.renderPass = state.omRenderPass;
info.renderPass = renderPass;
info.subpass = 0;
info.basePipelineHandle = baseHandle;
info.basePipelineIndex = -1;
@ -331,10 +336,6 @@ namespace dxvk {
bool DxvkGraphicsPipeline::validatePipelineState(
const DxvkGraphicsPipelineStateInfo& state) const {
// Make sure that we have an active render pass
if (state.omRenderPass == VK_NULL_HANDLE)
return false;
// Validate vertex input - each input slot consumed by the
// vertex shader must be provided by the input layout.
uint32_t providedVertexInputs = 0;

View File

@ -6,6 +6,7 @@
#include "dxvk_constant_state.h"
#include "dxvk_pipecache.h"
#include "dxvk_pipelayout.h"
#include "dxvk_renderpass.h"
#include "dxvk_resource.h"
#include "dxvk_shader.h"
#include "dxvk_stats.h"
@ -73,7 +74,6 @@ namespace dxvk {
VkBool32 omEnableLogicOp;
VkLogicOp omLogicOp;
VkRenderPass omRenderPass;
VkPipelineColorBlendAttachmentState omBlendAttachments[MaxNumRenderTargets];
};
@ -129,17 +129,20 @@ namespace dxvk {
* Retrieves a pipeline handle for the given pipeline
* state. If necessary, a new pipeline will be created.
* \param [in] state Pipeline state vector
* \param [in] renderPass The render pass
* \param [in,out] stats Stat counter
* \returns Pipeline handle
*/
VkPipeline getPipelineHandle(
const DxvkGraphicsPipelineStateInfo& state,
const DxvkRenderPass& renderPass,
DxvkStatCounters& stats);
private:
struct PipelineStruct {
DxvkGraphicsPipelineStateInfo stateVector;
VkRenderPass renderPass;
VkPipeline pipeline;
};
@ -167,10 +170,12 @@ namespace dxvk {
bool findPipeline(
const DxvkGraphicsPipelineStateInfo& state,
VkRenderPass renderPass,
VkPipeline& pipeline) const;
VkPipeline compilePipeline(
const DxvkGraphicsPipelineStateInfo& state,
VkRenderPass renderPass,
VkPipeline baseHandle) const;
void destroyPipelines();

View File

@ -4,6 +4,21 @@
namespace dxvk {
bool DxvkRenderPassFormat::matches(const DxvkRenderPassFormat& fmt) const {
bool eq = sampleCount == fmt.sampleCount;
for (uint32_t i = 0; i < MaxNumRenderTargets && eq; i++) {
eq &= color[i].format == fmt.color[i].format
&& color[i].layout == fmt.color[i].layout;
}
eq &= depth.format == fmt.depth.format
&& depth.layout == fmt.depth.layout;
return eq;
}
DxvkRenderPass::DxvkRenderPass(
const Rc<vk::DeviceFn>& vkd,
const DxvkRenderPassFormat& fmt)
@ -23,19 +38,8 @@ namespace dxvk {
}
bool DxvkRenderPass::hasCompatibleFormat(
const DxvkRenderPassFormat& fmt) const {
bool eq = m_format.sampleCount == fmt.sampleCount;
for (uint32_t i = 0; i < MaxNumRenderTargets && eq; i++) {
eq &= m_format.color[i].format == fmt.color[i].format
&& m_format.color[i].layout == fmt.color[i].layout;
}
eq &= m_format.depth.format == fmt.depth.format
&& m_format.depth.layout == fmt.depth.layout;
return eq;
bool DxvkRenderPass::hasCompatibleFormat(const DxvkRenderPassFormat& fmt) const {
return m_format.matches(fmt);
}

View File

@ -31,6 +31,8 @@ namespace dxvk {
VkSampleCountFlagBits sampleCount = VK_SAMPLE_COUNT_1_BIT;
DxvkAttachmentFormat depth;
DxvkAttachmentFormat color[MaxNumRenderTargets];
bool matches(const DxvkRenderPassFormat& fmt) const;
};
@ -94,6 +96,14 @@ namespace dxvk {
~DxvkRenderPass();
/**
* \brief Retrieves render pass format
* \returns The render pass format
*/
DxvkRenderPassFormat format() const {
return m_format;
}
/**
* \brief Checks whether a format is compatible
*