renderer_vulkan: state tracking for `Image` resources
This commit is contained in:
parent
3f692a4d7d
commit
85704e26a0
|
@ -203,21 +203,9 @@ Frame* RendererVulkan::PrepareFrameInternal(VideoCore::Image& image) {
|
||||||
Frame* frame = GetRenderFrame();
|
Frame* frame = GetRenderFrame();
|
||||||
|
|
||||||
// Post-processing (Anti-aliasing, FSR etc) goes here. For now just blit to the frame image.
|
// Post-processing (Anti-aliasing, FSR etc) goes here. For now just blit to the frame image.
|
||||||
const std::array pre_barriers{
|
image.Transit(vk::ImageLayout::eTransferSrcOptimal, vk::AccessFlagBits::eTransferRead);
|
||||||
vk::ImageMemoryBarrier{.srcAccessMask = vk::AccessFlagBits::eTransferWrite,
|
|
||||||
.dstAccessMask = vk::AccessFlagBits::eTransferRead,
|
const std::array pre_barrier{
|
||||||
.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,
|
|
||||||
}},
|
|
||||||
vk::ImageMemoryBarrier{
|
vk::ImageMemoryBarrier{
|
||||||
.srcAccessMask = vk::AccessFlagBits::eTransferRead,
|
.srcAccessMask = vk::AccessFlagBits::eTransferRead,
|
||||||
.dstAccessMask = vk::AccessFlagBits::eTransferWrite,
|
.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{
|
const vk::ImageMemoryBarrier post_barrier{
|
||||||
.srcAccessMask = vk::AccessFlagBits::eTransferWrite,
|
.srcAccessMask = vk::AccessFlagBits::eTransferWrite,
|
||||||
.dstAccessMask = vk::AccessFlagBits::eColorAttachmentWrite,
|
.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,
|
cmdbuf.pipelineBarrier(vk::PipelineStageFlagBits::eAllCommands,
|
||||||
vk::PipelineStageFlagBits::eAllCommands,
|
vk::PipelineStageFlagBits::eAllCommands,
|
||||||
vk::DependencyFlagBits::eByRegion, {}, {}, post_barrier);
|
vk::DependencyFlagBits::eByRegion, {}, {}, post_barrier);
|
||||||
|
|
|
@ -124,27 +124,41 @@ Image::Image(const Vulkan::Instance& instance_, Vulkan::Scheduler& scheduler_,
|
||||||
|
|
||||||
image.Create(image_ci);
|
image.Create(image_ci);
|
||||||
|
|
||||||
const vk::ImageMemoryBarrier init_barrier = {
|
Transit(vk::ImageLayout::eGeneral, vk::AccessFlagBits::eNone);
|
||||||
.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,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
|
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();
|
const auto cmdbuf = scheduler->CommandBuffer();
|
||||||
cmdbuf.pipelineBarrier(vk::PipelineStageFlagBits::eTopOfPipe,
|
cmdbuf.pipelineBarrier(pl_stage, dst_pl_stage, vk::DependencyFlagBits::eByRegion, {}, {},
|
||||||
vk::PipelineStageFlagBits::eTopOfPipe, vk::DependencyFlagBits::eByRegion,
|
barrier);
|
||||||
{}, {}, init_barrier);
|
|
||||||
|
layout = dst_layout;
|
||||||
|
access_mask = dst_mask;
|
||||||
|
pl_stage = dst_pl_stage;
|
||||||
}
|
}
|
||||||
|
|
||||||
Image::~Image() = default;
|
Image::~Image() = default;
|
||||||
|
|
|
@ -100,14 +100,21 @@ struct Image {
|
||||||
return cpu_addr < overlap_end && overlap_cpu_addr < cpu_addr_end;
|
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;
|
const Vulkan::Instance* instance;
|
||||||
Vulkan::Scheduler* scheduler;
|
Vulkan::Scheduler* scheduler;
|
||||||
ImageInfo info;
|
ImageInfo info;
|
||||||
UniqueImage image;
|
UniqueImage image;
|
||||||
vk::ImageAspectFlags aspect_mask;
|
vk::ImageAspectFlags aspect_mask = vk::ImageAspectFlagBits::eColor;
|
||||||
ImageFlagBits flags = ImageFlagBits::CpuModified;
|
ImageFlagBits flags = ImageFlagBits::CpuModified;
|
||||||
VAddr cpu_addr = 0;
|
VAddr cpu_addr = 0;
|
||||||
VAddr cpu_addr_end = 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
|
} // namespace VideoCore
|
||||||
|
|
|
@ -166,35 +166,14 @@ void TextureCache::RefreshImage(Image& image) {
|
||||||
.baseArrayLayer = 0,
|
.baseArrayLayer = 0,
|
||||||
.layerCount = VK_REMAINING_ARRAY_LAYERS,
|
.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,
|
image.Transit(vk::ImageLayout::eTransferDstOptimal, vk::AccessFlagBits::eTransferWrite);
|
||||||
vk::PipelineStageFlagBits::eTransfer, vk::DependencyFlagBits::eByRegion,
|
|
||||||
{}, {}, read_barrier);
|
|
||||||
cmdbuf.copyBufferToImage(staging.Handle(), image.image, vk::ImageLayout::eTransferDstOptimal,
|
cmdbuf.copyBufferToImage(staging.Handle(), image.image, vk::ImageLayout::eTransferDstOptimal,
|
||||||
image_copy);
|
image_copy);
|
||||||
cmdbuf.pipelineBarrier(vk::PipelineStageFlagBits::eTransfer,
|
|
||||||
vk::PipelineStageFlagBits::eAllGraphics,
|
image.Transit(vk::ImageLayout::eGeneral,
|
||||||
vk::DependencyFlagBits::eByRegion, {}, {}, write_barrier);
|
vk::AccessFlagBits::eShaderRead | vk::AccessFlagBits::eTransferRead);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextureCache::RegisterImage(ImageId image_id) {
|
void TextureCache::RegisterImage(ImageId image_id) {
|
||||||
|
|
Loading…
Reference in New Issue