mirror of
https://github.com/azahar-emu/azahar.git
synced 2026-06-06 02:33:44 -04:00
renderer_vulkan: Add TextureRuntime::ResolveTexture
Rather than use a big lambda, just rip this out into a proper function for other blit functions to utilize.
This commit is contained in:
parent
7ce88bc63b
commit
5ded99d326
2 changed files with 99 additions and 91 deletions
|
|
@ -492,6 +492,93 @@ 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();
|
||||
|
|
@ -604,6 +691,15 @@ bool TextureRuntime::BlitTextures(Surface& source, Surface& dest,
|
|||
|
||||
renderpass_cache.EndRendering();
|
||||
|
||||
// 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);
|
||||
}
|
||||
if (dest.sample_count > 1) {
|
||||
ResolveTexture(dest);
|
||||
}
|
||||
|
||||
const RecordParams params = {
|
||||
.aspect = source.Aspect(),
|
||||
.filter = MakeFilter(source.pixel_format),
|
||||
|
|
@ -614,96 +710,6 @@ bool TextureRuntime::BlitTextures(Surface& source, Surface& dest,
|
|||
.dst_image = dest.Image(),
|
||||
};
|
||||
|
||||
// Todo(wunk): Add a "dirty" flag for msaa resolves to avoid redundant image resolves
|
||||
const auto resolve_image = [&](const Surface& msaa_surface) {
|
||||
scheduler.Record([width = msaa_surface.GetScaledWidth(),
|
||||
height = msaa_surface.GetScaledHeight(), aspect = msaa_surface.Aspect(),
|
||||
access_flags = msaa_surface.AccessFlags(),
|
||||
pipeline_state_flags = msaa_surface.PipelineStageFlags(),
|
||||
msaa_image = msaa_surface.Image(Type::MultiSampled),
|
||||
dest_image = msaa_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, height, 1},
|
||||
};
|
||||
|
||||
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 = MakeSubresourceRange(aspect, 0),
|
||||
},
|
||||
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 = MakeSubresourceRange(aspect, 0),
|
||||
},
|
||||
};
|
||||
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 = MakeSubresourceRange(aspect, 0),
|
||||
},
|
||||
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 = MakeSubresourceRange(aspect, 0),
|
||||
},
|
||||
};
|
||||
|
||||
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);
|
||||
});
|
||||
};
|
||||
|
||||
// Must resolve images first
|
||||
if (source.sample_count > 1) {
|
||||
resolve_image(source);
|
||||
}
|
||||
if (dest.sample_count > 1) {
|
||||
resolve_image(dest);
|
||||
}
|
||||
|
||||
scheduler.Record([params, blit](vk::CommandBuffer cmdbuf) {
|
||||
const std::array source_offsets = {
|
||||
vk::Offset3D{static_cast<s32>(blit.src_rect.left),
|
||||
|
|
@ -833,7 +839,6 @@ Surface::Surface(TextureRuntime& runtime_, const VideoCore::SurfaceParams& param
|
|||
scheduler{runtime_.GetScheduler()}, traits{instance.GetTraits(pixel_format)},
|
||||
handles{Handle(instance), Handle(instance), Handle(instance), Handle(instance),
|
||||
Handle(instance)} {
|
||||
|
||||
if (pixel_format == VideoCore::PixelFormat::Invalid || !traits.transfer_support) {
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -163,6 +163,9 @@ 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