mirror of
https://github.com/doitsujin/dxvk.git
synced 2025-01-31 14:52:11 +01:00
[dxvk] Support image sub-regions for resolve operations
Required for legacy graphics APIs.
This commit is contained in:
parent
a3966b442b
commit
95bfac84f1
@ -1321,10 +1321,14 @@ namespace dxvk {
|
||||
cSrcSubres = srcSubresourceLayers,
|
||||
cFormat = format
|
||||
] (DxvkContext* ctx) {
|
||||
ctx->resolveImage(
|
||||
cDstImage, cDstSubres,
|
||||
cSrcImage, cSrcSubres,
|
||||
cFormat);
|
||||
VkImageResolve region;
|
||||
region.srcSubresource = cSrcSubres;
|
||||
region.srcOffset = VkOffset3D { 0, 0, 0 };
|
||||
region.dstSubresource = cDstSubres;
|
||||
region.dstOffset = VkOffset3D { 0, 0, 0 };
|
||||
region.extent = cDstImage->mipLevelExtent(cDstSubres.mipLevel);
|
||||
|
||||
ctx->resolveImage(cDstImage, cSrcImage, region, cFormat);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -213,16 +213,22 @@ namespace dxvk {
|
||||
// Resolve back buffer if it is multisampled. We
|
||||
// only have to do it only for the first frame.
|
||||
if (m_swapImageResolve != nullptr && i == 0) {
|
||||
VkImageSubresourceLayers resolveSubresources;
|
||||
resolveSubresources.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
resolveSubresources.mipLevel = 0;
|
||||
resolveSubresources.baseArrayLayer = 0;
|
||||
resolveSubresources.layerCount = 1;
|
||||
VkImageSubresourceLayers resolveSubresource;
|
||||
resolveSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
resolveSubresource.mipLevel = 0;
|
||||
resolveSubresource.baseArrayLayer = 0;
|
||||
resolveSubresource.layerCount = 1;
|
||||
|
||||
VkImageResolve resolveRegion;
|
||||
resolveRegion.srcSubresource = resolveSubresource;
|
||||
resolveRegion.srcOffset = VkOffset3D { 0, 0, 0 };
|
||||
resolveRegion.dstSubresource = resolveSubresource;
|
||||
resolveRegion.dstOffset = VkOffset3D { 0, 0, 0 };
|
||||
resolveRegion.extent = m_swapImage->info().extent;
|
||||
|
||||
m_context->resolveImage(
|
||||
m_swapImageResolve, resolveSubresources,
|
||||
m_swapImage, resolveSubresources,
|
||||
VK_FORMAT_UNDEFINED);
|
||||
m_swapImageResolve, m_swapImage,
|
||||
resolveRegion, VK_FORMAT_UNDEFINED);
|
||||
}
|
||||
|
||||
// Presentation semaphores and WSI swap chain image
|
||||
|
@ -1671,9 +1671,8 @@ namespace dxvk {
|
||||
|
||||
void DxvkContext::resolveImage(
|
||||
const Rc<DxvkImage>& dstImage,
|
||||
const VkImageSubresourceLayers& dstSubresources,
|
||||
const Rc<DxvkImage>& srcImage,
|
||||
const VkImageSubresourceLayers& srcSubresources,
|
||||
const VkImageResolve& region,
|
||||
VkFormat format) {
|
||||
this->spillRenderPass();
|
||||
|
||||
@ -1683,13 +1682,10 @@ namespace dxvk {
|
||||
if (srcImage->info().format == format
|
||||
&& dstImage->info().format == format) {
|
||||
this->resolveImageHw(
|
||||
dstImage, dstSubresources,
|
||||
srcImage, srcSubresources);
|
||||
dstImage, srcImage, region);
|
||||
} else {
|
||||
this->resolveImageFb(
|
||||
dstImage, dstSubresources,
|
||||
srcImage, srcSubresources,
|
||||
format);
|
||||
dstImage, srcImage, region, format);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2605,11 +2601,10 @@ namespace dxvk {
|
||||
|
||||
void DxvkContext::resolveImageHw(
|
||||
const Rc<DxvkImage>& dstImage,
|
||||
const VkImageSubresourceLayers& dstSubresources,
|
||||
const Rc<DxvkImage>& srcImage,
|
||||
const VkImageSubresourceLayers& srcSubresources) {
|
||||
auto dstSubresourceRange = vk::makeSubresourceRange(dstSubresources);
|
||||
auto srcSubresourceRange = vk::makeSubresourceRange(srcSubresources);
|
||||
const VkImageResolve& region) {
|
||||
auto dstSubresourceRange = vk::makeSubresourceRange(region.dstSubresource);
|
||||
auto srcSubresourceRange = vk::makeSubresourceRange(region.srcSubresource);
|
||||
|
||||
if (m_barriers.isImageDirty(dstImage, dstSubresourceRange, DxvkAccess::Write)
|
||||
|| m_barriers.isImageDirty(srcImage, srcSubresourceRange, DxvkAccess::Write))
|
||||
@ -2617,9 +2612,14 @@ namespace dxvk {
|
||||
|
||||
// We only support resolving to the entire image
|
||||
// area, so we might as well discard its contents
|
||||
VkImageLayout initialLayout = dstImage->info().layout;
|
||||
|
||||
if (dstImage->isFullSubresource(region.dstSubresource, region.extent))
|
||||
initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
|
||||
m_transitions.accessImage(
|
||||
dstImage, dstSubresourceRange,
|
||||
VK_IMAGE_LAYOUT_UNDEFINED, 0, 0,
|
||||
initialLayout, 0, 0,
|
||||
dstImage->pickLayout(VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL),
|
||||
VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||
VK_ACCESS_TRANSFER_WRITE_BIT);
|
||||
@ -2633,17 +2633,10 @@ namespace dxvk {
|
||||
|
||||
m_transitions.recordCommands(m_cmd);
|
||||
|
||||
VkImageResolve imageRegion;
|
||||
imageRegion.srcSubresource = srcSubresources;
|
||||
imageRegion.srcOffset = VkOffset3D { 0, 0, 0 };
|
||||
imageRegion.dstSubresource = dstSubresources;
|
||||
imageRegion.dstOffset = VkOffset3D { 0, 0, 0 };
|
||||
imageRegion.extent = srcImage->mipLevelExtent(srcSubresources.mipLevel);
|
||||
|
||||
m_cmd->cmdResolveImage(
|
||||
srcImage->handle(), srcImage->pickLayout(VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL),
|
||||
dstImage->handle(), dstImage->pickLayout(VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL),
|
||||
1, &imageRegion);
|
||||
1, ®ion);
|
||||
|
||||
m_barriers.accessImage(
|
||||
dstImage, dstSubresourceRange,
|
||||
@ -2670,12 +2663,11 @@ namespace dxvk {
|
||||
|
||||
void DxvkContext::resolveImageFb(
|
||||
const Rc<DxvkImage>& dstImage,
|
||||
const VkImageSubresourceLayers& dstSubresources,
|
||||
const Rc<DxvkImage>& srcImage,
|
||||
const VkImageSubresourceLayers& srcSubresources,
|
||||
const VkImageResolve& region,
|
||||
VkFormat format) {
|
||||
auto dstSubresourceRange = vk::makeSubresourceRange(dstSubresources);
|
||||
auto srcSubresourceRange = vk::makeSubresourceRange(srcSubresources);
|
||||
auto dstSubresourceRange = vk::makeSubresourceRange(region.dstSubresource);
|
||||
auto srcSubresourceRange = vk::makeSubresourceRange(region.srcSubresource);
|
||||
|
||||
if (m_barriers.isImageDirty(dstImage, dstSubresourceRange, DxvkAccess::Write)
|
||||
|| m_barriers.isImageDirty(srcImage, srcSubresourceRange, DxvkAccess::Write))
|
||||
@ -2700,31 +2692,32 @@ namespace dxvk {
|
||||
dstViewInfo.type = VK_IMAGE_VIEW_TYPE_2D_ARRAY;
|
||||
dstViewInfo.format = format;
|
||||
dstViewInfo.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
|
||||
dstViewInfo.aspect = dstSubresources.aspectMask;
|
||||
dstViewInfo.minLevel = dstSubresources.mipLevel;
|
||||
dstViewInfo.aspect = region.dstSubresource.aspectMask;
|
||||
dstViewInfo.minLevel = region.dstSubresource.mipLevel;
|
||||
dstViewInfo.numLevels = 1;
|
||||
dstViewInfo.minLayer = dstSubresources.baseArrayLayer;
|
||||
dstViewInfo.numLayers = dstSubresources.layerCount;
|
||||
dstViewInfo.minLayer = region.dstSubresource.baseArrayLayer;
|
||||
dstViewInfo.numLayers = region.dstSubresource.layerCount;
|
||||
|
||||
DxvkImageViewCreateInfo srcViewInfo;
|
||||
srcViewInfo.type = VK_IMAGE_VIEW_TYPE_2D_ARRAY;
|
||||
srcViewInfo.format = format;
|
||||
srcViewInfo.usage = VK_IMAGE_USAGE_SAMPLED_BIT;
|
||||
srcViewInfo.aspect = srcSubresources.aspectMask;
|
||||
srcViewInfo.minLevel = srcSubresources.mipLevel;
|
||||
srcViewInfo.aspect = region.srcSubresource.aspectMask;
|
||||
srcViewInfo.minLevel = region.srcSubresource.mipLevel;
|
||||
srcViewInfo.numLevels = 1;
|
||||
srcViewInfo.minLayer = srcSubresources.baseArrayLayer;
|
||||
srcViewInfo.numLayers = srcSubresources.layerCount;
|
||||
srcViewInfo.minLayer = region.srcSubresource.baseArrayLayer;
|
||||
srcViewInfo.numLayers = region.srcSubresource.layerCount;
|
||||
|
||||
Rc<DxvkImageView> dstImageView = m_device->createImageView(dstImage, dstViewInfo);
|
||||
Rc<DxvkImageView> srcImageView = m_device->createImageView(srcImage, srcViewInfo);
|
||||
|
||||
// Create a framebuffer and pipeline for the resolve op
|
||||
Rc<DxvkMetaResolveRenderPass> fb = new DxvkMetaResolveRenderPass(
|
||||
m_device->vkd(), dstImageView, srcImageView);
|
||||
|
||||
VkExtent3D passExtent = dstImageView->mipLevelExtent(0);
|
||||
|
||||
Rc<DxvkMetaResolveRenderPass> fb = new DxvkMetaResolveRenderPass(
|
||||
m_device->vkd(), dstImageView, srcImageView,
|
||||
dstImage->isFullSubresource(region.dstSubresource, region.extent));
|
||||
|
||||
auto pipeInfo = m_metaResolve->getPipeline(
|
||||
format, srcImage->info().sampleCount);
|
||||
|
||||
@ -2748,16 +2741,16 @@ namespace dxvk {
|
||||
m_cmd->updateDescriptorSets(1, &descriptorWrite);
|
||||
|
||||
VkViewport viewport;
|
||||
viewport.x = 0.0f;
|
||||
viewport.y = 0.0f;
|
||||
viewport.width = float(passExtent.width);
|
||||
viewport.height = float(passExtent.height);
|
||||
viewport.x = float(region.dstOffset.x);
|
||||
viewport.y = float(region.dstOffset.y);
|
||||
viewport.width = float(region.extent.width);
|
||||
viewport.height = float(region.extent.height);
|
||||
viewport.minDepth = 0.0f;
|
||||
viewport.maxDepth = 1.0f;
|
||||
|
||||
VkRect2D scissor;
|
||||
scissor.offset = { 0, 0 };
|
||||
scissor.extent = { passExtent.width, passExtent.height };
|
||||
scissor.offset = { region.dstOffset.x, region.dstOffset.y };
|
||||
scissor.extent = { region.extent.width, region.extent.height };
|
||||
|
||||
VkRenderPassBeginInfo info;
|
||||
info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
|
||||
@ -2770,13 +2763,20 @@ namespace dxvk {
|
||||
info.pClearValues = nullptr;
|
||||
|
||||
// Perform the actual resolve operation
|
||||
VkOffset2D srcOffset = {
|
||||
region.srcOffset.x,
|
||||
region.srcOffset.y };
|
||||
|
||||
m_cmd->cmdBeginRenderPass(&info, VK_SUBPASS_CONTENTS_INLINE);
|
||||
m_cmd->cmdBindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, pipeInfo.pipeHandle);
|
||||
m_cmd->cmdBindDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS,
|
||||
pipeInfo.pipeLayout, descriptorWrite.dstSet, 0, nullptr);
|
||||
m_cmd->cmdSetViewport(0, 1, &viewport);
|
||||
m_cmd->cmdSetScissor (0, 1, &scissor);
|
||||
m_cmd->cmdDraw(1, dstSubresources.layerCount, 0, 0);
|
||||
m_cmd->cmdPushConstants(pipeInfo.pipeLayout,
|
||||
VK_SHADER_STAGE_FRAGMENT_BIT,
|
||||
0, sizeof(srcOffset), &srcOffset);
|
||||
m_cmd->cmdDraw(1, region.dstSubresource.layerCount, 0, 0);
|
||||
m_cmd->cmdEndRenderPass();
|
||||
|
||||
m_barriers.accessImage(
|
||||
|
@ -629,16 +629,14 @@ namespace dxvk {
|
||||
* If it is \c VK_FORMAT_UNDEFINED, the resolve operation
|
||||
* will use the source image format.
|
||||
* \param [in] dstImage Destination image
|
||||
* \param [in] dstSubresources Subresources to write to
|
||||
* \param [in] srcImage Source image
|
||||
* \param [in] srcSubresources Subresources to read from
|
||||
* \param [in] region Region to resolve
|
||||
* \param [in] format Format for the resolve operation
|
||||
*/
|
||||
void resolveImage(
|
||||
const Rc<DxvkImage>& dstImage,
|
||||
const VkImageSubresourceLayers& dstSubresources,
|
||||
const Rc<DxvkImage>& srcImage,
|
||||
const VkImageSubresourceLayers& srcSubresources,
|
||||
const VkImageResolve& region,
|
||||
VkFormat format);
|
||||
|
||||
/**
|
||||
@ -950,15 +948,13 @@ namespace dxvk {
|
||||
|
||||
void resolveImageHw(
|
||||
const Rc<DxvkImage>& dstImage,
|
||||
const VkImageSubresourceLayers& dstSubresources,
|
||||
const Rc<DxvkImage>& srcImage,
|
||||
const VkImageSubresourceLayers& srcSubresources);
|
||||
const VkImageResolve& region);
|
||||
|
||||
void resolveImageFb(
|
||||
const Rc<DxvkImage>& dstImage,
|
||||
const VkImageSubresourceLayers& dstSubresources,
|
||||
const Rc<DxvkImage>& srcImage,
|
||||
const VkImageSubresourceLayers& srcSubresources,
|
||||
const VkImageResolve& region,
|
||||
VkFormat format);
|
||||
|
||||
void updatePredicate(
|
||||
|
@ -13,11 +13,12 @@ namespace dxvk {
|
||||
DxvkMetaResolveRenderPass::DxvkMetaResolveRenderPass(
|
||||
const Rc<vk::DeviceFn>& vkd,
|
||||
const Rc<DxvkImageView>& dstImageView,
|
||||
const Rc<DxvkImageView>& srcImageView)
|
||||
const Rc<DxvkImageView>& srcImageView,
|
||||
bool discardDst)
|
||||
: m_vkd(vkd),
|
||||
m_dstImageView(dstImageView),
|
||||
m_srcImageView(srcImageView),
|
||||
m_renderPass (createRenderPass ()),
|
||||
m_renderPass (createRenderPass(discardDst)),
|
||||
m_framebuffer (createFramebuffer()) { }
|
||||
|
||||
|
||||
@ -27,17 +28,22 @@ namespace dxvk {
|
||||
}
|
||||
|
||||
|
||||
VkRenderPass DxvkMetaResolveRenderPass::createRenderPass() const {
|
||||
VkRenderPass DxvkMetaResolveRenderPass::createRenderPass(bool discard) const {
|
||||
VkAttachmentDescription attachment;
|
||||
attachment.flags = 0;
|
||||
attachment.format = m_dstImageView->info().format;
|
||||
attachment.samples = VK_SAMPLE_COUNT_1_BIT;
|
||||
attachment.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
||||
attachment.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
|
||||
attachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
|
||||
attachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
||||
attachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
|
||||
attachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
attachment.initialLayout = m_dstImageView->imageInfo().layout;
|
||||
attachment.finalLayout = m_dstImageView->imageInfo().layout;
|
||||
|
||||
if (discard) {
|
||||
attachment.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
||||
attachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
}
|
||||
|
||||
VkAttachmentReference dstRef;
|
||||
dstRef.attachment = 0;
|
||||
@ -274,14 +280,19 @@ namespace dxvk {
|
||||
|
||||
VkPipelineLayout DxvkMetaResolveObjects::createPipelineLayout(
|
||||
VkDescriptorSetLayout descriptorSetLayout) const {
|
||||
VkPushConstantRange push;
|
||||
push.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
|
||||
push.offset = 0;
|
||||
push.size = sizeof(VkOffset2D);
|
||||
|
||||
VkPipelineLayoutCreateInfo info;
|
||||
info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
|
||||
info.pNext = nullptr;
|
||||
info.flags = 0;
|
||||
info.setLayoutCount = 1;
|
||||
info.pSetLayouts = &descriptorSetLayout;
|
||||
info.pushConstantRangeCount = 0;
|
||||
info.pPushConstantRanges = nullptr;
|
||||
info.pushConstantRangeCount = 1;
|
||||
info.pPushConstantRanges = &push;
|
||||
|
||||
VkPipelineLayout result = VK_NULL_HANDLE;
|
||||
if (m_vkd->vkCreatePipelineLayout(m_vkd->device(), &info, nullptr, &result) != VK_SUCCESS)
|
||||
|
@ -58,7 +58,8 @@ namespace dxvk {
|
||||
DxvkMetaResolveRenderPass(
|
||||
const Rc<vk::DeviceFn>& vkd,
|
||||
const Rc<DxvkImageView>& dstImageView,
|
||||
const Rc<DxvkImageView>& srcImageView);
|
||||
const Rc<DxvkImageView>& srcImageView,
|
||||
bool discardDst);
|
||||
|
||||
~DxvkMetaResolveRenderPass();
|
||||
|
||||
@ -80,7 +81,7 @@ namespace dxvk {
|
||||
VkRenderPass m_renderPass = VK_NULL_HANDLE;
|
||||
VkFramebuffer m_framebuffer = VK_NULL_HANDLE;
|
||||
|
||||
VkRenderPass createRenderPass() const;
|
||||
VkRenderPass createRenderPass(bool discard) const;
|
||||
|
||||
VkFramebuffer createFramebuffer() const;
|
||||
|
||||
|
@ -6,8 +6,13 @@ layout(binding = 0) uniform sampler2DMSArray s_image;
|
||||
|
||||
layout(location = 0) out vec4 o_color;
|
||||
|
||||
layout(push_constant)
|
||||
uniform u_info_t {
|
||||
ivec2 offset;
|
||||
} u_info;
|
||||
|
||||
void main() {
|
||||
ivec3 coord = ivec3(gl_FragCoord.xy, gl_Layer);
|
||||
ivec3 coord = ivec3(gl_FragCoord.xy + u_info.offset, gl_Layer);
|
||||
vec4 color = vec4(0.0f);
|
||||
for (int i = 0; i < c_samples; i++)
|
||||
color += texelFetch(s_image, coord, i);
|
||||
|
@ -9,8 +9,13 @@ uniform sampler2DMSArray s_image;
|
||||
|
||||
layout(location = 0) out vec4 o_color;
|
||||
|
||||
layout(push_constant)
|
||||
uniform u_info_t {
|
||||
ivec2 offset;
|
||||
} u_info;
|
||||
|
||||
void main() {
|
||||
ivec3 coord = ivec3(gl_FragCoord.xy, gl_Layer);
|
||||
ivec3 coord = ivec3(gl_FragCoord.xy + u_info.offset, gl_Layer);
|
||||
|
||||
// get a four-bit fragment index for each sample
|
||||
uint fragMask = fragmentMaskFetchAMD(s_image, coord);
|
||||
|
@ -4,7 +4,12 @@ layout(binding = 0) uniform isampler2DMSArray s_image;
|
||||
|
||||
layout(location = 0) out ivec4 o_color;
|
||||
|
||||
layout(push_constant)
|
||||
uniform u_info_t {
|
||||
ivec2 offset;
|
||||
} u_info;
|
||||
|
||||
void main() {
|
||||
ivec3 coord = ivec3(gl_FragCoord.xy, gl_Layer);
|
||||
ivec3 coord = ivec3(gl_FragCoord.xy + u_info.offset, gl_Layer);
|
||||
o_color = texelFetch(s_image, coord, 0);
|
||||
}
|
@ -4,7 +4,12 @@ layout(binding = 0) uniform usampler2DMSArray s_image;
|
||||
|
||||
layout(location = 0) out uvec4 o_color;
|
||||
|
||||
layout(push_constant)
|
||||
uniform u_info_t {
|
||||
ivec2 offset;
|
||||
} u_info;
|
||||
|
||||
void main() {
|
||||
ivec3 coord = ivec3(gl_FragCoord.xy, gl_Layer);
|
||||
ivec3 coord = ivec3(gl_FragCoord.xy + u_info.offset, gl_Layer);
|
||||
o_color = texelFetch(s_image, coord, 0);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user