mirror of
https://github.com/doitsujin/dxvk.git
synced 2024-12-11 01:24:12 +01:00
[dxvk] Removed explicit image barriers for render passes
Instead, the color format and layout will now be set in the render pass description. This slows down render pass lookups but may improve efficiency and work around driver bugs.
This commit is contained in:
parent
1da23755b7
commit
0900dfd0e3
@ -1108,9 +1108,6 @@ namespace dxvk {
|
||||
&& (m_state.om.framebuffer != nullptr)) {
|
||||
m_flags.set(DxvkContextFlag::GpRenderPassBound);
|
||||
|
||||
this->transformLayoutsRenderPassBegin(
|
||||
m_state.om.framebuffer->renderTargets());
|
||||
|
||||
const DxvkFramebufferSize fbSize
|
||||
= m_state.om.framebuffer->size();
|
||||
|
||||
@ -1139,9 +1136,6 @@ namespace dxvk {
|
||||
if (m_flags.test(DxvkContextFlag::GpRenderPassBound)) {
|
||||
m_flags.clr(DxvkContextFlag::GpRenderPassBound);
|
||||
m_cmd->cmdEndRenderPass();
|
||||
|
||||
this->transformLayoutsRenderPassEnd(
|
||||
m_state.om.framebuffer->renderTargets());
|
||||
}
|
||||
}
|
||||
|
||||
@ -1493,97 +1487,4 @@ namespace dxvk {
|
||||
m_barriers.recordCommands(m_cmd);
|
||||
}
|
||||
|
||||
|
||||
void DxvkContext::transformLayoutsRenderPassBegin(
|
||||
const DxvkRenderTargets& renderTargets) {
|
||||
// Ensure that all color attachments are in the optimal layout.
|
||||
// Any image that is used as a present source requires special
|
||||
// care as we cannot use it for reading.
|
||||
for (uint32_t i = 0; i < MaxNumRenderTargets; i++) {
|
||||
const Rc<DxvkImageView> target = renderTargets.getColorTarget(i);
|
||||
|
||||
if ((target != nullptr)
|
||||
&& (target->imageInfo().layout != VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)) {
|
||||
VkImageLayout srcLayout = target->imageInfo().layout;
|
||||
|
||||
if (srcLayout == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR)
|
||||
srcLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
|
||||
m_barriers.accessImage(
|
||||
target->image(),
|
||||
target->subresources(),
|
||||
srcLayout,
|
||||
target->imageInfo().stages,
|
||||
target->imageInfo().access,
|
||||
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
|
||||
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
|
||||
VK_ACCESS_COLOR_ATTACHMENT_READ_BIT |
|
||||
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT);
|
||||
}
|
||||
}
|
||||
|
||||
// Transform the depth-stencil view to the optimal layout
|
||||
const Rc<DxvkImageView> dsTarget = renderTargets.getDepthTarget();
|
||||
|
||||
if ((dsTarget != nullptr)
|
||||
&& (dsTarget->imageInfo().layout != VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL)) {
|
||||
m_barriers.accessImage(
|
||||
dsTarget->image(),
|
||||
dsTarget->subresources(),
|
||||
dsTarget->imageInfo().layout,
|
||||
dsTarget->imageInfo().stages,
|
||||
dsTarget->imageInfo().access,
|
||||
VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
|
||||
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);
|
||||
}
|
||||
|
||||
m_barriers.recordCommands(m_cmd);
|
||||
}
|
||||
|
||||
|
||||
void DxvkContext::transformLayoutsRenderPassEnd(
|
||||
const DxvkRenderTargets& renderTargets) {
|
||||
// Transform color attachments back to their original layouts and
|
||||
// make sure that they can be used for subsequent draw or compute
|
||||
// operations. Swap chain images are treated like any other image.
|
||||
for (uint32_t i = 0; i < MaxNumRenderTargets; i++) {
|
||||
const Rc<DxvkImageView> target = renderTargets.getColorTarget(i);
|
||||
|
||||
if (target != nullptr) {
|
||||
m_barriers.accessImage(
|
||||
target->image(),
|
||||
target->subresources(),
|
||||
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
|
||||
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
|
||||
VK_ACCESS_COLOR_ATTACHMENT_READ_BIT |
|
||||
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
|
||||
target->imageInfo().layout,
|
||||
target->imageInfo().stages,
|
||||
target->imageInfo().access);
|
||||
}
|
||||
}
|
||||
|
||||
// Transform the depth-stencil attachment back to its original layout.
|
||||
const Rc<DxvkImageView> dsTarget = renderTargets.getDepthTarget();
|
||||
|
||||
if (dsTarget != nullptr) {
|
||||
m_barriers.accessImage(
|
||||
dsTarget->image(),
|
||||
dsTarget->subresources(),
|
||||
VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
|
||||
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,
|
||||
dsTarget->imageInfo().layout,
|
||||
dsTarget->imageInfo().stages,
|
||||
dsTarget->imageInfo().access);
|
||||
}
|
||||
|
||||
m_barriers.recordCommands(m_cmd);
|
||||
}
|
||||
|
||||
}
|
@ -561,12 +561,6 @@ namespace dxvk {
|
||||
|
||||
void commitComputeBarriers();
|
||||
|
||||
void transformLayoutsRenderPassBegin(
|
||||
const DxvkRenderTargets& renderTargets);
|
||||
|
||||
void transformLayoutsRenderPassEnd(
|
||||
const DxvkRenderTargets& renderTargets);
|
||||
|
||||
};
|
||||
|
||||
}
|
@ -11,13 +11,19 @@ namespace dxvk {
|
||||
|
||||
for (uint32_t i = 0; i < MaxNumRenderTargets; i++) {
|
||||
if (m_colorTargets.at(i) != nullptr) {
|
||||
result.setColorFormat(i, m_colorTargets.at(i)->info().format);
|
||||
result.setColorFormat(i, DxvkRenderTargetFormat {
|
||||
m_colorTargets.at(i)->imageInfo().format,
|
||||
m_colorTargets.at(i)->imageInfo().layout,
|
||||
m_colorTargets.at(i)->imageInfo().layout });
|
||||
result.setSampleCount(m_colorTargets.at(i)->image()->info().sampleCount);
|
||||
}
|
||||
}
|
||||
|
||||
if (m_depthTarget != nullptr) {
|
||||
result.setDepthFormat(m_depthTarget->info().format);
|
||||
result.setDepthFormat(DxvkRenderTargetFormat {
|
||||
m_depthTarget->imageInfo().format,
|
||||
m_depthTarget->imageInfo().layout,
|
||||
m_depthTarget->imageInfo().layout });
|
||||
result.setSampleCount(m_depthTarget->image()->info().sampleCount);
|
||||
}
|
||||
|
||||
|
@ -2,23 +2,38 @@
|
||||
|
||||
namespace dxvk {
|
||||
|
||||
DxvkRenderPassFormat::DxvkRenderPassFormat() {
|
||||
for (uint32_t i = 0; i < MaxNumRenderTargets; i++)
|
||||
m_color[i] = VK_FORMAT_UNDEFINED;
|
||||
m_depth = VK_FORMAT_UNDEFINED;
|
||||
m_samples = VK_SAMPLE_COUNT_1_BIT;
|
||||
bool DxvkRenderTargetFormat::operator == (const DxvkRenderTargetFormat& other) const {
|
||||
return this->format == other.format
|
||||
&& this->initialLayout == other.initialLayout
|
||||
&& this->finalLayout == other.finalLayout;
|
||||
}
|
||||
|
||||
|
||||
bool DxvkRenderTargetFormat::operator != (const DxvkRenderTargetFormat& other) const {
|
||||
return !this->operator == (other);
|
||||
}
|
||||
|
||||
|
||||
size_t DxvkRenderTargetFormat::hash() const {
|
||||
std::hash<VkFormat> fhash;
|
||||
std::hash<VkImageLayout> lhash;
|
||||
|
||||
DxvkHashState result;
|
||||
result.add(fhash(this->format));
|
||||
result.add(lhash(this->initialLayout));
|
||||
result.add(lhash(this->finalLayout));
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
size_t DxvkRenderPassFormat::hash() const {
|
||||
DxvkHashState result;
|
||||
std::hash<VkFormat> fhash;
|
||||
std::hash<VkSampleCountFlagBits> shash;
|
||||
|
||||
DxvkHashState result;
|
||||
for (uint32_t i = 0; i < MaxNumRenderTargets; i++)
|
||||
result.add(fhash(m_color[i]));
|
||||
result.add(m_color[i].hash());
|
||||
|
||||
result.add(fhash(m_depth));
|
||||
result.add(m_depth.hash());
|
||||
result.add(shash(m_samples));
|
||||
return result;
|
||||
}
|
||||
@ -49,17 +64,19 @@ namespace dxvk {
|
||||
|
||||
// Render passes may not require the previous
|
||||
// contents of the attachments to be preserved.
|
||||
if (fmt.getDepthFormat() != VK_FORMAT_UNDEFINED) {
|
||||
const DxvkRenderTargetFormat depthFmt = fmt.getDepthFormat();
|
||||
|
||||
if (depthFmt.format != VK_FORMAT_UNDEFINED) {
|
||||
VkAttachmentDescription desc;
|
||||
desc.flags = 0;
|
||||
desc.format = fmt.getDepthFormat();
|
||||
desc.format = depthFmt.format;
|
||||
desc.samples = fmt.getSampleCount();
|
||||
desc.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
|
||||
desc.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
|
||||
desc.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
|
||||
desc.stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE;
|
||||
desc.initialLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
|
||||
desc.finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
|
||||
desc.initialLayout = depthFmt.initialLayout;
|
||||
desc.finalLayout = depthFmt.finalLayout;
|
||||
|
||||
depthRef.attachment = attachments.size();
|
||||
depthRef.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
|
||||
@ -68,20 +85,22 @@ namespace dxvk {
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < MaxNumRenderTargets; i++) {
|
||||
const DxvkRenderTargetFormat colorFmt = fmt.getColorFormat(i);
|
||||
|
||||
colorRef[i].attachment = VK_ATTACHMENT_UNUSED;
|
||||
colorRef[i].layout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
|
||||
if (fmt.getColorFormat(i) != VK_FORMAT_UNDEFINED) {
|
||||
if (colorFmt.format != VK_FORMAT_UNDEFINED) {
|
||||
VkAttachmentDescription desc;
|
||||
desc.flags = 0;
|
||||
desc.format = fmt.getColorFormat(i);
|
||||
desc.format = colorFmt.format;
|
||||
desc.samples = fmt.getSampleCount();
|
||||
desc.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
|
||||
desc.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
|
||||
desc.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
||||
desc.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
|
||||
desc.initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
||||
desc.finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
||||
desc.initialLayout = colorFmt.initialLayout;
|
||||
desc.finalLayout = colorFmt.finalLayout;
|
||||
|
||||
colorRef[i].attachment = attachments.size();
|
||||
colorRef[i].layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
||||
@ -98,10 +117,47 @@ namespace dxvk {
|
||||
subpass.colorAttachmentCount = colorRef.size();
|
||||
subpass.pColorAttachments = colorRef.data();
|
||||
subpass.pResolveAttachments = nullptr;
|
||||
subpass.pDepthStencilAttachment = fmt.getDepthFormat() != VK_FORMAT_UNDEFINED ? &depthRef : nullptr;
|
||||
subpass.pDepthStencilAttachment = depthFmt.format != VK_FORMAT_UNDEFINED ? &depthRef : nullptr;
|
||||
subpass.preserveAttachmentCount = 0;
|
||||
subpass.pPreserveAttachments = nullptr;
|
||||
|
||||
std::array<VkSubpassDependency, 2> subpassDeps = {{
|
||||
{ VK_SUBPASS_EXTERNAL, 0,
|
||||
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
|
||||
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT |
|
||||
VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT |
|
||||
VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
|
||||
VK_ACCESS_SHADER_READ_BIT |
|
||||
VK_ACCESS_SHADER_WRITE_BIT |
|
||||
VK_ACCESS_COLOR_ATTACHMENT_READ_BIT |
|
||||
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
|
||||
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT |
|
||||
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT |
|
||||
VK_ACCESS_TRANSFER_READ_BIT |
|
||||
VK_ACCESS_TRANSFER_WRITE_BIT,
|
||||
VK_ACCESS_COLOR_ATTACHMENT_READ_BIT |
|
||||
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
|
||||
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT |
|
||||
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, 0 },
|
||||
{ 0, VK_SUBPASS_EXTERNAL,
|
||||
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT |
|
||||
VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT |
|
||||
VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
|
||||
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
|
||||
VK_ACCESS_COLOR_ATTACHMENT_READ_BIT |
|
||||
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
|
||||
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT |
|
||||
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
|
||||
VK_ACCESS_SHADER_READ_BIT |
|
||||
VK_ACCESS_SHADER_WRITE_BIT |
|
||||
VK_ACCESS_COLOR_ATTACHMENT_READ_BIT |
|
||||
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
|
||||
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT |
|
||||
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT |
|
||||
VK_ACCESS_TRANSFER_READ_BIT |
|
||||
VK_ACCESS_TRANSFER_WRITE_BIT, 0 },
|
||||
}};
|
||||
|
||||
VkRenderPassCreateInfo info;
|
||||
info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
|
||||
info.pNext = nullptr;
|
||||
@ -110,8 +166,8 @@ namespace dxvk {
|
||||
info.pAttachments = attachments.data();
|
||||
info.subpassCount = 1;
|
||||
info.pSubpasses = &subpass;
|
||||
info.dependencyCount = 0;
|
||||
info.pDependencies = nullptr;
|
||||
info.dependencyCount = subpassDeps.size();
|
||||
info.pDependencies = subpassDeps.data();
|
||||
|
||||
if (m_vkd->vkCreateRenderPass(m_vkd->device(), &info, nullptr, &m_renderPass) != VK_SUCCESS)
|
||||
throw DxvkError("DxvkRenderPass::DxvkRenderPass: Failed to create render pass object");
|
||||
|
@ -9,6 +9,24 @@
|
||||
|
||||
namespace dxvk {
|
||||
|
||||
/**
|
||||
* \brief Format and layout info for a sigle render target
|
||||
*
|
||||
* Stores the format, initial layout and
|
||||
* final layout of a render target.
|
||||
*/
|
||||
struct DxvkRenderTargetFormat {
|
||||
VkFormat format = VK_FORMAT_UNDEFINED;
|
||||
VkImageLayout initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
VkImageLayout finalLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
|
||||
bool operator == (const DxvkRenderTargetFormat& other) const;
|
||||
bool operator != (const DxvkRenderTargetFormat& other) const;
|
||||
|
||||
size_t hash() const;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* \brief Render pass format
|
||||
*
|
||||
@ -19,8 +37,6 @@ namespace dxvk {
|
||||
|
||||
public:
|
||||
|
||||
DxvkRenderPassFormat();
|
||||
|
||||
/**
|
||||
* \brief Retrieves color target format
|
||||
*
|
||||
@ -29,7 +45,7 @@ namespace dxvk {
|
||||
* \param [in] id Color target index
|
||||
* \returns Color target format
|
||||
*/
|
||||
VkFormat getColorFormat(uint32_t id) const {
|
||||
DxvkRenderTargetFormat getColorFormat(uint32_t id) const {
|
||||
return m_color.at(id);
|
||||
}
|
||||
|
||||
@ -39,7 +55,7 @@ namespace dxvk {
|
||||
* If the color target has not been defined,
|
||||
* this will return \c VK_FORMAT_UNDEFINED.
|
||||
*/
|
||||
VkFormat getDepthFormat() const {
|
||||
DxvkRenderTargetFormat getDepthFormat() const {
|
||||
return m_depth;
|
||||
}
|
||||
|
||||
@ -60,7 +76,7 @@ namespace dxvk {
|
||||
* \param [in] id Color target index
|
||||
* \param [in] fmt Color target format
|
||||
*/
|
||||
void setColorFormat(uint32_t id, VkFormat fmt) {
|
||||
void setColorFormat(uint32_t id, DxvkRenderTargetFormat fmt) {
|
||||
m_color.at(id) = fmt;
|
||||
}
|
||||
|
||||
@ -68,7 +84,7 @@ namespace dxvk {
|
||||
* \brief Sets depth-stencil format
|
||||
* \param [in] fmt Depth-stencil format
|
||||
*/
|
||||
void setDepthFormat(VkFormat fmt) {
|
||||
void setDepthFormat(DxvkRenderTargetFormat fmt) {
|
||||
m_depth = fmt;
|
||||
}
|
||||
|
||||
@ -91,9 +107,9 @@ namespace dxvk {
|
||||
|
||||
private:
|
||||
|
||||
std::array<VkFormat, MaxNumRenderTargets> m_color;
|
||||
VkFormat m_depth;
|
||||
VkSampleCountFlagBits m_samples;
|
||||
std::array<DxvkRenderTargetFormat, MaxNumRenderTargets> m_color;
|
||||
DxvkRenderTargetFormat m_depth;
|
||||
VkSampleCountFlagBits m_samples = VK_SAMPLE_COUNT_1_BIT;
|
||||
|
||||
};
|
||||
|
||||
|
@ -132,7 +132,11 @@ namespace dxvk {
|
||||
|
||||
// Create the render pass object
|
||||
DxvkRenderPassFormat renderTargetFormat;
|
||||
renderTargetFormat.setColorFormat(0, fmt.format);
|
||||
|
||||
renderTargetFormat.setColorFormat(0,
|
||||
DxvkRenderTargetFormat { fmt.format,
|
||||
VK_IMAGE_LAYOUT_UNDEFINED,
|
||||
VK_IMAGE_LAYOUT_PRESENT_SRC_KHR });
|
||||
|
||||
m_renderPass = new DxvkRenderPass(
|
||||
m_vkd, renderTargetFormat);
|
||||
|
Loading…
Reference in New Issue
Block a user