1
0
mirror of https://github.com/doitsujin/dxvk.git synced 2024-12-02 10:24:12 +01:00

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

View File

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

View File

@ -77,32 +77,34 @@ namespace dxvk {
VkPipeline DxvkGraphicsPipeline::getPipelineHandle( VkPipeline DxvkGraphicsPipeline::getPipelineHandle(
const DxvkGraphicsPipelineStateInfo& state, const DxvkGraphicsPipelineStateInfo& state,
const DxvkRenderPass& renderPass,
DxvkStatCounters& stats) { DxvkStatCounters& stats) {
VkPipeline pipeline = VK_NULL_HANDLE; VkPipeline pipeline = VK_NULL_HANDLE;
VkRenderPass renderPassHandle = renderPass.getDefaultHandle();
{ std::lock_guard<sync::Spinlock> lock(m_mutex); { std::lock_guard<sync::Spinlock> lock(m_mutex);
if (this->findPipeline(state, pipeline)) if (this->findPipeline(state, renderPassHandle, pipeline))
return pipeline; return pipeline;
} }
// If no pipeline exists with the given state vector, // If no pipeline exists with the given state vector,
// create a new one and add it to the pipeline set. // create a new one and add it to the pipeline set.
VkPipeline newPipeline = this->validatePipelineState(state) VkPipeline newPipeline = this->validatePipelineState(state)
? this->compilePipeline(state, m_basePipeline) ? this->compilePipeline(state, renderPassHandle, m_basePipeline)
: VK_NULL_HANDLE; : VK_NULL_HANDLE;
{ 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
if (this->findPipeline(state, pipeline)) { if (this->findPipeline(state, renderPassHandle, pipeline)) {
m_vkd->vkDestroyPipeline(m_vkd->device(), newPipeline, nullptr); m_vkd->vkDestroyPipeline(m_vkd->device(), newPipeline, nullptr);
return pipeline; return pipeline;
} }
// Add new pipeline to the set // 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) if (m_basePipeline == VK_NULL_HANDLE)
m_basePipeline = newPipeline; m_basePipeline = newPipeline;
@ -115,9 +117,11 @@ namespace dxvk {
bool DxvkGraphicsPipeline::findPipeline( bool DxvkGraphicsPipeline::findPipeline(
const DxvkGraphicsPipelineStateInfo& state, const DxvkGraphicsPipelineStateInfo& state,
VkRenderPass renderPass,
VkPipeline& pipeline) const { VkPipeline& pipeline) const {
for (const PipelineStruct& pair : m_pipelines) { for (const PipelineStruct& pair : m_pipelines) {
if (pair.stateVector == state) { if (pair.stateVector == state
&& pair.renderPass == renderPass) {
pipeline = pair.pipeline; pipeline = pair.pipeline;
return true; return true;
} }
@ -129,6 +133,7 @@ namespace dxvk {
VkPipeline DxvkGraphicsPipeline::compilePipeline( VkPipeline DxvkGraphicsPipeline::compilePipeline(
const DxvkGraphicsPipelineStateInfo& state, const DxvkGraphicsPipelineStateInfo& state,
VkRenderPass renderPass,
VkPipeline baseHandle) const { VkPipeline baseHandle) const {
if (Logger::logLevel() <= LogLevel::Debug) { if (Logger::logLevel() <= LogLevel::Debug) {
Logger::debug("Compiling graphics pipeline..."); Logger::debug("Compiling graphics pipeline...");
@ -297,7 +302,7 @@ namespace dxvk {
info.pColorBlendState = &cbInfo; info.pColorBlendState = &cbInfo;
info.pDynamicState = &dyInfo; info.pDynamicState = &dyInfo;
info.layout = m_layout->pipelineLayout(); info.layout = m_layout->pipelineLayout();
info.renderPass = state.omRenderPass; info.renderPass = renderPass;
info.subpass = 0; info.subpass = 0;
info.basePipelineHandle = baseHandle; info.basePipelineHandle = baseHandle;
info.basePipelineIndex = -1; info.basePipelineIndex = -1;
@ -331,10 +336,6 @@ namespace dxvk {
bool DxvkGraphicsPipeline::validatePipelineState( bool DxvkGraphicsPipeline::validatePipelineState(
const DxvkGraphicsPipelineStateInfo& state) const { 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 // Validate vertex input - each input slot consumed by the
// vertex shader must be provided by the input layout. // vertex shader must be provided by the input layout.
uint32_t providedVertexInputs = 0; uint32_t providedVertexInputs = 0;

View File

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

View File

@ -4,6 +4,21 @@
namespace dxvk { 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( DxvkRenderPass::DxvkRenderPass(
const Rc<vk::DeviceFn>& vkd, const Rc<vk::DeviceFn>& vkd,
const DxvkRenderPassFormat& fmt) const DxvkRenderPassFormat& fmt)
@ -23,19 +38,8 @@ namespace dxvk {
} }
bool DxvkRenderPass::hasCompatibleFormat( bool DxvkRenderPass::hasCompatibleFormat(const DxvkRenderPassFormat& fmt) const {
const DxvkRenderPassFormat& fmt) const { return m_format.matches(fmt);
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;
} }

View File

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