mirror of
https://github.com/azahar-emu/azahar.git
synced 2026-06-05 18:23:39 -04:00
renderer_vulkan: Fix Multisample ConvertDS24S8ToRGBA8
Migrate `ResolveTexture` to `BlitHelper`. If the conversion was multi-sample, do a final resolve at the end of the conversion to ensure the non-multisample textures are updated as well. Fixes Pokemon!
This commit is contained in:
parent
a0a0cd648e
commit
0cb1680a20
4 changed files with 102 additions and 92 deletions
|
|
@ -523,6 +523,11 @@ bool BlitHelper::ConvertDS24S8ToRGBA8(Surface& source, Surface& dest,
|
|||
vk::PipelineStageFlagBits::eTransfer,
|
||||
vk::DependencyFlagBits::eByRegion, {}, {}, post_barriers);
|
||||
});
|
||||
|
||||
if (multisample) {
|
||||
// Resolve the destination image if needed
|
||||
ResolveTexture(dest);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -601,6 +606,99 @@ bool BlitHelper::DepthToBuffer(Surface& source, vk::Buffer buffer,
|
|||
return true;
|
||||
}
|
||||
|
||||
void BlitHelper::ResolveTexture(Surface& surface) {
|
||||
|
||||
scheduler.Record([width = surface.GetScaledWidth(), height = surface.GetScaledHeight(),
|
||||
aspect = surface.Aspect(), access_flags = surface.AccessFlags(),
|
||||
pipeline_state_flags = surface.PipelineStageFlags(),
|
||||
msaa_image = surface.Image(Type::MultiSampled),
|
||||
dest_image = surface.Image()](vk::CommandBuffer cmdbuf) {
|
||||
const vk::ImageResolve resolve_area = {
|
||||
.srcSubresource{
|
||||
.aspectMask = aspect,
|
||||
.mipLevel = 0,
|
||||
.baseArrayLayer = 0,
|
||||
.layerCount = 1,
|
||||
},
|
||||
.srcOffset = {},
|
||||
.dstSubresource{
|
||||
.aspectMask = aspect,
|
||||
.mipLevel = 0,
|
||||
.baseArrayLayer = 0,
|
||||
.layerCount = 1,
|
||||
},
|
||||
.dstOffset = {},
|
||||
.extent{
|
||||
.width = width,
|
||||
.height = height,
|
||||
.depth = 1,
|
||||
},
|
||||
};
|
||||
|
||||
const vk::ImageSubresourceRange subresource_range = vk::ImageSubresourceRange{
|
||||
.aspectMask = aspect,
|
||||
.baseMipLevel = 0,
|
||||
.levelCount = 1,
|
||||
.baseArrayLayer = 0,
|
||||
.layerCount = VK_REMAINING_ARRAY_LAYERS,
|
||||
};
|
||||
|
||||
const std::array read_barriers = {
|
||||
vk::ImageMemoryBarrier{
|
||||
.srcAccessMask = access_flags,
|
||||
.dstAccessMask = vk::AccessFlagBits::eTransferRead,
|
||||
.oldLayout = vk::ImageLayout::eGeneral,
|
||||
.newLayout = vk::ImageLayout::eTransferSrcOptimal,
|
||||
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
.image = msaa_image,
|
||||
.subresourceRange = subresource_range,
|
||||
},
|
||||
vk::ImageMemoryBarrier{
|
||||
.srcAccessMask = access_flags,
|
||||
.dstAccessMask = vk::AccessFlagBits::eTransferWrite,
|
||||
.oldLayout = vk::ImageLayout::eGeneral,
|
||||
.newLayout = vk::ImageLayout::eTransferDstOptimal,
|
||||
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
.image = dest_image,
|
||||
.subresourceRange = subresource_range,
|
||||
},
|
||||
};
|
||||
const std::array write_barriers = {
|
||||
vk::ImageMemoryBarrier{
|
||||
.srcAccessMask = vk::AccessFlagBits::eTransferRead,
|
||||
.dstAccessMask = access_flags,
|
||||
.oldLayout = vk::ImageLayout::eTransferSrcOptimal,
|
||||
.newLayout = vk::ImageLayout::eGeneral,
|
||||
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
.image = msaa_image,
|
||||
.subresourceRange = subresource_range,
|
||||
},
|
||||
vk::ImageMemoryBarrier{
|
||||
.srcAccessMask = vk::AccessFlagBits::eTransferWrite,
|
||||
.dstAccessMask = access_flags,
|
||||
.oldLayout = vk::ImageLayout::eTransferDstOptimal,
|
||||
.newLayout = vk::ImageLayout::eGeneral,
|
||||
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
.image = dest_image,
|
||||
.subresourceRange = subresource_range,
|
||||
},
|
||||
};
|
||||
|
||||
cmdbuf.pipelineBarrier(pipeline_state_flags, vk::PipelineStageFlagBits::eTransfer,
|
||||
vk::DependencyFlagBits::eByRegion, {}, {}, read_barriers);
|
||||
|
||||
cmdbuf.resolveImage(msaa_image, vk::ImageLayout::eTransferSrcOptimal, dest_image,
|
||||
vk::ImageLayout::eTransferDstOptimal, resolve_area);
|
||||
|
||||
cmdbuf.pipelineBarrier(vk::PipelineStageFlagBits::eTransfer, pipeline_state_flags,
|
||||
vk::DependencyFlagBits::eByRegion, {}, {}, write_barriers);
|
||||
});
|
||||
}
|
||||
|
||||
vk::Pipeline BlitHelper::MakeComputePipeline(vk::ShaderModule shader, vk::PipelineLayout layout) {
|
||||
const vk::ComputePipelineCreateInfo compute_info = {
|
||||
.stage = MakeStages(shader),
|
||||
|
|
|
|||
|
|
@ -39,6 +39,8 @@ public:
|
|||
bool DepthToBuffer(Surface& source, vk::Buffer buffer,
|
||||
const VideoCore::BufferTextureCopy& copy);
|
||||
|
||||
void ResolveTexture(Surface& surface);
|
||||
|
||||
private:
|
||||
vk::Pipeline MakeComputePipeline(vk::ShaderModule shader, vk::PipelineLayout layout);
|
||||
vk::Pipeline MakeDepthStencilBlitPipeline();
|
||||
|
|
|
|||
|
|
@ -495,93 +495,6 @@ void TextureRuntime::ClearTextureWithRenderpass(Surface& surface,
|
|||
});
|
||||
}
|
||||
|
||||
void TextureRuntime::ResolveTexture(Surface& surface) {
|
||||
|
||||
scheduler.Record([width = surface.GetScaledWidth(), height = surface.GetScaledHeight(),
|
||||
aspect = surface.Aspect(), access_flags = surface.AccessFlags(),
|
||||
pipeline_state_flags = surface.PipelineStageFlags(),
|
||||
msaa_image = surface.Image(Type::MultiSampled),
|
||||
dest_image = surface.Image()](vk::CommandBuffer cmdbuf) {
|
||||
const vk::ImageResolve resolve_area = {
|
||||
.srcSubresource{
|
||||
.aspectMask = aspect,
|
||||
.mipLevel = 0,
|
||||
.baseArrayLayer = 0,
|
||||
.layerCount = 1,
|
||||
},
|
||||
.srcOffset = {},
|
||||
.dstSubresource{
|
||||
.aspectMask = aspect,
|
||||
.mipLevel = 0,
|
||||
.baseArrayLayer = 0,
|
||||
.layerCount = 1,
|
||||
},
|
||||
.dstOffset = {},
|
||||
.extent{
|
||||
.width = width,
|
||||
.height = height,
|
||||
.depth = 1,
|
||||
},
|
||||
};
|
||||
|
||||
const vk::ImageSubresourceRange subresource_range = MakeSubresourceRange(aspect, 0);
|
||||
|
||||
const std::array read_barriers = {
|
||||
vk::ImageMemoryBarrier{
|
||||
.srcAccessMask = access_flags,
|
||||
.dstAccessMask = vk::AccessFlagBits::eTransferRead,
|
||||
.oldLayout = vk::ImageLayout::eGeneral,
|
||||
.newLayout = vk::ImageLayout::eTransferSrcOptimal,
|
||||
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
.image = msaa_image,
|
||||
.subresourceRange = subresource_range,
|
||||
},
|
||||
vk::ImageMemoryBarrier{
|
||||
.srcAccessMask = access_flags,
|
||||
.dstAccessMask = vk::AccessFlagBits::eTransferWrite,
|
||||
.oldLayout = vk::ImageLayout::eGeneral,
|
||||
.newLayout = vk::ImageLayout::eTransferDstOptimal,
|
||||
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
.image = dest_image,
|
||||
.subresourceRange = subresource_range,
|
||||
},
|
||||
};
|
||||
const std::array write_barriers = {
|
||||
vk::ImageMemoryBarrier{
|
||||
.srcAccessMask = vk::AccessFlagBits::eTransferRead,
|
||||
.dstAccessMask = access_flags,
|
||||
.oldLayout = vk::ImageLayout::eTransferSrcOptimal,
|
||||
.newLayout = vk::ImageLayout::eGeneral,
|
||||
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
.image = msaa_image,
|
||||
.subresourceRange = subresource_range,
|
||||
},
|
||||
vk::ImageMemoryBarrier{
|
||||
.srcAccessMask = vk::AccessFlagBits::eTransferWrite,
|
||||
.dstAccessMask = access_flags,
|
||||
.oldLayout = vk::ImageLayout::eTransferDstOptimal,
|
||||
.newLayout = vk::ImageLayout::eGeneral,
|
||||
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
.image = dest_image,
|
||||
.subresourceRange = subresource_range,
|
||||
},
|
||||
};
|
||||
|
||||
cmdbuf.pipelineBarrier(pipeline_state_flags, vk::PipelineStageFlagBits::eTransfer,
|
||||
vk::DependencyFlagBits::eByRegion, {}, {}, read_barriers);
|
||||
|
||||
cmdbuf.resolveImage(msaa_image, vk::ImageLayout::eTransferSrcOptimal, dest_image,
|
||||
vk::ImageLayout::eTransferDstOptimal, resolve_area);
|
||||
|
||||
cmdbuf.pipelineBarrier(vk::PipelineStageFlagBits::eTransfer, pipeline_state_flags,
|
||||
vk::DependencyFlagBits::eByRegion, {}, {}, write_barriers);
|
||||
});
|
||||
}
|
||||
|
||||
bool TextureRuntime::CopyTextures(Surface& source, Surface& dest,
|
||||
std::span<const VideoCore::TextureCopy> copies) {
|
||||
renderpass_cache.EndRendering();
|
||||
|
|
@ -697,10 +610,10 @@ bool TextureRuntime::BlitTextures(Surface& source, Surface& dest,
|
|||
// Must resolve images first
|
||||
// Todo(wunk): Add a "dirty" flag for msaa resolves to avoid redundant image resolves
|
||||
if (source.sample_count > 1) {
|
||||
ResolveTexture(source);
|
||||
blit_helper.ResolveTexture(source);
|
||||
}
|
||||
if (dest.sample_count > 1) {
|
||||
ResolveTexture(dest);
|
||||
blit_helper.ResolveTexture(dest);
|
||||
}
|
||||
|
||||
const RecordParams params = {
|
||||
|
|
|
|||
|
|
@ -163,9 +163,6 @@ private:
|
|||
/// Clears a partial texture rect using a clear rectangle
|
||||
void ClearTextureWithRenderpass(Surface& surface, const VideoCore::TextureClear& clear);
|
||||
|
||||
/// Resolves the multi-sampled texture of a surface, if available, into the current texture
|
||||
void ResolveTexture(Surface& surface);
|
||||
|
||||
private:
|
||||
const Instance& instance;
|
||||
Scheduler& scheduler;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue