1
0
mirror of https://github.com/doitsujin/dxvk.git synced 2025-01-29 17:52:18 +01:00

[dxvk] Optimized pipeline state updates

This commit is contained in:
Philip Rebohle 2018-01-10 20:40:10 +01:00
parent 1b67ffaed2
commit 9c90c1ac00
3 changed files with 101 additions and 128 deletions

View File

@ -47,11 +47,16 @@ namespace dxvk {
}
void DxvkContext::bindFramebuffer(
const Rc<DxvkFramebuffer>& fb) {
void DxvkContext::bindFramebuffer(const Rc<DxvkFramebuffer>& fb) {
if (m_state.om.framebuffer != fb) {
this->renderPassEnd();
m_state.om.framebuffer = fb;
if (fb != nullptr) {
m_state.gp.state.msSampleCount = fb->sampleCount();
m_state.gp.state.omRenderPass = fb->renderPass();
m_flags.set(DxvkContextFlag::GpDirtyPipelineState);
}
}
}
@ -770,8 +775,8 @@ namespace dxvk {
uint32_t viewportCount,
const VkViewport* viewports,
const VkRect2D* scissorRects) {
if (m_state.vp.viewportCount != viewportCount) {
m_state.vp.viewportCount = viewportCount;
if (m_state.gp.state.rsViewportCount != viewportCount) {
m_state.gp.state.rsViewportCount = viewportCount;
m_flags.set(DxvkContextFlag::GpDirtyPipelineState);
}
@ -801,9 +806,10 @@ namespace dxvk {
}
void DxvkContext::setInputAssemblyState(
const DxvkInputAssemblyState& state) {
m_state.ia = state;
void DxvkContext::setInputAssemblyState(const DxvkInputAssemblyState& ia) {
m_state.gp.state.iaPrimitiveTopology = ia.primitiveTopology;
m_state.gp.state.iaPrimitiveRestart = ia.primitiveRestart;
m_flags.set(DxvkContextFlag::GpDirtyPipelineState);
}
@ -817,41 +823,76 @@ namespace dxvk {
DxvkContextFlag::GpDirtyPipelineState,
DxvkContextFlag::GpDirtyVertexBuffers);
m_state.il.numAttributes = attributeCount;
m_state.il.numBindings = bindingCount;
m_state.gp.state.ilAttributeCount = attributeCount;
m_state.gp.state.ilBindingCount = bindingCount;
for (uint32_t i = 0; i < attributeCount; i++)
m_state.il.attributes[i] = attributes[i];
for (uint32_t i = 0; i < attributeCount; i++) {
m_state.gp.state.ilAttributes[i].location = attributes[i].location;
m_state.gp.state.ilAttributes[i].binding = attributes[i].binding;
m_state.gp.state.ilAttributes[i].format = attributes[i].format;
m_state.gp.state.ilAttributes[i].offset = attributes[i].offset;
}
for (uint32_t i = 0; i < bindingCount; i++)
m_state.il.bindings[i] = bindings[i];
std::memset(
m_state.gp.state.ilAttributes + attributeCount, 0,
sizeof(VkVertexInputAttributeDescription) * (MaxNumVertexAttributes - attributeCount));
for (uint32_t i = 0; i < bindingCount; i++) {
m_state.gp.state.ilBindings[i].binding = bindings[i].binding;
m_state.gp.state.ilBindings[i].inputRate = bindings[i].inputRate;
}
std::memset(
m_state.gp.state.ilBindings + bindingCount, 0,
sizeof(VkVertexInputBindingDescription) * (MaxNumVertexBindings - bindingCount));
}
void DxvkContext::setRasterizerState(
const DxvkRasterizerState& state) {
m_state.rs = state;
void DxvkContext::setRasterizerState(const DxvkRasterizerState& rs) {
m_state.gp.state.rsEnableDepthClamp = rs.enableDepthClamp;
m_state.gp.state.rsEnableDiscard = rs.enableDiscard;
m_state.gp.state.rsPolygonMode = rs.polygonMode;
m_state.gp.state.rsCullMode = rs.cullMode;
m_state.gp.state.rsFrontFace = rs.frontFace;
m_state.gp.state.rsDepthBiasEnable = rs.depthBiasEnable;
m_state.gp.state.rsDepthBiasConstant = rs.depthBiasConstant;
m_state.gp.state.rsDepthBiasClamp = rs.depthBiasClamp;
m_state.gp.state.rsDepthBiasSlope = rs.depthBiasSlope;
m_flags.set(DxvkContextFlag::GpDirtyPipelineState);
}
void DxvkContext::setMultisampleState(
const DxvkMultisampleState& state) {
m_state.ms = state;
void DxvkContext::setMultisampleState(const DxvkMultisampleState& ms) {
m_state.gp.state.msSampleMask = ms.sampleMask;
m_state.gp.state.msEnableAlphaToCoverage = ms.enableAlphaToCoverage;
m_state.gp.state.msEnableAlphaToOne = ms.enableAlphaToOne;
m_state.gp.state.msEnableSampleShading = ms.enableSampleShading;
m_state.gp.state.msMinSampleShading = ms.minSampleShading;
m_flags.set(DxvkContextFlag::GpDirtyPipelineState);
}
void DxvkContext::setDepthStencilState(
const DxvkDepthStencilState& state) {
m_state.ds = state;
void DxvkContext::setDepthStencilState(const DxvkDepthStencilState& ds) {
m_state.gp.state.dsEnableDepthTest = ds.enableDepthTest;
m_state.gp.state.dsEnableDepthWrite = ds.enableDepthWrite;
m_state.gp.state.dsEnableDepthBounds = ds.enableDepthBounds;
m_state.gp.state.dsEnableStencilTest = ds.enableStencilTest;
m_state.gp.state.dsDepthCompareOp = ds.depthCompareOp;
m_state.gp.state.dsStencilOpFront = ds.stencilOpFront;
m_state.gp.state.dsStencilOpBack = ds.stencilOpBack;
m_state.gp.state.dsDepthBoundsMin = ds.depthBoundsMin;
m_state.gp.state.dsDepthBoundsMax = ds.depthBoundsMax;
m_flags.set(DxvkContextFlag::GpDirtyPipelineState);
}
void DxvkContext::setLogicOpState(
const DxvkLogicOpState& state) {
m_state.lo = state;
void DxvkContext::setLogicOpState(const DxvkLogicOpState& lo) {
m_state.gp.state.omEnableLogicOp = lo.enableLogicOp;
m_state.gp.state.omLogicOp = lo.logicOp;
m_flags.set(DxvkContextFlag::GpDirtyPipelineState);
}
@ -859,7 +900,15 @@ namespace dxvk {
void DxvkContext::setBlendMode(
uint32_t attachment,
const DxvkBlendMode& blendMode) {
m_state.om.blendModes[attachment] = blendMode;
m_state.gp.state.omBlendAttachments[attachment].blendEnable = blendMode.enableBlending;
m_state.gp.state.omBlendAttachments[attachment].srcColorBlendFactor = blendMode.colorSrcFactor;
m_state.gp.state.omBlendAttachments[attachment].dstColorBlendFactor = blendMode.colorDstFactor;
m_state.gp.state.omBlendAttachments[attachment].colorBlendOp = blendMode.colorBlendOp;
m_state.gp.state.omBlendAttachments[attachment].srcAlphaBlendFactor = blendMode.alphaSrcFactor;
m_state.gp.state.omBlendAttachments[attachment].dstAlphaBlendFactor = blendMode.alphaDstFactor;
m_state.gp.state.omBlendAttachments[attachment].alphaBlendOp = blendMode.alphaBlendOp;
m_state.gp.state.omBlendAttachments[attachment].colorWriteMask = blendMode.writeMask;
m_flags.set(DxvkContextFlag::GpDirtyPipelineState);
}
@ -925,7 +974,7 @@ namespace dxvk {
if (m_flags.test(DxvkContextFlag::GpDirtyPipeline)) {
m_flags.clr(DxvkContextFlag::GpDirtyPipeline);
m_state.gp.bs.clear();
m_state.gp.state.bsBindingState.clear();
m_state.gp.pipeline = m_device->createGraphicsPipeline(
m_state.gp.vs.shader, m_state.gp.tcs.shader, m_state.gp.tes.shader,
m_state.gp.gs.shader, m_state.gp.fs.shader);
@ -939,79 +988,14 @@ namespace dxvk {
if (m_flags.test(DxvkContextFlag::GpDirtyPipelineState)) {
m_flags.clr(DxvkContextFlag::GpDirtyPipelineState);
DxvkGraphicsPipelineStateInfo gpState;
gpState.bsBindingState = m_state.gp.bs;
for (uint32_t i = 0; i < m_state.gp.state.ilBindingCount; i++)
m_state.gp.state.ilBindings[i].stride = m_state.vi.vertexStrides[i];
gpState.iaPrimitiveTopology = m_state.ia.primitiveTopology;
gpState.iaPrimitiveRestart = m_state.ia.primitiveRestart;
gpState.ilAttributeCount = m_state.il.numAttributes;
gpState.ilBindingCount = m_state.il.numBindings;
for (uint32_t i = 0; i < m_state.il.numAttributes; i++) {
gpState.ilAttributes[i].location = m_state.il.attributes[i].location;
gpState.ilAttributes[i].binding = m_state.il.attributes[i].binding;
gpState.ilAttributes[i].format = m_state.il.attributes[i].format;
gpState.ilAttributes[i].offset = m_state.il.attributes[i].offset;
}
for (uint32_t i = 0; i < m_state.il.numBindings; i++) {
gpState.ilBindings[i].binding = m_state.il.bindings[i].binding;
gpState.ilBindings[i].inputRate = m_state.il.bindings[i].inputRate;
gpState.ilBindings[i].stride = m_state.vi.vertexStrides[i];
}
gpState.rsEnableDepthClamp = m_state.rs.enableDepthClamp;
gpState.rsEnableDiscard = m_state.rs.enableDiscard;
gpState.rsPolygonMode = m_state.rs.polygonMode;
gpState.rsCullMode = m_state.rs.cullMode;
gpState.rsFrontFace = m_state.rs.frontFace;
gpState.rsDepthBiasEnable = m_state.rs.depthBiasEnable;
gpState.rsDepthBiasConstant = m_state.rs.depthBiasConstant;
gpState.rsDepthBiasClamp = m_state.rs.depthBiasClamp;
gpState.rsDepthBiasSlope = m_state.rs.depthBiasSlope;
gpState.rsViewportCount = m_state.vp.viewportCount;
gpState.msSampleCount = m_state.om.framebuffer->sampleCount();
gpState.msSampleMask = m_state.ms.sampleMask;
gpState.msEnableAlphaToCoverage = m_state.ms.enableAlphaToCoverage;
gpState.msEnableAlphaToOne = m_state.ms.enableAlphaToOne;
gpState.msEnableSampleShading = m_state.ms.enableSampleShading;
gpState.msMinSampleShading = m_state.ms.minSampleShading;
gpState.dsEnableDepthTest = m_state.ds.enableDepthTest;
gpState.dsEnableDepthWrite = m_state.ds.enableDepthWrite;
gpState.dsEnableDepthBounds = m_state.ds.enableDepthBounds;
gpState.dsEnableStencilTest = m_state.ds.enableStencilTest;
gpState.dsDepthCompareOp = m_state.ds.depthCompareOp;
gpState.dsStencilOpFront = m_state.ds.stencilOpFront;
gpState.dsStencilOpBack = m_state.ds.stencilOpBack;
gpState.dsDepthBoundsMin = m_state.ds.depthBoundsMin;
gpState.dsDepthBoundsMax = m_state.ds.depthBoundsMax;
gpState.omEnableLogicOp = m_state.lo.enableLogicOp;
gpState.omLogicOp = m_state.lo.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) {
const DxvkBlendMode& mode = m_state.om.blendModes[i];
gpState.omBlendAttachments[i].blendEnable = mode.enableBlending;
gpState.omBlendAttachments[i].srcColorBlendFactor = mode.colorSrcFactor;
gpState.omBlendAttachments[i].dstColorBlendFactor = mode.colorDstFactor;
gpState.omBlendAttachments[i].colorBlendOp = mode.colorBlendOp;
gpState.omBlendAttachments[i].srcAlphaBlendFactor = mode.alphaSrcFactor;
gpState.omBlendAttachments[i].dstAlphaBlendFactor = mode.alphaDstFactor;
gpState.omBlendAttachments[i].alphaBlendOp = mode.alphaBlendOp;
gpState.omBlendAttachments[i].colorWriteMask = mode.writeMask;
}
}
for (uint32_t i = m_state.gp.state.ilBindingCount; i < MaxNumVertexBindings; i++)
m_state.gp.state.ilBindings[i].stride = 0;
m_cmd->cmdBindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS,
m_state.gp.pipeline->getPipelineHandle(gpState));
m_state.gp.pipeline->getPipelineHandle(m_state.gp.state));
}
}
@ -1052,7 +1036,7 @@ namespace dxvk {
this->updateShaderDescriptors(
VK_PIPELINE_BIND_POINT_GRAPHICS,
m_state.gp.bs,
m_state.gp.state.bsBindingState,
m_state.gp.pipeline->layout());
}
}
@ -1063,7 +1047,7 @@ namespace dxvk {
const Rc<DxvkBindingLayout>& layout) {
DxvkBindingState& bs =
bindPoint == VK_PIPELINE_BIND_POINT_GRAPHICS
? m_state.gp.bs
? m_state.gp.state.bsBindingState
: m_state.cp.bs;
bool updatePipelineState = false;
@ -1167,8 +1151,8 @@ namespace dxvk {
void DxvkContext::updateViewports() {
m_cmd->cmdSetViewport(0, m_state.vp.viewportCount, m_state.vp.viewports.data());
m_cmd->cmdSetScissor (0, m_state.vp.viewportCount, m_state.vp.scissorRects.data());
m_cmd->cmdSetViewport(0, m_state.gp.state.rsViewportCount, m_state.vp.viewports.data());
m_cmd->cmdSetScissor (0, m_state.gp.state.rsViewportCount, m_state.vp.scissorRects.data());
}
@ -1204,7 +1188,7 @@ namespace dxvk {
if (m_flags.test(DxvkContextFlag::GpDirtyVertexBuffers)) {
m_flags.clr(DxvkContextFlag::GpDirtyVertexBuffers);
for (uint32_t i = 0; i < m_state.il.numBindings; i++) {
for (uint32_t i = 0; i < m_state.gp.state.ilBindingCount; i++) {
const DxvkBufferSlice& vbo = m_state.vi.vertexBuffers[i];
const VkBuffer handle = vbo.handle();
@ -1212,11 +1196,9 @@ namespace dxvk {
if (handle != VK_NULL_HANDLE) {
m_cmd->cmdBindVertexBuffers(
m_state.il.bindings[i].binding,
m_state.gp.state.ilBindings[i].binding,
1, &handle, &offset);
m_cmd->trackResource(vbo.resource());
} else {
Logger::err(str::format("DxvkContext: Unbound vertex buffer: ", i));
}
}
}

View File

@ -419,10 +419,10 @@ namespace dxvk {
/**
* \brief Sets input assembly state
* \param [in] state New state object
* \param [in] ia New state object
*/
void setInputAssemblyState(
const DxvkInputAssemblyState& state);
const DxvkInputAssemblyState& ia);
/**
* \brief Sets input layout
@ -440,31 +440,31 @@ namespace dxvk {
/**
* \brief Sets rasterizer state
* \param [in] state New state object
* \param [in] rs New state object
*/
void setRasterizerState(
const DxvkRasterizerState& state);
const DxvkRasterizerState& rs);
/**
* \brief Sets multisample state
* \param [in] state New state object
* \param [in] ms New state object
*/
void setMultisampleState(
const DxvkMultisampleState& state);
const DxvkMultisampleState& ms);
/**
* \brief Sets depth stencil state
* \param [in] state New state object
* \param [in] ds New state object
*/
void setDepthStencilState(
const DxvkDepthStencilState& state);
const DxvkDepthStencilState& ds);
/**
* \brief Sets logic op state
* \param [in] state New state object
* \param [in] lo New state object
*/
void setLogicOpState(
const DxvkLogicOpState& state);
const DxvkLogicOpState& lo);
/**
* \brief Sets blend mode for an attachment

View File

@ -49,19 +49,16 @@ namespace dxvk {
struct DxvkViewportState {
uint32_t viewportCount = 0;
std::array<VkViewport, DxvkLimits::MaxNumViewports> viewports;
std::array<VkRect2D, DxvkLimits::MaxNumViewports> scissorRects;
};
struct DxvkOutputMergerState {
Rc<DxvkFramebuffer> framebuffer;
Rc<DxvkFramebuffer> framebuffer;
std::array<DxvkBlendMode,
DxvkLimits::MaxNumRenderTargets> blendModes;
float blendConstants[4];
uint32_t stencilReference;
float blendConstants[4];
uint32_t stencilReference;
};
@ -71,13 +68,13 @@ namespace dxvk {
struct DxvkGraphicsPipelineState {
DxvkBindingState bs;
DxvkShaderStage vs;
DxvkShaderStage tcs;
DxvkShaderStage tes;
DxvkShaderStage gs;
DxvkShaderStage fs;
DxvkGraphicsPipelineStateInfo state;
Rc<DxvkGraphicsPipeline> pipeline;
};
@ -96,14 +93,8 @@ namespace dxvk {
* and constant pipeline state objects.
*/
struct DxvkContextState {
DxvkInputAssemblyState ia;
DxvkInputLayout il;
DxvkVertexInputState vi;
DxvkViewportState vp;
DxvkRasterizerState rs;
DxvkMultisampleState ms;
DxvkDepthStencilState ds;
DxvkLogicOpState lo;
DxvkOutputMergerState om;
DxvkGraphicsPipelineState gp;