Merge pull request #139 from shadps4-emu/render_vk/img_state_trk

renderer_vulkan: state tracking for `Image` resources
This commit is contained in:
psucien 2024-05-17 23:40:11 +02:00 committed by GitHub
commit aa88458ad8
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 60 additions and 71 deletions

View file

@ -203,21 +203,9 @@ Frame* RendererVulkan::PrepareFrameInternal(VideoCore::Image& image) {
Frame* frame = GetRenderFrame();
// Post-processing (Anti-aliasing, FSR etc) goes here. For now just blit to the frame image.
const std::array pre_barriers{
vk::ImageMemoryBarrier{.srcAccessMask = vk::AccessFlagBits::eTransferWrite,
.dstAccessMask = vk::AccessFlagBits::eTransferRead,
.oldLayout = vk::ImageLayout::eUndefined,
.newLayout = vk::ImageLayout::eTransferSrcOptimal,
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.image = image.image,
.subresourceRange{
.aspectMask = vk::ImageAspectFlagBits::eColor,
.baseMipLevel = 0,
.levelCount = 1,
.baseArrayLayer = 0,
.layerCount = VK_REMAINING_ARRAY_LAYERS,
}},
image.Transit(vk::ImageLayout::eTransferSrcOptimal, vk::AccessFlagBits::eTransferRead);
const std::array pre_barrier{
vk::ImageMemoryBarrier{
.srcAccessMask = vk::AccessFlagBits::eTransferRead,
.dstAccessMask = vk::AccessFlagBits::eTransferWrite,
@ -235,6 +223,17 @@ Frame* RendererVulkan::PrepareFrameInternal(VideoCore::Image& image) {
},
},
};
const auto cmdbuf = scheduler.CommandBuffer();
cmdbuf.pipelineBarrier(vk::PipelineStageFlagBits::eTransfer,
vk::PipelineStageFlagBits::eTransfer, vk::DependencyFlagBits::eByRegion,
{}, {}, pre_barrier);
cmdbuf.blitImage(
image.image, image.layout, frame->image, vk::ImageLayout::eTransferDstOptimal,
MakeImageBlit(image.info.size.width, image.info.size.height, frame->width, frame->height),
vk::Filter::eLinear);
const vk::ImageMemoryBarrier post_barrier{
.srcAccessMask = vk::AccessFlagBits::eTransferWrite,
.dstAccessMask = vk::AccessFlagBits::eColorAttachmentWrite,
@ -252,16 +251,6 @@ Frame* RendererVulkan::PrepareFrameInternal(VideoCore::Image& image) {
},
};
const auto cmdbuf = scheduler.CommandBuffer();
cmdbuf.pipelineBarrier(vk::PipelineStageFlagBits::eTransfer,
vk::PipelineStageFlagBits::eTransfer, vk::DependencyFlagBits::eByRegion,
{}, {}, pre_barriers);
cmdbuf.blitImage(
image.image, vk::ImageLayout::eTransferSrcOptimal, frame->image,
vk::ImageLayout::eTransferDstOptimal,
MakeImageBlit(image.info.size.width, image.info.size.height, frame->width, frame->height),
vk::Filter::eLinear);
cmdbuf.pipelineBarrier(vk::PipelineStageFlagBits::eAllCommands,
vk::PipelineStageFlagBits::eAllCommands,
vk::DependencyFlagBits::eByRegion, {}, {}, post_barrier);

View file

@ -124,27 +124,41 @@ Image::Image(const Vulkan::Instance& instance_, Vulkan::Scheduler& scheduler_,
image.Create(image_ci);
const vk::ImageMemoryBarrier init_barrier = {
.srcAccessMask = vk::AccessFlagBits::eNone,
.dstAccessMask = vk::AccessFlagBits::eNone,
.oldLayout = vk::ImageLayout::eUndefined,
.newLayout = vk::ImageLayout::eGeneral,
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.image = image,
.subresourceRange{
.aspectMask = vk::ImageAspectFlagBits::eColor,
.baseMipLevel = 0,
.levelCount = VK_REMAINING_MIP_LEVELS,
.baseArrayLayer = 0,
.layerCount = VK_REMAINING_ARRAY_LAYERS,
},
};
Transit(vk::ImageLayout::eGeneral, vk::AccessFlagBits::eNone);
}
void Image::Transit(vk::ImageLayout dst_layout, vk::Flags<vk::AccessFlagBits> dst_mask) {
if (dst_layout == layout && dst_mask == access_mask) {
return;
}
const vk::ImageMemoryBarrier barrier = {.srcAccessMask = access_mask,
.dstAccessMask = dst_mask,
.oldLayout = layout,
.newLayout = dst_layout,
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.image = image,
.subresourceRange{
.aspectMask = aspect_mask,
.baseMipLevel = 0,
.levelCount = 1,
.baseArrayLayer = 0,
.layerCount = VK_REMAINING_ARRAY_LAYERS,
}};
// Adjust pipieline stage
vk::PipelineStageFlagBits dst_pl_stage = (dst_mask == vk::AccessFlagBits::eTransferRead ||
dst_mask == vk::AccessFlagBits::eTransferWrite)
? vk::PipelineStageFlagBits::eTransfer
: vk::PipelineStageFlagBits::eAllGraphics;
const auto cmdbuf = scheduler->CommandBuffer();
cmdbuf.pipelineBarrier(vk::PipelineStageFlagBits::eTopOfPipe,
vk::PipelineStageFlagBits::eTopOfPipe, vk::DependencyFlagBits::eByRegion,
{}, {}, init_barrier);
cmdbuf.pipelineBarrier(pl_stage, dst_pl_stage, vk::DependencyFlagBits::eByRegion, {}, {},
barrier);
layout = dst_layout;
access_mask = dst_mask;
pl_stage = dst_pl_stage;
}
Image::~Image() = default;

View file

@ -100,14 +100,21 @@ struct Image {
return cpu_addr < overlap_end && overlap_cpu_addr < cpu_addr_end;
}
void Transit(vk::ImageLayout dst_layout, vk::Flags<vk::AccessFlagBits> dst_mask);
const Vulkan::Instance* instance;
Vulkan::Scheduler* scheduler;
ImageInfo info;
UniqueImage image;
vk::ImageAspectFlags aspect_mask;
vk::ImageAspectFlags aspect_mask = vk::ImageAspectFlagBits::eColor;
ImageFlagBits flags = ImageFlagBits::CpuModified;
VAddr cpu_addr = 0;
VAddr cpu_addr_end = 0;
// Resource state tracking
vk::Flags<vk::PipelineStageFlagBits> pl_stage = vk::PipelineStageFlagBits::eAllCommands;
vk::Flags<vk::AccessFlagBits> access_mask = vk::AccessFlagBits::eNone;
vk::ImageLayout layout = vk::ImageLayout::eUndefined;
};
} // namespace VideoCore

