mirror of
https://github.com/doitsujin/dxvk.git
synced 2024-11-30 22:24:15 +01:00
[dxvk] Implemented typeless resolve
This should allow a large number of Unity-based games to render at least a menu.
This commit is contained in:
parent
cb3daaf856
commit
b419b3dfbd
@ -904,40 +904,42 @@ namespace dxvk {
|
||||
if (format == VK_FORMAT_UNDEFINED)
|
||||
format = srcImage->info().format;
|
||||
|
||||
VkImageSubresourceRange dstSubresourceRange = {
|
||||
dstSubresources.aspectMask,
|
||||
dstSubresources.mipLevel, 1,
|
||||
dstSubresources.baseArrayLayer,
|
||||
dstSubresources.layerCount };
|
||||
|
||||
VkImageSubresourceRange srcSubresourceRange = {
|
||||
srcSubresources.aspectMask,
|
||||
srcSubresources.mipLevel, 1,
|
||||
srcSubresources.baseArrayLayer,
|
||||
srcSubresources.layerCount };
|
||||
|
||||
// We only support resolving to the entire image
|
||||
// area, so we might as well discard its contents
|
||||
m_barriers.accessImage(
|
||||
dstImage, dstSubresourceRange,
|
||||
VK_IMAGE_LAYOUT_UNDEFINED,
|
||||
dstImage->info().stages,
|
||||
dstImage->info().access,
|
||||
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||
VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||
VK_ACCESS_TRANSFER_WRITE_BIT);
|
||||
m_barriers.accessImage(
|
||||
srcImage, srcSubresourceRange,
|
||||
srcImage->info().layout,
|
||||
srcImage->info().stages,
|
||||
srcImage->info().access,
|
||||
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
|
||||
VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||
VK_ACCESS_TRANSFER_READ_BIT);
|
||||
m_barriers.recordCommands(m_cmd);
|
||||
|
||||
if (srcImage->info().format == format
|
||||
&& dstImage->info().format == format) {
|
||||
if (dstImage->info().format == format
|
||||
&& srcImage->info().format == format) {
|
||||
// Use the built-in Vulkan resolve function if the image
|
||||
// formats both match the format of the resolve operation.
|
||||
VkImageSubresourceRange dstSubresourceRange = {
|
||||
dstSubresources.aspectMask,
|
||||
dstSubresources.mipLevel, 1,
|
||||
dstSubresources.baseArrayLayer,
|
||||
dstSubresources.layerCount };
|
||||
|
||||
VkImageSubresourceRange srcSubresourceRange = {
|
||||
srcSubresources.aspectMask,
|
||||
srcSubresources.mipLevel, 1,
|
||||
srcSubresources.baseArrayLayer,
|
||||
srcSubresources.layerCount };
|
||||
|
||||
// We only support resolving to the entire image
|
||||
// area, so we might as well discard its contents
|
||||
m_barriers.accessImage(
|
||||
dstImage, dstSubresourceRange,
|
||||
VK_IMAGE_LAYOUT_UNDEFINED,
|
||||
dstImage->info().stages,
|
||||
dstImage->info().access,
|
||||
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||
VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||
VK_ACCESS_TRANSFER_WRITE_BIT);
|
||||
m_barriers.accessImage(
|
||||
srcImage, srcSubresourceRange,
|
||||
srcImage->info().layout,
|
||||
srcImage->info().stages,
|
||||
srcImage->info().access,
|
||||
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
|
||||
VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||
VK_ACCESS_TRANSFER_READ_BIT);
|
||||
m_barriers.recordCommands(m_cmd);
|
||||
|
||||
VkImageResolve imageRegion;
|
||||
imageRegion.srcSubresource = srcSubresources;
|
||||
imageRegion.srcOffset = VkOffset3D { 0, 0, 0 };
|
||||
@ -951,27 +953,48 @@ namespace dxvk {
|
||||
dstImage->handle(),
|
||||
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||
1, &imageRegion);
|
||||
} else {
|
||||
// TODO implement
|
||||
}
|
||||
|
||||
m_barriers.accessImage(
|
||||
dstImage, dstSubresourceRange,
|
||||
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||
VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||
VK_ACCESS_TRANSFER_WRITE_BIT,
|
||||
dstImage->info().layout,
|
||||
dstImage->info().stages,
|
||||
dstImage->info().access);
|
||||
m_barriers.accessImage(
|
||||
srcImage, srcSubresourceRange,
|
||||
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
|
||||
VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||
VK_ACCESS_TRANSFER_READ_BIT,
|
||||
srcImage->info().layout,
|
||||
srcImage->info().stages,
|
||||
srcImage->info().access);
|
||||
m_barriers.recordCommands(m_cmd);
|
||||
m_barriers.accessImage(
|
||||
dstImage, dstSubresourceRange,
|
||||
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||
VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||
VK_ACCESS_TRANSFER_WRITE_BIT,
|
||||
dstImage->info().layout,
|
||||
dstImage->info().stages,
|
||||
dstImage->info().access);
|
||||
m_barriers.accessImage(
|
||||
srcImage, srcSubresourceRange,
|
||||
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
|
||||
VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||
VK_ACCESS_TRANSFER_READ_BIT,
|
||||
srcImage->info().layout,
|
||||
srcImage->info().stages,
|
||||
srcImage->info().access);
|
||||
m_barriers.recordCommands(m_cmd);
|
||||
} else {
|
||||
// The trick here is to submit an empty render pass which
|
||||
// performs the resolve op on properly typed image views.
|
||||
const Rc<DxvkMetaResolveFramebuffer> fb =
|
||||
new DxvkMetaResolveFramebuffer(m_device->vkd(),
|
||||
dstImage, dstSubresources,
|
||||
srcImage, srcSubresources, format);
|
||||
|
||||
VkRenderPassBeginInfo info;
|
||||
info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
|
||||
info.pNext = nullptr;
|
||||
info.renderPass = fb->renderPass();
|
||||
info.framebuffer = fb->framebuffer();
|
||||
info.renderArea = VkRect2D { { 0, 0 }, {
|
||||
dstImage->info().extent.width,
|
||||
dstImage->info().extent.height } };
|
||||
info.clearValueCount = 0;
|
||||
info.pClearValues = nullptr;
|
||||
|
||||
m_cmd->cmdBeginRenderPass(&info, VK_SUBPASS_CONTENTS_INLINE);
|
||||
m_cmd->cmdEndRenderPass();
|
||||
|
||||
m_cmd->trackResource(fb);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -6,6 +6,7 @@
|
||||
#include "dxvk_context_state.h"
|
||||
#include "dxvk_data.h"
|
||||
#include "dxvk_event.h"
|
||||
#include "dxvk_meta_resolve.h"
|
||||
#include "dxvk_query.h"
|
||||
#include "dxvk_query_pool.h"
|
||||
#include "dxvk_util.h"
|
||||
|
134
src/dxvk/dxvk_meta_resolve.cpp
Normal file
134
src/dxvk/dxvk_meta_resolve.cpp
Normal file
@ -0,0 +1,134 @@
|
||||
#include "dxvk_meta_resolve.h"
|
||||
|
||||
namespace dxvk {
|
||||
|
||||
DxvkMetaResolveFramebuffer::DxvkMetaResolveFramebuffer(
|
||||
const Rc<vk::DeviceFn>& vkd,
|
||||
const Rc<DxvkImage>& dstImage,
|
||||
VkImageSubresourceLayers dstLayers,
|
||||
const Rc<DxvkImage>& srcImage,
|
||||
VkImageSubresourceLayers srcLayers,
|
||||
VkFormat format)
|
||||
: m_vkd(vkd) {
|
||||
// Create a render pass with one render
|
||||
// target and one resolve attachment.
|
||||
std::array<VkAttachmentDescription, 2> attachmentInfos = {{
|
||||
VkAttachmentDescription {
|
||||
0, format, dstImage->info().sampleCount,
|
||||
VK_ATTACHMENT_LOAD_OP_DONT_CARE,
|
||||
VK_ATTACHMENT_STORE_OP_STORE,
|
||||
VK_ATTACHMENT_LOAD_OP_DONT_CARE,
|
||||
VK_ATTACHMENT_STORE_OP_STORE,
|
||||
VK_IMAGE_LAYOUT_UNDEFINED,
|
||||
dstImage->info().layout },
|
||||
VkAttachmentDescription {
|
||||
0, format, srcImage->info().sampleCount,
|
||||
VK_ATTACHMENT_LOAD_OP_LOAD,
|
||||
VK_ATTACHMENT_STORE_OP_STORE,
|
||||
VK_ATTACHMENT_LOAD_OP_LOAD,
|
||||
VK_ATTACHMENT_STORE_OP_STORE,
|
||||
srcImage->info().layout,
|
||||
srcImage->info().layout },
|
||||
}};
|
||||
|
||||
// Make sure layout transitions are correctly ordered
|
||||
std::array<VkSubpassDependency, 2> subpassDeps = {{
|
||||
{ VK_SUBPASS_EXTERNAL, 0,
|
||||
srcImage->info().stages | dstImage->info().stages,
|
||||
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
|
||||
srcImage->info().access | dstImage->info().access,
|
||||
VK_ACCESS_COLOR_ATTACHMENT_READ_BIT |
|
||||
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, 0 },
|
||||
{ 0, VK_SUBPASS_EXTERNAL,
|
||||
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
|
||||
srcImage->info().stages | dstImage->info().stages,
|
||||
VK_ACCESS_COLOR_ATTACHMENT_READ_BIT |
|
||||
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
|
||||
srcImage->info().access | dstImage->info().access, 0 },
|
||||
}};
|
||||
|
||||
VkAttachmentReference dstAttachmentRef = { 0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL };
|
||||
VkAttachmentReference srcAttachmentRef = { 1, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL };
|
||||
|
||||
VkSubpassDescription spInfo;
|
||||
spInfo.flags = 0;
|
||||
spInfo.inputAttachmentCount = 0;
|
||||
spInfo.pInputAttachments = nullptr;
|
||||
spInfo.colorAttachmentCount = 1;
|
||||
spInfo.pColorAttachments = &srcAttachmentRef;
|
||||
spInfo.pResolveAttachments = &dstAttachmentRef;
|
||||
spInfo.pDepthStencilAttachment = nullptr;
|
||||
spInfo.preserveAttachmentCount = 0;
|
||||
spInfo.pPreserveAttachments = nullptr;
|
||||
|
||||
VkRenderPassCreateInfo rpInfo;
|
||||
rpInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
|
||||
rpInfo.pNext = nullptr;
|
||||
rpInfo.flags = 0;
|
||||
rpInfo.attachmentCount = attachmentInfos.size();
|
||||
rpInfo.pAttachments = attachmentInfos.data();
|
||||
rpInfo.subpassCount = 1;
|
||||
rpInfo.pSubpasses = &spInfo;
|
||||
rpInfo.dependencyCount = subpassDeps.size();
|
||||
rpInfo.pDependencies = subpassDeps.data();
|
||||
|
||||
m_vkd->vkCreateRenderPass(m_vkd->device(), &rpInfo, nullptr, &m_renderPass);
|
||||
|
||||
// Create views for the destination and source image
|
||||
VkImageViewCreateInfo dstInfo;
|
||||
dstInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
|
||||
dstInfo.pNext = nullptr;
|
||||
dstInfo.flags = 0;
|
||||
dstInfo.image = dstImage->handle();
|
||||
dstInfo.viewType = VK_IMAGE_VIEW_TYPE_2D_ARRAY;
|
||||
dstInfo.format = format;
|
||||
dstInfo.components = VkComponentMapping {
|
||||
VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY,
|
||||
VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY };
|
||||
dstInfo.subresourceRange = VkImageSubresourceRange {
|
||||
dstLayers.aspectMask, dstLayers.mipLevel, 1,
|
||||
dstLayers.baseArrayLayer, dstLayers.layerCount };
|
||||
|
||||
VkImageViewCreateInfo srcInfo;
|
||||
srcInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
|
||||
srcInfo.pNext = nullptr;
|
||||
srcInfo.flags = 0;
|
||||
srcInfo.image = srcImage->handle();
|
||||
srcInfo.viewType = VK_IMAGE_VIEW_TYPE_2D_ARRAY;
|
||||
srcInfo.format = format;
|
||||
srcInfo.components = VkComponentMapping {
|
||||
VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY,
|
||||
VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY };
|
||||
srcInfo.subresourceRange = VkImageSubresourceRange {
|
||||
srcLayers.aspectMask, srcLayers.mipLevel, 1,
|
||||
srcLayers.baseArrayLayer, srcLayers.layerCount };
|
||||
|
||||
m_vkd->vkCreateImageView(m_vkd->device(), &dstInfo, nullptr, &m_dstImageView);
|
||||
m_vkd->vkCreateImageView(m_vkd->device(), &srcInfo, nullptr, &m_srcImageView);
|
||||
|
||||
// Create a framebuffer containing the two image views
|
||||
std::array<VkImageView, 2> attachments = {{ m_dstImageView, m_srcImageView }};
|
||||
|
||||
VkFramebufferCreateInfo fboInfo;
|
||||
fboInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
|
||||
fboInfo.pNext = nullptr;
|
||||
fboInfo.flags = 0;
|
||||
fboInfo.renderPass = m_renderPass;
|
||||
fboInfo.attachmentCount = attachments.size();
|
||||
fboInfo.pAttachments = attachments.data();
|
||||
fboInfo.width = dstImage->info().extent.width;
|
||||
fboInfo.height = dstImage->info().extent.height;
|
||||
fboInfo.layers = dstLayers.layerCount;
|
||||
|
||||
m_vkd->vkCreateFramebuffer(m_vkd->device(), &fboInfo, nullptr, &m_framebuffer);
|
||||
}
|
||||
|
||||
|
||||
DxvkMetaResolveFramebuffer::~DxvkMetaResolveFramebuffer() {
|
||||
m_vkd->vkDestroyFramebuffer(m_vkd->device(), m_framebuffer, nullptr);
|
||||
m_vkd->vkDestroyImageView (m_vkd->device(), m_srcImageView, nullptr);
|
||||
m_vkd->vkDestroyImageView (m_vkd->device(), m_dstImageView, nullptr);
|
||||
m_vkd->vkDestroyRenderPass (m_vkd->device(), m_renderPass, nullptr);
|
||||
}
|
||||
|
||||
}
|
50
src/dxvk/dxvk_meta_resolve.h
Normal file
50
src/dxvk/dxvk_meta_resolve.h
Normal file
@ -0,0 +1,50 @@
|
||||
#pragma once
|
||||
|
||||
#include <unordered_map>
|
||||
|
||||
#include "dxvk_barrier.h"
|
||||
#include "dxvk_cmdlist.h"
|
||||
#include "dxvk_resource.h"
|
||||
|
||||
namespace dxvk {
|
||||
|
||||
/**
|
||||
* \brief Meta resolve framebuffer
|
||||
*
|
||||
* Stores a framebuffer and image view objects
|
||||
* for a meta resolve operation. Can be tracked.
|
||||
*/
|
||||
class DxvkMetaResolveFramebuffer : public DxvkResource {
|
||||
|
||||
public:
|
||||
|
||||
DxvkMetaResolveFramebuffer(
|
||||
const Rc<vk::DeviceFn>& vkd,
|
||||
const Rc<DxvkImage>& dstImage,
|
||||
VkImageSubresourceLayers dstLayers,
|
||||
const Rc<DxvkImage>& srcImage,
|
||||
VkImageSubresourceLayers srcLayers,
|
||||
VkFormat format);
|
||||
|
||||
~DxvkMetaResolveFramebuffer();
|
||||
|
||||
VkRenderPass renderPass() const {
|
||||
return m_renderPass;
|
||||
}
|
||||
|
||||
VkFramebuffer framebuffer() const {
|
||||
return m_framebuffer;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
const Rc<vk::DeviceFn> m_vkd;
|
||||
|
||||
VkRenderPass m_renderPass;
|
||||
VkImageView m_dstImageView;
|
||||
VkImageView m_srcImageView;
|
||||
VkFramebuffer m_framebuffer;
|
||||
|
||||
};
|
||||
|
||||
}
|
@ -26,6 +26,7 @@ dxvk_src = files([
|
||||
'dxvk_lifetime.cpp',
|
||||
'dxvk_main.cpp',
|
||||
'dxvk_memory.cpp',
|
||||
'dxvk_meta_resolve.cpp',
|
||||
'dxvk_options.cpp',
|
||||
'dxvk_pipecache.cpp',
|
||||
'dxvk_pipelayout.cpp',
|
||||
|
Loading…
Reference in New Issue
Block a user