[dxvk] Use dynamic rendering for regular graphics pipelines

For now, just do whatever we were previously doing for render passes,
but explicitly.
This commit is contained in:
Philip Rebohle 2022-07-02 20:39:20 +02:00
parent 5b6a598ed6
commit 343eba693d
No known key found for this signature in database
GPG Key ID: C8CC613427A31C99
6 changed files with 389 additions and 112 deletions

View File

@ -1932,10 +1932,7 @@ namespace dxvk {
}
if (attachmentIndex < 0) {
if (m_execBarriers.isImageDirty(
imageView->image(),
imageView->imageSubresources(),
DxvkAccess::Write))
if (m_execBarriers.isImageDirty(imageView->image(), imageView->imageSubresources(), DxvkAccess::Write))
m_execBarriers.recordCommands(m_cmd);
// Set up and bind a temporary framebuffer
@ -3982,6 +3979,133 @@ namespace dxvk {
}
void DxvkContext::renderPassEmitInitBarriers(
const DxvkFramebufferInfo& framebufferInfo,
const DxvkRenderPassOps& ops) {
// If any of the involved images are dirty, emit all pending barriers now.
// Otherwise, skip this step so that we can more efficiently batch barriers.
for (uint32_t i = 0; i < framebufferInfo.numAttachments(); i++) {
const auto& attachment = framebufferInfo.getAttachment(i);
if (m_execBarriers.isImageDirty(
attachment.view->image(),
attachment.view->imageSubresources(),
DxvkAccess::Write)) {
m_execBarriers.recordCommands(m_cmd);
break;
}
}
// Transition all images to the render layout as necessary
const auto& depthAttachment = framebufferInfo.getDepthTarget();
if (depthAttachment.layout != ops.depthOps.loadLayout
&& depthAttachment.view != nullptr) {
VkImageAspectFlags depthAspects = depthAttachment.view->info().aspect;
VkPipelineStageFlags depthStages =
VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT |
VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
VkAccessFlags depthAccess = 0;
if (((depthAspects & VK_IMAGE_ASPECT_DEPTH_BIT) && ops.depthOps.loadOpD == VK_ATTACHMENT_LOAD_OP_LOAD)
|| ((depthAspects & VK_IMAGE_ASPECT_STENCIL_BIT) && ops.depthOps.loadOpS == VK_ATTACHMENT_LOAD_OP_LOAD))
depthAccess |= VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT;
if (((depthAspects & VK_IMAGE_ASPECT_DEPTH_BIT) && ops.depthOps.loadOpD != VK_ATTACHMENT_LOAD_OP_LOAD)
|| ((depthAspects & VK_IMAGE_ASPECT_STENCIL_BIT) && ops.depthOps.loadOpS != VK_ATTACHMENT_LOAD_OP_LOAD)
|| (depthAttachment.layout != VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL))
depthAccess |= VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
if (depthAttachment.layout != VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL) {
depthStages |= m_device->getShaderPipelineStages();
depthAccess |= VK_ACCESS_SHADER_READ_BIT;
}
m_execBarriers.accessImage(
depthAttachment.view->image(),
depthAttachment.view->imageSubresources(),
ops.depthOps.loadLayout,
depthStages, 0,
depthAttachment.layout,
depthStages, depthAccess);
}
for (uint32_t i = 0; i < MaxNumRenderTargets; i++) {
const auto& colorAttachment = framebufferInfo.getColorTarget(i);
if (colorAttachment.layout != ops.colorOps[i].loadLayout
&& colorAttachment.view != nullptr) {
VkAccessFlags colorAccess = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
if (ops.colorOps[i].loadOp == VK_ATTACHMENT_LOAD_OP_LOAD)
colorAccess |= VK_ACCESS_COLOR_ATTACHMENT_READ_BIT;
m_execBarriers.accessImage(
colorAttachment.view->image(),
colorAttachment.view->imageSubresources(),
ops.colorOps[i].loadLayout,
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0,
colorAttachment.layout,
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
colorAccess);
}
}
// Unconditionally emit barriers here. We need to do this
// even if there are no layout transitions, since we don't
// track resource usage during render passes.
m_execBarriers.recordCommands(m_cmd);
}
void DxvkContext::renderPassEmitPostBarriers(
const DxvkFramebufferInfo& framebufferInfo,
const DxvkRenderPassOps& ops) {
const auto& depthAttachment = framebufferInfo.getDepthTarget();
if (depthAttachment.view != nullptr) {
m_execBarriers.accessImage(
depthAttachment.view->image(),
depthAttachment.view->imageSubresources(),
depthAttachment.layout,
VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT |
VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT |
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
ops.depthOps.storeLayout,
depthAttachment.view->imageInfo().stages,
depthAttachment.view->imageInfo().access);
}
for (uint32_t i = 0; i < MaxNumRenderTargets; i++) {
const auto& colorAttachment = framebufferInfo.getColorTarget(i);
if (colorAttachment.view != nullptr) {
m_execBarriers.accessImage(
colorAttachment.view->image(),
colorAttachment.view->imageSubresources(),
colorAttachment.layout,
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
VK_ACCESS_COLOR_ATTACHMENT_READ_BIT |
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
ops.colorOps[i].storeLayout,
colorAttachment.view->imageInfo().stages,
colorAttachment.view->imageInfo().access);
}
}
m_execBarriers.accessMemory(
ops.barrier.srcStages,
ops.barrier.srcAccess,
ops.barrier.dstStages,
ops.barrier.dstAccess);
// Do not flush barriers here. This is intended since
// we pre-record them when binding the framebuffer.
}
void DxvkContext::renderPassBindFramebuffer(
const DxvkFramebufferInfo& framebufferInfo,
const DxvkRenderPassOps& ops,
@ -3989,26 +4113,75 @@ namespace dxvk {
const VkClearValue* clearValues) {
const DxvkFramebufferSize fbSize = framebufferInfo.size();
Rc<DxvkFramebuffer> framebuffer = this->lookupFramebuffer(framebufferInfo);
this->renderPassEmitInitBarriers(framebufferInfo, ops);
this->renderPassEmitPostBarriers(framebufferInfo, ops);
VkRect2D renderArea;
renderArea.offset = VkOffset2D { 0, 0 };
renderArea.extent = VkExtent2D { fbSize.width, fbSize.height };
VkRenderPassBeginInfo info;
info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
info.pNext = nullptr;
info.renderPass = framebufferInfo.renderPass()->getHandle(ops);
info.framebuffer = framebuffer->handle();
info.renderArea = renderArea;
info.clearValueCount = clearValueCount;
info.pClearValues = clearValues;
m_cmd->cmdBeginRenderPass(&info,
VK_SUBPASS_CONTENTS_INLINE);
m_cmd->trackResource<DxvkAccess::None>(framebuffer);
uint32_t clearValueIndex = 0;
uint32_t colorInfoCount = 0;
std::array<VkRenderingAttachmentInfoKHR, MaxNumRenderTargets> colorInfos;
for (uint32_t i = 0; i < MaxNumRenderTargets; i++) {
const auto& colorTarget = framebufferInfo.getColorTarget(i);
colorInfos[i] = { VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR };
if (colorTarget.view != nullptr) {
colorInfos[i].imageView = colorTarget.view->handle();
colorInfos[i].imageLayout = colorTarget.layout;
colorInfos[i].loadOp = ops.colorOps[i].loadOp;
colorInfos[i].storeOp = VK_ATTACHMENT_STORE_OP_STORE;
if (ops.colorOps[i].loadOp == VK_ATTACHMENT_LOAD_OP_CLEAR)
colorInfos[i].clearValue = clearValues[clearValueIndex];
clearValueIndex += 1;
colorInfoCount = i + 1;
}
}
VkRenderingAttachmentInfoKHR depthInfo = { VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR };
VkImageAspectFlags depthStencilAspects = 0;
if (framebufferInfo.getDepthTarget().view != nullptr) {
const auto& depthTarget = framebufferInfo.getDepthTarget();
depthStencilAspects = depthTarget.view->info().aspect;
depthInfo.imageView = depthTarget.view->handle();
depthInfo.imageLayout = depthTarget.layout;
depthInfo.loadOp = ops.depthOps.loadOpD;
depthInfo.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
if (ops.depthOps.loadOpD == VK_ATTACHMENT_LOAD_OP_CLEAR)
depthInfo.clearValue = clearValues[clearValueIndex];
}
VkRenderingAttachmentInfoKHR stencilInfo = depthInfo;
if (framebufferInfo.getDepthTarget().view != nullptr) {
stencilInfo.loadOp = ops.depthOps.loadOpS;
stencilInfo.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
if (ops.depthOps.loadOpS == VK_ATTACHMENT_LOAD_OP_CLEAR)
stencilInfo.clearValue = clearValues[clearValueIndex];
}
VkRenderingInfoKHR renderingInfo = { VK_STRUCTURE_TYPE_RENDERING_INFO_KHR };
renderingInfo.renderArea.offset = VkOffset2D { 0, 0 };
renderingInfo.renderArea.extent = VkExtent2D { fbSize.width, fbSize.height };
renderingInfo.layerCount = fbSize.layers;
if (colorInfoCount) {
renderingInfo.colorAttachmentCount = colorInfoCount;
renderingInfo.pColorAttachments = colorInfos.data();
}
if (depthStencilAspects & VK_IMAGE_ASPECT_DEPTH_BIT)
renderingInfo.pDepthAttachment = &depthInfo;
if (depthStencilAspects & VK_IMAGE_ASPECT_STENCIL_BIT)
renderingInfo.pStencilAttachment = &stencilInfo;
m_cmd->cmdBeginRendering(&renderingInfo);
for (uint32_t i = 0; i < framebufferInfo.numAttachments(); i++) {
m_cmd->trackResource<DxvkAccess::None> (framebufferInfo.getAttachment(i).view);
m_cmd->trackResource<DxvkAccess::Write>(framebufferInfo.getAttachment(i).view->image());
@ -4019,7 +4192,11 @@ namespace dxvk {
void DxvkContext::renderPassUnbindFramebuffer() {
m_cmd->cmdEndRenderPass();
m_cmd->cmdEndRendering();
// TODO Try to get rid of this for performance reasons.
// This only exists to emulate render pass barriers.
m_execBarriers.recordCommands(m_cmd);
}
@ -4499,7 +4676,9 @@ namespace dxvk {
DxvkFramebufferInfo fbInfo = makeFramebufferInfo(m_state.om.renderTargets);
this->updateRenderTargetLayouts(fbInfo, m_state.om.framebufferInfo);
// Update relevant graphics pipeline state
m_state.gp.state.ms.setSampleCount(fbInfo.getSampleCount());
m_state.gp.state.rt = fbInfo.getRtInfo();
m_state.om.framebufferInfo = fbInfo;
for (uint32_t i = 0; i < MaxNumRenderTargets; i++) {

View File

@ -1286,6 +1286,14 @@ namespace dxvk {
void startRenderPass();
void spillRenderPass(bool suspend);
void renderPassEmitInitBarriers(
const DxvkFramebufferInfo& framebufferInfo,
const DxvkRenderPassOps& ops);
void renderPassEmitPostBarriers(
const DxvkFramebufferInfo& framebufferInfo,
const DxvkRenderPassOps& ops);
void renderPassBindFramebuffer(
const DxvkFramebufferInfo& framebufferInfo,
const DxvkRenderPassOps& ops,

View File

@ -88,6 +88,27 @@ namespace dxvk {
}
DxvkRtInfo DxvkFramebufferInfo::getRtInfo() const {
VkFormat depthStencilFormat = VK_FORMAT_UNDEFINED;
VkImageAspectFlags depthStencilReadOnlyAspects = 0;
if (m_renderTargets.depth.view != nullptr) {
depthStencilFormat = m_renderTargets.depth.view->info().format;
depthStencilReadOnlyAspects = m_renderTargets.depth.view->formatInfo()->aspectMask
& ~vk::getWritableAspectsForLayout(m_renderTargets.depth.layout);
}
std::array<VkFormat, MaxNumRenderTargets> colorFormats = { };
for (uint32_t i = 0; i < MaxNumRenderTargets; i++) {
if (m_renderTargets.color[i].view != nullptr)
colorFormats[i] = m_renderTargets.color[i].view->info().format;
}
return DxvkRtInfo(MaxNumRenderTargets, colorFormats.data(),
depthStencilFormat, depthStencilReadOnlyAspects);
}
DxvkRenderPassFormat DxvkFramebufferInfo::getRenderPassFormat(const DxvkRenderTargets& renderTargets) {
DxvkRenderPassFormat format;

View File

@ -1,6 +1,7 @@
#pragma once
#include "dxvk_image.h"
#include "dxvk_graphics_state.h"
#include "dxvk_renderpass.h"
namespace dxvk {
@ -225,6 +226,12 @@ namespace dxvk {
*/
DxvkFramebufferKey key() const;
/**
* \brief Generates render target state
* \returns Render target state info
*/
DxvkRtInfo getRtInfo() const;
/**
* \brief Generatess render pass format
*

View File

@ -120,9 +120,6 @@ namespace dxvk {
this->logPipelineState(LogLevel::Debug, state);
}
// Render pass format and image layouts
DxvkRenderPassFormat passFormat = renderPass->format();
// Set up dynamic states as needed
std::array<VkDynamicState, 6> dynamicStates;
uint32_t dynamicStateCount = 0;
@ -180,29 +177,41 @@ namespace dxvk {
if (fsm) stages.push_back(fsm.stageInfo(&specInfo));
// Fix up color write masks using the component mappings
std::array<VkPipelineColorBlendAttachmentState, MaxNumRenderTargets> omBlendAttachments;
VkImageAspectFlags rtReadOnlyAspects = state.rt.getDepthStencilReadOnlyAspects();
VkFormat rtDepthFormat = state.rt.getDepthStencilFormat();
auto rtDepthFormatInfo = imageFormatInfo(rtDepthFormat);
std::array<VkPipelineColorBlendAttachmentState, MaxNumRenderTargets> omBlendAttachments = { };
std::array<VkFormat, DxvkLimits::MaxNumRenderTargets> rtColorFormats;
uint32_t rtColorFormatCount = 0;
const VkColorComponentFlags fullMask
= VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT
| VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
for (uint32_t i = 0; i < MaxNumRenderTargets; i++) {
auto formatInfo = imageFormatInfo(passFormat.color[i].format);
omBlendAttachments[i] = state.omBlend[i].state();
rtColorFormats[i] = state.rt.getColorFormat(i);
if (!(m_fsOut & (1 << i)) || !formatInfo) {
omBlendAttachments[i].colorWriteMask = 0;
} else {
if (omBlendAttachments[i].colorWriteMask != fullMask) {
omBlendAttachments[i].colorWriteMask = util::remapComponentMask(
state.omBlend[i].colorWriteMask(), state.omSwizzle[i].mapping());
}
if (rtColorFormats[i]) {
rtColorFormatCount = i + 1;
omBlendAttachments[i].colorWriteMask &= formatInfo->componentMask;
auto formatInfo = imageFormatInfo(rtColorFormats[i]);
omBlendAttachments[i] = state.omBlend[i].state();
if (omBlendAttachments[i].colorWriteMask == formatInfo->componentMask) {
omBlendAttachments[i].colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT
| VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
if (!(m_fsOut & (1 << i)) || !formatInfo) {
omBlendAttachments[i].colorWriteMask = 0;
} else {
if (omBlendAttachments[i].colorWriteMask != fullMask) {
omBlendAttachments[i].colorWriteMask = util::remapComponentMask(
state.omBlend[i].colorWriteMask(), state.omSwizzle[i].mapping());
}
omBlendAttachments[i].colorWriteMask &= formatInfo->componentMask;
if (omBlendAttachments[i].colorWriteMask == formatInfo->componentMask) {
omBlendAttachments[i].colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT
| VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
}
}
}
}
@ -241,16 +250,11 @@ namespace dxvk {
viAttribs[i].binding = viBindingMap[state.ilAttributes[i].binding()];
}
VkPipelineVertexInputDivisorStateCreateInfoEXT viDivisorInfo;
viDivisorInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_DIVISOR_STATE_CREATE_INFO_EXT;
viDivisorInfo.pNext = nullptr;
VkPipelineVertexInputDivisorStateCreateInfoEXT viDivisorInfo = { VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_DIVISOR_STATE_CREATE_INFO_EXT };
viDivisorInfo.vertexBindingDivisorCount = viDivisorCount;
viDivisorInfo.pVertexBindingDivisors = viDivisorDesc.data();
VkPipelineVertexInputStateCreateInfo viInfo;
viInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
viInfo.pNext = &viDivisorInfo;
viInfo.flags = 0;
VkPipelineVertexInputStateCreateInfo viInfo = { VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, &viDivisorInfo };
viInfo.vertexBindingDescriptionCount = state.il.bindingCount();
viInfo.pVertexBindingDescriptions = viBindings.data();
viInfo.vertexAttributeDescriptionCount = state.il.attributeCount();
@ -263,60 +267,34 @@ namespace dxvk {
if (!m_pipeMgr->m_device->features().extVertexAttributeDivisor.vertexAttributeInstanceRateDivisor)
viInfo.pNext = viDivisorInfo.pNext;
VkPipelineInputAssemblyStateCreateInfo iaInfo;
iaInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
iaInfo.pNext = nullptr;
iaInfo.flags = 0;
VkPipelineInputAssemblyStateCreateInfo iaInfo = { VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO };
iaInfo.topology = state.ia.primitiveTopology();
iaInfo.primitiveRestartEnable = state.ia.primitiveRestart();
VkPipelineTessellationStateCreateInfo tsInfo;
tsInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO;
tsInfo.pNext = nullptr;
tsInfo.flags = 0;
VkPipelineTessellationStateCreateInfo tsInfo = { VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO };
tsInfo.patchControlPoints = state.ia.patchVertexCount();
VkPipelineViewportStateCreateInfo vpInfo;
vpInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
vpInfo.pNext = nullptr;
vpInfo.flags = 0;
VkPipelineViewportStateCreateInfo vpInfo = { VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO };
vpInfo.viewportCount = state.rs.viewportCount();
vpInfo.pViewports = nullptr;
vpInfo.scissorCount = state.rs.viewportCount();
vpInfo.pScissors = nullptr;
VkPipelineRasterizationConservativeStateCreateInfoEXT conservativeInfo;
conservativeInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_CONSERVATIVE_STATE_CREATE_INFO_EXT;
conservativeInfo.pNext = nullptr;
conservativeInfo.flags = 0;
VkPipelineRasterizationConservativeStateCreateInfoEXT conservativeInfo = { VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_CONSERVATIVE_STATE_CREATE_INFO_EXT };
conservativeInfo.conservativeRasterizationMode = state.rs.conservativeMode();
conservativeInfo.extraPrimitiveOverestimationSize = 0.0f;
VkPipelineRasterizationStateStreamCreateInfoEXT xfbStreamInfo;
xfbStreamInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_STREAM_CREATE_INFO_EXT;
xfbStreamInfo.pNext = nullptr;
xfbStreamInfo.flags = 0;
VkPipelineRasterizationStateStreamCreateInfoEXT xfbStreamInfo = { VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_STREAM_CREATE_INFO_EXT };
xfbStreamInfo.rasterizationStream = uint32_t(rasterizedStream);
VkPipelineRasterizationDepthClipStateCreateInfoEXT rsDepthClipInfo;
rsDepthClipInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_DEPTH_CLIP_STATE_CREATE_INFO_EXT;
rsDepthClipInfo.pNext = nullptr;
rsDepthClipInfo.flags = 0;
VkPipelineRasterizationDepthClipStateCreateInfoEXT rsDepthClipInfo = { VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_DEPTH_CLIP_STATE_CREATE_INFO_EXT };
rsDepthClipInfo.depthClipEnable = state.rs.depthClipEnable();
VkPipelineRasterizationStateCreateInfo rsInfo;
rsInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
rsInfo.pNext = nullptr;
rsInfo.flags = 0;
VkPipelineRasterizationStateCreateInfo rsInfo = { VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO };
rsInfo.depthClampEnable = VK_TRUE;
rsInfo.rasterizerDiscardEnable = rasterizedStream < 0;
rsInfo.polygonMode = state.rs.polygonMode();
rsInfo.cullMode = state.rs.cullMode();
rsInfo.frontFace = state.rs.frontFace();
rsInfo.depthBiasEnable = state.rs.depthBiasEnable();
rsInfo.depthBiasConstantFactor= 0.0f;
rsInfo.depthBiasClamp = 0.0f;
rsInfo.depthBiasSlopeFactor = 0.0f;
rsInfo.lineWidth = 1.0f;
if (rasterizedStream > 0)
@ -332,10 +310,7 @@ namespace dxvk {
uint32_t sampleMask = state.ms.sampleMask();
VkPipelineMultisampleStateCreateInfo msInfo;
msInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
msInfo.pNext = nullptr;
msInfo.flags = 0;
VkPipelineMultisampleStateCreateInfo msInfo = { VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO };
msInfo.rasterizationSamples = sampleCount;
msInfo.sampleShadingEnable = m_common.msSampleShadingEnable;
msInfo.minSampleShading = m_common.msSampleShadingFactor;
@ -343,43 +318,41 @@ namespace dxvk {
msInfo.alphaToCoverageEnable = state.ms.enableAlphaToCoverage();
msInfo.alphaToOneEnable = VK_FALSE;
VkPipelineDepthStencilStateCreateInfo dsInfo;
dsInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
dsInfo.pNext = nullptr;
dsInfo.flags = 0;
VkPipelineDepthStencilStateCreateInfo dsInfo = { VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO };
dsInfo.depthTestEnable = state.ds.enableDepthTest();
dsInfo.depthWriteEnable = state.ds.enableDepthWrite() && !util::isDepthReadOnlyLayout(passFormat.depth.layout);
dsInfo.depthWriteEnable = state.ds.enableDepthWrite() && !(rtReadOnlyAspects & VK_IMAGE_ASPECT_DEPTH_BIT);
dsInfo.depthCompareOp = state.ds.depthCompareOp();
dsInfo.depthBoundsTestEnable = state.ds.enableDepthBoundsTest();
dsInfo.stencilTestEnable = state.ds.enableStencilTest();
dsInfo.front = state.dsFront.state();
dsInfo.back = state.dsBack.state();
dsInfo.minDepthBounds = 0.0f;
dsInfo.maxDepthBounds = 1.0f;
VkPipelineColorBlendStateCreateInfo cbInfo;
cbInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
cbInfo.pNext = nullptr;
cbInfo.flags = 0;
VkPipelineColorBlendStateCreateInfo cbInfo = { VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO };
cbInfo.logicOpEnable = state.om.enableLogicOp();
cbInfo.logicOp = state.om.logicOp();
cbInfo.attachmentCount = DxvkLimits::MaxNumRenderTargets;
cbInfo.attachmentCount = rtColorFormatCount;
cbInfo.pAttachments = omBlendAttachments.data();
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;
VkPipelineDynamicStateCreateInfo dyInfo = { VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO };
dyInfo.dynamicStateCount = dynamicStateCount;
dyInfo.pDynamicStates = dynamicStates.data();
VkGraphicsPipelineCreateInfo info;
info.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
info.pNext = nullptr;
info.flags = 0;
VkPipelineRenderingCreateInfoKHR rtInfo = { VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR };
if (rtColorFormatCount) {
rtInfo.colorAttachmentCount = rtColorFormatCount;
rtInfo.pColorAttachmentFormats = rtColorFormats.data();
}
if (rtDepthFormat) {
if (rtDepthFormatInfo->aspectMask & VK_IMAGE_ASPECT_DEPTH_BIT)
rtInfo.depthAttachmentFormat = rtDepthFormat;
if (rtDepthFormatInfo->aspectMask & VK_IMAGE_ASPECT_STENCIL_BIT)
rtInfo.stencilAttachmentFormat = rtDepthFormat;
}
VkGraphicsPipelineCreateInfo info = { VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, &rtInfo };
info.stageCount = stages.size();
info.pStages = stages.data();
info.pVertexInputState = &viInfo;
@ -392,12 +365,9 @@ namespace dxvk {
info.pColorBlendState = &cbInfo;
info.pDynamicState = &dyInfo;
info.layout = m_bindings->getPipelineLayout();
info.renderPass = renderPass->getDefaultHandle();
info.subpass = 0;
info.basePipelineHandle = VK_NULL_HANDLE;
info.basePipelineIndex = -1;
if (tsInfo.patchControlPoints == 0)
if (!tsInfo.patchControlPoints)
info.pTessellationState = nullptr;
// Time pipeline compilation for debugging purposes

View File

@ -477,6 +477,97 @@ namespace dxvk {
};
/**
* \brief Packed render target formats
*
* Compact representation of depth-stencil and color attachments,
* as well as the read-only mask for the depth-stencil attachment,
* which needs to be known at pipeline compile time.
*/
class DxvkRtInfo {
public:
DxvkRtInfo() = default;
DxvkRtInfo(
uint32_t colorFormatCount,
const VkFormat* colorFormats,
VkFormat depthStencilFormat,
VkImageAspectFlags depthStencilReadOnlyAspects)
: m_packedData(0ull) {
m_packedData |= encodeDepthStencilFormat(depthStencilFormat);
m_packedData |= encodeDepthStencilAspects(depthStencilReadOnlyAspects);
for (uint32_t i = 0; i < colorFormatCount; i++)
m_packedData |= encodeColorFormat(colorFormats[i], i);
}
VkFormat getColorFormat(uint32_t index) const {
return decodeColorFormat(m_packedData, index);
}
VkFormat getDepthStencilFormat() const {
return decodeDepthStencilFormat(m_packedData);
}
VkImageAspectFlags getDepthStencilReadOnlyAspects() const {
return decodeDepthStencilAspects(m_packedData);
}
private:
uint64_t m_packedData;
static uint64_t encodeDepthStencilAspects(VkImageAspectFlags aspects) {
return uint64_t(aspects) << 61;
}
static uint64_t encodeDepthStencilFormat(VkFormat format) {
return format
? (uint64_t(format) - uint64_t(VK_FORMAT_E5B9G9R9_UFLOAT_PACK32)) << 56
: (uint64_t(0));
}
static uint64_t encodeColorFormat(VkFormat format, uint32_t index) {
uint64_t value = uint64_t(format);
if (value >= uint64_t(VK_FORMAT_A4R4G4B4_UNORM_PACK16_EXT)) {
value -= uint64_t(VK_FORMAT_A4R4G4B4_UNORM_PACK16_EXT);
value += uint64_t(VK_FORMAT_E5B9G9R9_UFLOAT_PACK32) + 1;
} else if (value > uint64_t(VK_FORMAT_E5B9G9R9_UFLOAT_PACK32)) {
value = 0;
}
return value << (7 * index);
}
static VkImageAspectFlags decodeDepthStencilAspects(uint64_t value) {
return VkImageAspectFlags((value >> 61) & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT));
}
static VkFormat decodeDepthStencilFormat(uint64_t value) {
value = (value >> 56) & 0x1F;
return value
? VkFormat(value + uint64_t(VK_FORMAT_E5B9G9R9_UFLOAT_PACK32))
: VkFormat(VK_FORMAT_UNDEFINED);
}
static VkFormat decodeColorFormat(uint64_t value, uint32_t index) {
value = (value >> (7 * index)) & 0x7F;
if (value > uint64_t(VK_FORMAT_E5B9G9R9_UFLOAT_PACK32)) {
value -= uint64_t(VK_FORMAT_E5B9G9R9_UFLOAT_PACK32) + 1ull;
value += uint64_t(VK_FORMAT_A4R4G4B4_UNORM_PACK16_EXT);
}
return VkFormat(value);
}
};
/**
* \brief Packed attachment blend mode
*
@ -685,6 +776,7 @@ namespace dxvk {
DxvkMsInfo ms;
DxvkDsInfo ds;
DxvkOmInfo om;
DxvkRtInfo rt;
DxvkScInfo sc;
DxvkDsStencilOp dsFront;
DxvkDsStencilOp dsBack;