View file

@ -166,35 +166,14 @@ void TextureCache::RefreshImage(Image& image) {
.baseArrayLayer = 0,
.layerCount = VK_REMAINING_ARRAY_LAYERS,
};
const vk::ImageMemoryBarrier read_barrier = {
.srcAccessMask = vk::AccessFlagBits::eShaderRead,
.dstAccessMask = vk::AccessFlagBits::eTransferWrite,
.oldLayout = vk::ImageLayout::eGeneral,
.newLayout = vk::ImageLayout::eTransferDstOptimal,
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.image = image.image,
.subresourceRange = range,
};
const vk::ImageMemoryBarrier write_barrier = {
.srcAccessMask = vk::AccessFlagBits::eTransferWrite,
.dstAccessMask = vk::AccessFlagBits::eShaderRead | vk::AccessFlagBits::eTransferRead,
.oldLayout = vk::ImageLayout::eTransferDstOptimal,
.newLayout = vk::ImageLayout::eGeneral,
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.image = image.image,
.subresourceRange = range,
};
cmdbuf.pipelineBarrier(vk::PipelineStageFlagBits::eAllGraphics,
vk::PipelineStageFlagBits::eTransfer, vk::DependencyFlagBits::eByRegion,
{}, {}, read_barrier);
image.Transit(vk::ImageLayout::eTransferDstOptimal, vk::AccessFlagBits::eTransferWrite);
cmdbuf.copyBufferToImage(staging.Handle(), image.image, vk::ImageLayout::eTransferDstOptimal,
image_copy);
cmdbuf.pipelineBarrier(vk::PipelineStageFlagBits::eTransfer,
vk::PipelineStageFlagBits::eAllGraphics,
vk::DependencyFlagBits::eByRegion, {}, {}, write_barrier);
image.Transit(vk::ImageLayout::eGeneral,
vk::AccessFlagBits::eShaderRead | vk::AccessFlagBits::eTransferRead);
}
void TextureCache::RegisterImage(ImageId image_id) {