1
0
mirror of https://github.com/doitsujin/dxvk.git synced 2025-03-14 04:29:15 +01:00

[dxvk] Major refactoring of graphics pipeline state lookup in order to support more dynamic state

This commit is contained in:
Philip Rebohle 2017-12-07 21:47:38 +01:00
parent ade00add8d
commit 796c200e32
7 changed files with 260 additions and 85 deletions

View File

@ -561,7 +561,8 @@ namespace dxvk {
}
m_context->bindVertexBuffer(
StartSlot + i, dxvkBinding);
StartSlot + i, dxvkBinding,
binding.stride);
}
}

View File

@ -1,3 +1,5 @@
#include <cstring>
#include "dxvk_constant_state.h"
namespace dxvk {

View File

@ -6,7 +6,7 @@ namespace dxvk {
DxvkContext::DxvkContext(const Rc<DxvkDevice>& device)
: m_device(device) {
Logger::info(str::format(sizeof(DxvkGraphicsPipelineStateInfo)));
}
@ -183,11 +183,17 @@ namespace dxvk {
void DxvkContext::bindVertexBuffer(
uint32_t binding,
const DxvkBufferBinding& buffer) {
const DxvkBufferBinding& buffer,
uint32_t stride) {
if (m_state.vi.vertexBuffers.at(binding) != buffer) {
m_state.vi.vertexBuffers.at(binding) = buffer;
m_flags.set(DxvkContextFlag::GpDirtyVertexBuffers);
}
if (m_state.vi.vertexStrides.at(binding) != stride) {
m_state.vi.vertexStrides.at(binding) = stride;
m_flags.set(DxvkContextFlag::GpDirtyPipelineState);
}
}
@ -499,15 +505,65 @@ namespace dxvk {
}
DxvkGraphicsPipelineStateInfo gpState;
gpState.inputAssemblyState = m_state.co.inputAssemblyState;
gpState.inputLayout = m_state.co.inputLayout;
gpState.rasterizerState = m_state.co.rasterizerState;
gpState.multisampleState = m_state.co.multisampleState;
gpState.depthStencilState = m_state.co.depthStencilState;
gpState.blendState = m_state.co.blendState;
gpState.renderPass = m_state.om.framebuffer->renderPass();
gpState.viewportCount = m_state.vp.viewportCount;
// TODO add vertex buffer strides
const auto& ia = m_state.co.inputAssemblyState->info();
gpState.iaPrimitiveTopology = ia.topology;
gpState.iaPrimitiveRestart = ia.primitiveRestartEnable;
const auto& il = m_state.co.inputLayout->info();
gpState.ilAttributeCount = il.vertexAttributeDescriptionCount;
gpState.ilBindingCount = il.vertexBindingDescriptionCount;
for (uint32_t i = 0; i < gpState.ilAttributeCount; i++)
gpState.ilAttributes[i] = il.pVertexAttributeDescriptions[i];
for (uint32_t i = 0; i < gpState.ilBindingCount; i++) {
gpState.ilBindings[i] = il.pVertexBindingDescriptions[i];
gpState.ilBindings[i].stride = m_state.vi.vertexStrides.at(i);
}
const auto& rs = m_state.co.rasterizerState->info();
gpState.rsEnableDepthClamp = rs.depthClampEnable;
gpState.rsEnableDiscard = rs.rasterizerDiscardEnable;
gpState.rsPolygonMode = rs.polygonMode;
gpState.rsCullMode = rs.cullMode;
gpState.rsFrontFace = rs.frontFace;
gpState.rsDepthBiasEnable = rs.depthBiasEnable;
gpState.rsDepthBiasConstant = rs.depthBiasConstantFactor;
gpState.rsDepthBiasClamp = rs.depthBiasClamp;
gpState.rsDepthBiasSlope = rs.depthBiasSlopeFactor;
gpState.rsViewportCount = m_state.vp.viewportCount;
// TODO implement multisampling support properly
const auto& ms = m_state.co.multisampleState->info();
gpState.msSampleCount = VK_SAMPLE_COUNT_1_BIT;
gpState.msSampleMask = *ms.pSampleMask;
gpState.msEnableAlphaToCoverage = ms.alphaToCoverageEnable;
gpState.msEnableAlphaToOne = ms.alphaToOneEnable;
gpState.msEnableSampleShading = ms.sampleShadingEnable;
gpState.msMinSampleShading = ms.minSampleShading;
const auto& ds = m_state.co.depthStencilState->info();
gpState.dsEnableDepthTest = ds.depthTestEnable;
gpState.dsEnableDepthWrite = ds.depthWriteEnable;
gpState.dsEnableDepthBounds = ds.depthBoundsTestEnable;
gpState.dsEnableStencilTest = ds.stencilTestEnable;
gpState.dsDepthCompareOp = ds.depthCompareOp;
gpState.dsStencilOpFront = ds.front;
gpState.dsStencilOpBack = ds.back;
gpState.dsDepthBoundsMin = ds.minDepthBounds;
gpState.dsDepthBoundsMax = ds.maxDepthBounds;
const auto& om = m_state.co.blendState->info();
gpState.omEnableLogicOp = om.logicOpEnable;
gpState.omLogicOp = om.logicOp;
gpState.omRenderPass = m_state.om.framebuffer->renderPass();
const auto& rt = m_state.om.framebuffer->renderTargets();
for (uint32_t i = 0; i < DxvkLimits::MaxNumRenderTargets; i++) {
if (rt.getColorTarget(i) != nullptr)
gpState.omBlendAttachments[i] = om.pAttachments[i];
}
m_cmd->cmdBindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS,
m_state.gp.pipeline->getPipelineHandle(gpState));

View File

@ -140,7 +140,8 @@ namespace dxvk {
*/
void bindVertexBuffer(
uint32_t binding,
const DxvkBufferBinding& buffer);
const DxvkBufferBinding& buffer,
uint32_t stride);
/**
* \brief Clears subresources of a color image

View File

@ -42,6 +42,8 @@ namespace dxvk {
std::array<DxvkBufferBinding,
DxvkLimits::MaxNumVertexBindings> vertexBuffers;
std::array<uint32_t,
DxvkLimits::MaxNumVertexBindings> vertexStrides;
};

View File

@ -1,40 +1,38 @@
#include <cstring>
#include "dxvk_graphics.h"
namespace dxvk {
template<typename T>
size_t hashPtr(T* ptr) {
return reinterpret_cast<size_t>(ptr);
}
size_t DxvkGraphicsPipelineStateInfo::hash() const {
DxvkHashState state;
state.add(hashPtr(this->inputAssemblyState.ptr()));
state.add(hashPtr(this->inputLayout.ptr()));
state.add(hashPtr(this->rasterizerState.ptr()));
state.add(hashPtr(this->multisampleState.ptr()));
state.add(hashPtr(this->depthStencilState.ptr()));
state.add(hashPtr(this->blendState.ptr()));
state.add(std::hash<VkRenderPass>()(this->renderPass));
state.add(viewportCount);
return state;
DxvkGraphicsPipelineStateInfo::DxvkGraphicsPipelineStateInfo() {
std::memset(this, 0, sizeof(DxvkGraphicsPipelineStateInfo));
}
bool DxvkGraphicsPipelineStateInfo::operator == (const DxvkGraphicsPipelineStateInfo& other) const {
return this->inputAssemblyState == other.inputAssemblyState
&& this->inputLayout == other.inputLayout
&& this->rasterizerState == other.rasterizerState
&& this->multisampleState == other.multisampleState
&& this->depthStencilState == other.depthStencilState
&& this->blendState == other.blendState
&& this->renderPass == other.renderPass
&& this->viewportCount == other.viewportCount;
DxvkGraphicsPipelineStateInfo::DxvkGraphicsPipelineStateInfo(
const DxvkGraphicsPipelineStateInfo& other) {
std::memcpy(this, &other, sizeof(DxvkGraphicsPipelineStateInfo));
}
bool DxvkGraphicsPipelineStateInfo::operator != (const DxvkGraphicsPipelineStateInfo& other) const {
return !this->operator == (other);
DxvkGraphicsPipelineStateInfo& DxvkGraphicsPipelineStateInfo::operator = (
const DxvkGraphicsPipelineStateInfo& other) {
std::memcpy(this, &other, sizeof(DxvkGraphicsPipelineStateInfo));
return *this;
}
size_t DxvkGraphicsPipelineStateHash::operator () (
const DxvkGraphicsPipelineStateInfo& state) const {
// TODO implement hash
return 0;
}
size_t DxvkGraphicsPipelineStateEq::operator () (
const DxvkGraphicsPipelineStateInfo& a,
const DxvkGraphicsPipelineStateInfo& b) const {
return std::memcmp(&a, &b, sizeof(DxvkGraphicsPipelineStateInfo)) == 0;
}
@ -101,42 +99,110 @@ namespace dxvk {
if (m_gs != nullptr) stages.push_back(m_gs->stageInfo());
if (m_fs != nullptr) stages.push_back(m_fs->stageInfo());
VkPipelineViewportStateCreateInfo vpInfo;
vpInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
vpInfo.pNext = nullptr;
vpInfo.flags = 0;
vpInfo.viewportCount = state.viewportCount;
vpInfo.pViewports = nullptr;
vpInfo.scissorCount = state.viewportCount;
vpInfo.pScissors = nullptr;
VkPipelineVertexInputStateCreateInfo viInfo;
viInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
viInfo.pNext = nullptr;
viInfo.flags = 0;
viInfo.vertexBindingDescriptionCount = state.ilBindingCount;
viInfo.pVertexBindingDescriptions = state.ilBindings;
viInfo.vertexAttributeDescriptionCount = state.ilAttributeCount;
viInfo.pVertexAttributeDescriptions = state.ilAttributes;
VkPipelineDynamicStateCreateInfo dsInfo;
dsInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
dsInfo.pNext = nullptr;
dsInfo.flags = 0;
dsInfo.dynamicStateCount = dynamicStates.size();
dsInfo.pDynamicStates = dynamicStates.data();
VkPipelineInputAssemblyStateCreateInfo iaInfo;
iaInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
iaInfo.pNext = nullptr;
iaInfo.flags = 0;
iaInfo.topology = state.iaPrimitiveTopology;
iaInfo.primitiveRestartEnable = state.iaPrimitiveRestart;
VkPipelineViewportStateCreateInfo vpInfo;
vpInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
vpInfo.pNext = nullptr;
vpInfo.flags = 0;
vpInfo.viewportCount = state.rsViewportCount;
vpInfo.pViewports = nullptr;
vpInfo.scissorCount = state.rsViewportCount;
vpInfo.pScissors = nullptr;
VkPipelineRasterizationStateCreateInfo rsInfo;
rsInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
rsInfo.pNext = nullptr;
rsInfo.flags = 0;
rsInfo.depthClampEnable = state.rsEnableDepthClamp;
rsInfo.rasterizerDiscardEnable= state.rsEnableDiscard;
rsInfo.polygonMode = state.rsPolygonMode;
rsInfo.cullMode = state.rsCullMode;
rsInfo.frontFace = state.rsFrontFace;
rsInfo.depthBiasEnable = state.rsDepthBiasEnable;
rsInfo.depthBiasConstantFactor= state.rsDepthBiasConstant;
rsInfo.depthBiasClamp = state.rsDepthBiasClamp;
rsInfo.depthBiasSlopeFactor = state.rsDepthBiasSlope;
rsInfo.lineWidth = 1.0f;
VkPipelineMultisampleStateCreateInfo msInfo;
msInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
msInfo.pNext = nullptr;
msInfo.flags = 0;
msInfo.rasterizationSamples = state.msSampleCount;
msInfo.sampleShadingEnable = state.msEnableSampleShading;
msInfo.minSampleShading = state.msMinSampleShading;
msInfo.pSampleMask = &state.msSampleMask;
msInfo.alphaToCoverageEnable = state.msEnableAlphaToCoverage;
msInfo.alphaToOneEnable = state.msEnableAlphaToOne;
VkPipelineDepthStencilStateCreateInfo dsInfo;
dsInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
dsInfo.pNext = nullptr;
dsInfo.flags = 0;
dsInfo.depthTestEnable = state.dsEnableDepthTest;
dsInfo.depthWriteEnable = state.dsEnableDepthWrite;
dsInfo.depthCompareOp = state.dsDepthCompareOp;
dsInfo.depthBoundsTestEnable = state.dsEnableDepthBounds;
dsInfo.stencilTestEnable = state.dsEnableStencilTest;
dsInfo.front = state.dsStencilOpFront;
dsInfo.back = state.dsStencilOpBack;
dsInfo.minDepthBounds = state.dsDepthBoundsMin;
dsInfo.maxDepthBounds = state.dsDepthBoundsMax;
VkPipelineColorBlendStateCreateInfo cbInfo;
cbInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
cbInfo.pNext = nullptr;
cbInfo.flags = 0;
cbInfo.logicOpEnable = state.omEnableLogicOp;
cbInfo.logicOp = state.omLogicOp;
cbInfo.attachmentCount = DxvkLimits::MaxNumRenderTargets;
cbInfo.pAttachments = state.omBlendAttachments;
for (uint32_t i = 0; i < 4; i++)
cbInfo.blendConstants[i] = 0.0f;
VkPipelineDynamicStateCreateInfo dyInfo;
dyInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
dyInfo.pNext = nullptr;
dyInfo.flags = 0;
dyInfo.dynamicStateCount = dynamicStates.size();
dyInfo.pDynamicStates = dynamicStates.data();
VkGraphicsPipelineCreateInfo info;
info.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
info.pNext = nullptr;
info.flags = 0;
info.stageCount = stages.size();
info.pStages = stages.data();
info.pVertexInputState = &state.inputLayout->info();
info.pInputAssemblyState = &state.inputAssemblyState->info();
info.pTessellationState = nullptr; // TODO implement
info.pViewportState = &vpInfo;
info.pRasterizationState = &state.rasterizerState->info();
info.pMultisampleState = &state.multisampleState->info();
info.pDepthStencilState = &state.depthStencilState->info();
info.pColorBlendState = &state.blendState->info();
info.pDynamicState = &dsInfo;
info.layout = m_layout->pipelineLayout();
info.renderPass = state.renderPass;
info.subpass = 0;
info.basePipelineHandle = VK_NULL_HANDLE;
info.basePipelineIndex = 0;
info.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
info.pNext = nullptr;
info.flags = 0;
info.stageCount = stages.size();
info.pStages = stages.data();
info.pVertexInputState = &viInfo;
info.pInputAssemblyState = &iaInfo;
info.pTessellationState = nullptr; // TODO implement
info.pViewportState = &vpInfo;
info.pRasterizationState = &rsInfo;
info.pMultisampleState = &msInfo;
info.pDepthStencilState = &dsInfo;
info.pColorBlendState = &cbInfo;
info.pDynamicState = &dyInfo;
info.layout = m_layout->pipelineLayout();
info.renderPass = state.omRenderPass;
info.subpass = 0;
info.basePipelineHandle = VK_NULL_HANDLE; // TODO use this
info.basePipelineIndex = 0;
VkPipeline pipeline = VK_NULL_HANDLE;
if (m_vkd->vkCreateGraphicsPipelines(m_vkd->device(),

View File

@ -20,20 +20,65 @@ namespace dxvk {
* the current pipeline state vector.
*/
struct DxvkGraphicsPipelineStateInfo {
Rc<DxvkInputAssemblyState> inputAssemblyState;
Rc<DxvkInputLayout> inputLayout;
Rc<DxvkRasterizerState> rasterizerState;
Rc<DxvkMultisampleState> multisampleState;
Rc<DxvkDepthStencilState> depthStencilState;
Rc<DxvkBlendState> blendState;
DxvkGraphicsPipelineStateInfo();
DxvkGraphicsPipelineStateInfo(
const DxvkGraphicsPipelineStateInfo& other);
VkRenderPass renderPass;
uint32_t viewportCount;
DxvkGraphicsPipelineStateInfo& operator = (
const DxvkGraphicsPipelineStateInfo& other);
size_t hash() const;
VkPrimitiveTopology iaPrimitiveTopology;
VkBool32 iaPrimitiveRestart;
bool operator == (const DxvkGraphicsPipelineStateInfo& other) const;
bool operator != (const DxvkGraphicsPipelineStateInfo& other) const;
uint32_t ilAttributeCount;
uint32_t ilBindingCount;
VkVertexInputAttributeDescription ilAttributes[DxvkLimits::MaxNumVertexAttributes];
VkVertexInputBindingDescription ilBindings[DxvkLimits::MaxNumVertexBindings];
VkBool32 rsEnableDepthClamp;
VkBool32 rsEnableDiscard;
VkPolygonMode rsPolygonMode;
VkCullModeFlags rsCullMode;
VkFrontFace rsFrontFace;
VkBool32 rsDepthBiasEnable;
float rsDepthBiasConstant;
float rsDepthBiasClamp;
float rsDepthBiasSlope;
uint32_t rsViewportCount;
VkSampleCountFlagBits msSampleCount;
uint32_t msSampleMask;
VkBool32 msEnableAlphaToCoverage;
VkBool32 msEnableAlphaToOne;
VkBool32 msEnableSampleShading;
float msMinSampleShading;
VkBool32 dsEnableDepthTest;
VkBool32 dsEnableDepthWrite;
VkBool32 dsEnableDepthBounds;
VkBool32 dsEnableStencilTest;
VkCompareOp dsDepthCompareOp;
VkStencilOpState dsStencilOpFront;
VkStencilOpState dsStencilOpBack;
float dsDepthBoundsMin;
float dsDepthBoundsMax;
VkBool32 omEnableLogicOp;
VkLogicOp omLogicOp;
VkRenderPass omRenderPass;
VkPipelineColorBlendAttachmentState omBlendAttachments[DxvkLimits::MaxNumRenderTargets];
};
struct DxvkGraphicsPipelineStateHash {
size_t operator () (const DxvkGraphicsPipelineStateInfo& state) const;
};
struct DxvkGraphicsPipelineStateEq {
size_t operator () (
const DxvkGraphicsPipelineStateInfo& a,
const DxvkGraphicsPipelineStateInfo& b) const;
};
@ -91,7 +136,9 @@ namespace dxvk {
std::unordered_map<
DxvkGraphicsPipelineStateInfo,
VkPipeline, DxvkHash> m_pipelines;
VkPipeline,
DxvkGraphicsPipelineStateHash,
DxvkGraphicsPipelineStateEq> m_pipelines;
VkPipeline compilePipeline(
const DxvkGraphicsPipelineStateInfo& state) const;